from __future__ import print_function from builtins import map import idaapi from idc import * from miasm.analysis.machine import Machine from miasm.ir.translators import Translator import miasm.expression.expression as m2_expr def guess_machine(addr=None): "Return an instance of Machine corresponding to the IDA guessed processor" processor_name = get_inf_attr(INF_PROCNAME) info = idaapi.get_inf_structure() if info.is_64bit(): size = 64 elif info.is_32bit(): size = 32 else: size = None if processor_name == "metapc": size2machine = { 64: "x86_64", 32: "x86_32", None: "x86_16", } machine = Machine(size2machine[size]) elif processor_name == "ARM": # TODO ARM/thumb # hack for thumb: set armt = True in globals :/ # set bigendiant = True is bigendian # Thumb, size, endian info2machine = {(True, 32, True): "armtb", (True, 32, False): "armtl", (False, 32, True): "armb", (False, 32, False): "arml", (False, 64, True): "aarch64b", (False, 64, False): "aarch64l", } # Get T reg to detect arm/thumb function # Default is arm is_armt = False if addr is not None: t_reg = get_sreg(addr, "T") is_armt = t_reg == 1 is_bigendian = info.is_be() infos = (is_armt, size, is_bigendian) if not infos in info2machine: raise NotImplementedError('not fully functional') machine = Machine(info2machine[infos]) from miasm.analysis.disasm_cb import guess_funcs, guess_multi_cb from miasm.analysis.disasm_cb import arm_guess_subcall, arm_guess_jump_table guess_funcs.append(arm_guess_subcall) guess_funcs.append(arm_guess_jump_table) elif processor_name == "msp430": machine = Machine("msp430") elif processor_name == "mipsl": machine = Machine("mips32l") elif processor_name == "mipsb": machine = Machine("mips32b") elif processor_name == "PPC": machine = Machine("ppc32b") else: print(repr(processor_name)) raise NotImplementedError('not fully functional') return machine class TranslatorIDA(Translator): """Translate a Miasm expression to a IDA colored string""" # Implemented language __LANG__ = "ida_w_color" def __init__(self, loc_db=None, **kwargs): super(TranslatorIDA, self).__init__(**kwargs) self.loc_db = loc_db def str_protected_child(self, child, parent): return ("(%s)" % ( self.from_expr(child)) if m2_expr.should_parenthesize_child(child, parent) else self.from_expr(child) ) def from_ExprInt(self, expr): return idaapi.COLSTR(str(expr), idaapi.SCOLOR_NUMBER) def from_ExprId(self, expr): out = idaapi.COLSTR(str(expr), idaapi.SCOLOR_REG) return out def from_ExprLoc(self, expr): if self.loc_db is not None: out = self.loc_db.pretty_str(expr.loc_key) else: out = str(expr) out = idaapi.COLSTR(out, idaapi.SCOLOR_REG) return out def from_ExprMem(self, expr): ptr = self.from_expr(expr.ptr) size = idaapi.COLSTR('@' + str(expr.size), idaapi.SCOLOR_RPTCMT) out = '%s[%s]' % (size, ptr) return out def from_ExprSlice(self, expr): base = self.from_expr(expr.arg) start = idaapi.COLSTR(str(expr.start), idaapi.SCOLOR_RPTCMT) stop = idaapi.COLSTR(str(expr.stop), idaapi.SCOLOR_RPTCMT) out = "(%s)[%s:%s]" % (base, start, stop) return out def from_ExprCompose(self, expr): out = "{" out += ", ".join(["%s, %s, %s" % (self.from_expr(subexpr), idaapi.COLSTR(str(idx), idaapi.SCOLOR_RPTCMT), idaapi.COLSTR(str(idx + subexpr.size), idaapi.SCOLOR_RPTCMT)) for idx, subexpr in expr.iter_args()]) out += "}" return out def from_ExprCond(self, expr): cond = self.str_protected_child(expr.cond, expr) src1 = self.from_expr(expr.src1) src2 = self.from_expr(expr.src2) out = "%s?(%s,%s)" % (cond, src1, src2) return out def from_ExprOp(self, expr): if expr._op == '-': # Unary minus return '-' + self.str_protected_child(expr._args[0], expr) if expr.is_associative() or expr.is_infix(): return (' ' + expr._op + ' ').join([self.str_protected_child(arg, expr) for arg in expr._args]) return (expr._op + '(' + ', '.join( self.from_expr(arg) for arg in expr._args ) + ')') def from_ExprAssign(self, expr): return "%s = %s" % tuple(map(expr.from_expr, (expr.dst, expr.src))) def expr2colorstr(expr, loc_db): """Colorize an Expr instance for IDA @expr: Expr instance to colorize @loc_db: LocationDB instance """ translator = TranslatorIDA(loc_db=loc_db) return translator.from_expr(expr) class translatorForm(idaapi.Form): """Translator Form. Offer a ComboBox with available languages (ie. IR translators) and the corresponding translation.""" flags = (idaapi.Form.MultiLineTextControl.TXTF_FIXEDFONT | \ idaapi.Form.MultiLineTextControl.TXTF_READONLY) def __init__(self, expr): "@expr: Expr instance" # Init self.languages = list(Translator.available_languages()) self.expr = expr # Initial translation text = Translator.to_language(self.languages[0]).from_expr(self.expr) # Create the Form idaapi.Form.__init__(self, r"""STARTITEM 0 Python Expression {FormChangeCb} """, { 'result': idaapi.Form.MultiLineTextControl(text=text, flags=translatorForm.flags), 'cbLanguage': idaapi.Form.DropdownListControl( items=self.languages, readonly=True, selval=0), 'FormChangeCb': idaapi.Form.FormChangeCb(self.OnFormChange), }) def OnFormChange(self, fid): if fid == self.cbLanguage.id: # Display the Field (may be hide) self.ShowField(self.result, True) # Translate the expression dest_lang = self.languages[self.GetControlValue(self.cbLanguage)] try: text = Translator.to_language(dest_lang).from_expr(self.expr) except Exception as error: self.ShowField(self.result, False) return -1 # Update the form self.SetControlValue(self.result, idaapi.textctrl_info_t(text=str(text), flags=translatorForm.flags)) return 1