Files
2020-05-27 14:34:02 +02:00

208 lines
6.9 KiB
Python

import sys
import ida_pro
import ida_funcs
import ida_lumina
import ida_typeinf
import ida_bytes
import idautils
dquot_escaped_str = ida_pro.str2user
if sys.version_info.major >= 3:
int_types = [int]
else:
int_types = [int, long]
def escaped_bytestr(bts):
return "".join(map(lambda b: "\\x%02X" % ord(b), bts))
class func_md_t:
def __init__(self, pfn, retrieve=True):
if type(pfn) in int_types:
pfn = ida_funcs.get_func(pfn)
self.pfn_ea = pfn.start_ea
self.func_info = ida_lumina.func_info_t()
if retrieve:
funcsize, self.sig = ida_lumina.calc_func_metadata(self.func_info, pfn)
def pfn(self):
return ida_funcs.get_func(self.pfn_ea)
class idb_md_t:
def __init__(self):
# take a snapshot right away
self.functions = []
for ea in idautils.Functions():
self.functions.append(func_md_t(ea))
class differ_t:
def __init__(self, flags=0):
self.flags = flags
self.lines = []
self.pfn_ea = None
def put(self, line):
self.lines.append(line)
def on_function_diff_start(self, pfn_ea):
pass
def on_score_changed(self, pfn, was, now):
pass
def on_func_name_changed(self, pfn, was, now):
pass
def on_func_proto_changed(self, pfn, was, now):
pass
def on_func_cmt_changed(self, pfn, was, now, rep):
pass
def on_cmt_changed(self, ea, was, now, rep):
pass
def on_extra_cmt_changed(self, ea, was, now, is_prev):
pass
def on_user_stkpnt_changed(self, ea, was, now):
pass
def on_frame_mem_changed(self, offset, was, now):
pass
def on_insn_ops_repr_changed(self, ea, was, now):
pass
def diff_function(self, left, right):
assert(left.pfn_ea == right.pfn_ea)
self.pfn_ea = left.pfn_ea
self.on_function_diff_start(left.pfn_ea)
class trampoline_t(ida_lumina.func_md_diff_handler_t):
def __init__(self, pfn, differ):
ida_lumina.func_md_diff_handler_t.__init__(self)
self.pfn = pfn
self.differ = differ
def _toea(self, fchunk_nr, fchunk_off):
site = ida_lumina.insn_site_t()
site.fchunk_nr = fchunk_nr
site.fchunk_off = fchunk_off
return site.toea(self.pfn)
def on_score_changed(self, l, r):
self.differ.on_score_changed(self.pfn, l, r)
def on_name_changed(self, l, r):
self.differ.on_func_name_changed(self.pfn, l, r)
def on_proto_changed(self, l, r):
ltif, rtif = ida_typeinf.tinfo_t(), ida_typeinf.tinfo_t()
self.differ.on_func_proto_changed(
self.pfn,
ltif if ltif.deserialize(None, l.type, l.fields) else None,
rtif if rtif.deserialize(None, r.type, r.fields) else None)
def on_function_comment_changed(self, l, r, rep):
self.differ.on_func_cmt_changed(self.pfn, l, r, rep)
def on_comment_changed(self, fchunk_nr, fchunk_off, l, r, rep):
ea = self._toea(fchunk_nr, fchunk_off)
self.differ.on_cmt_changed(ea, l, r, rep)
def on_extra_comment_changed(self, fchunk_nr, fchunk_off, l, r, is_prev):
ea = self._toea(fchunk_nr, fchunk_off)
self.differ.on_extra_cmt_changed(ea, l, r, is_prev)
def on_user_stkpnt_changed(self, fchunk_nr, fchunk_off, l, r):
ea = self._toea(fchunk_nr, fchunk_off)
self.differ.on_user_stkpnt_changed(ea, l, r)
def on_frame_member_changed(self, offset, l, r):
self.differ.on_frame_mem_changed(offset, l, r)
def on_insn_ops_repr_changed(self, fchunk_nr, fchunk_off, l, r):
ea = self._toea(fchunk_nr, fchunk_off)
self.differ.on_insn_ops_repr_changed(ea, l, r)
trampoline = trampoline_t(left.pfn(), self)
ida_lumina.diff_metadata(
trampoline,
left.func_info,
right.func_info,
self.flags)
class diff2script_t(differ_t):
def on_function_diff_start(self, pfn_ea):
self.put("pfn = ida_funcs.get_func(0x%x)" % pfn_ea)
def on_func_name_changed(self, pfn, was, now):
raise Exception("unimp!")
def on_func_proto_changed(self, pfn, was, now):
raise Exception("unimp!")
def on_func_cmt_changed(self, pfn, was, now, rep):
self.put("""ida_funcs.set_func_cmt(pfn, "%s", %s)""" % (
dquot_escaped_str(now or ''),
rep))
def on_cmt_changed(self, ea, was, now, rep):
self.put("""ida_bytes.set_cmt(0x%x, "%s", %s)""" % (
ea,
dquot_escaped_str(now or ''),
rep))
def on_extra_cmt_changed(self, ea, was, now, is_prev):
raise Exception("unimp!")
def on_user_stkpnt_changed(self, ea, was, now):
if now is not None:
self.put("""ida_frame.add_user_stkpnt(0x%x, %s)""" % (ea, hex(now)))
else:
self.put("""ida_frame.del_stkpnt(pfn, 0x%x)""" % (ea,))
def on_frame_mem_changed(self, offset, was, now):
put = self.put
put("""ida_struct.del_struc_member(frame, 0x%x)""" % offset)
if now:
put("""opinfo = None""")
put("""tif = ida_typeinf.tinfo_t()""")
if now.type.type:
put("""if tif.deserialize(None, "%s", "%s"):""" % (
escaped_bytestr(now.type.type),
escaped_bytestr(now.type.fields)))
put(""" ok, size, flags, opinfo, alsize = ida_typeinf.get_idainfo_by_type(tif)""")
elif ida_bytes.is_off0(now.flags):
put("""opinfo = ida_nalt.opinfo_t()""")
put("""opinfo.ri.target = 0x%x""" % now.opinfo.ri.target)
put("""opinfo.ri.base = 0x%x""" % now.opinfo.ri.base)
put("""opinfo.ri.tdelta = 0x%x""" % now.opinfo.ri.tdelta)
put("""opinfo.ri.flags = 0x%x""" % now.opinfo.ri.flags)
put("""ida_struct.add_struc_member(frame, "%s", 0x%x, 0x%x, opinfo, %d)""" % (
dquot_escaped_str(now.name),
offset,
now.info.flags,
now.nbytes))
put("""mptr = ida_struct.get_member(frame, 0x%x)""" % offset)
put("""if not tif.empty():""")
put(""" ida_struct.set_member_tinfo(frame, mptr, 0, tif, ida_struct.SET_MEMTI_USERTI)""")
put(""" ida_nalt.set_userti(mptr.id)""")
if now.cmt:
put("""ida_struct.set_member_cmt(mptr, "%s", False)""" % dquot_escaped_str(now.cmt))
if now.rptcmt:
put("""ida_struct.set_member_cmt(mptr, "%s", True)""" % dquot_escaped_str(now.rptcmt))
def on_insn_ops_repr_changed(self, ea, was, now):
raise Exception("Unimp")