def disasm_one_inst(self, inst, addr): if addr % 4 != 0: if not os.getenv("IDP_UNALIGNED_WARNING"): Warning("Unaligned instruction address: {:x} ".format(addr)) os.environ["IDP_UNALIGNED_WARNING"] = "Warned." self.log_with_addr("Unaligned instruction address.") if len(self.disasm_cache) > 0x10000: # TODO: Ideally disasm_cache would be an OrderedDict, but there's no C implementation in Pyhton 2, and this really slows it down. self.disasm_cache = {} # I'm assuming the jumps are always to packet start addresses, so I also disassemble # the rest of the packet instructions # TODO: can i assume that? i still have to disassemble till the end of the packet, always. for packet_addr in range(addr, addr + PACKET_MAX_SIZE, INST_SIZE): if idaapi.isLoaded(packet_addr): hi = self.disasm_wrapper(idaapi.get_long(packet_addr), packet_addr) if addr == packet_addr: self.log_with_addr( "Disassembling packet {:08x}: {:s}".format( packet_addr, str(hi.text))) if hi.end_packet: break else: break return self.disasm_wrapper(inst, addr)
def disasm_one_inst(self, inst, addr): if addr % 4 != 0: if not os.getenv("IDP_UNALIGNED_WARNING"): Warning("Unaligned instruction address: {:x} ".format(addr)) os.environ["IDP_UNALIGNED_WARNING"] = "Warned." self.log_with_addr("Unaligned instruction address.") if len(self.disasm_cache) > 0x10000: # TODO: Ideally disasm_cache would be an OrderedDict, but there's no C implementation in Pyhton 2, and this really slows it down. self.disasm_cache = {} # I'm assuming the jumps are always to packet start addresses, so I also disassemble # the rest of the packet instructions # TODO: can i assume that? i still have to disassemble till the end of the packet, always. for packet_addr in range(addr, addr + PACKET_MAX_SIZE, INST_SIZE): if idaapi.isLoaded(packet_addr): hi = self.disasm_wrapper(idaapi.get_long(packet_addr), packet_addr) if addr == packet_addr: self.log_with_addr("Disassembling packet {:08x}: {:s}".format(packet_addr, str(hi.text))) if hi.end_packet: break else: break return self.disasm_wrapper(inst, addr)
def main(): # begin to locate linker module base has_art = False module_base = GetFirstModule() while module_base != None: module_name = GetModuleName(module_base) if module_name.find('linker') >= 0: has_art = True break module_base = GetNextModule(module_base) if has_art == False: print '[*]unable to find libart.so module base' return module_size = GetModuleSize(module_base) print '[*]found linker base=>0x%08X, Size=0x%08X' % (module_base, module_size) print("\t[-]begin to search DT_INIT And DT_INIT_ARRAY") init_func_ea = 0 init_array_ea = 0 for ea_offset in range(module_base, module_base + module_size): # i don't want to write a huge single line like 'if x and x and x and...', so many ifs apear if 0x4620 == idaapi.get_word(ea_offset): if 0x20F0F8D4 == idaapi.get_long(ea_offset + 2): if 0x4479 == idaapi.get_word(ea_offset + 6): if 0xFEA9F7FF == idaapi.get_word(ea_offset + 8): if 0x490D == idaapi.get_word(ea_offset + 12): if 0x2200 == idaapi.get_long(ea_offset + 14): if 0x9200 == idaapi.get_word(ea_offset + 16): init_func_ea = ea_offset + 8 init_array_ea = ea_offset + 30 break print "\t[-]found INIT=>0x%08X INIT_ARRAY=>0x%08X" % (init_func_ea, init_array_ea) print("\t[-]try set breakpoint there") AddBpt(init_func_ea) AddBpt(init_array_ea) print("[*]script by freakish, enjoy~~") print("[*]script finish")
def decrypt(ea, key): # Virtual address to IMAGE_IMPORT_DESCRIPTOR->FirstThunk va_iat = 0 # Virtual address to IMAGE_IMPORT_DESCRIPTOR->OriginalFirstThunk va_int = 0 tmp_ea = ea # Back-tracing to locate the IMAGE_IMPORT_DESCRIPTOR from import address table passed from the callback for xref in idautils.XrefsTo(ea, 0): if XrefTypeName(xref.type) == 'Data_Offset': va_iat = xref.frm - 0x10 if va_iat != 0: print "Import Name Table->%08x" % (idaapi.get_long(va_iat) + IMG_BASE) va_int = idaapi.get_long(va_iat) + IMG_BASE else: return if va_int != 0: va_itd = idaapi.get_long(va_int) # Enumerate array of IMAGE_THUNK_DATA while va_itd != 0: va_itd = va_itd + IMG_BASE if va_itd > IMG_BASE and va_itd <= IMG_END: print "Image thunk data->%08x" % va_itd va_ibn = va_itd + 2 ch = idaapi.get_byte(va_ibn) str = '' while ch != 0 and ch != 255: str += chr(ch ^ key) va_ibn += 1 ch = idaapi.get_byte(va_ibn) # Save the decoded import name print "IMAGE_IMPORT_BY_NAME->Name (%08x): %s" % (va_itd + 2, str) idc.MakeName(tmp_ea, str) tmp_ea += 4 # Next IMAGE_THUNK_DATA va_int += 4 va_itd = idaapi.get_long(va_int) else: return
def decrypt(ea, key): # Virtual address to IMAGE_IMPORT_DESCRIPTOR->FirstThunk va_iat = 0 # Virtual address to IMAGE_IMPORT_DESCRIPTOR->OriginalFirstThunk va_int = 0 tmp_ea = ea # Back-tracing to locate the IMAGE_IMPORT_DESCRIPTOR from import address table passed from the callback for xref in idautils.XrefsTo(ea, 0): if XrefTypeName(xref.type) == 'Data_Offset': va_iat = xref.frm - 0x10 if va_iat != 0: print "Import Name Table->%08x" % (idaapi.get_long(va_iat) + IMG_BASE) va_int = idaapi.get_long(va_iat) + IMG_BASE else: return if va_int != 0: va_itd = idaapi.get_long(va_int) # Enumerate array of IMAGE_THUNK_DATA while va_itd != 0: va_itd = va_itd + IMG_BASE if va_itd > IMG_BASE and va_itd <= IMG_END: print "Image thunk data->%08x" % va_itd va_ibn = va_itd + 2 ch = idaapi.get_byte(va_ibn) str = '' while ch != 0 and ch != 255: str += chr(ch ^ key) va_ibn += 1 ch = idaapi.get_byte(va_ibn) # Save the decoded import name print "IMAGE_IMPORT_BY_NAME->Name (%08x): %s" % (va_itd+2, str) idc.MakeName(tmp_ea, str) tmp_ea += 4 # Next IMAGE_THUNK_DATA va_int += 4 va_itd = idaapi.get_long(va_int) else: return
def ev_ana_insn(self, insn): b1 = idaapi.get_byte(insn.ea) if b1 >= 0x70 and b1 <= 0x7F: d1 = idaapi.get_byte(insn.ea + 1) b2 = idaapi.get_byte(insn.ea + 2) d2 = idaapi.get_byte(insn.ea + 3) if b2 == b1 ^ 0x01 and d1 - 2 == d2: idaapi.put_byte(insn.ea, 0xEB) idaapi.put_word(insn.ea + 2, 0x9090) elif b1 == 0x0F: b1_1 = idaapi.get_byte(insn.ea + 1) d1 = idaapi.get_long(insn.ea + 2) b2 = idaapi.get_byte(insn.ea + 6) b2_1 = idaapi.get_byte(insn.ea + 7) d2 = idaapi.get_long(insn.ea + 8) if b2 == 0x0F and b1_1 ^ 0x01 == b2_1 and d1 - 6 == d2: idaapi.put_byte(insn.ea, 0xE9) idaapi.put_long(insn.ea + 1, d1 + 1) idaapi.put_byte(insn.ea + 5, 0x90) idaapi.put_word(insn.ea + 6, 0x9090) idaapi.put_long(insn.ea + 8, 0x90909090) return False
def main(): # begin to locate libart.so module base has_art = False module_base = GetFirstModule() while module_base != None: module_name = GetModuleName(module_base) if module_name.find('libart.so') >= 0: has_art = True break module_base = GetNextModule(module_base) if has_art == False: print '[*]unable to find libart.so module base' return module_size = GetModuleSize(module_base) print '[*]found libart.so base=>0x%08X, Size=0x%08X' % (module_base, module_size) print("\t[-]begin to search JNI_OnLoad") blx_r12_ea = 0 for ea_offset in range(module_base, module_base + module_size): # i don't want to write a huge single line like 'if x and x and x and...', so many ifs apear if 0x2100 == idaapi.get_word(ea_offset): if 0x4630 == idaapi.get_word(ea_offset + 2): if 0x47E0 == idaapi.get_word(ea_offset + 4): if 0x6871 == idaapi.get_word(ea_offset + 6): if 0x4684 == idaapi.get_word(ea_offset + 8): if 0x02CCF8D1 == idaapi.get_long(ea_offset + 10): if 0x1C03 == idaapi.get_word(ea_offset + 14): blx_r12_ea = ea_offset + 4 break print "\t[-]found string JNI_OnLoad BLX R12 addr=>0x%X" % blx_r12_ea print("\t[-]try set breakpoint there") AddBpt(blx_r12_ea) print("[*]script by freakish, enjoy~~") print("[*]script finish")
def ev_ana_insn(self, insn): global hashesToNames insnbytes = idaapi.get_bytes(insn.ea, 3) if insnbytes == '\x0f\xff\xf0': apicrc = idaapi.get_long(insn.ea + 3) apiname = hashesToNames.get(apicrc) if apiname is None: print "ERROR: apicrc 0x%x NOT FOUND!" % (apicrc) #apiname = "UNKNOWN_APICALL" print "apicall: %s @ 0x%x" % (apiname, insn.ea) insn.itype = NN_apicall insn.Op1.type = idaapi.o_imm insn.Op1.value = apicrc insn.Op1.dtyp = idaapi.dt_dword insn.size = 7 #eat up 7 bytes return True return False
def out(self): """ Generate text representation of an instruction in 'cmd' structure. This function shouldn't change the database, flags or anything else. All these actions should be performed only by u_emu() function. Returns: nothing """ self.profiler.enable() # self.log_custom("out({:s})".format(hex(self.cmd.ea))) buf = idaapi.init_output_buffer(1024) hi = self.disasm_one_inst(idaapi.get_long(self.cmd.ea), self.cmd.ea) # TODO: can I assume the cmd object is already set with the ana() information? as not to call the disasm again # and disrupt the packet disasm flow order if hi.template is None or hi.is_unknown or os.getenv( "IDP_OUT_SIMPLE_SYNTAX"): out_keyword(str(hi.text)) # This simple syntax is useful to produce generic asm code for comparison else: self.out_operands_separately(hi) # The str() conversion is necessary because the HexagonDisassembler uses the # python future compatibility module that uses unicode as default strings, # and IDA can't handle that. # TODO: maybe I shoud convert everythin to str() in the disasm (or don't use the future.unicode import) # TODO: Split in out() and out_one_operand() term_output_buffer() cvar.gl_comm = 1 # show IDA comments (http://www.hexblog.com/?p=116) MakeLine(buf) self.profiler.disable() return
def main(): text_ea = None #for some reason SegByName() isn't working for me - maybe an IDA 7 regression? for seg in Segments(): if get_segm_name(seg) == ".text": text_ea = seg if text_ea is None: print "ERROR: Unable to get .text segment!" return # first find all the functions for head in Heads(text_ea, SegEnd(text_ea)): func_ea = idaapi.get_func(head) if func_ea is None: if idaapi.get_bytes(head, 13) == '\x8b\xff\xe8\x00\x00\x00\x00\x83\xc4\x04\x0f\xff\xf0': print "Unrecognized apicall function at @ 0x%x"%(head) MakeFunction(head) #now name the functions for funcea in Functions(text_ea, SegEnd(text_ea)): functionName = GetFunctionName(funcea) for (startea, endea) in Chunks(funcea): for head in Heads(startea, endea): insnbytes = idaapi.get_bytes(head, 3) if insnbytes == '\x0f\xff\xf0': apicrc = idaapi.get_long(head+3) apiname = hashesToNames.get(apicrc) if apiname is None: print "ERROR: apicrc 0x%x NOT FOUND! @ 0x%x"%(apicrc, head) else: print "PROCESS - apicall: %s @ 0x%x"%(apiname, head) func_ea = idaapi.get_func(head).start_ea fname = idc.GetFunctionName(func_ea) if fname.startswith("sub_"): MakeName(func_ea, "apicall_" + apiname)
def check_ubfm_shift(ea): if idaapi.getseg(ea).use64(): opcode = idaapi.get_long(ea) # opc o = (opcode >> 29) & 3 # constant k = (opcode >> 23) & 0x3F if (o & 1) == 0 and k == 0x26: # sf s = (opcode >> 31) & 1 # N N = (opcode >> 22) & 1 if s == N: # imm imms = (opcode >> 10) & 0x3F immr = (opcode >> 16) & 0x3F mask = 0x1F | ((s & N) << 5) if imms == mask: return idaapi.ARM_lsr if o else idaapi.ARM_asr, opcode, s, immr elif immr == imms + 1: return idaapi.ARM_lsl if o else idaapi.ARM_null, opcode, s, mask - imms return idaapi.ARM_null, 0, 0, 0
def check_mov_sequence(ea): oldea = ea reg = -1 total = 0 is64 = False while idaapi.getseg(ea).use64(): d = idaapi.get_long(ea) # reg r = d & 0x1F if reg >= 0 and reg != r: break newval = DecodeMov(d, total, reg < 0) if newval is None: break if reg >= 0 and idaapi.get_first_fcref_to(ea) != idaapi.BADADDR: break if (d >> 31) & 1: is64 = True total = newval reg = r ea += 4 return ea - oldea, reg, is64, total
def out(self): """ Generate text representation of an instruction in 'cmd' structure. This function shouldn't change the database, flags or anything else. All these actions should be performed only by u_emu() function. Returns: nothing """ self.profiler.enable() # self.log_custom("out({:s})".format(hex(self.cmd.ea))) buf = idaapi.init_output_buffer(1024) hi = self.disasm_one_inst(idaapi.get_long(self.cmd.ea), self.cmd.ea) # TODO: can I assume the cmd object is already set with the ana() information? as not to call the disasm again # and disrupt the packet disasm flow order if hi.template is None or hi.is_unknown or os.getenv("IDP_OUT_SIMPLE_SYNTAX"): out_keyword(str(hi.text)) # This simple syntax is useful to produce generic asm code for comparison else: self.out_operands_separately(hi) # The str() conversion is necessary because the HexagonDisassembler uses the # python future compatibility module that uses unicode as default strings, # and IDA can't handle that. # TODO: maybe I shoud convert everythin to str() in the disasm (or don't use the future.unicode import) # TODO: Split in out() and out_one_operand() term_output_buffer() cvar.gl_comm = 1 # show IDA comments (http://www.hexblog.com/?p=116) MakeLine(buf) self.profiler.disable() return
def load_one_file(li, options, idx, basename=None): bypass_plt = OPT_BYPASS_PLT in options f = load_nxo(li) if idx == 0: if f.armv7: idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_PC_FLAT) else: idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_64BIT) idc.SetCharPrm(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3) idaapi.set_compiler_id(idaapi.COMP_GNU) idaapi.add_til2('gnulnx_arm' if f.armv7 else 'gnulnx_arm64', 1) # don't create tails idc.set_inf_attr(idc.INF_AF, idc.get_inf_attr(idc.INF_AF) & ~idc.AF_FTAIL) if OPT_LOAD_31_BIT in options: loadbase = 0x8000000 step = 0x1000000 elif f.armv7: loadbase = 0x60000000 step = 0x10000000 else: loadbase = 0x7100000000 step = 0x100000000 loadbase += idx * step f.binfile.seek(0) as_string = f.binfile.read(f.bssoff) idaapi.mem2base(as_string, loadbase) seg_prefix = basename if basename is not None else '' for start, end, name, kind in f.sections: if name.startswith('.got'): kind = 'CONST' idaapi.add_segm(0, loadbase+start, loadbase+end, seg_prefix+name, kind) segm = idaapi.get_segm_by_name(seg_prefix+name) if kind == 'CONST': segm.perm = idaapi.SEGPERM_READ elif kind == 'CODE': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC elif kind == 'DATA': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE elif kind == 'BSS': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE idaapi.update_segm(segm) idaapi.set_segm_addressing(segm, 1 if f.armv7 else 2) # do imports # TODO: can we make imports show up in "Imports" window? undef_count = 0 for s in f.symbols: if not s.shndx and s.name: undef_count += 1 last_ea = max(loadbase + end for start, end, name, kind in f.sections) undef_entry_size = 8 undef_ea = ((last_ea + 0xFFF) & ~0xFFF) + undef_entry_size # plus 8 so we don't end up on the "end" symbol undef_seg = basename + '.UNDEF' if basename is not None else 'UNDEF' idaapi.add_segm(0, undef_ea, undef_ea+undef_count*undef_entry_size, undef_seg, 'XTRN') segm = idaapi.get_segm_by_name(undef_seg) segm.type = idaapi.SEG_XTRN idaapi.update_segm(segm) for i,s in enumerate(f.symbols): if not s.shndx and s.name: idc.MakeQword(undef_ea) idaapi.do_name_anyway(undef_ea, s.name) s.resolved = undef_ea undef_ea += undef_entry_size elif i != 0: assert s.shndx s.resolved = loadbase + s.value if s.name: if s.type == STT_FUNC: idaapi.add_entry(s.resolved, s.resolved, s.name, 0) else: idaapi.do_name_anyway(s.resolved, s.name) else: # NULL symbol s.resolved = 0 funcs = set() for s in f.symbols: if s.name and s.shndx and s.value: if s.type == STT_FUNC: funcs.add(loadbase+s.value) symend = loadbase+s.value+s.size if Dword(symend) != 0: funcs.add(symend) got_name_lookup = {} for offset, r_type, sym, addend in f.relocations: target = offset + loadbase if r_type in (R_ARM_GLOB_DAT, R_ARM_JUMP_SLOT, R_ARM_ABS32): if not sym: print 'error: relocation at %X failed' % target else: idaapi.put_long(target, sym.resolved) elif r_type == R_ARM_RELATIVE: idaapi.put_long(target, idaapi.get_long(target) + loadbase) elif r_type in (R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT, R_AARCH64_ABS64): idaapi.put_qword(target, sym.resolved + addend) if addend == 0: got_name_lookup[offset] = sym.name elif r_type == R_AARCH64_RELATIVE: idaapi.put_qword(target, loadbase + addend) if addend < f.textsize: funcs.add(loadbase + addend) else: print 'TODO r_type %d' % (r_type,) ida_make_offset(f, target) for func, target in f.plt_entries: if target in got_name_lookup: addr = loadbase + func funcs.add(addr) idaapi.do_name_anyway(addr, got_name_lookup[target]) if not f.armv7: funcs |= find_bl_targets(loadbase, loadbase+f.textsize) if bypass_plt: plt_lookup = f.plt_lookup for pco in xrange(0, f.textsize, 4): pc = loadbase + pco d = Dword(pc) if (d & 0x7c000000) == (0x94000000 & 0x7c000000): imm = d & 0x3ffffff if imm & 0x2000000: imm |= ~0x1ffffff if 0 <= imm <= 2: continue target = (pc + imm * 4) - loadbase if target in plt_lookup: new_target = plt_lookup[target] + loadbase new_instr = (d & ~0x3ffffff) | (((new_target - pc) / 4) & 0x3ffffff) idaapi.put_long(pc, new_instr) for pco in xrange(0, f.textsize, 4): pc = loadbase + pco d = Dword(pc) if d == 0x14000001: funcs.add(pc + 4) for pc, _ in f.eh_table: funcs.add(loadbase + pc) for addr in sorted(funcs, reverse=True): idaapi.auto_make_proc(addr) return 1
def do_import_name(ea, name): idaapi.do_name_anyway(ea, "_import_" + name) #guess wrapper if idaapi.get_long(ea - 4) == 0xE51FF004: # "ldr pc, [pc, #-4]" idaapi.do_name_anyway(ea - 4, name)
def load_file(li, neflags, format): idaapi.set_processor_type("arm", idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) f = load_nxo(li) if f.armv7: SetShortPrm(INF_LFLAGS, GetShortPrm(INF_LFLAGS) | LFLG_PC_FLAT) else: SetShortPrm(INF_LFLAGS, GetShortPrm(INF_LFLAGS) | LFLG_64BIT) SetCharPrm(INF_DEMNAMES, idaapi.DEMNAM_GCC3) idaapi.set_compiler_id(idaapi.COMP_GNU) idaapi.add_til2('gnulnx_arm' if f.armv7 else 'gnulnx_arm64', 1) loadbase = 0x60000000 if f.armv7 else 0x7100000000 f.binfile.seek(0) as_string = f.binfile.read(f.bssoff) idaapi.mem2base(as_string, loadbase) if f.text[1] != None: li.file2base(f.text[1], loadbase + f.text[2], loadbase + f.text[2] + f.text[3], True) if f.ro[1] != None: li.file2base(f.ro[1], loadbase + f.ro[2], loadbase + f.ro[2] + f.ro[3], True) if f.data[1] != None: li.file2base(f.data[1], loadbase + f.data[2], loadbase + f.data[2] + f.data[3], True) for start, end, name, kind in f.sections: if name.startswith('.got'): kind = 'CONST' idaapi.add_segm(0, loadbase + start, loadbase + end, name, kind) segm = idaapi.get_segm_by_name(name) if kind == 'CONST': segm.perm = idaapi.SEGPERM_READ elif kind == 'CODE': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC elif kind == 'DATA': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE elif kind == 'BSS': segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE idaapi.update_segm(segm) idaapi.set_segm_addressing(segm, 1 if f.armv7 else 2) # do imports # TODO: can we make imports show up in "Imports" window? undef_count = 0 for s in f.symbols: if not s.shndx and s.name: undef_count += 1 last_ea = max(loadbase + end for start, end, name, kind in f.sections) undef_entry_size = 8 undef_ea = ( (last_ea + 0xFFF) & ~0xFFF ) + undef_entry_size # plus 8 so we don't end up on the "end" symbol idaapi.add_segm(0, undef_ea, undef_ea + undef_count * undef_entry_size, "UNDEF", "XTRN") segm = idaapi.get_segm_by_name("UNDEF") segm.type = idaapi.SEG_XTRN idaapi.update_segm(segm) for i, s in enumerate(f.symbols): if not s.shndx and s.name: MakeQword(undef_ea) idaapi.do_name_anyway(undef_ea, s.name) s.resolved = undef_ea undef_ea += undef_entry_size elif i != 0: assert s.shndx s.resolved = loadbase + s.value if s.name: if s.type == STT_FUNC: print hex(s.resolved), s.name idaapi.add_entry(s.resolved, s.resolved, s.name, 0) else: idaapi.do_name_anyway(s.resolved, s.name) else: # NULL symbol s.resolved = 0 funcs = set() for s in f.symbols: if s.name and s.shndx and s.value: if s.type == STT_FUNC: funcs.add(loadbase + s.value) got_name_lookup = {} for offset, r_type, sym, addend in f.relocations: target = offset + loadbase if r_type in (R_ARM_GLOB_DAT, R_ARM_JUMP_SLOT, R_ARM_ABS32): if not sym: print 'error: relocation at %X failed' % target else: idaapi.put_long(target, sym.resolved) elif r_type == R_ARM_RELATIVE: idaapi.put_long(target, idaapi.get_long(target) + loadbase) elif r_type in (R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT, R_AARCH64_ABS64): idaapi.put_qword(target, sym.resolved + addend) if addend == 0: got_name_lookup[offset] = sym.name elif r_type == R_AARCH64_RELATIVE: idaapi.put_qword(target, loadbase + addend) if addend < f.textsize: funcs.add(loadbase + addend) else: print 'TODO r_type %d' % (r_type, ) ida_make_offset(f, target) for func, target in f.plt_entries: if target in got_name_lookup: addr = loadbase + func funcs.add(addr) idaapi.do_name_anyway(addr, got_name_lookup[target]) funcs |= find_bl_targets(loadbase, loadbase + f.textsize) for addr in sorted(funcs, reverse=True): AutoMark(addr, AU_CODE) AutoMark(addr, AU_PROC) return 1