mirror of
https://github.com/cea-sec/miasm
synced 2026-06-21 13:48:18 +00:00
199 lines
6.7 KiB
Python
199 lines
6.7 KiB
Python
import idaapi
|
|
from idc import *
|
|
|
|
from miasm2.analysis.machine import Machine
|
|
from miasm2.ir.translators import Translator
|
|
import miasm2.expression.expression as m2_expr
|
|
|
|
def guess_machine():
|
|
"Return an instance of Machine corresponding to the IDA guessed processor"
|
|
|
|
processor_name = GetLongPrm(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",
|
|
}
|
|
is_armt = globals().get('armt', False)
|
|
is_bigendian = globals().get('bigendian', False)
|
|
infos = (is_armt, size, is_bigendian)
|
|
if not infos in info2machine:
|
|
raise NotImplementedError('not fully functional')
|
|
machine = Machine(info2machine[infos])
|
|
|
|
from miasm2.analysis.disasm_cb import guess_funcs, guess_multi_cb
|
|
from miasm2.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, regs_ids=None, **kwargs):
|
|
super(TranslatorIDA, self).__init__(**kwargs)
|
|
if regs_ids is None:
|
|
regs_ids = {}
|
|
self.regs_ids = regs_ids
|
|
|
|
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 = str(expr)
|
|
if expr in self.regs_ids:
|
|
out = idaapi.COLSTR(out, idaapi.SCOLOR_REG)
|
|
return out
|
|
|
|
def from_ExprMem(self, expr):
|
|
ptr = self.from_expr(expr.arg)
|
|
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_ExprAff(self, expr):
|
|
return "%s = %s" % tuple(map(expr.from_expr, (expr.dst, expr.src)))
|
|
|
|
|
|
|
|
def expr2colorstr(regs_ids, expr):
|
|
"""Colorize an Expr instance for IDA
|
|
@regs_ids: list of ExprId corresponding to available registers
|
|
@expr: Expr instance to colorize
|
|
"""
|
|
|
|
translator = TranslatorIDA(regs_ids)
|
|
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}
|
|
<Language:{cbLanguage}>
|
|
<Translation:{result}>
|
|
""", {
|
|
'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, 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
|