def set_struct(name): if idaapi.get_struc_id(str(name)) != idaapi.BADADDR: idaapi.del_struc(idaapi.get_struc(idaapi.get_struc_id(name))) ok = idc.add_struc(-1, str(name), 0) if not ok: print("Could not add struct {name}".format(name=name))
def define(ea): if BaseClassDescriptor.isDefined(ea): return td = TypeDescriptor(BaseClassDescriptor.__typeDescriptorPtr(ea)) attrs = BaseClassDescriptor.__attributes(ea) if attrs != 0 and attrs != 0x40: print '%08X: Suspicious attributes value: %08X' % (ea, attrs) # raise RttiError('%08X: Suspicious attributes value: %08X' % (ea, attrs)) isV2 = (attrs & 0x40) != 0 if isV2: strid = idaapi.get_struc_id('_s__RTTIBaseClassDescriptor2') else: strid = idaapi.get_struc_id('_s__RTTIBaseClassDescriptor') size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) pmd = BaseClassDescriptor.__where(ea) name = '??_R1' name += mangleNumber(pmd.mdisp) name += mangleNumber(pmd.pdisp) name += mangleNumber(pmd.vdisp) name += mangleNumber(attrs) name += td.baseMangledName + '8' idaapi.set_name(ea, name, 0) if isV2: ClassHierarchyDescriptor.define(BaseClassDescriptor.__v2ChdPtr(ea))
def find_WdfDeviceCreateDeviceInterface(): function_offset = OFFSET_WdfDeviceCreateDeviceInterface calls_to_pfn_list = [] try: for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"]+function_offset): call_pfnWdfDeviceCreateDeviceInterface = xref.frm calls_to_pfn_list.append(call_pfnWdfDeviceCreateDeviceInterface) except StopIteration: # this is case 2 or 3 pass if len(calls_to_pfn_list) == 0: call_pfnWdfDeviceCreateDeviceInterface = find_wdf_callback_through_immediate("call", 0, function_offset) if call_pfnWdfDeviceCreateDeviceInterface: calls_to_pfn_list.append(call_pfnWdfDeviceCreateDeviceInterface) idc.OpStroffEx(call_pfnWdfDeviceCreateDeviceInterface,0,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) if len(calls_to_pfn_list) == 0: call_pfnWdfDeviceCreateDeviceInterface = find_wdf_callback_through_immediate("mov", 1,function_offset) if call_pfnWdfDeviceCreateDeviceInterface: calls_to_pfn_list.append(call_pfnWdfDeviceCreateDeviceInterface) idc.OpStroffEx(call_pfnWdfDeviceCreateDeviceInterface,1,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) for k, pfn_call in enumerate(calls_to_pfn_list): lea_guid = find_function_arg(pfn_call, "lea", "r8", 0) interface_guid = idc.GetOperandValue(lea_guid, 1) idc.MakeName(interface_guid, '_InterfaceGUID' + str(k)) assign_struct_to_address(interface_guid, "GUID") g_vars["_InterfaceGUID" + str(k)] = interface_guid print("_InterfaceGUID: ", hex(interface_guid)) guid_bytes = idc.GetManyBytes(interface_guid, 0x10) print_guid(guid_bytes)
def define(ea): if BaseClassDescriptor.isDefined(ea): return td = TypeDescriptor(BaseClassDescriptor.__typeDescriptorPtr(ea)) attrs = BaseClassDescriptor.__attributes(ea) if attrs != 0 and attrs != 0x40: print "%08X: Suspicious attributes value: %08X" % (ea, attrs) # raise RttiError('%08X: Suspicious attributes value: %08X' % (ea, attrs)) isV2 = (attrs & 0x40) != 0 if isV2: strid = idaapi.get_struc_id("_s__RTTIBaseClassDescriptor2") else: strid = idaapi.get_struc_id("_s__RTTIBaseClassDescriptor") size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) pmd = BaseClassDescriptor.__where(ea) name = "??_R1" name += mangleNumber(pmd.mdisp) name += mangleNumber(pmd.pdisp) name += mangleNumber(pmd.vdisp) name += mangleNumber(attrs) name += td.baseMangledName + "8" idaapi.set_name(ea, name, 0) if isV2: ClassHierarchyDescriptor.define(BaseClassDescriptor.__v2ChdPtr(ea))
class RTTIBaseClassDescriptor(RTTIStruc): msid = get_struc_id("PMD") if msid != BADADDR: del_struc(msid) msid = add_struc(0xFFFFFFFF, "PMD", False) add_struc_member(msid, "mdisp", BADADDR, FF_DATA | FF_DWRD, -1, 4) add_struc_member(msid, "pdisp", BADADDR, FF_DATA | FF_DWRD, -1, 4) add_struc_member(msid, "vdisp", BADADDR, FF_DATA | FF_DWRD, -1, 4) pmdid = msid pmdstruc = get_struc(pmdid) pmdsize = get_struc_size(pmdid) msid = get_struc_id("RTTIBaseClassDescriptor") if msid != BADADDR: del_struc(msid) msid = add_struc(0xFFFFFFFF, "RTTIBaseClassDescriptor", False) add_struc_member(msid, "pTypeDescriptor", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, 00000000, 4) add_struc_member(msid, "numContainerBases", BADADDR, FF_DWRD | FF_DATA, -1, 4) add_struc_member(msid, "PMD", BADADDR, FF_DATA | FF_DWRD | FF_STRU, pmdid, pmdsize) add_struc_member(msid, "attributes", BADADDR, FF_DWRD | FF_DATA, -1, 4) tid = msid struc = get_struc(tid) size = get_struc_size(tid) print "Completed Registering RTTIBaseClassDescriptor"
def find_WdfControlDeviceInitAllocate(): function_offset = OFFSET_WdfControlDeviceInitAllocate call_pfn = None try: for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] + function_offset): call_pfn = xref.frm except StopIteration: # this is case 2 or 3 pass if call_pfn is None: call_pfn = find_wdf_callback_through_immediate("call", 0, function_offset) if call_pfn: idc.OpStroffEx(call_pfn, 0, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) if call_pfn is None: call_pfn = find_wdf_callback_through_immediate("mov", 1, function_offset) if call_pfn: idc.OpStroffEx(call_pfn, 1, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) lea_sddl = find_function_arg(call_pfn, "lea", "r8", 0) unicode_sddl = idc.get_operand_value(lea_sddl, 1) idc.set_name(unicode_sddl, 'control_device_sddl') assign_struct_to_address(unicode_sddl, "_UNICODE_STRING") print("Control Device SDDL at: ", hex(unicode_sddl))
def find_WdfDriverCreate(): function_offset = OFFSET_WdfDriverCreate # If the XREF to wdfFunctions + function_offset exists.. then we're in case 1! try: call_pfnWdfDriverCreate = idautils.XrefsTo(g_vars["_WDFFUNCTIONS"]+function_offset).next().frm except StopIteration: # this is case 2! call_pfnWdfDriverCreate = find_wdf_callback_through_immediate("mov", 1,function_offset) if call_pfnWdfDriverCreate != None: idc.OpStroffEx(call_pfnWdfDriverCreate,1,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) else: call_pfnWdfDriverCreate = find_wdf_callback_through_immediate("call", 0, function_offset) idc.OpStroffEx(call_pfnWdfDriverCreate,0,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) if call_pfnWdfDriverCreate != None: # First identify the RealDriverEntry :) current_func = idaapi.get_func(call_pfnWdfDriverCreate) idc.MakeName(current_func.startEA, "_DriverEntry_") argument_DriverConfig_addr = find_function_arg_with_operand_value(call_pfnWdfDriverCreate, "mov", "rsp", 0x20, 0) register_DriverConfig = idc.GetOpnd(argument_DriverConfig_addr, 1) lea_DriverConfig_addr = find_function_arg(argument_DriverConfig_addr, "lea", register_DriverConfig, 0) # Get stack and the stack operand offset current_func = idaapi.get_func(lea_DriverConfig_addr) stack_id = idc.GetFrame(current_func) opnd = idc.GetOpnd(lea_DriverConfig_addr, 1) if "rsp" in opnd: stack_member_offset = idc.GetOperandValue(lea_DriverConfig_addr, 1) elif "rbp" in opnd: var_x = opnd.split("+")[-1][:-1] # [rbp+57h+var_80] -> var_80 members, _ = retrieve_stack_members(current_func) inverted_members = {v:k for k, v in members.items()} try: stack_member_offset = inverted_members[var_x] except KeyError as msg: print msg return else: print("+] WdfDriverCreate() Unidentified register stack layout") return #idc.SetMemberName(stack_id, stack_member_offset, "_DriverConfig") struct_id = idaapi.get_struc_id("_WDF_DRIVER_CONFIG") struct_size = idc.GetStrucSize(struct_id) # First check if we have already touch this function stack before #if function_stack_erased(current_func): # need to take care of the already defined structs # pass #else: delete_all_function_stack_members(current_func, force=True) idc.AddStrucMember(stack_id, "driver_config", stack_member_offset, idc.FF_BYTE|idc.FF_DATA, -1, struct_size) idc.SetMemberType(stack_id, stack_member_offset, idc.FF_STRU|idc.FF_DATA, struct_id, 1)
def find_WdfIoQueueCreate(): function_offset = OFFSET_WdfIoQueueCreate calls_to_pfn_list = [] try: for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] + function_offset): call_pfnWdfIoQueueCreate = xref.frm calls_to_pfn_list.append(call_pfnWdfIoQueueCreate) except StopIteration: # this is case 2 or 3 pass if len(calls_to_pfn_list) == 0: call_pfnWdfIoQueueCreate = find_wdf_callback_through_immediate( "call", 0, function_offset) if call_pfnWdfIoQueueCreate: calls_to_pfn_list.append(call_pfnWdfIoQueueCreate) idc.OpStroffEx(call_pfnWdfIoQueueCreate, 0, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) if len(calls_to_pfn_list) == 0: call_pfnWdfIoQueueCreate = find_wdf_callback_through_immediate( "mov", 1, function_offset) if call_pfnWdfIoQueueCreate: calls_to_pfn_list.append(call_pfnWdfIoQueueCreate) idc.OpStroffEx(call_pfnWdfIoQueueCreate, 1, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) for pfn_call in calls_to_pfn_list: lea_argument_addr = find_function_arg(pfn_call, "lea", "r8", 0) # Get stack and the stack operand offset current_func = idaapi.get_func(lea_argument_addr) stack_id = idc.GetFrame(current_func) stack_member_offset = idc.get_operand_value(lea_argument_addr, 1) struct_id = idaapi.get_struc_id("_WDF_IO_QUEUE_CONFIG") struct_size = idc.GetStrucSize(struct_id) # First check if we have already touch this function stack before if function_stack_erased(current_func): # need to take care of the already defined structs # If the arguments collide then this will fail pass else: delete_all_function_stack_members(current_func) print("Erased the stack members") idc.AddStrucMember(stack_id, "queue_config", stack_member_offset, idc.FF_BYTE | idc.FF_DATA, -1, struct_size) idc.SetMemberType(stack_id, stack_member_offset, idc.FF_STRU | idc.FF_DATA, struct_id, 1) print("IOQueue Creation at: " + hex(pfn_call))
def define(ea): if CompleteObjectLocator.isDefined(ea): return if not CompleteObjectLocator.isValid(ea): raise RttiError("%08X: doesn't look like a correct CompleteObjectLocator" % (ea)) # Ensure referenced structs are defined. # An exception will be thrown if something goes wrong. tdPtr = idaapi.get_full_long(ea + 12) td = TypeDescriptor(tdPtr) chdPtr = idaapi.get_full_long(ea + 16) chd = ClassHierarchyDescriptor(chdPtr) strid = idaapi.get_struc_id("_s__RTTICompleteObjectLocator") size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) if chd.isMultipleInheritance: if chd.isVirtualInheritance: print "%08X: Cannot handle virtual inheritance yet." % (ea) else: # '??_R4' + td.baseMangledName + '6B' + baseClassTd.baseMangledName + '@' # '??_7' + ... print "%08X: Cannot handle multiple inheritance yet." % (ea) else: idaapi.set_name(ea, "??_R4" + td.baseMangledName + "6B@", 0)
def define(ea): if CompleteObjectLocator.isDefined(ea): return if not CompleteObjectLocator.isValid(ea): raise RttiError( "%08X: doesn't look like a correct CompleteObjectLocator" % (ea)) # Ensure referenced structs are defined. # An exception will be thrown if something goes wrong. tdPtr = idaapi.get_full_long(ea + 12) td = TypeDescriptor(tdPtr) chdPtr = idaapi.get_full_long(ea + 16) chd = ClassHierarchyDescriptor(chdPtr) strid = idaapi.get_struc_id('_s__RTTICompleteObjectLocator') size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) if chd.isMultipleInheritance: if chd.isVirtualInheritance: print '%08X: Cannot handle virtual inheritance yet.' % (ea) else: # '??_R4' + td.baseMangledName + '6B' + baseClassTd.baseMangledName + '@' # '??_7' + ... print '%08X: Cannot handle multiple inheritance yet.' % (ea) else: idaapi.set_name(ea, '??_R4' + td.baseMangledName + '6B@', 0)
def __init__(self, name): sid = -1 nametype = type(name) if nametype is str: self.name = name sid = idaapi.get_struc_id(name) elif nametype is int or nametype is long: sid = name self.name = idaapi.get_struc_name(sid) self.sid = sid ssize = 0 memberlist = None offs = 0 if not warnBad(sid): struc = idaapi.get_struc(sid) ssize = idaapi.get_struc_size(sid) #memberqty = idc.GetMemberQty(sid) memberqty = struc.memqty memberlist = [None] * memberqty for i in range(0, memberqty): #memberlist.append(idamember(sid, offs)) memberlist[i] = idamember(sid, offs) offs = idaapi.get_struc_next_offset(struc, offs) self.size = ssize self.members = memberlist
class RTTICompleteObjectLocator(RTTIStruc): # Init class statics msid = get_struc_id("RTTICompleteObjectLocator") if msid != BADADDR: del_struc(get_struc(msid)) msid = add_struc(0xFFFFFFFF, "RTTICompleteObjectLocator", False) add_struc_member(get_struc(msid), "signature", BADADDR, FF_DATA | FF_DWRD, None, 4) add_struc_member(get_struc(msid), "offset", BADADDR, FF_DATA | FF_DWRD, None, 4) add_struc_member(get_struc(msid), "cdOffset", BADADDR, FF_DATA | FF_DWRD, None, 4) add_struc_member(get_struc(msid), "pTypeDescriptor", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) add_struc_member(get_struc(msid), "pClassDescriptor", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) if u.x64: add_struc_member(get_struc(msid), "pSelf", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) tid = msid struc = get_struc(tid) size = get_struc_size(tid) print "Completed Registering RTTICompleteObjectLocator" def __init__(self, ea, vtable): filepath = GetIdbPath()[:-4] fp = open(r"{filepath}.txt".format(filepath=filepath), 'a') # fp.write(filepath) print "Create file" do_unknown_range(ea, self.size, DOUNK_DELNAMES) if doStruct(ea, self.size, self.tid): # Get adress of type descriptor from CompleteLocator # print "Complete Object Locator at: 0x%x" % ea offset = get_member_by_name(self.struc, "pTypeDescriptor").soff typeDescriptor = get_32bit(ea + offset) + u.x64_imagebase() # print "Looking for type Descriptor at: 0x%x" % typeDescriptor rtd = RTTITypeDescriptor(typeDescriptor) if rtd.class_name: # print "Type Descriptor at: 0x%x" % typeDescriptor offset = get_member_by_name(self.struc, "pClassDescriptor").soff classHierarchyDes = get_32bit(ea + offset) + u.x64_imagebase() rchd = RTTIClassHierarchyDescriptor(classHierarchyDes) # filter out None entries rchd.bases = filter(lambda x: x, rchd.bases) classes[strip(rtd.class_name)] = [strip(b) for b in rchd.bases] MakeNameEx(vtable, "vtable__" + strip(rtd.class_name), SN_NOWARN) tempStr = hex(vtable).rstrip('L') + '\t' + strip( rtd.class_name) + '\t' + str(GuessType( Dword(vtable + 4))) + '\n' if ('std' not in tempStr[:15] and 'ATL' not in tempStr[:15]): fp.write(tempStr) else: # if the RTTITypeDescriptor doesn't have a valid name for us to # read, then this wasn't a valid RTTICompleteObjectLocator MakeUnknown(ea, self.size, DOUNK_SIMPLE) fp.close()
def process_funcs(all_funcs): for func in all_funcs: # rename idc.set_name(func.start_ea, f"string_{func.start_ea:X}") # set type struc_id = idaapi.get_struc_id("std::string") # print(f"{struc_id:x}") if struc_id == idaapi.BADADDR: idc.set_local_type(-1, "struct std::string {char *ptr; size_t length; char buf[0x10];};", idaapi.PT_TYP) print("create std::string") func_tinfo = idaapi.tinfo_t() cfunc = idaapi.decompile(func.start_ea) cfunc.get_func_type(func_tinfo) func_details = idaapi.func_type_data_t() func_tinfo.get_func_details(func_details) std_string_tinfo = idaapi.tinfo_t() std_string_tinfo.get_named_type(idaapi.get_idati(), "std::string") std_string_ptr_tinfo = idaapi.tinfo_t() std_string_ptr_tinfo.create_ptr(std_string_tinfo) func_details[0].type = std_string_ptr_tinfo func_tinfo.create_func(func_details) idaapi.apply_tinfo(func.start_ea, func_tinfo, idaapi.TINFO_DEFINITE)
def check_before_upload(): reserved_id = idaapi.get_struc_id("reserverd_by_idarling") if reserved_id == ida_idaapi.BADADDR: # First time, create 20 structures for i in range(20): idaapi.add_struc(ida_idaapi.BADADDR, None) idaapi.add_struc(ida_idaapi.BADADDR, "reserverd_by_idarling")
def createStruct(self, name): sid = idaapi.get_struc_id(name) if sid != -1: idc.del_struc(sid) sid = idc.add_struc(-1, name, 0) self.types_id['name'] = sid return sid
def get_flag_and_id(size, type): flag = 0x00000000 typeid = -1 if size == 1: flag = 0x00000000 # byte elif size == 2: flag = 0x10000000 # word elif size == 4: flag = 0x20000000 # dword elif size == 8: flag = 0x30000000 # qword try: typeTable = type.get("table") except AttributeError: return {"flag": flag, "typeid": typeid} if typeTable == "PDOMCStructure" or typeTable == "PDOMCPPClassType": flag = 0x60000000 typeid = idaapi.get_struc_id(str(type.get("name"))) return {"flag": flag, "typeid": typeid} elif typeTable == "PDOMCEnumeration" or typeTable == "PDOMCPPEnumeration": typeid = idaapi.get_enum_size( idaapi.get_enum(str(type.get("name")))) elif typeTable == "PDOMCTypedef" or typeTable == "PDOMCPPTypedef": return IDAtools.get_flag_and_id(size, type.get("type")) return {"flag": flag, "typeid": typeid}
def __setstate__(self, state): ownername, index, name, (cmtt, cmtf), ofs, t = state fullname = '.'.join((owername, name)) identifier = idaapi.get_struc_id(ownername) if identifier == idaapi.BADADDR: logging.warn( "{:s}.instance({:s}).member_t : Creating structure {:s} -- [{:#x}] {:s}{:s}" .format( __name__, ownername, ownername, ofs, name, " // {:s}".format(cmtt or cmtf) if cmtt or cmtf else '')) identifier = idaapi.add_struc(idaapi.BADADDR, ownername) self.__owner = owner = instance(identifier, offset=0) flag, mytype, nbytes = t # FIXME: handle .strtype (strings), .ec (enums), .cd (custom) opinfo = idaapi.opinfo_t() opinfo.tid = 0 if mytype is None else mytype.id res = idaapi.add_struc_member(owner.ptr, name, ofs, flag, opinfo, nbytes) # FIXME: handle these errors properly # duplicate name if res == idaapi.STRUC_ERROR_MEMBER_NAME: if idaapi.get_member_by_name(owner.ptr, name).soff != ofs: newname = "{:s}_{:x}".format(name, ofs) logging.warn( "{:s}.instace({:s}).member_t : Duplicate name found for {:s}, renaming to {:s}." .format(__name__, ownername, name, newname)) idaapi.set_member_name(owner.ptr, ofs, newname) else: logging.info( "{:s}.instance({:s}).member_t : Field at {:+#x} contains the same name {:s}." .format(__name__, ownername, ofs, name)) # duplicate field elif res == idaapi.STRUC_ERROR_MEMBER_OFFSET: logging.info( "{:s}.instance({:s}).member_t : Field already found at {:+#x}. Overwriting with {:s}." .format(__name__, ownername, ofs, name)) idaapi.set_member_type(owner.ptr, ofs, flag, opinfo, nbytes) idaapi.set_member_name(owner.ptr, ofs, name) # invalid size elif res == idaapi.STRUC_ERROR_MEMBER_SIZE: logging.warn( "{:s}.instance({:s}).member_t : Issue creating structure member {:s} : {:#x}" .format(__name__, ownername, fullname, res)) # unknown elif res != idaapi.STRUC_ERROR_MEMBER_OK: logging.warn( "{:s}.instance({:s}).member_t : Issue creating structure member {:s} : {:#x}" .format(__name__, ownername, fullname, res)) self.__index = index self.__owner = owner idaapi.set_member_cmt(self.ptr, cmtt, True) idaapi.set_member_cmt(self.ptr, cmtf, False) return
def tid_is_struc(tid): # get_struc_name return name for struc or enum tid_name = idaapi.get_struc_name(tid) if idaapi.get_struc_id(tid_name) != idc.BADADDR: return True return False
def by_name(name, **options): '''Return a structure by it's name.''' id = idaapi.get_struc_id(name) if id == idaapi.BADADDR: raise LookupError( "{:s}.by_name({!r}) : Unable to locate structure with given name.". format(__name__, name)) return instance(id, **options)
def __setstate__(self, state): ownername, index, name, (cmtt, cmtf), ofs, t = state identifier = idaapi.get_struc_id(ownername) if identifier == idaapi.BADADDR: logging.warn('member_t : Creating structure %s -- [%x] %s%s' % (ownername, ofs, name, ' // %s' % (cmtt or cmtf) if cmtt or cmtf else '')) identifier = idaapi.add_struc(idaapi.BADADDR, ownername) self.__owner = owner = instance(identifier, offset=0) flag, mytype, nbytes = t # FIXME: handle .strtype (strings), .ec (enums), .cd (custom) opinfo = idaapi.opinfo_t() opinfo.tid = 0 if mytype is None else mytype.id res = idaapi.add_struc_member(owner.ptr, name, ofs, flag, opinfo, nbytes) # FIXME: handle these errors properly # duplicate name if res == idaapi.STRUC_ERROR_MEMBER_NAME: if idaapi.get_member_by_name(owner.ptr, name).soff != ofs: newname = '%s_%x' % (name, ofs) logging.warn( 'structure_t(%s).member_t : Duplicate name found for %s, renaming to %s' % (ownername, name, newname)) idaapi.set_member_name(owner.ptr, ofs, newname) else: logging.info( 'structure_t(%s).member_t : Field at %x contains the same name %s' % (ownername, ofs, name)) # duplicate field elif res == idaapi.STRUC_ERROR_MEMBER_OFFSET: logging.info( 'structure_t(%s).member_t : Field already found at %x. Overwriting with %s' % (ownername, ofs, name)) idaapi.set_member_type(owner.ptr, ofs, flag, opinfo, nbytes) idaapi.set_member_name(owner.ptr, ofs, name) # invalid size elif res == idaapi.STRUC_ERROR_MEMBER_SIZE: logging.warn( 'member_t : Issue creating structure member %s.%s : %x' % (ownername, name, res)) # unknown elif res != idaapi.STRUC_ERROR_MEMBER_OK: logging.warn( 'member_t : Issue creating structure member %s.%s : %x' % (ownername, name, res)) self.__index = index self.__owner = owner idaapi.set_member_cmt(self.ptr, cmtt, True) idaapi.set_member_cmt(self.ptr, cmtf, False) return
def assign_struct_to_address(address, struct_name): idc.ApplyType(address, get_Tinfo_from_name(struct_name)) struct_id = idaapi.get_struc_id(struct_name) if struct_id != 0xffffffffffffffff: struct_size = idaapi.get_struc_size(struct_id) for i in range(struct_size): idc.MakeUnkn(address+i, 0) return idaapi.doStruct(address, struct_size, struct_id) return False
def processStruct(self, regPrefix, structName): til = ctypes.c_void_p.in_dll(g_dll, 'idati') tid = idaapi.get_struc_id(structName) if (tid is None) or (tid == 0) or (tid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get tid_t for %s' % structName) struc = g_dll.get_struc(tid) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for %s' % structName) members = loadMembers(struc, structName) for off, name, memb in members: funcname = self.filterName(regPrefix, name) typ_type = ctypes.POINTER(ctypes.c_ubyte)() typ_fields = ctypes.POINTER(ctypes.c_ubyte)() typ_cmt = ctypes.POINTER(ctypes.c_ubyte)() typ_fieldcmts = ctypes.POINTER(ctypes.c_ubyte)() typ_sclass = ctypes.c_ulong() value = ctypes.c_ulong() ret = get_named_type(til, funcname, idaapi.NTF_SYMM, ctypes.byref(typ_type), ctypes.byref(typ_fields), ctypes.byref(typ_cmt), ctypes.byref(typ_fieldcmts), ctypes.byref(typ_sclass), ctypes.byref(value)) if ret == 0: self.logger.debug('Could not find %s', funcname) else: if typ_type[0] != idaapi.BT_FUNC: #not positive that the first type value has to be BT_FUNC or not... # and whether it's important to only apply to funcs or not self.logger.debug( 'Found named type, but not a function: %s', funcname) else: type_arr = ctypes.create_string_buffer(0x400) type_arr[0] = chr(idaapi.BT_PTR) manualTypeCopy(type_arr, 1, len(type_arr), typ_type) ret = g_dll.set_member_tinfo( til, struc, memb, ctypes.c_uint(0), type_arr, typ_fields, ctypes.c_uint(0), ) name_buffer = ctypes.create_string_buffer(0x400) print_type_to_one_line(name_buffer, len(name_buffer), til, typ_type, funcname, typ_cmt, typ_fields, typ_fieldcmts) if ret == 0: self.logger.info('Failed to set_member_tinfo: %s', name_buffer.value) else: self.logger.info('set_member_tinfo: %s', name_buffer.value)
def is_gap(structure_name,field_offset): sid = idaapi.get_struc_id(structure_name) if sid != idaapi.BADADDR: sptr = idaapi.get_struc(sid) mptr = idaapi.get_member(sptr, field_offset) if mptr: return False else: return True
def assign_struct_to_address(address, struct_name): idc.apply_type(address, get_Tinfo_from_name(struct_name)) struct_id = idaapi.get_struc_id(struct_name) if struct_id != 0xffffffffffffffff: struct_size = idaapi.get_struc_size(struct_id) for i in range(struct_size): ida_bytes.del_items(address + i, 0) return idaapi.create_struct(address, struct_size, struct_id) return False
def get_struct_member_type(structure_name, field_offset): sid = idaapi.get_struc_id(structure_name) if sid != idaapi.BADADDR: sptr = idaapi.get_struc(sid) mptr = idaapi.get_member(sptr, field_offset) if mptr: tif = idaapi.tinfo_t() idaapi.get_member_tinfo2(mptr, tif) return tif return None
def get(name): id = idaapi.get_struc_id(name) if id == idaapi.BADADDR: try: raise DeprecationWarning except: logging.warn('%s.get auto-creation is being deprecated' % __name__, exc_info=True) id = idaapi.add_struc(idaapi.BADADDR, name) return instance(id)
def get(name): '''Returns an instance of the structure named ``name``.''' id = idaapi.get_struc_id(name) if id == idaapi.BADADDR: try: raise DeprecationWarning except: logging.warn("{:s}.get auto-creation is being deprecated".format( __name__, exc_info=True)) id = idaapi.add_struc(idaapi.BADADDR, name) return instance(id)
def define_ke_task_desc(ea, task_desc_name): print "{}: 0x{:X}".format(task_desc_name, ea) sid = idaapi.get_struc_id("ke_task_desc") struct_size = idaapi.get_struc_size(sid) # undefined addr and define struct idaapi.del_items(ea, struct_size, idaapi.DELIT_DELNAMES) idaapi.create_struct(ea, struct_size, sid) idaapi.set_name(ea, task_desc_name, idaapi.SN_FORCE)
def define_ke_state_handler(ea): # undefined addr and define struct sid = idaapi.get_struc_id("ke_state_handler") struct_size = idaapi.get_struc_size(sid) idaapi.del_items(ea, struct_size, idaapi.DELIT_DELNAMES) idaapi.create_struct(ea, struct_size, sid) msg_table = idaapi.get_dword(ea) msg_cnt = idaapi.get_word(ea + 4) print "msg_table: 0x{:X}, msg_cnt: {}".format(msg_table, msg_cnt) sid = idaapi.get_struc_id("ke_msg_handler") struct_size = idaapi.get_struc_size(sid) idaapi.del_items(msg_table, struct_size, idaapi.DELIT_DELNAMES) idaapi.create_struct(msg_table, struct_size, sid) idc.make_array(msg_table, msg_cnt) for i in range(msg_cnt): define_func(idaapi.get_dword(msg_table + 4 + i * 8))
def run(self): try: self.logger.debug('Starting up') dlg = StructTyperWidget() dlg.setStructs(loadStructs()) oldTo = idaapi.set_script_timeout(0) res = dlg.exec_() idaapi.set_script_timeout(oldTo) if res == QtGui.QDialog.DialogCode.Accepted: regPrefix = dlg.getRegPrefix() sid = None struc = None if dlg.ui.rb_useStackFrame.isChecked(): ea = idc.here() sid = idc.GetFrame(ea) struc = idaapi.get_frame(ea) self.logger.debug('Dialog result: accepted stack frame') if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for stack frame at 0x%x' % ea) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for stack frame at 0x%x' % ea) #need the actual pointer value, not the swig wrapped struc_t struc= long(struc.this) else: structName = dlg.getActiveStruct() self.logger.debug('Dialog result: accepted %s "%s"', type(structName), structName) sid = idc.GetStrucIdByName(structName) if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for %s' % structName) tid = idaapi.get_struc_id(structName) if (tid is None) or (tid == 0) or (tid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get tid_t for %s' % structName) struc = g_dll.get_struc(tid) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for %s' % structName) foundMembers = self.processStruct(regPrefix, struc, sid) if dlg.ui.rb_useStackFrame.isChecked() and (foundMembers != 0): #reanalyze current function if we're analyzing a stack frame & found some func pointers funcstart = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_START) funcend = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_END) if (funcstart != idc.BADADDR) and (funcend != idc.BADADDR): idc.AnalyzeArea(funcstart, funcend) elif res == QtGui.QDialog.DialogCode.Rejected: self.logger.info('Dialog result: canceled by user') else: self.logger.debug('Unknown result') raise RuntimeError('Dialog unknown result') except Exception, err: self.logger.exception("Exception caught: %s", str(err))
def __setstate__(self, state): ownername, baseoffset, _ = state identifier = idaapi.get_struc_id(ownername) if identifier == idaapi.BADADDR: raise LookupError, 'Failure creating a members_t for structure_t {!r}'.format( ownername) logging.warn( 'members_t : Creating structure %s -- [%x] %d members' % (ownername, baseoffset, len(members))) identifier = idaapi.add_struc(idaapi.BADADDR, ownername) self.baseoffset = baseoffset self.__owner = instance(identifier, offset=baseoffset) return
def define(ea): if TypeDescriptor.isDefined(ea): return if not TypeDescriptor.isValid(ea): raise RttiError("%08X: This doesn't look like a TypeDescriptor." % ea) # FIXME: 64-bit compatibility mangledName = getAsciiz(ea + 8) # Define data in DB structLength = 8 + len(mangledName) + 1 idaapi.do_unknown_range(ea, structLength, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, structLength, idaapi.get_struc_id("_TypeDescriptor")) idaapi.set_name(ea, TypeDescriptor.makeName(ea), 0)
def set_struct_member(structname, name, flag_andTypeID, size): id = idc.get_struc_id(str(structname)) offset = -1 flag = flag_andTypeID.get("flag") typeid = flag_andTypeID.get("typeid") nbytes = size try: ok = 0 if not idaapi.get_member_by_name( idaapi.get_struc(idaapi.get_struc_id(str(structname))), str(name)): ok = idc.add_struc_member(id, str(name), offset, flag, typeid, nbytes) if not ok: if not idaapi.get_member_by_name( idaapi.get_struc(idaapi.get_struc_id(str(structname))), str(name)): print("Could not add struct member {name} at {structname}". format(name=name, structname=structname)) except: pass
def get_member_from_struct(ea, sname, mname): """ get_member_from_struct: ea, sname, mname Retrieves a DWORD member named 'mname' from struct 'sname' starting at address 'ea'. """ sid = idaapi.get_struc_id(sname) stru = idaapi.get_struc(sid) member = idaapi.get_member_by_name(stru, mname) # TODO check size return idc.Dword(ea + member.soff)
def __setstate__(self, state): name, (cmtt, cmtf), members = state identifier = idaapi.get_struc_id(name) if identifier == idaapi.BADADDR: logging.warn('Creating structure %s [%d fields]%s' % (name, len(members), ' // %s' % (cmtf or cmtt) if cmtf or cmtt else '')) identifier = idaapi.add_struc(idaapi.BADADDR, name) # FIXME: although set_struc_idx and stuff doesn't seem too important. idaapi.set_struc_cmt(identifier, cmtt, True) idaapi.set_struc_cmt(identifier, cmtf, False) self.__id = identifier self.__members = members return
def forceStruct(ea, name): """ forceStruct: ea, name Does all the necessary things to force IDA to convert the memory starting at address 'ea' into a struct of type 'name'. Returns the address after the struct. """ sid = idaapi.get_struc_id(name) ssize = idaapi.get_struc_size(sid) idaapi.do_unknown_range(ea, ssize, DOUNK_DELNAMES) x = idaapi.doStruct(ea, ssize, sid) return ea + ssize
def define(ea): if ClassHierarchyDescriptor.isDefined(ea): return if not ClassHierarchyDescriptor.isValid(ea): raise RttiError("%08X: Doesn't look like a correct ClassHierarchyDescriptor" % ea) strid = idaapi.get_struc_id("_s__RTTIClassHierarchyDescriptor") size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) bca = BaseClassArray( ClassHierarchyDescriptor.__baseClassArrayPtr(ea), ClassHierarchyDescriptor.__baseClassCount(ea) ) # Entry 0 describes the class itself => I can find out the class name. idaapi.set_name(ea, "??_R3" + bca[0].typeDescriptor.baseMangledName + "8", 0)
def processStruct(self, regPrefix, structName): til = ctypes.c_void_p.in_dll(g_dll, 'idati') tid = idaapi.get_struc_id(structName) if (tid is None) or (tid == 0) or (tid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get tid_t for %s' % structName) struc = g_dll.get_struc(tid) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for %s' % structName) members = loadMembers(struc, structName) for off, name, memb in members: funcname = self.filterName(regPrefix, name) typ_type = ctypes.POINTER(ctypes.c_ubyte)() typ_fields = ctypes.POINTER(ctypes.c_ubyte)() typ_cmt = ctypes.POINTER(ctypes.c_ubyte)() typ_fieldcmts = ctypes.POINTER(ctypes.c_ubyte)() typ_sclass = ctypes.c_ulong() value = ctypes.c_ulong() ret = get_named_type( til, funcname, idaapi.NTF_SYMM, ctypes.byref(typ_type), ctypes.byref(typ_fields), ctypes.byref(typ_cmt), ctypes.byref(typ_fieldcmts), ctypes.byref(typ_sclass), ctypes.byref(value) ) if ret == 0: self.logger.debug('Could not find %s', funcname) else: if typ_type[0] != idaapi.BT_FUNC: #not positive that the first type value has to be BT_FUNC or not... # and whether it's important to only apply to funcs or not self.logger.debug('Found named type, but not a function: %s', funcname) else: type_arr = ctypes.create_string_buffer(0x400) type_arr[0] = chr(idaapi.BT_PTR) manualTypeCopy(type_arr, 1, len(type_arr), typ_type) ret = g_dll.set_member_tinfo( til, struc, memb, ctypes.c_uint(0), type_arr, typ_fields, ctypes.c_uint(0), ) name_buffer = ctypes.create_string_buffer(0x400) print_type_to_one_line( name_buffer, len(name_buffer), til, typ_type, funcname, typ_cmt, typ_fields, typ_fieldcmts ) if ret == 0: self.logger.info('Failed to set_member_tinfo: %s', name_buffer.value) else: self.logger.info('set_member_tinfo: %s', name_buffer.value)
def get(name): id = idaapi.get_struc_id(name) if id == idaapi.BADADDR: id = idaapi.add_struc(name) return instance(id)
import sark import idautils import idaapi import csv with open('c:/Users/Joe/struct.csv', 'r') as csvfile: for row in csv.reader(csvfile): print row try: struct_id = sark.structure.create_struct(row[0]) except sark.exceptions.SarkStructAlreadyExists: struct_id = idaapi.get_struc_id(row[0]) print struct_id sark.structure.add_struct_member(struct_id, row[2], int(row[1]), int(row[3]))