mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-12-07 13:49:46 +00:00
gdb scripts
This commit is contained in:
parent
787b8f4e1f
commit
749439a92c
3 changed files with 101 additions and 3 deletions
3
scripts/.gitignore
vendored
3
scripts/.gitignore
vendored
|
|
@ -1 +1,2 @@
|
|||
__pycache__
|
||||
__pycache__
|
||||
gdb_data/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import gdb
|
||||
import json
|
||||
|
||||
patches = dict()
|
||||
|
||||
|
|
@ -6,7 +7,7 @@ class PatchNop(gdb.Command):
|
|||
def __init__ (self):
|
||||
super().__init__ ("patch-nop", gdb.COMMAND_USER)
|
||||
|
||||
def invoke (self, arg, from_tty):
|
||||
def invoke(self, arg, from_tty):
|
||||
addr = int(arg, base=0)
|
||||
if addr in patches:
|
||||
print("Already patched")
|
||||
|
|
@ -24,13 +25,90 @@ class PatchRevert(gdb.Command):
|
|||
def __init__ (self):
|
||||
super().__init__ ("patch-revert", gdb.COMMAND_USER)
|
||||
|
||||
def invoke (self, arg, from_tty):
|
||||
def invoke(self, arg, from_tty):
|
||||
inferior = gdb.selected_inferior()
|
||||
for addr, mem in patches.items():
|
||||
print("Restoring", hex(addr))
|
||||
inferior.write_memory(addr, mem)
|
||||
patches.clear()
|
||||
|
||||
_vtables_cache = None
|
||||
|
||||
def get_vtables():
|
||||
global _vtables_cache
|
||||
if _vtables_cache is None:
|
||||
print("Loading VTables")
|
||||
_vtables_cache = {}
|
||||
for k, v in json.load(open("gdb_data/vtables.json")).items():
|
||||
_vtables_cache[int(k)] = v
|
||||
return _vtables_cache
|
||||
|
||||
class MemReader:
|
||||
def __init__(self):
|
||||
self.inferior = gdb.selected_inferior()
|
||||
|
||||
def read_uint(self, addr: int):
|
||||
try:
|
||||
return int.from_bytes(self.inferior.read_memory(addr, 4), byteorder="little", signed=False)
|
||||
except gdb.MemoryError:
|
||||
return None
|
||||
|
||||
class ValueIdentifier:
|
||||
def __init__(self, addr: int):
|
||||
self.addr = addr
|
||||
self.mem = MemReader()
|
||||
self.vtables = get_vtables()
|
||||
self.type = None
|
||||
self.name = None
|
||||
self.identify()
|
||||
|
||||
def identify(self):
|
||||
if self.addr == 0:
|
||||
self.type = "null"
|
||||
return
|
||||
if self.addr in self.vtables:
|
||||
self.type = "pointer to vtable"
|
||||
self.name = self.vtables[self.addr]
|
||||
return
|
||||
val = self.mem.read_uint(self.addr)
|
||||
if val is None:
|
||||
self.type = "unreadable pointer"
|
||||
else:
|
||||
#print(f"Checking if {hex(val)} is a vtable")
|
||||
if val in self.vtables:
|
||||
self.type = "pointer to value of type"
|
||||
self.name = self.vtables[val]
|
||||
return
|
||||
|
||||
class Identify(gdb.Command):
|
||||
def __init__ (self):
|
||||
super().__init__ ("identify", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
addr = int(arg, base=0)
|
||||
vi = ValueIdentifier(addr)
|
||||
print(vi.type, vi.name)
|
||||
|
||||
class Layout(gdb.Command):
|
||||
def __init__ (self):
|
||||
super().__init__ ("layout", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
splt = arg.split()
|
||||
addr = int(splt[0], base=0)
|
||||
amount = 1024
|
||||
if len(splt) > 1:
|
||||
amount = int(splt[1])
|
||||
mem = MemReader()
|
||||
for i in range(amount):
|
||||
p = mem.read_uint(addr+i*4)
|
||||
if p is not None:
|
||||
vi = ValueIdentifier(p)
|
||||
if vi.type is not None and vi.type != "null" and vi.type != "unreadable pointer":
|
||||
print(f"Field {hex(i*4)} ({hex(addr+i*4)}, {hex(p)})", vi.type, vi.name)
|
||||
|
||||
|
||||
PatchNop()
|
||||
PatchRevert()
|
||||
Identify()
|
||||
Layout()
|
||||
|
|
|
|||
19
scripts/gdb_parse_ghidra.py
Normal file
19
scripts/gdb_parse_ghidra.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import xml.etree.ElementTree as ET
|
||||
import os
|
||||
import json
|
||||
|
||||
base_path = "scripts/gdb_data/"
|
||||
os.makedirs(base_path, exist_ok=True)
|
||||
|
||||
source_path = "/home/quant/noita.exe.xml"
|
||||
tree = ET.parse(source_path)
|
||||
root = tree.getroot()
|
||||
|
||||
vtables = dict()
|
||||
|
||||
for symbol in root.find('SYMBOL_TABLE'):
|
||||
addr = int(symbol.attrib["ADDRESS"], base=16)
|
||||
if symbol.attrib["NAME"] == "vftable":
|
||||
vtables[addr] = symbol.attrib["NAMESPACE"]
|
||||
|
||||
json.dump(vtables, open(base_path+"vtables.json", "w"))
|
||||
Loading…
Add table
Add a link
Reference in a new issue