From 2aa6109f3415acde04ab03f3c26bd3295a2b0349 Mon Sep 17 00:00:00 2001 From: NullExir Date: Thu, 13 Feb 2025 02:21:30 +0100 Subject: [PATCH] vtable_structs: Attempting to port into IDA-9.0 - Note: Changes do not yet resolve runtime issues. - Replace deprecated API calls with updated equivalents. --- vtable_structs.py | 54 +++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/vtable_structs.py b/vtable_structs.py index 132d4e1..a669295 100644 --- a/vtable_structs.py +++ b/vtable_structs.py @@ -1,6 +1,7 @@ import idc import idautils import idaapi +import ida_typeinf import ctypes import time @@ -215,12 +216,12 @@ def get_class_from_ea(classtype, ea): bytestr = idaapi.get_bytes(ea, ctypes.sizeof(classtype)) return classtype.from_buffer_copy(bytestr) -def add_struc_ex(name): - strucid = idaapi.get_struc_id(name) - if strucid == idc.BADADDR: - strucid = idaapi.add_struc(idc.BADADDR, name) +# def add_struc_ex(name): +# strucid = idc.get_struc_id(name) +# if strucid == idc.BADADDR: +# strucid = idc.add_struc(idc.BADADDR, name, 0) - return strucid +# return strucid # Anything past Classname:: # Thank you CTFPlayer::SOCacheUnsubscribed... @@ -394,27 +395,40 @@ def calc_member_tinfo(vfunc): InfoCache.tinfos[vfunc.funcref.ea] = tinfo return tinfo +def add_struc_new(name): + tid = idaapi.get_named_type_tid(name) + if tid != idaapi.BADADDR: + # The struct already exists. + print("Struct {!r} Already exists!".format(name)) + + tid = idaapi.tinfo_t.create_udt(idaapi.BADADDR, name, 0) + + if tid == idaapi.BADADDR: + print(f"{tid} Struct creation failed.") + else: + print(f"creating struct {tid}") + + return tid def create_structs(data): # Now this is an awesome API function that we most certainly need idaapi.begin_type_updating(idaapi.UTP_STRUCT) for classname, vtables in data.items(): - classstrucid = add_struc_ex(classname) - classstruc = idaapi.get_struc(classstrucid) + classstrucid = add_struc_new(classname) + for thisoffs, vfuncs in vtables.items(): thisoffs = abs(thisoffs) postfix = f"_{thisoffs:04X}" if thisoffs != 0 else "" structype = f"{classname}{postfix}{idaapi.VTBL_SUFFIX}" structype = idaapi.validate_name(structype, idaapi.VNT_TYPE, idaapi.SN_IDBENC) - vtablestrucid = add_struc_ex(structype) - vtablestruc = idaapi.get_struc(vtablestrucid) + vtablestrucid = add_struc_new(structype) for i, vfunc in enumerate(vfuncs): offs = i * ctypes.sizeof(ea_t) targetname = vfunc.funcref.sname - currmem = idaapi.get_member(vtablestruc, offs) + currmem = idc.get_member_id(vtablestrucid, offs) if currmem: # memname = idaapi.get_member_name(currmem.id) # # Can have a postfix so we use in operator @@ -446,35 +460,35 @@ def create_structs(data): opinfo.ri.base = 0 opinfo.ri.tdelta = 0 - serr = idaapi.add_struc_member(vtablestruc, targetname, offs, FF_PTR|idc.FF_0OFF, opinfo, ctypes.sizeof(ea_t)) + serr = idc.add_struc_member(vtablestrucid, targetname, offs, FF_PTR|idc.FF_0OFF, opinfo, ctypes.sizeof(ea_t)) # Failed, so there was either an invalid name or a name collision if serr == idaapi.STRUC_ERROR_MEMBER_NAME: targetname = idaapi.validate_name(targetname, idaapi.VNT_IDENT, idaapi.SN_IDBENC) - serr = idaapi.add_struc_member(vtablestruc, targetname, offs, FF_PTR|idc.FF_0OFF, opinfo, ctypes.sizeof(ea_t)) + serr = idc.add_struc_member(vtablestrucid, targetname, offs, FF_PTR|idc.FF_0OFF, opinfo, ctypes.sizeof(ea_t)) if serr == idaapi.STRUC_ERROR_MEMBER_NAME: targetname = f"{targetname}_{offs:X}" - serr = idaapi.add_struc_member(vtablestruc, targetname, offs, FF_PTR|idc.FF_0OFF, opinfo, ctypes.sizeof(ea_t)) + serr = idc.add_struc_member(vtablestrucid, targetname, offs, FF_PTR|idc.FF_0OFF, opinfo, ctypes.sizeof(ea_t)) if serr != idaapi.STRUC_ERROR_MEMBER_OK: - print(vtablestruc, vtablestrucid) + print(vtablestrucid, vtablestrucid) print(f"Failed to add member {classname}::{vfunc.funcref.sname} ({targetname}) at offset {offs:#x} -> {serr}") continue tinfo = calc_member_tinfo(vfunc) if tinfo is not None: - mem = idaapi.get_member(vtablestruc, offs) - idaapi.set_member_tinfo(vtablestruc, mem, 0, tinfo, 0) + mem = idc.get_member_id(vtablestrucid, offs) + idaapi.set_member_tinfo(vtablestrucid, mem, 0, tinfo, 0) - vmember = idaapi.get_member(classstruc, thisoffs) + vmember = idc.get_member_id(classstrucid, thisoffs) if not vmember: - if idaapi.add_struc_member(classstruc, f"{idaapi.VTBL_MEMNAME}{postfix}", thisoffs, idc.FF_DATA | FF_PTR, None, ctypes.sizeof(ea_t)) == idaapi.STRUC_ERROR_MEMBER_OK: + if idc.add_struc_member(classstrucid, f"{idaapi.VTBL_MEMNAME}{postfix}", thisoffs, idc.FF_DATA | FF_PTR, None, ctypes.sizeof(ea_t)) == idaapi.STRUC_ERROR_MEMBER_OK: global STRUCTS STRUCTS += 1 tinfo = idaapi.tinfo_t() if idaapi.guess_tinfo(tinfo, vtablestrucid) != idaapi.GUESS_FUNC_FAILED: - mem = idaapi.get_member(classstruc, thisoffs) + mem = idc.get_member_id(classstrucid, thisoffs) tinfo.create_ptr(tinfo) - idaapi.set_member_tinfo(classstruc, mem, 0, tinfo, 0) + idaapi.set_member_tinfo(classstrucid, mem, 0, tinfo, 0) def read_vtables_linux(): WaitBox.show("Parsing typeinfo")