def __init__(self, ea): self.ea = ea self.funcname_or_segname = "" self.text = "" if not ida_bytes.is_code(ida_bytes.get_flags(ea)): ida_ua.create_insn(ea) # text t = ida_lines.generate_disasm_line(ea) if t: self.text = ida_lines.tag_remove(t) # funcname_or_segname n = ida_funcs.get_func_name(ea) \ or ida_segment.get_segm_name(ida_segment.getseg(ea)) if n: self.funcname_or_segname = n
def restore_x(unique_name=None, start=None): ea = ida_kernwin.get_screen_ea() # signature if not unique_name: if not start: seg = ida_segment.getseg(ea) start = seg.start_ea sig_bytes = ida_bytes.get_bytes(start, SIGNATURE_SIZE) sig_hash = hashlib.md5(sig_bytes).hexdigest() unique_name = sig_hash if not start: seg = ida_segment.getseg(ea) start = seg.start_ea if MD5_hash_data_file and os.path.isfile(MD5_hash_data_file): with open(MD5_hash_data_file, "rb") as ifile: received_data = pickle.loads(ifile.read()) saved_data = received_data print("dumpDyn::restore\n\ Name: {}\n\ Restore address: {}\n".format(unique_name, hex(start))) # (start_addr, end_addr, names, comms, bpts, funcs) if unique_name in saved_data: current_data = saved_data[unique_name] # restore names names = current_data[2] for name in names: # names: (rel_addr, name, is_code) ida_name.set_name(start + name[0], name[1]) flags = ida_bytes.get_flags(start + name[0]) if name[2] and not ida_bytes.is_code(flags): ida_auto.auto_make_code(start + name[0]) # restore comments # comms: (rel_addr, TYPE, comment) comms = current_data[3] for comm in comms: # 0:MakeComm and 1:MakeRptCmt ida_bytes.set_cmt(start + comm[0], comm[2], comm[1]) # restore breakpoints # bpts: (rel_addr, size, type) bpts = current_data[4] for bpt in bpts: ida_dbg.add_bpt(start + bpt[0], bpt[1], bpt[2]) # restore functions funcs_addr = current_data[5] for addr in funcs_addr: ida_auto.auto_make_proc(start + addr) # make code & func
def get_mem_string(cls, addr): """ 获取内存中的字符串 """ addr_t = addr dref = idautils.DataRefsFrom(addr_t) strs = [cls.strings[x] for x in dref if x in cls.strings] # 处理几种特殊情况 # LDR R1, =sub_xxxx # LDR R1, =loc_xxxx if idc.print_operand(addr, 1)[:5] in ['=sub_', '=loc_']: return [] # LDR R1, =unk_53B4B6 # .rodata:0053B4B6 http: # .rodata:0053B4BB //%s%s if strs != [] and strs[0].find('%') == -1: strs = [] dref = idautils.DataRefsFrom(addr_t) for x in dref: segname = ida_segment.get_segm_name(ida_segment.getseg(x)) if segname not in ['.text', '.bss']: strs.append(cls.get_string_from_mem(x)) # LDR R1, =(aFailedToGetAnI+0x22) # LDR R2, =(aSS - 0xCFA4) # ADD R2, PC, R2 if strs == []: dref = idautils.DataRefsFrom(addr_t) for x in dref: segname = ida_segment.get_segm_name(ida_segment.getseg(x)) if segname not in ['.text', '.bss']: strs.append(cls.get_string_from_mem(x)) elif len(list(idautils.DataRefsFrom(x))) == 0: reg_t = idc.print_operand(addr_t, 0) num1 = ida_bytes.get_wide_dword(x) while get_mnem(addr_t) != 'ADD' or (idc.print_operand(addr_t, 0) != reg_t and idc.print_operand(addr_t, 1) != 'PC'): addr_t = ida_bytes.next_head(addr_t, ida_idaapi.BADADDR) num2 = addr_t + 8 addr_t = num1 + num2 strs.append(cls.get_string_from_mem(addr_t)) # MOVW R1, #0x87B4 # MOVT.W R1, #0x52 if strs == [] and get_mnem(addr_t) == 'MOVW': reg_t = idc.print_operand(addr_t, 0) num1 = int(idc.print_operand(addr_t, 1).split('#')[1], 16) while get_mnem(addr_t) not in ['MOVTGT', 'MOVTLE', 'MOVT'] or idc.print_operand(addr_t, 0) != reg_t: addr_t = ida_bytes.next_head(addr_t, ida_idaapi.BADADDR) num2 = int(idc.print_operand(addr_t, 1).split('#')[1], 16) addr_t = (num2<<16) + num1 strs.append(cls.get_string_from_mem(addr_t)) return strs
def main(): # Get current ea ea = ida_kernwin.get_screen_ea() # Get segment class seg = ida_segment.getseg(ea) # Loop from segment start to end func_ea = seg.start_ea # Get a function at the start of the segment (if any) func = ida_funcs.get_func(func_ea) if func is None: # No function there, try to get the next one func = ida_funcs.get_next_func(func_ea) seg_end = seg.end_ea while func is not None and func.start_ea < seg_end: funcea = func.start_ea print("Function %s at 0x%x" % (ida_funcs.get_func_name(funcea), funcea)) ref = ida_xref.get_first_cref_to(funcea) while ref != ida_idaapi.BADADDR: print(" called from %s(0x%x)" % (ida_funcs.get_func_name(ref), ref)) ref = ida_xref.get_next_cref_to(funcea, ref) func = ida_funcs.get_next_func(funcea)
def get_code_segments(): segments = [] for ea in idautils.Segments(): s = ida_segment.getseg(ea) if ida_segment.get_segm_class(s) == 'CODE': segments.append(s) return segments
def adjust_addr(sections, addr): """ Adjust the address if there are differences in section base addresses :param sections: Dictionary containing section info :param addr: Address that might need adjusted :return: Adjusted address """ bn_section_start = None section_name = None for name, section in sections.items(): if addr >= int(section['start']) and addr <= int(section['end']): bn_section_start = int(section['start']) section_name = name break # Make sure the section was found (this check should always pass) if section_name is None: print('Section not found in bnida analysis data for addr: {:08x}'.format(addr)) return None # Retrieve section start in IDA and adjust the addr ida_sections = idautils.Segments() for ea in ida_sections: segm = ida_segment.getseg(ea) if ida_segment.get_segm_name(segm) == section_name: return addr - bn_section_start + segm.start_ea print('Section not found - name:{} addr:{:08x}'.format(section_name, addr)) return None
def find_interesting(base_ea, base_end): mv_ea = find_macho_valid(base_ea) if mv_ea != ida_idaapi.BADADDR: ldk_ea = find_loaded_kernelcache(mv_ea) lk_ea = find_load_kernelcache(ldk_ea) pk_ea = find_panic(base_ea) go_ea = find_do_go(base_ea) pr_ea = find_do_printf(base_ea) i4l_ea = find_image4_load(base_ea) i4d_ea = find_img4decodeinit(base_ea) aes_ea = find_aes_crypto_cmd(base_ea) udt_ea = find_update_device_tree(base_ea) ml_ea = find_macho_load(base_ea) pgv_ea = find_pmgr_binning_mode_get_value(base_ea) i4p_ea = find_image4_get_partial(base_ea) mt_ea = find_main_task(base_ea) bc_ea = find_boot_check_panic(base_ea, base_end) pc_ea = find_putchar(base_ea) if pc_ea != ida_idaapi.BADADDR and mv_ea == ida_idaapi.BADADDR: # this is a SecureROM image segm = ida_segment.getseg(base_ea) if segm: idaapi.set_segm_name(segm, "SecureROM", 0) print("[+] Identified as a SecureROM image")
def on_get_annotations(self, address, size, mouse_offs): caption = "Return instructions:" spaces = 40 * '-' ann = [(None, None, caption, self.colormap[-1])] if len(self.ret_locs): i = 0 offs = self._get_selection_offs() nret = len(self.ret_locs) for x in xrange(offs, nret): _, __, ret = self.ret_locs[x] seg = getseg(ret) textcol = self.txtcol if seg is not None: if not seg.perm & SEGPERM_EXEC: # red text color if ret not within executable segment textcol = 0xEE0000 ann.append((ret, self.ptrcol, " %X [%s]" % (ret, generate_disasm_line( ret, GENDSM_FORCE_CODE | GENDSM_REMOVE_TAGS)), textcol)) i += 1 if i > self.threshold: ann.append((None, None, "<%d more not shown>" % (len(self.ret_locs) - i), self.colormap[-1])) break return ann
def create_rom_segment(): success = add_segm(0, ROM_START_ADDRESS, ROM_START_ADDRESS + ROM_SIZE, "ROM", "CODE") == 1 msg("creating ROM segment..%s" % ("ok!\n" if success else "failure!\n")) if (not success): return set_segm_addressing(getseg(ROM_START_ADDRESS), 0)
def create_ram_segment(): success = add_segm(0, RAM_START_ADDRESS, RAM_START_ADDRESS + RAM_SIZE, "RAM", None) == 1 msg("creating RAM segment..%s" % ("ok!\n" if success else "failure!\n")) if (not success): return set_segm_addressing(getseg(RAM_START_ADDRESS), 0)
def getConst(ea, offset): strings = [] consts = [] optype1 = idc.get_operand_type(ea, offset) if optype1 == idaapi.o_imm: imm_value = idc.get_operand_value(ea, offset) if 0<= imm_value <= 10: consts.append(imm_value) else: if idaapi.isLoaded(imm_value) and ida_segment.getseg(imm_value): str_value = idc.get_strlit_contents(imm_value) if str_value is None: str_value = idc.get_strlit_contents(imm_value+0x40000) if str_value is None: consts.append(imm_value) else: re = all(40 <= ord(c) < 128 for c in str_value) if re: strings.append(str_value) else: consts.append(imm_value) else: re = all(40 <= ord(c) < 128 for c in str_value) if re: strings.append(str_value) else: consts.append(imm_value) else: consts.append(imm_value) return strings, consts
def search_guid(guid): if isinstance(guid, basestring): target_guid = GUID(string = guid) else: print "UNSUPPORTED FORMAT" return for seg_addr in idautils.Segments(): seg = ida_segment.getseg(seg_addr) cur_addr = seg.start_ea seg_end = seg.end_ea while cur_addr < seg_end: d = [ida_bytes.get_dword(cur_addr), ida_bytes.get_dword(cur_addr+0x4), ida_bytes.get_dword(cur_addr+0x8), ida_bytes.get_dword(cur_addr+0xC)] if (d[0] == 0 and d[1] == 0 and d[2] == 0 and d[3] == 0) or \ ( d[0] == 0xFFFFFFFF and d[1] == 0xFFFFFFFF and d[2] == 0xFFFFFFFF and d[3] == 0xFFFFFFFF ): cur_addr += 0x10 else: cur_guid = GUID(bytes=struct.pack( "<LLLL", d[0], d[1], d[2], d[3] )) if str(target_guid) == str(cur_guid): print " - Found GUID {} at 0x{:08x}".format( str(target_guid), cur_addr ) return cur_addr += 1 print (" - GUID %s not found" % (str(target_guid)))
def create_exprom_segment(): success = add_segm(0, EXPROM_START_ADDRESS, EXPROM_START_ADDRESS + EXPROM_SIZE, "EXP_ROM", None) == 1 msg("creating EXP_ROM segment..%s" % ("ok!\n" if success else "failure!\n")) if (not success): return set_segm_addressing(getseg(EXPROM_START_ADDRESS), 0)
def get_segments(): """ 返回所有segment的名字列表(但其实是section) """ seg_names = [] for ea in idautils.Segments(): seg = ida_segment.getseg(ea) seg_names.append(ida_segment.get_segm_name(seg)) return seg_names
def load_trainer(li): if (not INES_MASK_SRAM(hdr.rom_control_byte_0)): success = add_segm(0, TRAINER_START_ADDRESS, TRAINER_START_ADDRESS + TRAINER_SIZE, "TRAINER", "CODE") == 1 msg("creating TRAINER segment..%s", "ok!\n" if success else "failure!\n") set_segm_addressing(getseg(TRAINER_START_ADDRESS), 0) li.file2base(INES_HDR_SIZE, TRAINER_START_ADDRESS, TRAINER_START_ADDRESS + TRAINER_SIZE, FILEREG_PATCHABLE)
def _on_rangecommentchanged(self, kind, start_ea, comment, repeatable): comment = Unicoder.encode(comment) if kind == ida_range.RANGE_KIND_FUNC: func = ida_funcs.get_func(start_ea) ida_funcs.set_func_cmt(func, comment, repeatable) elif kind == ida_range.RANGE_KIND_SEGMENT: segment = ida_segment.getseg(start_ea) ida_segment.set_segment_cmt(segment, comment, repeatable) else: raise Exception('Unsupported range kind: {}'.format(kind))
def __call__(self): cmt = self.cmt if self.kind == ida_range.RANGE_KIND_FUNC: func = ida_funcs.get_func(self.start_ea) ida_funcs.set_func_cmt(func, cmt, self.rptble) elif self.kind == ida_range.RANGE_KIND_SEGMENT: segment = ida_segment.getseg(self.start_ea) ida_segment.set_segment_cmt(segment, cmt, self.rptble) else: raise Exception("Unsupported range kind: %d" % self.kind)
def __call__(self): cmt = Event.encode(self.cmt) if self.kind == ida_range.RANGE_KIND_FUNC: func = ida_funcs.get_func(self.start_ea) ida_funcs.set_func_cmt(func, cmt, self.rptble) elif self.kind == ida_range.RANGE_KIND_SEGMENT: segment = ida_segment.getseg(self.start_ea) ida_segment.set_segment_cmt(segment, cmt, self.rptble) else: logger.warning("Unsupported range kind: %d" % self.kind)
def find_interesting(base_ea, base_end): mv_ea = find_macho_valid(base_ea, base_end) if mv_ea != ida_idaapi.BADADDR: ldk_ea = find_loaded_kernelcache(mv_ea) if ldk_ea != ida_idaapi.BADADDR: lk_ea = find_load_kernelcache(ldk_ea) pk_ea = find_panic(base_ea) go_ea = find_do_go(base_ea) pr_ea = find_do_printf(base_ea) i4vc_ea = find_image4_validate_property_callback(base_ea, base_end) if i4vc_ea != ida_idaapi.BADADDR: i4l_ea = find_image4_load(i4vc_ea) i4i_ea = find_image4_validate_property_callback_interposer(base_ea) if i4i_ea != ida_idaapi.BADADDR: i4ip_ea = find_image4_validate_property_callback_interposer_ptr(i4i_ea) rmr_ea = find_record_memory_range(base_ea) i4d_ea = find_img4decodeinit(base_ea) scf_ea = find_stack_chk_fail(base_ea) aes_ea = find_aes_crypto_cmd(base_ea, base_end) udt_ea = find_update_device_tree(base_ea) ml_ea = find_macho_load(base_ea) if ml_ea != ida_idaapi.BADADDR: lko_ea = find_load_kernelcache_object(ml_ea) pgv_ea = find_pmgr_binning_mode_get_value(base_ea) i4p_ea = find_image4_get_partial(base_ea) mt_ea = find_main_task(base_ea) tei_ea = find_target_early_init(base_ea) bc_ea = find_boot_check_panic(base_ea, base_end) pei_ea = find_platform_early_init(base_ea, base_end) crv_ea = find_chipid_get_chip_revision(base_ea, base_end) pid_ea = find_platform_init_display(base_ea) pc_ea = find_putchar(base_ea, base_end) # just to be sure if br_flag == false: if pc_ea != ida_idaapi.BADADDR and mv_ea == ida_idaapi.BADADDR: # this is a SecureROM image segm = ida_segment.getseg(base_ea) if segm: idaapi.set_segm_name(segm, "SecureROM", 0) print("[+] Identified as a SecureROM image")
def ptrs(self): for seg_beg in filter(lambda x: getseg(x).type == SEG_DATA, Segments()): seg_end = get_segm_end(seg_beg) head = seg_beg while True: head = next_head(head, seg_end) if head == BADADDR: break head_ptr = Pointer(head) if head_ptr.type.rstrip(" *") == self.name: yield head_ptr
def find_in_segment(self, value, seg_name_or_ea): """ Searches memory for given value within the range of a specific segment. :param bytes value: byte string to search for :param seg_name_or_ea: segment name or address within segment. :return int: address where value was located or -1 if not found """ if isinstance(seg_name_or_ea, str): segment = ida_segment.get_segm_by_name(seg_name_or_ea) else: segment = ida_segment.getseg(seg_name_or_ea) return self.find(value, start=segment.start_ea, end=segment.end_ea)
def init_functions(force=False, target_seg_name=None): global func_initialized if not force and func_initialized: return # Linear sweep to find functions for ea in idautils.Segments(): # TODO: skip other segments that are not code. seg = ida_segment.getseg(ea) seg_name = ida_segment.get_segm_name(seg) # We only check target segment since it may take too much time. if target_seg_name and seg_name == target_seg_name: continue # TODO: we may use other strategy not just sweep linearly. print("Linear sweep analysis: %x -> %x (%s)" % (seg.start_ea, seg.end_ea, seg_name)) analyze_linear_sweep(seg.start_ea, seg.end_ea) # Find function pointer candidates for ea in idautils.Segments(): # TODO: skip other segments that are not code. seg = ida_segment.getseg(ea) seg_name = ida_segment.get_segm_name(seg) # We only check target segment since it may take too much time. if target_seg_name and seg_name == target_seg_name: continue # Analyze functions by pointers print("Function pointer analysis: %x -> %x (%s)" % (seg.start_ea, seg.end_ea, seg_name)) analyze_func_ptr(seg.start_ea, seg.end_ea) func_initialized = True
def rename_guids(): labels = {} # Load GUIDs guids = dict( (str(GUID(array=v)), k) for k, v in efiguids.GUIDs.iteritems() ) guids.update(dict((v, k) for k, v in local_guids.iteritems())) # Find all the data segments in this binary for seg_addr in idautils.Segments(): seg = ida_segment.getseg(seg_addr) if seg.type == ida_segment.SEG_DATA or True: print "Processing data segment at 0x{:08x}".format(seg_addr) # Find any GUIDs we know about in the data segment cur_addr = seg.start_ea seg_end = seg.end_ea while cur_addr < seg_end: d = [ida_bytes.get_dword(cur_addr), ida_bytes.get_dword(cur_addr+0x4), ida_bytes.get_dword(cur_addr+0x8), ida_bytes.get_dword(cur_addr+0xC)] if (d[0] == 0 and d[1] == 0 and d[2] == 0 and d[3] == 0) or \ ( d[0] == 0xFFFFFFFF and d[1] == 0xFFFFFFFF and d[2] == 0xFFFFFFFF and d[3] == 0xFFFFFFFF ): cur_addr += 0x10 else: guid = GUID(bytes=struct.pack( "<LLLL", d[0], d[1], d[2], d[3] )) gstr = str(guid) if gstr in guids.keys(): print " - Found GUID {} ({}) at 0x{:08x}".format( gstr, guids[gstr], cur_addr ) struct_label = get_next_unused_label( underscore_to_global(guids[gstr]) ) ida_name.set_name(cur_addr, struct_label) labels[struct_label] = (cur_addr, guids[gstr]) cur_addr += 0xf cur_addr += 0x01 else: print "Skipping non-data segment at 0x{:08x}".format(seg_addr) return labels
def main(): # Get current ea ea = ida_kernwin.get_screen_ea() if ea == ida_idaapi.BADADDR: print("Could not get get_screen_ea()") return seg = ida_segment.getseg(ea) if seg: # Loop from start to end in the current segment for funcea in idautils.Functions(seg.start_ea, seg.end_ea): print("Function %s at 0x%x" % (ida_funcs.get_func_name(funcea), funcea)) # Find all code references to funcea for ref in idautils.CodeRefsTo(funcea, 1): print(" called from %s(0x%x)" % (ida_funcs.get_func_name(ref), ref)) else: print("Please position the cursor within a segment")
def find(s=None, x=False, asm_where=None): b, ret = FindInstructions(s, asm_where) if b: # executable segs only? if x: results = [] for ea in ret: seg = ida_segment.getseg(ea) if (not seg) or (seg.perm & ida_segment.SEGPERM_EXEC) == 0: continue results.append(SearchResult(ea)) else: results = [SearchResult(ea) for ea in ret] title = "Search result for: [%s]" % s ida_kernwin.close_chooser(title) c = SearchResultChoose(title, results) c.Show(True) else: print(ret)
def get_sections(): """ Get section names and start/end addrs from IDA database :return: Dict containing section info """ sections = {} for ea in idautils.Segments(): segm = ida_segment.getseg(ea) name = ida_segment.get_segm_name(segm) if name == 'LOAD': continue curr = {} curr['start'] = segm.start_ea curr['end'] = segm.end_ea sections[name] = curr return sections
def xex_load_exports(li): global export_table_va export_table = HvImageExportTable() slen = ctypes.sizeof(export_table) bytes = ida_bytes.get_bytes(export_table_va, slen) fit = min(len(bytes), slen) ctypes.memmove(ctypes.addressof(export_table), bytes, fit) if export_table.Magic[0] != XEX_EXPORT_MAGIC_0 or export_table.Magic[ 1] != XEX_EXPORT_MAGIC_1 or export_table.Magic[ 2] != XEX_EXPORT_MAGIC_2: print("[+] Export table magic is invalid! (0x%X 0x%X 0x%X)" % (export_table.Magic[0], export_table.Magic[1], export_table.Magic[2])) return 0 print("[+] Loading module exports...") print(export_table) ordinal_addrs_va = export_table_va + slen for i in range(0, export_table.Count): func_ord = export_table.Base + i func_va = ida_bytes.get_dword(ordinal_addrs_va + (i * 4)) if func_va == 0: continue func_va = func_va + (export_table.ImageBaseAddress << 16) func_name = x360_imports.DoNameGen(idc.get_root_filename(), 0, func_ord) # Add to exports list & mark as func if inside a code section func_segmclass = ida_segment.get_segm_class( ida_segment.getseg(func_va)) idc.add_entry(func_ord, func_va, func_name, 1 if func_segmclass == "CODE" else 0) if func_segmclass == "CODE": idc.add_func(func_va) return 1
def init_strings(force=False, target_seg_name=None): global string_initialized if not force and string_initialized: return for ea in idautils.Segments(): seg = ida_segment.getseg(ea) seg_name = ida_segment.get_segm_name(seg) # We only check target segment since it may take too much time. if target_seg_name and seg_name == target_seg_name: continue print("Initializing %x -> %x (%s)" % (seg.start_ea, seg.end_ea, seg_name)) # TODO: we may use other strategy to find string pointers analyze_str_ptr(seg.start_ea, seg.end_ea) analyze_ida_str() string_initialized = True
def get_line_comments(): """ Iterate through every address in a segment and check for comments :return: Dict containing line comments """ last_comment = '' comments = {} for ea in idautils.Segments(): segm = ida_segment.getseg(ea) name = ida_segment.get_segm_name(segm) if name == 'LOAD': continue for i in range(segm.start_ea, segm.end_ea): comment = get_single_line_comment(i) if comment and comment != last_comment: comments[i] = comment last_comment = comment return comments
def _Assemble(ea, line): """ Please refer to Assemble() - INTERNAL USE ONLY """ if type(line) == bytes: lines = [line] else: lines = line ret = [] for line in lines: seg = ida_segment.getseg(ea) if not seg: return (False, "No segment at ea") ip = ea - (ida_segment.sel2para(seg.sel) << 4) buf = ida_idp.AssembleLine(ea, seg.sel, ip, seg.bitness, line) if not buf: return (False, "Assembler failed: " + line) ea += len(buf) ret.append(buf) if len(ret) == 1: ret = ret[0] return (True, ret)
def DumpSegPTE(ea): s = ida_segment.getseg(ea) DumpPTE(s.start_ea, s.end_ea)
def CallStackWalk(nn): class Result: """ Class holding the result of one call stack item Each call stack item instance has the following attributes: caller = ea of caller displ = display string sp = stack pointer """ def __init__(self, caller, sp): self.caller = caller self.sp = sp f = ida_funcs.get_func(caller) self.displ = "%08x: " % caller if f: self.displ += ida_funcs.get_func_name(caller) t = caller - f.start_ea if t > 0: self.displ += "+" + hex(t) else: self.displ += hex(caller) self.displ += " [" + hex(sp) + "]" def __str__(self): return self.displ # get stack pointer sp = idautils.cpu.Esp seg = ida_segment.getseg(sp) if not seg: return (False, "Could not locate stack segment!") stack_seg = Seg(seg) word_size = 2 ** (seg.bitness + 1) callers = [] sp = idautils.cpu.Esp - word_size while sp < stack_seg.end_ea: sp += word_size ptr = next(idautils.GetDataList(sp, 1, word_size)) seg = ida_segment.getseg(ptr) # only accept executable segments if (not seg) or ((seg.perm & ida_segment.SEGPERM_EXEC) == 0): continue # try to find caller caller = IsPrevInsnCall(ptr) # we have no recognized caller, skip! if caller is None: continue # do we have a debug name that is near? if nn: ret = nn.find(caller) if ret: ea = ret[0] # function exists? f = ida_funcs.get_func(ea) if not f: # create function ida_funcs.add_func(ea) # get the flags f = ida_bytes.get_flags(caller) # no code there? if not ida_bytes.is_code(f): ida_ua.create_insn(caller) callers.append(Result(caller, sp)) # return (True, callers)