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 on_get_annotations(self, address, size, mouse_offs): caption = " Mov instructions:" spaces = 40 * '-' cursor_ea = address + mouse_offs head = get_item_head(cursor_ea) ann = [ (head, self.ptrcol, "%X: %s" % (head, generate_disasm_line( head, GENDSM_FORCE_CODE | GENDSM_REMOVE_TAGS)), self.ptrcol), (None, None, "", None), (None, None, caption, self.colormap[0]) ] if len(self.annotations): i = 0 offs = self._get_selection_offs() ann_cnt = len(self.annotations) for x in xrange(offs, ann_cnt): _, acc, ea = self.annotations[x] textcol = self.txtcol ann.append((ea, self.insn_colors[acc], " %X: %s" % (ea, generate_disasm_line( ea, GENDSM_FORCE_CODE | GENDSM_REMOVE_TAGS)), self.insn_colors[acc])) i += 1 if i > self.threshold: ann.append((None, None, " <%d more not shown>" % (len(self.annotations) - i), self.colormap[0])) break return ann
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 handle_dll_calls(self): dll_call_count = ida_bytes.get_dword(self.E_info_entry_ea + self.dll_call_count_offset) dll_call_lib_names_ea = ida_bytes.get_dword( self.E_info_entry_ea + self.dll_call_lib_names_offset) dll_call_func_names_ea = ida_bytes.get_dword( self.E_info_entry_ea + self.dll_call_func_names_offset) self.dll_calls = Dll_calls(dll_call_lib_names_ea, dll_call_func_names_ea, dll_call_count) ida_auto.auto_wait() ea = ida_name.get_name_ea(idaapi.BADADDR, "j__krnl_MCallDllCmd") code_fref_eas = [] fref_ea = ida_xref.get_first_fcref_to(ea) while fref_ea != idaapi.BADADDR: code_fref_eas.append(fref_ea) fref_ea = ida_xref.get_next_cref_to(ea, fref_ea) for ref_ea in code_fref_eas: #get prev mov instruction prev_ins_ea = idaapi.get_item_head(ref_ea - 1) ins = ida_lines.generate_disasm_line(prev_ins_ea, ida_lines.GENDSM_REMOVE_TAGS) if (ins.startswith("mov eax,")): index = ida_bytes.get_dword(prev_ins_ea + 1) cmt = self.dll_calls[index] ida_bytes.set_cmt(ref_ea, cmt, False)
def _make_item(self, idx): ea = self.xrefs[idx] both_mask = ida_hexrays.GCO_USE | ida_hexrays.GCO_DEF both = (self.gco.flags & both_mask) == both_mask if ea == self.curr_ea and both: type_str = "use/def" elif idx < self.ndefs: type_str = "def" else: type_str = "use" insn = ida_lines.generate_disasm_line(ea, ida_lines.GENDSM_REMOVE_TAGS) return [type_str, "%08x" % ea, insn]
def dbg_step_over(self): eip = ida_dbg.get_reg_val("EIP") disasm = ida_lines.tag_remove( ida_lines.generate_disasm_line( eip)) self.log("Step over: EIP=0x%x, disassembly=%s" % (eip, disasm)) self.steps += 1 if self.steps >= 5: ida_dbg.request_exit_process() else: ida_dbg.request_step_over()
def dbg_trace(self, tid, ea): # Log all traced addresses if ea < ida_ida.inf_get_min_ea() or ea > ida_ida.inf_get_max_ea(): raise Exception( "Received a trace callback for an address outside this database!" ) self._log("trace %08X" % ea) self.traces += 1 insn = ida_ua.insn_t() insnlen = ida_ua.decode_insn(insn, ea) # log disassembly and ESP for call instructions if insnlen > 0 and insn.itype in [NN_callni, NN_call, NN_callfi]: self._log("call insn: %s" % generate_disasm_line( ea, GENDSM_FORCE_CODE | GENDSM_REMOVE_TAGS)) self._log("ESP=%08X" % ida_dbg.get_reg_val("ESP")) return 1
def data(self): func = ida_funcs.get_func(self.offset) def clean(asm): """This removes markers of function offsets, including hidden variable length offsets that are of different length on 32 and 64 bit address IDA. Otherwise, IDA of different offset lengths will truncate incorrect number of bytes""" hex_chars = int(log(ida_idaapi.BADADDR + 1, 2) / 4) pattern = ( r"\x01(.{1})\x01\([0-9a-zA-Z]{%s}([\w\s!@$?_]*?)\x02\1\x02\)" "" % hex_chars) replace = "\x01\g<1>\g<2>\x02\g<1>" return re.sub(pattern, replace, asm) # make sure only nodes inside the function are accounted for # this solves cascaded functions (when multiple functions share same ends) def node_contained(node): return (ida_funcs.func_contains(func, node.startEA) and ida_funcs.func_contains(func, node.endEA - 1)) nodes = filter(node_contained, ida_gdl.FlowChart(func)) node_ids = map(lambda n: n.id, nodes) nodes_data = [] for node in nodes: assembly = [ clean(ida_lines.generate_disasm_line(ea)) for ea in idautils.Heads(node.startEA, node.endEA) ] successive_nodes = [ succ.id for succ in node.succs() if succ.id in node_ids ] serialized_node = { 'id': node.id, 'type': node.type, 'start': node.startEA, 'end': node.endEA, 'successive': successive_nodes, 'assembly': assembly } nodes_data.append(serialized_node) return nodes_data
def _hook_code(self, uc, address, size, user_data): if self.trace_option & TRACE_CODE: disasm = generate_disasm_line( address, GENDSM_FORCE_CODE | GENDSM_MULTI_LINE | GENDSM_REMOVE_TAGS) self._add_trace( f"### Trace instruction at address={address:#x}, size={size:d}:\t{disasm!s}" ) if address in self.altFunc.keys(): func, argc, balance = self.altFunc[address] try: sp = uc.reg_read(self.REG_SP) if self.REG_RA is None: RA = unpack(self.pack_fmt, str(uc.mem_read(sp, self.step)))[0] sp += self.step else: RA = uc.reg_read(self.REG_RA) args = [] i = 0 while i < argc and i < len(self.REG_ARGS): args.append(uc.reg_read(self.REG_ARGS[i])) i += 1 sp2 = sp while i < argc: args.append( unpack(self.pack_fmt, str(uc.mem_read(sp2, self.step)))[0]) sp2 += self.step i += 1 res = func(self, uc, args) if type(res) != int: res = 0 uc.reg_write(self.REG_RES, res) uc.reg_write(self.REG_PC, RA) if balance: uc.reg_write(self.REG_SP, sp2) else: uc.reg_write(self.REG_SP, sp) except Exception as e: self._add_trace("alt exception: %s" % e)
def _data(cls, offset): flow_chart = ida_gdl.FlowChart(ida_funcs.get_func(offset)) nodes = {} for node in flow_chart: assembly = [ ida_lines.generate_disasm_line(ea) for ea in idautils.Heads(node.startEA, node.endEA) ] successive_nodes = [succ.id for succ in node.succs()] serialized_node = { 'id': node.id, 'type': node.type, 'start': node.startEA, 'end': node.endEA, 'successive': successive_nodes, 'assembly': assembly } nodes[node.id] = serialized_node return nodes
def on_get_annotations(self, address, size, mouse_offs): item_ea = get_item_head(address + mouse_offs) cursor_ea = address + mouse_offs name = get_name(item_ea) if len(name): name = "(%s)" % name else: name = "" ann = [ (item_ea, self.red[0], "Item: %X" % (item_ea), self.colormap[-1]), (None, None, " Size: %d %s" % (get_item_size(get_item_head(cursor_ea)), name), self.colormap[-3]), (cursor_ea, self.colormap[-1], "Cursor: %X" % (cursor_ea), self.colormap[-1]), (None, None, " %s" % generate_disasm_line( cursor_ea, GENDSM_FORCE_CODE | GENDSM_REMOVE_TAGS), self.colormap[-3]), (None, None, " Value: %02X" % get_byte(cursor_ea), self.colormap[-3]), ] return ann
def disasm(ea): return ida_lines.tag_remove(ida_lines.generate_disasm_line(ea))