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 is_code(va): if is_head(va): flags = idc.get_full_flags(va) return ida_bytes.is_code(flags) else: head = get_head(va) return is_code(head)
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 getBlocks(self, function_offset): blocks = [] function_chart = ida_gdl.FlowChart(ida_funcs.get_func(function_offset)) for block in function_chart: extracted_block = [] for instruction in idautils.Heads(block.start_ea, block.end_ea): if ida_bytes.is_code(ida_bytes.get_flags(instruction)): extracted_block.append(instruction) if extracted_block: blocks.append(extracted_block) return sorted(blocks)
def postprocess_action(self): self._plugin.logger.debug("postprocess_action()") if len(self.actions): name, ea = self.actions.pop() if name == "MakeUnknown": flags = ida_bytes.get_full_flags(ea) if ida_bytes.is_unknown(flags): self._send_packet(evt.MakeUnknown(ea)) elif name == "MakeCode": flags = ida_bytes.get_full_flags(ea) if ida_bytes.is_code(flags): self._send_packet(evt.MakeCodeEvent(ea))
def _has_code(self): """ Checks if any address in the changed data area has code in it :return: (int) address of the code start, or None. """ for i in xrange(self.data): maybe_start_of_item = ida_bytes.get_item_head(self.address + i) if ida_bytes.is_code( ida_bytes.get_full_flags(maybe_start_of_item)): return self.address + i return None
def Callees(ea): pfn = ida_funcs.get_func(ea) callees = [] if pfn: for item in pfn: F = ida_bytes.get_flags(item) if ida_bytes.is_code(F): insn = ida_ua.insn_t() if ida_ua.decode_insn(insn, item): if ida_idp.is_call_insn(insn): if insn.ops[0].type in [ida_ua.o_near, ida_ua.o_far]: callees.append(insn.ops[0].addr) return list(dict.fromkeys(callees))
def get_stacked_bytes(dec_func_addr): func_stacked_bytes_addr_dict = {} xrefs = idautils.CodeRefsTo(dec_func_addr, 0) for xref in xrefs: prev_addr = idc.prev_head(xref) prev_addr_2 = idc.prev_head(prev_addr) if idc.print_insn_mnem(prev_addr_2) == "call": func_name = idc.print_operand(prev_addr_2, 0) func_addr = idc.get_name_ea_simple(func_name) func_stacked_bytes_addr_dict[xref] = func_addr # enc_mod_addr = list(set(enc_mod_addr)) # [Debug] Get unique functions only for xref, stacked_bytes_addr in func_stacked_bytes_addr_dict.items(): print(f"Address: {hex(stacked_bytes_addr)}") func_ea = idc.get_func_attr(stacked_bytes_addr, idc.FUNCATTR_START) bytes_collected = bytearray() # Collected stack string store here for ins in idautils.FuncItems(func_ea): if ida_bytes.is_code(ida_bytes.get_full_flags(ins)): if idc.print_insn_mnem(ins) == "mov": if idc.get_operand_type(ins, 1) == idc.o_imm: # disasm = idc.GetDisasm(ins) # [Debug] hex_str_len = len( idc.print_operand(ins, 1).lstrip("0").rstrip("h")) const_hex_byte = idc.print_operand( ins, 1).lstrip("0").rstrip("h") if hex_str_len != 8: # Skip if const hex byte less than 8 append_zero = "0" * (8 - hex_str_len) const_hex_byte = append_zero + const_hex_byte # print(struct.pack("<I", int(const_hex_byte, 16))) # [Debug] # else: # print(struct.pack("<I", int(const_hex_byte, 16))) # [Debug] bytes_collected += struct.pack("<I", int(const_hex_byte, 16)) if len(bytes_collected) >= 1: cmt_str = "" if dec_func_addr == 0x10001253: # fn_name_addr print(f"{decode_fnname(bytes_collected[4:])}") cmt_str = decode_fnname(bytes_collected[4:]) elif dec_func_addr == 0x1000122B: # mod_name_addr print(f"{decode_modname(bytes_collected[4:])}") cmt_str = decode_modname(bytes_collected[4:]) idc.set_cmt(xref, cmt_str, 1) # Comment near xref decoder function else: print(f"[-] {hex(stacked_bytes_addr)} addr error")
def _convert_address_to_function(func): """Convert an address that IDA has classified incorrectly into a proper function.""" # If everything goes wrong, we'll try to restore this function. orig = idc.first_func_chunk(func) # If the address is not code, let's undefine whatever it is. if not ida_bytes.is_code(ida_bytes.get_full_flags(func)): if not is_mapped(func): # Well, that's awkward. return False item = ida_bytes.get_item_head(func) itemend = ida_bytes.get_item_end(func) if item != idc.BADADDR: _log(1, 'Undefining item {:#x} - {:#x}', item, itemend) ida_bytes.del_items(item, ida_bytes.DELIT_EXPAND) idc.create_insn(func) # Give IDA a chance to analyze the new code or else we won't be able to create a # function. #ida_auto.auto_wait() autoanalyze() idc.plan_and_wait(item, itemend) else: # Just try removing the chunk from its current function. IDA can add it to another function # automatically, so make sure it's removed from all functions by doing it in loop until it # fails. for i in range(1024): if not idc.remove_fchunk(func, func): break # Now try making a function. if ida_funcs.add_func(func) != 0: return True # This is a stubborn chunk. Try recording the list of chunks, deleting the original function, # creating the new function, then re-creating the original function. if orig != idc.BADADDR: chunks = list(idautils.Chunks(orig)) if ida_funcs.del_func(orig) != 0: # Ok, now let's create the new function, and recreate the original. if ida_funcs.add_func(func) != 0: if ida_funcs.add_func(orig) != 0: # Ok, so we created the functions! Now, if any of the original chunks are not # contained in a function, we'll abort and undo. if all(idaapi.get_func(start) for start, end in chunks): return True # Try to undo the damage. for start, _ in chunks: ida_funcs.del_func(start) # Everything we've tried so far has failed. If there was originally a function, try to restore # it. if orig != idc.BADADDR: _log(0, 'Trying to restore original function {:#x}', orig) ida_funcs.add_func(orig) return False
def show_microcode(): """Generates and displays microcode for an address range. An address range can be a selection of code or that of the current function.""" sel, sea, eea = kw.read_range_selection(None) pfn = ida_funcs.get_func(kw.get_screen_ea()) if not sel and not pfn: return (False, "Position cursor within a function or select range") if not sel and pfn: sea = pfn.start_ea eea = pfn.end_ea addr_fmt = "%016x" if ida_ida.inf_is_64bit() else "%08x" fn_name = (ida_funcs.get_func_name(pfn.start_ea) if pfn else "0x%s-0x%s" % (addr_fmt % sea, addr_fmt % eea)) F = ida_bytes.get_flags(sea) if not ida_bytes.is_code(F): return (False, "The selected range must start with an instruction") text, mmat, mba_flags = ask_desired_maturity() if text is None and mmat is None: return (True, "Cancelled") if not sel and pfn: mbr = hr.mba_ranges_t(pfn) else: mbr = hr.mba_ranges_t() mbr.ranges.push_back(ida_range.range_t(sea, eea)) hf = hr.hexrays_failure_t() ml = hr.mlist_t() mba = hr.gen_microcode(mbr, hf, ml, hr.DECOMP_WARNINGS, mmat) if not mba: return (False, "0x%s: %s" % (addr_fmt % hf.errea, hf.desc())) vp = printer_t() mba.set_mba_flags(mba_flags) mba._print(vp) mcv = microcode_viewer_t() if not mcv.Create( mba, "0x%s-0x%s (%s)" % (addr_fmt % sea, addr_fmt % eea, text), text, fn_name, vp.get_mc()): return (False, "Error creating viewer") mcv.Show() return (True, "Successfully generated microcode for 0x%s..0x%s" % (addr_fmt % sea, addr_fmt % eea))
def get_custom_viewer_hint(self, view, place): try: widget = ida_kernwin.get_current_widget() if ida_kernwin.get_widget_type(widget) != ida_kernwin.BWN_DISASM: return None curline = ida_kernwin.get_custom_viewer_curline(view, True) # sometimes get_custom_viewer_place() returns [x, y] and sometimes [place_t, x, y]. # we want the place_t. viewer_place = ida_kernwin.get_custom_viewer_place(view, True) if len(viewer_place) != 3: return None _, x, y = viewer_place ea = place.toea() # "color" is a bit of misnomer: its the type of the symbol currently hinted color = get_color_at_char(curline, x) if color != ida_lines.COLOR_ADDR: return None # grab the FAR references to code (not necessarilty a branch/call/jump by itself) far_code_references = [ xref.to for xref in idautils.XrefsFrom(ea, ida_xref.XREF_FAR) if ida_bytes.is_code(ida_bytes.get_flags(xref.to)) ] if len(far_code_references) != 1: return None fva = far_code_references[0] # ensure its actually a function if not idaapi.get_func(fva): return None # this magic constant is the number of "important lines" to display by default. # the remaining lines get shown if you scroll down while the hint is displayed, revealing more lines. return render_function_hint(fva), DEFAULT_IMPORTANT_LINES_NUM except Exception as e: logger.warning( 'unexpected exception: %s. Get in touch with @williballenthin.', e, exc_info=True) return None
def get_custom_viewer_hint(self, viewer, place): widget_type = ida_kernwin.get_widget_type(viewer) if widget_type != ida_kernwin.BWN_DISASM: return flags = ida_bytes.get_flags(place.toea()) if place else 0 if not ida_bytes.is_code(flags): return item = AMIE.extract_item(viewer) if not item: return tag, val = item hint = self.arch.hint(place.toea(), tag, val) if not hint: return return AMIE.format_hint(*hint)
def main(): typelib = None for typelib_name in DEFAULT_TYPELIBS: typelib = ida_typeinf.load_til(typelib_name) if typelib: break if not typelib: print(f"Unable to load mssdk") return # print(f"Loaded mssdk type library: {typelib.name}") status_enum = ida_typeinf.import_type(typelib, -1, "MACRO_STATUS") if status_enum == ida_netnode.BADNODE: print(f"Unable to load type MACRO_STATUS") # print(f"Loaded MACRO_STATUS") # Grab the enum members enum_map = get_enum_map(status_enum) cur_member_id = ida_enum.get_first_enum_member(status_enum) while cur_member_id: cur_value = idaapi.get_const_value(cur_member_id) enum_map[cur_value] = cur_member_id cur_member_id = ida_enum.get_next_enum_member(cur_member_id) # Iterate over all untyped immediates imm_ea = ida_ida.cvar.inf.min_ea while (imm_ea != idaapi.BADADDR): imm_ea = ida_search.find_notype( imm_ea, ida_search.SEARCH_NEXT | ida_search.SEARCH_DOWN)[0] if ida_bytes.is_code(ida_bytes.get_flags(imm_ea)): enum_value = idc.get_operand_value(imm_ea, 1) # Only handle likely error types right now.. if (enum_value & DWORD_MASK) > 0xC0000000: try: cid = enum_map[enum_value] # print(f"Applying {hex(enum_value & DWORD_MASK)} at {hex(imm_ea)}") # We don't need the member, we can just apply the enum type to the address ida_bytes.op_enum(imm_ea, 1, status_enum, 0) except KeyError: continue
def get_conflict(self): """ :return: None if there's no conflict, empty string if there's no change, data if there's a change. """ # TODO: Fill docstring, plus, make the function return 0,1,2 and save the current data by itself. conflicts = "" conflict_flag = False for i in xrange(self.data): current_address = self.address + i head_address = ida_bytes.get_item_head(current_address) if ida_bytes.is_code(ida_bytes.get_full_flags(head_address)): conflict_flag = True ea_flags = ida_bytes.get_full_flags(head_address) if not ida_bytes.is_data(ea_flags): continue conflict_flag = True conflicts += '%s at 0x%x\n' % ( self.TYPE_TO_NAME[ea_flags & ida_bytes.DT_TYPE], head_address) if conflict_flag: return conflicts return None
def color_head(ea): flags = ida_bytes.get_flags(ea) if not ida_bytes.is_code(flags): return mnem = ida_ua.print_insn_mnem(ea) if mnem == 'call': logger.debug('call: 0x%x', ea) idc.set_color(ea, idc.CIC_ITEM, CALL_COLOR) elif mnem == 'xor': if idc.get_operand_value(ea, 0) != idc.get_operand_value(ea, 1): logger.debug('non-zero xor: 0x%x', ea) idc.set_color(ea, idc.CIC_ITEM, ENCRYPT_COLOR) elif mnem in ('sdit', 'sgdt', 'sldt', 'smsw', 'str', 'in', 'cpuid'): logger.debug('anti-vm: 0x%x', ea) idc.set_color(ea, idc.CIC_ITEM, ANTIANALYSIS_COLOR) elif mnem == 'in': if idc.get_operand_value(ea, 0) in ("3", "2D"): logger.debug('anti-debug: 0x%x', ea) idc.set_color(ea, idc.CIC_ITEM, ANTIANALYSIS_COLOR) elif mnem in ('rdtsc', 'icebp'): logger.debug('anti-debug: 0x%x', ea) idc.set_color(ea, idc.CIC_ITEM, ANTIANALYSIS_COLOR)
def save_x(unique_name=None, start=None, size=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 or not size: seg = ida_segment.getseg(ea) start = seg.start_ea size = seg.size() # (start_addr, end_addr, names, comms) saved_data = {} 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()) if received_data: saved_data = received_data # save names (func_names, labels, etc) # (addr, name, is_code) names_addr_name = [] names = idautils.Names() for addr, name in names: if start <= addr <= start + size: flags = ida_bytes.get_flags(addr) names_addr_name.append( (addr - start, name, ida_bytes.is_code(flags))) # save comments comms_addr_type_comm = [] # (addr, TYPE, comment) # type 0:comment 1:rpt_comment end = start + size for i in range(start, end + 1): if ida_bytes.get_cmt(i, 0): # 0 Comment comms_addr_type_comm.append((i - start, 0, ida_bytes.get_cmt(i, 0))) if ida_bytes.get_cmt(i, 1): # 1 RptCmt comms_addr_type_comm.append((i - start, 1, ida_bytes.get_cmt(i, 1))) # breakpoints bpts_addr_size_type = [] bpt = ida_dbg.bpt_t() global remove_on_exit_bpts for i in range(start, end + 1): if ida_dbg.get_bpt(i, bpt): bpts_addr_size_type.append((i - start, bpt.size, bpt.type)) remove_on_exit_bpts.append(i) # functions funcs_addr = [] flag = ida_bytes.get_flags(start) if ida_bytes.is_func(flag): funcs_addr.append(0) # start addr next_func = ida_funcs.get_next_func(start) while next_func: funcs_addr.append(next_func.start_ea - start) next_func = ida_funcs.get_next_func(next_func.start_ea) # SAVE saved_data[unique_name] = (start, start + end, names_addr_name, comms_addr_type_comm, bpts_addr_size_type, funcs_addr) if MD5_hash_data_file: with open(MD5_hash_data_file, "wb") as ifile: serial_data = pickle.dumps(saved_data) ifile.write(serial_data) print("dumpDyn::save:\n\ Name: {}\n\ Start address: {}".format(unique_name, hex(start)))
import idautils import ida_bytes import idaapi for ea in idautils.Heads(): if ida_bytes.is_code(ida_bytes.get_flags(ea)) and idaapi.is_call_insn(ea): idaapi.set_item_color(ea, 0xFFFFFFA0)
def get_all_calls(): is_64bit = set_version_and_platform_specific_elements() call_list = [] call_addr_list = [] #check if stack segment is None. It's a problem if is_64bit: sp = cpu.Rsp ip = cpu.Rip else: sp = cpu.Esp ip = cpu.Eip if idaapi.getseg(cpu.Rsp) is None: warning("Stack segment is None") return False #information about current fun is_current_fun = True call_list.append(get_info_about_call(ip, "", sp, is_current_fun)) call_addr_list.append(ip) #iterate by stack if is_64bit: #at the begging return address is set as a current ip return_addr = cpu.Rip curr_sp = cpu.Rsp curr_bp = cpu.Rbp for i in range(0, MAX_NUMBER_FUNCTION_TO_SHOW): return_addr, curr_sp, curr_bp = calculate_caller_function_frame_info_x64( return_addr, curr_sp, curr_bp) if return_addr == idaapi.BADADDR or return_addr == 0: break curr_segment = idaapi.getseg(return_addr) #segmenst must exists and be executable if not curr_segment or (curr_segment.perm & idaapi.SEGPERM_EXEC) == 0: continue is_call, curr_call_addr = check_previous_inst_is_call( return_addr, is_64bit) if not is_call: continue #if bytes are not disassembled, then do it flags = ida_bytes.get_full_flags(curr_call_addr) if not ida_bytes.is_code(flags): idc.create_insn(curr_call_addr) #save a call argument call_list.append( get_info_about_call(curr_call_addr, print_operand(curr_call_addr, 0), return_addr)) call_addr_list.append(curr_call_addr) else: curr_ebp = cpu.Ebp ptr_size = 4 pfn_get_ptr = idc.get_wide_dword for i in range(0, MAX_NUMBER_FUNCTION_TO_SHOW): return_addr = pfn_get_ptr(curr_ebp + ptr_size) debug('ret: {:08X}'.format(return_addr)) curr_ebp = pfn_get_ptr(curr_ebp) debug('ebp: {:08X}'.format(curr_ebp)) if return_addr == idaapi.BADADDR or return_addr == 0: break curr_segment = idaapi.getseg(return_addr) #segmenst must exists and be executable if not curr_segment or (curr_segment.perm & idaapi.SEGPERM_EXEC) == 0: continue is_call, curr_call_addr = check_previous_inst_is_call( return_addr, is_64bit) if not is_call: continue #if bytes are not disassembled, then do it flags = ida_bytes.get_full_flags(curr_call_addr) if not ida_bytes.is_code(flags): idc.create_insn(curr_call_addr) #save a call argument call_list.append( get_info_about_call(curr_call_addr, print_operand(curr_call_addr, 0), curr_ebp)) call_addr_list.append(curr_call_addr) return True, call_list, call_addr_list
def is_code(ea): flags = ida_bytes.get_full_flags(ea) return ida_bytes.is_code(flags) and ida_bytes.is_head(flags)
def show_xrefs(ea, gco, xrefs, ndefs): title = "xrefs to %s at %08x" % (gco.name, ea) xc = xref_chooser_t(xrefs, title, ndefs, ea, gco) i = xc.Show(True) if i >= 0: ida_kernwin.jumpto(xrefs[i]) if ida_hexrays.init_hexrays_plugin(): ea = ida_kernwin.get_screen_ea() pfn = ida_funcs.get_func(ea) w = ida_kernwin.warning if pfn: F = ida_bytes.get_flags(ea) if ida_bytes.is_code(F): gco = ida_hexrays.gco_info_t() if ida_hexrays.get_current_operand(gco): # generate microcode hf = ida_hexrays.hexrays_failure_t() mbr = ida_hexrays.mba_ranges_t(pfn) mba = ida_hexrays.gen_microcode(mbr, hf, None, ida_hexrays.DECOMP_WARNINGS, ida_hexrays.MMAT_PREOPTIMIZED) if mba: merr = mba.build_graph() if merr == ida_hexrays.MERR_OK: ncalls = mba.analyze_calls(ida_hexrays.ACFL_GUESS) if ncalls < 0: print( "%08x: failed to determine some calling conventions",
def dump_heads(out): # out is a file like object, sys.stdout or an acual file object # There doesn't seem to a good way to determine what function a # particular address is in. Almost everyone recommends iterating # of the functions, and then getting the bytes out of each, but # that's not really what we want because it skips non function # bytes and reports them in the wrong order. It appears that the # best we can do is to build a map in advance. :-( a2fmap = build_a2fmap() min_ea = idaapi.cvar.inf.minEA max_ea = idaapi.cvar.inf.maxEA ea = min_ea while ea != ida_idaapi.BADADDR: ida_auto.show_addr(ea) isize = ida_bytes.get_item_size(ea) ibytes = ida_bytes.get_bytes(ea, isize) ihexbytes = binascii.b2a_hex(ibytes).upper() iflags = ida_bytes.get_flags(ea) # Skip the PE header? if not ida_bytes.is_head(iflags): ea = ida_bytes.next_head(ea, max_ea) continue # Loop up this address in the address-to-function map. if ea in a2fmap: faddrs = a2fmap[ea] else: faddrs = [ea] tcode = "ERROR" imnem = "???" iops = "???" if ida_bytes.is_code(iflags): tcode = "INSN" imnem = "???" iops = "???" insn = idautils.DecodeInstruction(ea) if insn == None: imnem = "BAD" iops = "" elif not insn.is_canon_insn(): imnem = "NCAN" iops = "" else: imnem = insn.get_canon_mnem() sops = [] for n in range(8): ostr = ida_ua.print_operand(ea, n) if ostr is not None: ostrnt = ida_lines.tag_remove(ostr) if ostrnt != '': sops.append(ostrnt) iops = ', '.join(sops) elif ida_bytes.is_data(iflags): tcode = "DATA" imnem = "db" iops = "???" if ida_bytes.is_align(iflags): tcode += "_ALIGN" #elif ida_bytes.is_struct(iflags): # tcode += "_STRUCT" #elif ida_bytes.is_char(iflags): # tcode += "_STR" # There are other types that IDA recognizes. elif ida_bytes.is_unknown(iflags): tcode = "UNK-%08X" % iflags imnem = "???" iops = "???" for faddr in sorted(faddrs): out.write('"PART",0x%08X,"%s",0x%08X,"%s","%s","%s"\n' % (ea, tcode, faddr, ihexbytes, imnem, iops)) ea = ida_bytes.next_head(ea, max_ea) print "Analysis complete!"
movs = ["mov", "xchg"] ida_api_is_new = False try: import ida_auto ida_api_is_new = True except ImportError: pass user_pos = ida_kernwin.get_screen_ea() after_function_before_user_pos = ida_funcs.get_prev_func(user_pos).end_ea + 1 before_function_after_user_pos = ida_funcs.get_next_func(user_pos).start_ea - 1 hopefully_a_sane_start_of_function = (after_function_before_user_pos & ~0x0F) + 0x10 make_fun_pos = None if ida_bytes.is_code(ida_bytes.get_flags(hopefully_a_sane_start_of_function)): make_fun_pos = hopefully_a_sane_start_of_function def re_analyze_relevant_range(): ida_bytes.del_items( after_function_before_user_pos, 0, before_function_after_user_pos - after_function_before_user_pos) if not make_fun_pos is None: assume_code_at(make_fun_pos) else: run_autoanalysis(after_function_before_user_pos, before_function_after_user_pos) def run_autoanalysis(start, end=None):
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)
def is_code(ea): if idaapi.IDA_SDK_VERSION <= 699: retval = idc.IsCode(ea) else: retval = ida_bytes.is_code(ea) return retval
def match(F): return ida_bytes.is_code(F) and not ida_bytes.is_flow(F)