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 _process(self): cf = self.vu.cfunc ci = ida_hexrays.ctree_item_t() ccode = cf.get_pseudocode() for ypos in range(cf.hdrlines, len(ccode)): tline = ccode.at(ypos).line # TODO: optimize the following loop idx = 0 while idx < len(tline): citem_len = 0 # get all items on a line if cf.get_line_item(tline, idx, True, None, ci, None): iea = ci.it.ea if iea != BADADDR: # generate color-tagged/addr-tagged text of current item citem = ci.it.print1(None) citem_len = len(ida_lines.tag_remove(citem)) # find (tagged) item text in current line pos = tline.find(citem) while pos != -1: # calculate x position of item text in line # by subtracting the number of color tag # characters up to position "pos" xpos = len(ida_lines.tag_remove(tline[:pos])) self._add_item(iea, xpos, ypos, citem_len) pos = tline.find(citem, pos + citem_len) idx += ida_lines.tag_advance(tline[idx], 1) return
def __init__(self, text="", parent=None): self._text = ida_lines.tag_remove(text) self._tagged_text = text # public attributes self.parent = parent self.address = ida_idaapi.BADADDR
def query(q, ea_list=None, full=False, fmt=lambda x: "%x: %s" % (x.ea, ida_lines.tag_remove(x.print1(None)))): """run query on list of addresses, print results arguments: q: lambda/function: f(cfunc_t, citem_t) returning a bool ea_list: iterable of addresses/functions to process full: False -> find cexpr_t only (faster but doesn't find cinsn_t items) True -> find citem_t elements, which includes cexpr_t and cinsn_t fmt: lambda/callback-function to be called for formatting output """ if not ea_list: ea_list = [ida_kernwin.get_screen_ea()] r = exec_query(q, ea_list=ea_list, full=full) print("<query> done! %d unique hits." % len(r)) try: for e in r: print(fmt(e)) except: print("<query> error!") return
def parse_table(ea): table = u64(idc.get_bytes(ea, 8)) addr = table func_table = [] while True: pm4type, opcode, handler = read_entry(addr) if handler == 0: break # get gnm name and packet count gnm_name, packet_count = parse_function(handler) # decompile the handler func = ida_hexrays.decompile(handler) lines = func.get_pseudocode() code_lines = [] for sline in lines: line = ida_lines.tag_remove(sline.line) code_lines.append(line) print('{}\t{} {} {:X} {:08X}'.format(gnm_name, packet_count, pm4type, opcode, handler)) if not gnm_name: gnm_name = 'sub_{:X}'.format(handler) func_table.append( (gnm_name, packet_count, pm4type, opcode, handler, code_lines)) addr += 16 return func_table
def _update(self, vu): if vu: focus = None if vu.get_current_item(ida_hexrays.USE_MOUSE): focus = vu.item.e if vu.item.is_citem() else None _ea = _exp = _type = _objid = "???" if vu.get_current_item(ida_hexrays.USE_MOUSE): item = vu.item.it isexpr = item.is_expr() item_type = ida_hexrays.get_ctype_name(item.op) if isexpr: _exp = item.cexpr.print1(None) _exp = ida_lines.tag_remove(_exp) _ea = "%x" % item.ea _type = "c%ct_%s" % ("o" if isexpr else "i", item_type) _objid = "%x" % item.obj_id self.SetControlValue(self.lbl_ea, _ea) self.SetControlValue(self.lbl_exp, _exp) self.SetControlValue(self.lbl_op, _type) self.SetControlValue(self.lbl_objid, _objid) gd = graph_dumper_t() gd.apply_to(vu.cfunc.body if not focus else focus, vu.cfunc.body) expr = "(%s)" % " and\n".join(gd.lines) tc = self.GetControlValue(self.mstr_pexp) tc.text = expr self.SetControlValue(self.mstr_pexp, tc) self.SetControlValue(self.lbl_sea, "%x" % ida_kernwin.get_screen_ea()) return
def process_erasures(self, mba): self.performed_erasures_global.extend(self.deferred_erasures_local) for erase in self.deferred_erasures_local: import ida_lines self.report_info("Erasing %08X: %s" % (erase.ins_mov.ea, ida_lines.tag_remove(erase.ins_mov._print()))) # Be gone, sucker mba.get_mblock(erase.block).make_nop(erase.ins_mov) self.deferred_erasures_local = []
def cstr(self): """ Property which return the C code corresponding to the decompilation of this :class:`CNode` as a onliner. This will include the children of this object. :return str: The human readable C string corresponding to this :class:`CNode` as a onliner. """ s = self._citem.print1(self._hxcfunc._cfunc.__ref__()) return ida_pro.str2user(ida_lines.tag_remove(s))
def matches(ea, reqs, gets): results = [] for offs, ins in reqs: mnem = ida_lines.tag_remove(ida_ua.print_insn_mnem(ea + offs) or '') if ins[0] != mnem: return None i = 0 for arg in ins[1:]: opnd = ida_lines.tag_remove( ida_ua.print_operand(ea + offs, i) or '') if opnd != arg and re.match('^' + arg + '$', opnd) is None: return None i += 1 for get in gets: if type(get) == tuple: reqi, opi, fun = get results += [fun(idc.get_operand_value(ea + reqs[reqi][0], opi))] else: results += [get] return results
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 OnKeydown(self, vkey, shift): if shift == 0 and vkey == ord("G"): microcode_graphviewer_t(self._mba, self.title).Show() return True elif shift == 0 and vkey == ord("I"): widget = self.GetWidget() line = kw.get_custom_viewer_curline(widget, False) line = ida_lines.tag_remove(line) if '.' in line: block, serial = line.split('.')[:2] serial = serial.strip().split(' ')[0] microcode_insnviewer_t(self._mba, self.mmat_name, self.fn_name, int(block), int(serial)).Show() return True return False
def query_db(q, full=False, fmt=lambda x: "%x: %s" % (x.ea, ida_lines.tag_remove(x.print1(None)))): """run query on idb, print results arguments: q: lambda/function: f(cfunc_t, citem_t) returning a bool full: False -> find cexpr_t only (faster but doesn't find cinsn_t items) True -> find citem_t elements, which includes cexpr_t and cinsn_t fmt: lambda/callback-function to be called for formatting output """ return query(q, ea_list=idautils.Functions(), full=full, fmt=fmt)
def __init__(self, cfunc=None, i=None): if isinstance(cfunc, hx.cfuncptr_t): self.entry = cfunc.entry_ea elif isinstance(cfunc, int): self.entry = cfunc else: self.entry = BADADDR if isinstance(i, (hx.cexpr_t, hx.cinsn_t)): self.ea = i.ea if not isinstance(cfunc, hx.cfuncptr_t) else self.find_closest_address(cfunc, i) self.v = ida_lines.tag_remove(i.print1(None)) elif isinstance(i, tuple): self.ea, self.v = i else: self.ea = BADADDR self.v = "<undefined>"
def OnKeydown(self, vkey, shift): if shift == 0 and vkey == ord("G"): MCGraphView(self._mba, self._func, self._mmat).Show() return True elif shift == 0 and vkey == ord("I"): widget = self.GetWidget() line = ida_kernwin.get_custom_viewer_curline(widget, False) line = ida_lines.tag_remove(line) if '.' in line: block, serial = line.split('.')[:2] serial = serial.strip().split(' ')[0] MCInsnView(self._mba, self._func, self._mmat, int(block), int(serial)).Show() return True return False
def display(f, fmt=lambda x: "%x: %s" % (x.ea, ida_lines.tag_remove(x.print1(None)))): """execute function f and print results according to fmt. arguments: f: function that is expected to return a list of citem_t/cexpr_t objects fmt: lambda/callback-function to be called for formatting output """ try: for e in f(): print(fmt(e)) except Exception as exc: print("<display> error!:", exc) return
def _apply_query_filter(self, vu, pc): new_pc = [] title = kw.get_widget_title(vu.ct) if title in TEXT_INPUT_FORMS.keys() and pc: sq = TEXT_INPUT_FORMS[title] query = sq.query options = sq.options case_sensitive = options & TextInputForm.SO_FIND_CASE # TODO if options & TextInputForm.SO_FIND_TEXT: kw.set_highlight(vu.ct, query, HL_FLAGS) tmpquery = query.lower() if not case_sensitive else query for sl in pc: haystack = il.tag_remove(sl.line).lstrip().rstrip() haystack = haystack.lower( ) if not case_sensitive else haystack if tmpquery in haystack: new_pc.append(sl.line) else: if options & TextInputForm.SO_FILTER_COLOR: # add line but remove color new_pc.append(self._remove_color_tags(sl.line)) elif options & TextInputForm.SO_FILTER_TEXT: # do not add non-matching text pass elif options & TextInputForm.SO_FIND_REGEX: kw.set_highlight(vu.ct, None, 0) for sl in pc: try: if self._search(query, sl, case_sensitive): new_pc.append(sl.line) else: if options & TextInputForm.SO_FILTER_COLOR: new_pc.append(self._remove_color_tags(sl.line)) elif options & TextInputForm.SO_FILTER_TEXT: # do not add non-matching text pass except re.error as error: kw.msg("%s: %s: \"%s\"" % (PLUGIN_NAME, error, query)) return pc.clear() sl = kw.simpleline_t() for line in new_pc: sl.line = line pc.push_back(sl) return
def _process_lines(self, lines): self._blockcmts = {} curblk = "-1" self._blockcmts[curblk] = [] for i, line in enumerate(lines): plain_line = ida_lines.tag_remove(line).lstrip() if plain_line.startswith(';'): # msg("%s" % plain_line) re_ret = re.findall("BLOCK ([0-9]+) ", plain_line) if len(re_ret) > 0: curblk = re_ret[0] self._blockcmts[curblk] = [line] else: self._blockcmts[curblk].append(line) if "0" in self._blockcmts: self._blockcmts["0"] = self._blockcmts["-1"] + self._blockcmts["0"] del self._blockcmts["-1"]
def get_decompiled_func(): f = ida_funcs.get_func(ida_kernwin.get_screen_ea()) if f is None: Util.clear_output_window() print("[SPIRIT] Please position the cursor within a function") return True cfunc = ida_hexrays.decompile(f) if cfunc is None: Util.clear_output_window() print("[SPIRIT] Failed to decompile!") return True sb = cfunc.get_pseudocode() function_arr = [] for line in sb: function_arr.append(ida_lines.tag_remove(line.line)) return function_arr
def __init__(self, q, ea_list=None, full=False, fmt=lambda x:"%x: %s" % (x.ea, ida_lines.tag_remove(x.print1(None))), flags=ida_kernwin.CH_RESTORE | ida_kernwin.CH_QFLT, width=None, height=None, embedded=False, modal=False): ida_kernwin.Choose.__init__( self, "Hexrays Toolbox", [ ["List of results", 60]], flags = flags, width = width, height = height, embedded = embedded) if ea_list is None: ea_list =[ida_kernwin.get_screen_ea()] self.items = exec_query(q, ea_list, full) self.fmt = fmt self.Show()
def find_forward_numeric_def(blk, mop): ml = mlist_t() if not insert_op(blk, ml, mop): return False, None, None # Find a forward definition assign_insn = my_find_def_forwards(blk, ml, None) if assign_insn: hexrays_util.report_info3("Forward search found %s" % ida_lines.tag_remove(assign_insn._print())) # We only want MOV instructions with numeric left-hand sides if assign_insn.opcode != m_mov or assign_insn.l.t != mop_n: return False, None, None # Return the numeric operand if we found it return True, assign_insn.l, assign_insn return False, None, None
def _apply_query_filter(self, vu, pc): new_pc = [] title = kw.get_widget_title(vu.ct) if title in TEXT_INPUT_FORMS.keys() and pc: sq = TEXT_INPUT_FORMS[title] query = sq.query options = sq.options # TODO if options & TextInputForm.SO_FIND_TEXT: kw.set_highlight(vu.ct, query, kw.HIF_LOCKED) for sl in pc: if query in il.tag_remove(sl.line).lstrip().rstrip(): new_pc.append(sl.line) else: if options & TextInputForm.SO_FILTER_COLOR: new_pc.append(self._remove_color_tags(sl.line)) elif options & TextInputForm.SO_FILTER_TEXT: # do not add non-matching text pass elif options & TextInputForm.SO_FIND_REGEX: kw.set_highlight(vu.ct, None, 0) for sl in pc: try: if self._search(query, sl): new_pc.append(sl.line) else: if options & TextInputForm.SO_FILTER_COLOR: new_pc.append(self._remove_color_tags(sl.line)) elif options & TextInputForm.SO_FILTER_TEXT: # do not add non-matching text pass except re.error as error: kw.msg("%s: %s: \"%s\"" % (PLUGIN_NAME, error, query)) return pc.clear() sl = kw.simpleline_t() for line in new_pc: sl.line = line pc.push_back(sl) return
def OnKeydown(self, vkey, shift): if vkey == ord("G"): g = microcode_graphviewer_t(self._mba, self.title, self.lines) if g: g.Show() self._fit_graph(g) self._dock_widgets( g, dockpos=kw.DP_FLOATING if shift else kw.DP_RIGHT) return True elif vkey == ord("I"): """TODO: at some point, the textual representation of the mba should manually be created. -> we would no longer have to parse the textual output that is created by the gen_microcode() function .> we may insert COLOR_ADDR tags which would allow us to contextually link different viewers""" widget = self.GetWidget() line = kw.get_custom_viewer_curline(widget, False) line = ida_lines.tag_remove(line) p = line.find(" ") if p != -1 and '.' in line[:p]: block, serial = line.split('.')[:2] serial = serial.strip().split(' ')[0] g = microcode_insnviewer_t(self._mba, self.mmat_name, self.fn_name, int(block), int(serial)) if g: g.Show() self._fit_graph(g) self._dock_widgets( g, dockpos=kw.DP_FLOATING if shift else kw.DP_TAB) else: message = ( "There is something wrong with the output generated by gen_microcode()!\n" "Please rerun '%s.py'!" % PLUGIN_NAME) if line.startswith(";") or not (len(line)): message = "Please position the cursor on a microcode instruction." kw.warning(message) return True return False
def main(): if not ida_hexrays.init_hexrays_plugin(): return False print("Hex-rays version %s has been detected" % ida_hexrays.get_hexrays_version()) f = ida_funcs.get_func(ida_kernwin.get_screen_ea()) if f is None: print("Please position the cursor within a function") return True cfunc = ida_hexrays.decompile(f) if cfunc is None: print("Failed to decompile!") return True sv = cfunc.get_pseudocode() for sline in sv: print(ida_lines.tag_remove(sline.line)) return True
def activate(self, ctx): if ctx.has_flag(ida_kernwin.ACF_HAS_SELECTION): tp0, tp1 = ctx.cur_sel._from, ctx.cur_sel.to ud = ida_kernwin.get_viewer_user_data(ctx.widget) lnar = ida_kernwin.linearray_t(ud) lnar.set_place(tp0.at) lines = [] while True: cur_place = lnar.get_place() first_line_ref = ida_kernwin.l_compare2(cur_place, tp0.at, ud) last_line_ref = ida_kernwin.l_compare2(cur_place, tp1.at, ud) if last_line_ref > 0: # beyond last line break line = ida_lines.tag_remove(lnar.down()) if last_line_ref == 0: # at last line line = line[0:tp1.x] elif first_line_ref == 0: # at first line line = ' ' * tp0.x + line[tp0.x:] lines.append(line) for line in lines: print(line) return 1
def find_forward_stack_var_def(cluster_head, op_copy, chain): # Must be a non-NULL stack variable if not op_copy or op_copy.t != mop_S: return None # Find the definition ok, num, ins = find_forward_numeric_def(cluster_head, op_copy) if not ok: return None hexrays_util.report_info3("Forward method found %s!" % ida_lines.tag_remove(num._print())) # If the found definition was suitable, add the assignment to the chain mi = mov_info_t() mi.op_copy = num mi.block = cluster_head.serial mi.ins_mov = ins chain.append(mi) # Return the number return num
def activate(self, ctx): # get the current item vu = ida_hexrays.get_widget_vdui(ctx.widget) vu.get_current_item(ida_hexrays.USE_KEYBOARD) # REGION1, will be referenced later # check that the current item is a union field if not vu.item.is_citem(): ida_kernwin.warning("Please position the cursor on a union member") return 0 e = vu.item.e while True: op = e.op if op != ida_hexrays.cot_memptr and op != ida_hexrays.cot_memref: ida_kernwin.warning( "Please position the cursor on a union member") return 0 e = e.x if op == ida_hexrays.cot_memptr: if e.type.is_union(): break else: if ida_typeinf.remove_pointer(e.type).is_union(): break if not e.type.is_udt(): ida_kernwin.warning( "Please position the cursor on a union member") return 0 # END REGION1 # REGION2 # calculate the member offset off = 0 e = vu.item.e while True: e2 = e.x tif = ida_typeinf.remove_pointer(e2.type) if not tif.is_union(): off += e.m e = e2 if e2.op != ida_hexrays.cot_memptr and e2.op != ida_hexrays.cot_memref: break if not e2.type.is_udt(): break # END REGION2 # REGION3 # go up and collect more member references (in order to calculate the final offset) p = vu.item.e while True: p2 = vu.cfunc.body.find_parent_of(p) if p2.op == ida_hexrays.cot_memptr: break if p2.op == ida_hexrays.cot_memref: e2 = p2.cexpr tif = ida_typeinf.remove_pointer(e2.x.type) if not tif.is_union(): off += e2.m p = p2 continue if p2.op == ida_hexrays.cot_ref: # handle &a.b + N (this expression may appear if the user previously selected # a wrong field) delta = 0 add = vu.cfunc.body.find_parent_of(p2) if add.op == ida_hexrays.cot_cast: add = vu.cfunc.body.find_parent_of(add) if add.op == ida_hexrays.cot_add and add.y.op == ida_hexrays.cot_num: delta = add.y.numval() objsize = add.type.get_ptrarr_objsize() nbytes = delta * objsize off += nbytes # we could use helpers like WORD/BYTE/... to calculate a more precise offset # if ( p2->op == cot_call && (e2->exflags & EXFL_LVALUE) != 0 ) break # END REGION3 # REGION4 ea = vu.item.e.ea # the item itself may be unaddressable. # TODO: find its addressable parent if ea == ida_idaapi.BADADDR: ida_kernwin.warning("Sorry, the current item is not addressable") return 0 # END REGION4 # REGION5 # prepare the text representation for the item, # use the neighborhoods of cursor line = ida_lines.tag_remove( ida_kernwin.get_custom_viewer_curline(vu.ct, False)) line_len = len(line) x = max(0, vu.cpos.x - 10) l = min(10, line_len - vu.cpos.x) + 10 line = line[x:x + l] # END REGION5 # REGION6 ops = ida_hexrays.ui_stroff_ops_t() op = ops.push_back() op.offset = off op.text = line # END REGION6 # REGION7 class set_union_sel_t(ida_hexrays.ui_stroff_applicator_t): def __init__(self, ea): ida_hexrays.ui_stroff_applicator_t.__init__(self) self.ea = ea def apply(self, opnum, path, top_tif, spath): typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, top_tif, '', '') ida_kernwin.msg("User selected %s of type %s\n" % (spath, typename)) if path.empty(): return False vu.cfunc.set_user_union_selection(self.ea, path) vu.cfunc.save_user_unions() return True # END REGION7 # REGION8 su = set_union_sel_t(ea) res = ida_hexrays.select_udt_by_offset(None, ops, su) if res != 0: # regenerate ctree vu.refresh_view(True) # END REGION8 return 1
def _search(self, regexp, sl): line = il.tag_remove(sl.line).lstrip().rstrip() return re.search(regexp, line) is not None
def get_expr_name(self, expr): name = expr.print1(None) name = ida_lines.tag_remove(name) name = ida_pro.str2user(name) return name
def _search(self, regexp, sl, case_sensitive=False): line = il.tag_remove(sl.line).lstrip().rstrip() return re.search(regexp, line, flags=re.I if not case_sensitive else 0) is not None
def _search(self, pattern, sl): line = il.tag_remove(sl.line).lstrip().rstrip() return re.search(pattern, line) is not None