mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
IDA Pro 6.6 support
What's new: - added the decompiler bindings - Expose simpleline_t type to IDAPython. That lets the user to set the bgcolor & text for each line in the decompilation. - Wrapped new functions from the IDA SDK Various fixes: for non-code locations, idc.GetOpnd() would create instructions instead of returning empty result - idb_event::area_cmt_changed was never received in IDB_Hooks (and descendants) - idb_event::ti_changed, and idb_event::op_ti_changed notifications were not accessible in IDAPython - op_t.value was truncated to 32 bits under IDA64. - print_tinfo() wouldn't return a valid string. - readsel2() was not usable. - read_selection() was buggy for 64-bit programs. - StructMembers() considered holes in structures, and didn't properly iterate through the whole structure definition. - There was no way to call calc_switch_cases() from IDAPython. - when using multi-select/multi-edit choosers, erroneous event codes could be sent at beginning & end of batch deletion of lines. - When, in a PluginForm#OnCreate, the layout of IDA was requested to change (for example by starting a debugging session), that PluginForm could be deleted and create an access violation. - tinfo_t objects created from IDAPython could cause an assertion failure at exit time. - Usage of IDAPython's DropdownListControl was broken.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to use the graphing functionality in Python
|
||||
# This is an example illustrating how to use the user graphing functionality
|
||||
# in Python
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
from idaapi import GraphViewer
|
||||
|
||||
+26
-27
@@ -1,27 +1,26 @@
|
||||
import idaapi
|
||||
|
||||
def main():
|
||||
if not idaapi.init_hexrays_plugin():
|
||||
return False
|
||||
|
||||
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
|
||||
|
||||
f = idaapi.get_func(idaapi.get_screen_ea());
|
||||
if f is None:
|
||||
print "Please position the cursor within a function"
|
||||
return True
|
||||
|
||||
cfunc = idaapi.decompile(f);
|
||||
if cfunc is None:
|
||||
print "Failed to decompile!"
|
||||
return True
|
||||
|
||||
sv = cfunc.get_pseudocode();
|
||||
for i in xrange(0, sv.size()):
|
||||
line = idaapi.tag_remove(str(sv[i]));
|
||||
print line
|
||||
|
||||
return True
|
||||
|
||||
if main():
|
||||
idaapi.term_hexrays_plugin();
|
||||
import idaapi
|
||||
|
||||
def main():
|
||||
if not idaapi.init_hexrays_plugin():
|
||||
return False
|
||||
|
||||
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
|
||||
|
||||
f = idaapi.get_func(idaapi.get_screen_ea());
|
||||
if f is None:
|
||||
print "Please position the cursor within a function"
|
||||
return True
|
||||
|
||||
cfunc = idaapi.decompile(f);
|
||||
if cfunc is None:
|
||||
print "Failed to decompile!"
|
||||
return True
|
||||
|
||||
sv = cfunc.get_pseudocode();
|
||||
for sline in sv:
|
||||
print idaapi.tag_remove(sline.line);
|
||||
|
||||
return True
|
||||
|
||||
if main():
|
||||
idaapi.term_hexrays_plugin();
|
||||
|
||||
+196
-196
@@ -1,196 +1,196 @@
|
||||
""" Invert the then and else blocks of a cif_t.
|
||||
|
||||
Author: EiNSTeiN_ <einstein@g3nius.org>
|
||||
|
||||
This is a rewrite in Python of the vds3 example that comes with hexrays sdk.
|
||||
|
||||
|
||||
The main difference with the original C code is that when we create the inverted
|
||||
condition object, the newly created cexpr_t instance is given to the hexrays and
|
||||
must not be freed by swig. To achieve this, we have to change the 'thisown' flag
|
||||
when appropriate. See http://www.swig.org/Doc1.3/Python.html#Python_nn35
|
||||
|
||||
"""
|
||||
|
||||
import idautils
|
||||
import idaapi
|
||||
import idc
|
||||
|
||||
import traceback
|
||||
|
||||
NETNODE_NAME = '$ hexrays-inverted-if'
|
||||
|
||||
class hexrays_callback_info(object):
|
||||
|
||||
def __init__(self):
|
||||
self.vu = None
|
||||
|
||||
self.node = idaapi.netnode()
|
||||
if not self.node.create(NETNODE_NAME):
|
||||
# node exists
|
||||
self.load()
|
||||
else:
|
||||
self.stored = []
|
||||
|
||||
return
|
||||
|
||||
def load(self):
|
||||
|
||||
self.stored = []
|
||||
|
||||
try:
|
||||
data = self.node.getblob(0, 'I')
|
||||
if data:
|
||||
self.stored = eval(data)
|
||||
print 'Invert-if: Loaded %s' % (repr(self.stored), )
|
||||
except:
|
||||
print 'Failed to load invert-if locations'
|
||||
traceback.print_exc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
def save(self):
|
||||
|
||||
try:
|
||||
self.node.setblob(repr(self.stored), 0, 'I')
|
||||
except:
|
||||
print 'Failed to save invert-if locations'
|
||||
traceback.print_exc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
def invert_if(self, cfunc, insn):
|
||||
|
||||
if insn.opname != 'if':
|
||||
return False
|
||||
|
||||
cif = insn.details
|
||||
|
||||
if not cif.ithen or not cif.ielse:
|
||||
return False
|
||||
|
||||
idaapi.qswap(cif.ithen, cif.ielse)
|
||||
cond = idaapi.cexpr_t(cif.expr)
|
||||
notcond = idaapi.lnot(cond)
|
||||
cond.thisown = 0 # the new wrapper 'notcond' now holds the reference to the cexpr_t
|
||||
|
||||
cif.expr.swap(notcond)
|
||||
|
||||
return True
|
||||
|
||||
def add_location(self, ea):
|
||||
if ea in self.stored:
|
||||
self.stored.remove(ea)
|
||||
else:
|
||||
self.stored.append(ea)
|
||||
self.save()
|
||||
return
|
||||
|
||||
def find_if_statement(self, vu):
|
||||
|
||||
vu.get_current_item(idaapi.USE_KEYBOARD)
|
||||
item = vu.item
|
||||
|
||||
if item.is_citem() and item.it.op == idaapi.cit_if and item.it.to_specific_type.cif.ielse is not None:
|
||||
return item.it.to_specific_type
|
||||
|
||||
if vu.tail.citype == idaapi.VDI_TAIL and vu.tail.loc.itp == idaapi.ITP_ELSE:
|
||||
# for tail marks, we know only the corresponding ea,
|
||||
# not the pointer to if-statement
|
||||
# find it by walking the whole ctree
|
||||
class if_finder_t(idaapi.ctree_visitor_t):
|
||||
def __init__(self, ea):
|
||||
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
|
||||
|
||||
self.ea = ea
|
||||
self.found = None
|
||||
return
|
||||
|
||||
def visit_insn(self, i):
|
||||
if i.op == idaapi.cit_if and i.ea == self.ea:
|
||||
self.found = i
|
||||
return 1 # stop enumeration
|
||||
return 0
|
||||
|
||||
iff = if_finder_t(vu.tail.loc.ea)
|
||||
if iff.apply_to(vu.cfunc.body, None):
|
||||
return iff.found
|
||||
|
||||
return
|
||||
|
||||
def invert_if_event(self, vu):
|
||||
|
||||
cfunc = vu.cfunc.__deref__()
|
||||
|
||||
i = self.find_if_statement(vu)
|
||||
if not i:
|
||||
return False
|
||||
|
||||
if self.invert_if(cfunc, i):
|
||||
vu.refresh_ctext()
|
||||
|
||||
self.add_location(i.ea)
|
||||
|
||||
return True
|
||||
|
||||
def restore(self, cfunc):
|
||||
|
||||
class visitor(idaapi.ctree_visitor_t):
|
||||
|
||||
def __init__(self, inverter, cfunc):
|
||||
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
|
||||
self.inverter = inverter
|
||||
self.cfunc = cfunc
|
||||
return
|
||||
|
||||
def visit_insn(self, i):
|
||||
try:
|
||||
if i.op == idaapi.cit_if and i.ea in self.inverter.stored:
|
||||
self.inverter.invert_if(self.cfunc, i)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return 0 # continue enumeration
|
||||
|
||||
visitor(self, cfunc).apply_to(cfunc.body, None)
|
||||
|
||||
return
|
||||
|
||||
def menu_callback(self):
|
||||
try:
|
||||
self.invert_if_event(self.vu)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return 0
|
||||
|
||||
def event_callback(self, event, *args):
|
||||
|
||||
try:
|
||||
if event == idaapi.hxe_keyboard:
|
||||
vu, keycode, shift = args
|
||||
|
||||
if idaapi.lookup_key_code(keycode, shift, True) == idaapi.get_key_code("I") and shift == 0:
|
||||
if self.invert_if_event(vu):
|
||||
return 1
|
||||
|
||||
elif event == idaapi.hxe_right_click:
|
||||
self.vu, = args
|
||||
idaapi.add_custom_viewer_popup_item(self.vu.ct, "Invert then/else", "I", self.menu_callback)
|
||||
|
||||
elif event == idaapi.hxe_maturity:
|
||||
cfunc, maturity = args
|
||||
|
||||
if maturity == idaapi.CMAT_FINAL:
|
||||
self.restore(cfunc)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
return 0
|
||||
|
||||
if idaapi.init_hexrays_plugin():
|
||||
i = hexrays_callback_info()
|
||||
idaapi.install_hexrays_callback(i.event_callback)
|
||||
else:
|
||||
print 'invert-if: hexrays is not available.'
|
||||
|
||||
""" Invert the then and else blocks of a cif_t.
|
||||
|
||||
Author: EiNSTeiN_ <einstein@g3nius.org>
|
||||
|
||||
This is a rewrite in Python of the vds3 example that comes with hexrays sdk.
|
||||
|
||||
|
||||
The main difference with the original C code is that when we create the inverted
|
||||
condition object, the newly created cexpr_t instance is given to the hexrays and
|
||||
must not be freed by swig. To achieve this, we have to change the 'thisown' flag
|
||||
when appropriate. See http://www.swig.org/Doc1.3/Python.html#Python_nn35
|
||||
|
||||
"""
|
||||
|
||||
import idautils
|
||||
import idaapi
|
||||
import idc
|
||||
|
||||
import traceback
|
||||
|
||||
NETNODE_NAME = '$ hexrays-inverted-if'
|
||||
|
||||
class hexrays_callback_info(object):
|
||||
|
||||
def __init__(self):
|
||||
self.vu = None
|
||||
|
||||
self.node = idaapi.netnode()
|
||||
if not self.node.create(NETNODE_NAME):
|
||||
# node exists
|
||||
self.load()
|
||||
else:
|
||||
self.stored = []
|
||||
|
||||
return
|
||||
|
||||
def load(self):
|
||||
|
||||
self.stored = []
|
||||
|
||||
try:
|
||||
data = self.node.getblob(0, 'I')
|
||||
if data:
|
||||
self.stored = eval(data)
|
||||
print 'Invert-if: Loaded %s' % (repr(self.stored), )
|
||||
except:
|
||||
print 'Failed to load invert-if locations'
|
||||
traceback.print_exc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
def save(self):
|
||||
|
||||
try:
|
||||
self.node.setblob(repr(self.stored), 0, 'I')
|
||||
except:
|
||||
print 'Failed to save invert-if locations'
|
||||
traceback.print_exc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
def invert_if(self, cfunc, insn):
|
||||
|
||||
if insn.opname != 'if':
|
||||
return False
|
||||
|
||||
cif = insn.details
|
||||
|
||||
if not cif.ithen or not cif.ielse:
|
||||
return False
|
||||
|
||||
idaapi.qswap(cif.ithen, cif.ielse)
|
||||
cond = idaapi.cexpr_t(cif.expr)
|
||||
notcond = idaapi.lnot(cond)
|
||||
cond.thisown = 0 # the new wrapper 'notcond' now holds the reference to the cexpr_t
|
||||
|
||||
cif.expr.swap(notcond)
|
||||
|
||||
return True
|
||||
|
||||
def add_location(self, ea):
|
||||
if ea in self.stored:
|
||||
self.stored.remove(ea)
|
||||
else:
|
||||
self.stored.append(ea)
|
||||
self.save()
|
||||
return
|
||||
|
||||
def find_if_statement(self, vu):
|
||||
|
||||
vu.get_current_item(idaapi.USE_KEYBOARD)
|
||||
item = vu.item
|
||||
|
||||
if item.is_citem() and item.it.op == idaapi.cit_if and item.it.to_specific_type.cif.ielse is not None:
|
||||
return item.it.to_specific_type
|
||||
|
||||
if vu.tail.citype == idaapi.VDI_TAIL and vu.tail.loc.itp == idaapi.ITP_ELSE:
|
||||
# for tail marks, we know only the corresponding ea,
|
||||
# not the pointer to if-statement
|
||||
# find it by walking the whole ctree
|
||||
class if_finder_t(idaapi.ctree_visitor_t):
|
||||
def __init__(self, ea):
|
||||
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
|
||||
|
||||
self.ea = ea
|
||||
self.found = None
|
||||
return
|
||||
|
||||
def visit_insn(self, i):
|
||||
if i.op == idaapi.cit_if and i.ea == self.ea:
|
||||
self.found = i
|
||||
return 1 # stop enumeration
|
||||
return 0
|
||||
|
||||
iff = if_finder_t(vu.tail.loc.ea)
|
||||
if iff.apply_to(vu.cfunc.body, None):
|
||||
return iff.found
|
||||
|
||||
return
|
||||
|
||||
def invert_if_event(self, vu):
|
||||
|
||||
cfunc = vu.cfunc.__deref__()
|
||||
|
||||
i = self.find_if_statement(vu)
|
||||
if not i:
|
||||
return False
|
||||
|
||||
if self.invert_if(cfunc, i):
|
||||
vu.refresh_ctext()
|
||||
|
||||
self.add_location(i.ea)
|
||||
|
||||
return True
|
||||
|
||||
def restore(self, cfunc):
|
||||
|
||||
class visitor(idaapi.ctree_visitor_t):
|
||||
|
||||
def __init__(self, inverter, cfunc):
|
||||
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
|
||||
self.inverter = inverter
|
||||
self.cfunc = cfunc
|
||||
return
|
||||
|
||||
def visit_insn(self, i):
|
||||
try:
|
||||
if i.op == idaapi.cit_if and i.ea in self.inverter.stored:
|
||||
self.inverter.invert_if(self.cfunc, i)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return 0 # continue enumeration
|
||||
|
||||
visitor(self, cfunc).apply_to(cfunc.body, None)
|
||||
|
||||
return
|
||||
|
||||
def menu_callback(self):
|
||||
try:
|
||||
self.invert_if_event(self.vu)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return 0
|
||||
|
||||
def event_callback(self, event, *args):
|
||||
|
||||
try:
|
||||
if event == idaapi.hxe_keyboard:
|
||||
vu, keycode, shift = args
|
||||
|
||||
if idaapi.lookup_key_code(keycode, shift, True) == idaapi.get_key_code("I") and shift == 0:
|
||||
if self.invert_if_event(vu):
|
||||
return 1
|
||||
|
||||
elif event == idaapi.hxe_right_click:
|
||||
self.vu, = args
|
||||
idaapi.add_custom_viewer_popup_item(self.vu.ct, "Invert then/else", "I", self.menu_callback)
|
||||
|
||||
elif event == idaapi.hxe_maturity:
|
||||
cfunc, maturity = args
|
||||
|
||||
if maturity == idaapi.CMAT_FINAL:
|
||||
self.restore(cfunc)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
return 0
|
||||
|
||||
if idaapi.init_hexrays_plugin():
|
||||
i = hexrays_callback_info()
|
||||
idaapi.install_hexrays_callback(i.event_callback)
|
||||
else:
|
||||
print 'invert-if: hexrays is not available.'
|
||||
|
||||
|
||||
+123
-123
@@ -1,123 +1,123 @@
|
||||
""" Print user-defined details to the output window.
|
||||
|
||||
Author: EiNSTeiN_ <einstein@g3nius.org>
|
||||
|
||||
This is a rewrite in Python of the vds4 example that comes with hexrays sdk.
|
||||
"""
|
||||
|
||||
import idautils
|
||||
import idaapi
|
||||
import idc
|
||||
|
||||
import traceback
|
||||
|
||||
def run():
|
||||
|
||||
cfunc = idaapi.decompile(idaapi.get_screen_ea())
|
||||
if not cfunc:
|
||||
print 'Please move the cursor into a function.'
|
||||
return
|
||||
|
||||
entry_ea = cfunc.entry_ea
|
||||
print "Dump of user-defined information for function at %x" % (entry_ea, )
|
||||
|
||||
# Display user defined labels.
|
||||
labels = idaapi.restore_user_labels(entry_ea);
|
||||
if labels is not None:
|
||||
print "------- %u user defined labels" % (len(labels), )
|
||||
for org_label, name in labels.iteritems():
|
||||
print "Label %d: %s" % (org_label, str(name))
|
||||
idaapi.user_labels_free(labels)
|
||||
|
||||
# Display user defined comments
|
||||
cmts = idaapi.restore_user_cmts(entry_ea);
|
||||
if cmts is not None:
|
||||
print "------- %u user defined comments" % (len(cmts), )
|
||||
for tl, cmt in cmts.iteritems():
|
||||
print "Comment at %x, preciser %x:\n%s\n" % (tl.ea, tl.itp, str(cmt))
|
||||
idaapi.user_cmts_free(cmts)
|
||||
|
||||
# Display user defined citem iflags
|
||||
iflags = idaapi.restore_user_iflags(entry_ea)
|
||||
if iflags is not None:
|
||||
print "------- %u user defined citem iflags" % (len(iflags), )
|
||||
for cl, t in iflags.iteritems():
|
||||
print "%a(%d): %08X%s" % (cl.ea, cl.op, f, " CIT_COLLAPSED" if f & CIT_COLLAPSED else "")
|
||||
idaapi.user_iflags_free(iflags)
|
||||
|
||||
# Display user defined number formats
|
||||
numforms = idaapi.restore_user_numforms(entry_ea)
|
||||
if numforms is not None:
|
||||
print "------- %u user defined number formats" % (len(numforms), )
|
||||
for ol, nf in numforms.iteritems():
|
||||
|
||||
print "Number format at %a, operand %d: %s" % (ol.ea, ol.opnum, "negated " if (nf.props & NF_NEGATE) != 0 else "")
|
||||
|
||||
if nf.isEnum():
|
||||
print "enum %s (serial %d)" % (str(nf.type_name), nf.serial)
|
||||
|
||||
elif nf.isChar():
|
||||
print "char"
|
||||
|
||||
elif nf.isStroff():
|
||||
print "struct offset %s" % (str(nf.type_name), )
|
||||
|
||||
else:
|
||||
print "number base=%d" % (idaapi.getRadix(nf.flags, ol.opnum), )
|
||||
|
||||
idaapi.user_numforms_free(numforms)
|
||||
|
||||
# Display user-defined local variable information
|
||||
# First defined the visitor class
|
||||
class dump_lvar_info_t(idaapi.user_lvar_visitor_t):
|
||||
|
||||
def __init__(self):
|
||||
idaapi.user_lvar_visitor_t.__init__(self)
|
||||
self.displayed_header = False
|
||||
return
|
||||
|
||||
def get_info_qty_for_saving(self):
|
||||
return 0
|
||||
|
||||
def get_info_for_saving(self, lv):
|
||||
return False
|
||||
|
||||
def handle_retrieved_info(self, lv):
|
||||
|
||||
try:
|
||||
if not self.displayed_header:
|
||||
self.displayed_header = True;
|
||||
print "------- User defined local variable information"
|
||||
|
||||
print "Lvar defined at %x" % (lv.ll.defea, )
|
||||
|
||||
if len(str(lv.name)):
|
||||
print " Name: %s" % (str(lv.name), )
|
||||
|
||||
if len(str(lv.type)):
|
||||
#~ print_type_to_one_line(buf, sizeof(buf), idati, .c_str());
|
||||
print " Type: %s" % (str(lv.type), )
|
||||
|
||||
if len(str(lv.cmt)):
|
||||
print " Comment: %s" % (str(lv.cmt), )
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return 0
|
||||
|
||||
def handle_retrieved_mapping(self, lm):
|
||||
return 0
|
||||
|
||||
def get_info_mapping_for_saving(self):
|
||||
return None
|
||||
|
||||
# Now iterate over all user definitions
|
||||
dli = dump_lvar_info_t();
|
||||
idaapi.restore_user_lvar_settings(entry_ea, dli)
|
||||
|
||||
return
|
||||
|
||||
|
||||
if idaapi.init_hexrays_plugin():
|
||||
run()
|
||||
else:
|
||||
print 'dump user info: hexrays is not available.'
|
||||
""" Print user-defined details to the output window.
|
||||
|
||||
Author: EiNSTeiN_ <einstein@g3nius.org>
|
||||
|
||||
This is a rewrite in Python of the vds4 example that comes with hexrays sdk.
|
||||
"""
|
||||
|
||||
import idautils
|
||||
import idaapi
|
||||
import idc
|
||||
|
||||
import traceback
|
||||
|
||||
def run():
|
||||
|
||||
cfunc = idaapi.decompile(idaapi.get_screen_ea())
|
||||
if not cfunc:
|
||||
print 'Please move the cursor into a function.'
|
||||
return
|
||||
|
||||
entry_ea = cfunc.entry_ea
|
||||
print "Dump of user-defined information for function at %x" % (entry_ea, )
|
||||
|
||||
# Display user defined labels.
|
||||
labels = idaapi.restore_user_labels(entry_ea);
|
||||
if labels is not None:
|
||||
print "------- %u user defined labels" % (len(labels), )
|
||||
for org_label, name in labels.iteritems():
|
||||
print "Label %d: %s" % (org_label, str(name))
|
||||
idaapi.user_labels_free(labels)
|
||||
|
||||
# Display user defined comments
|
||||
cmts = idaapi.restore_user_cmts(entry_ea);
|
||||
if cmts is not None:
|
||||
print "------- %u user defined comments" % (len(cmts), )
|
||||
for tl, cmt in cmts.iteritems():
|
||||
print "Comment at %x, preciser %x:\n%s\n" % (tl.ea, tl.itp, str(cmt))
|
||||
idaapi.user_cmts_free(cmts)
|
||||
|
||||
# Display user defined citem iflags
|
||||
iflags = idaapi.restore_user_iflags(entry_ea)
|
||||
if iflags is not None:
|
||||
print "------- %u user defined citem iflags" % (len(iflags), )
|
||||
for cl, t in iflags.iteritems():
|
||||
print "%a(%d): %08X%s" % (cl.ea, cl.op, f, " CIT_COLLAPSED" if f & CIT_COLLAPSED else "")
|
||||
idaapi.user_iflags_free(iflags)
|
||||
|
||||
# Display user defined number formats
|
||||
numforms = idaapi.restore_user_numforms(entry_ea)
|
||||
if numforms is not None:
|
||||
print "------- %u user defined number formats" % (len(numforms), )
|
||||
for ol, nf in numforms.iteritems():
|
||||
|
||||
print "Number format at %a, operand %d: %s" % (ol.ea, ol.opnum, "negated " if (nf.props & NF_NEGATE) != 0 else "")
|
||||
|
||||
if nf.isEnum():
|
||||
print "enum %s (serial %d)" % (str(nf.type_name), nf.serial)
|
||||
|
||||
elif nf.isChar():
|
||||
print "char"
|
||||
|
||||
elif nf.isStroff():
|
||||
print "struct offset %s" % (str(nf.type_name), )
|
||||
|
||||
else:
|
||||
print "number base=%d" % (idaapi.getRadix(nf.flags, ol.opnum), )
|
||||
|
||||
idaapi.user_numforms_free(numforms)
|
||||
|
||||
# Display user-defined local variable information
|
||||
# First defined the visitor class
|
||||
class dump_lvar_info_t(idaapi.user_lvar_visitor_t):
|
||||
|
||||
def __init__(self):
|
||||
idaapi.user_lvar_visitor_t.__init__(self)
|
||||
self.displayed_header = False
|
||||
return
|
||||
|
||||
def get_info_qty_for_saving(self):
|
||||
return 0
|
||||
|
||||
def get_info_for_saving(self, lv):
|
||||
return False
|
||||
|
||||
def handle_retrieved_info(self, lv):
|
||||
|
||||
try:
|
||||
if not self.displayed_header:
|
||||
self.displayed_header = True;
|
||||
print "------- User defined local variable information"
|
||||
|
||||
print "Lvar defined at %x" % (lv.ll.defea, )
|
||||
|
||||
if len(str(lv.name)):
|
||||
print " Name: %s" % (str(lv.name), )
|
||||
|
||||
if len(str(lv.type)):
|
||||
#~ print_type_to_one_line(buf, sizeof(buf), idati, .c_str());
|
||||
print " Type: %s" % (str(lv.type), )
|
||||
|
||||
if len(str(lv.cmt)):
|
||||
print " Comment: %s" % (str(lv.cmt), )
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return 0
|
||||
|
||||
def handle_retrieved_mapping(self, lm):
|
||||
return 0
|
||||
|
||||
def get_info_mapping_for_saving(self):
|
||||
return None
|
||||
|
||||
# Now iterate over all user definitions
|
||||
dli = dump_lvar_info_t();
|
||||
idaapi.restore_user_lvar_settings(entry_ea, dli)
|
||||
|
||||
return
|
||||
|
||||
|
||||
if idaapi.init_hexrays_plugin():
|
||||
run()
|
||||
else:
|
||||
print 'dump user info: hexrays is not available.'
|
||||
|
||||
+62
-62
@@ -1,62 +1,62 @@
|
||||
""" It demonstrates how to iterate a cblock_t object.
|
||||
|
||||
Author: EiNSTeiN_ <einstein@g3nius.org>
|
||||
|
||||
This is a rewrite in Python of the vds7 example that comes with hexrays sdk.
|
||||
"""
|
||||
|
||||
import idautils
|
||||
import idaapi
|
||||
import idc
|
||||
|
||||
import traceback
|
||||
|
||||
class cblock_visitor_t(idaapi.ctree_visitor_t):
|
||||
|
||||
def __init__(self):
|
||||
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST)
|
||||
return
|
||||
|
||||
def visit_insn(self, ins):
|
||||
|
||||
try:
|
||||
if ins.op == idaapi.cit_block:
|
||||
self.dump_block(ins.ea, ins.cblock)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
return 0
|
||||
|
||||
def dump_block(self, ea, b):
|
||||
# iterate over all block instructions
|
||||
print "dumping block %x" % (ea, )
|
||||
for ins in b:
|
||||
print " %x: insn %s" % (ins.ea, ins.opname)
|
||||
|
||||
return
|
||||
|
||||
class hexrays_callback_info(object):
|
||||
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def event_callback(self, event, *args):
|
||||
|
||||
try:
|
||||
if event == idaapi.hxe_maturity:
|
||||
cfunc, maturity = args
|
||||
|
||||
if maturity == idaapi.CMAT_BUILT:
|
||||
cbv = cblock_visitor_t()
|
||||
cbv.apply_to(cfunc.body, None)
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
return 0
|
||||
|
||||
if idaapi.init_hexrays_plugin():
|
||||
i = hexrays_callback_info()
|
||||
idaapi.install_hexrays_callback(i.event_callback)
|
||||
else:
|
||||
print 'cblock visitor: hexrays is not available.'
|
||||
""" It demonstrates how to iterate a cblock_t object.
|
||||
|
||||
Author: EiNSTeiN_ <einstein@g3nius.org>
|
||||
|
||||
This is a rewrite in Python of the vds7 example that comes with hexrays sdk.
|
||||
"""
|
||||
|
||||
import idautils
|
||||
import idaapi
|
||||
import idc
|
||||
|
||||
import traceback
|
||||
|
||||
class cblock_visitor_t(idaapi.ctree_visitor_t):
|
||||
|
||||
def __init__(self):
|
||||
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST)
|
||||
return
|
||||
|
||||
def visit_insn(self, ins):
|
||||
|
||||
try:
|
||||
if ins.op == idaapi.cit_block:
|
||||
self.dump_block(ins.ea, ins.cblock)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
return 0
|
||||
|
||||
def dump_block(self, ea, b):
|
||||
# iterate over all block instructions
|
||||
print "dumping block %x" % (ea, )
|
||||
for ins in b:
|
||||
print " %x: insn %s" % (ins.ea, ins.opname)
|
||||
|
||||
return
|
||||
|
||||
class hexrays_callback_info(object):
|
||||
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def event_callback(self, event, *args):
|
||||
|
||||
try:
|
||||
if event == idaapi.hxe_maturity:
|
||||
cfunc, maturity = args
|
||||
|
||||
if maturity == idaapi.CMAT_BUILT:
|
||||
cbv = cblock_visitor_t()
|
||||
cbv.apply_to(cfunc.body, None)
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
return 0
|
||||
|
||||
if idaapi.init_hexrays_plugin():
|
||||
i = hexrays_callback_info()
|
||||
idaapi.install_hexrays_callback(i.event_callback)
|
||||
else:
|
||||
print 'cblock visitor: hexrays is not available.'
|
||||
|
||||
+316
-319
@@ -1,319 +1,316 @@
|
||||
""" Xref plugin for Hexrays Decompiler
|
||||
|
||||
Author: EiNSTeiN_ <einstein@g3nius.org>
|
||||
|
||||
Show decompiler-style Xref when the X key is pressed in the Decompiler window.
|
||||
|
||||
- It supports any global name: functions, strings, integers, etc.
|
||||
- It supports structure member.
|
||||
|
||||
"""
|
||||
|
||||
import idautils
|
||||
import idaapi
|
||||
import idc
|
||||
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from PyQt4 import QtCore, QtGui
|
||||
print 'Using PyQt'
|
||||
except:
|
||||
print 'PyQt not available'
|
||||
|
||||
try:
|
||||
from PySide import QtGui, QtCore
|
||||
print 'Using PySide'
|
||||
except:
|
||||
print 'PySide not available'
|
||||
|
||||
XREF_EA = 0
|
||||
XREF_STRUC_MEMBER = 1
|
||||
|
||||
class XrefsForm(idaapi.PluginForm):
|
||||
|
||||
def __init__(self, target):
|
||||
|
||||
idaapi.PluginForm.__init__(self)
|
||||
|
||||
self.target = target
|
||||
|
||||
if type(self.target) == idaapi.cfunc_t:
|
||||
|
||||
self.__type = XREF_EA
|
||||
self.__ea = self.target.entry_ea
|
||||
self.__name = 'Xrefs of %x' % (self.__ea, )
|
||||
|
||||
elif type(self.target) == idaapi.cexpr_t and self.target.opname == 'obj':
|
||||
|
||||
self.__type = XREF_EA
|
||||
self.__ea = self.target.obj_ea
|
||||
self.__name = 'Xrefs of %x' % (self.__ea, )
|
||||
|
||||
elif type(self.target) == idaapi.cexpr_t and self.target.opname in ('memptr', 'memref'):
|
||||
|
||||
self.__type = XREF_STRUC_MEMBER
|
||||
name = self.get_struc_name()
|
||||
self.__name = 'Xrefs of %s' % (name, )
|
||||
|
||||
else:
|
||||
raise ValueError('cannot show xrefs for this kind of target')
|
||||
|
||||
return
|
||||
|
||||
def get_struc_name(self):
|
||||
|
||||
x = self.target.operands['x']
|
||||
m = self.target.operands['m']
|
||||
|
||||
xtype = typestring(x.type.u_str())
|
||||
xtype.remove_ptr_or_array()
|
||||
typename = str(xtype)
|
||||
|
||||
sid = idc.GetStrucIdByName(typename)
|
||||
member = idc.GetMemberName(sid, m)
|
||||
|
||||
return '%s::%s' % (typename, member)
|
||||
|
||||
def OnCreate(self, form):
|
||||
|
||||
# Get parent widget
|
||||
try:
|
||||
self.parent = self.FormToPySideWidget(form)
|
||||
except:
|
||||
self.parent = self.FormToPyQtWidget(form)
|
||||
|
||||
self.populate_form()
|
||||
|
||||
return
|
||||
|
||||
def Show(self):
|
||||
idaapi.PluginForm.Show(self, self.__name)
|
||||
return
|
||||
|
||||
def populate_form(self):
|
||||
# Create layout
|
||||
layout = QtGui.QVBoxLayout()
|
||||
|
||||
layout.addWidget(QtGui.QLabel(self.__name))
|
||||
self.table = QtGui.QTableWidget()
|
||||
layout.addWidget(self.table)
|
||||
|
||||
self.table.setColumnCount(3)
|
||||
self.table.setHorizontalHeaderItem(0, QtGui.QTableWidgetItem("Address"))
|
||||
self.table.setHorizontalHeaderItem(1, QtGui.QTableWidgetItem("Function"))
|
||||
self.table.setHorizontalHeaderItem(2, QtGui.QTableWidgetItem("Line"))
|
||||
|
||||
self.table.setColumnWidth(0, 80)
|
||||
self.table.setColumnWidth(1, 150)
|
||||
self.table.setColumnWidth(2, 450)
|
||||
|
||||
self.table.cellDoubleClicked.connect(self.double_clicked)
|
||||
|
||||
#~ self.table.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows )
|
||||
self.parent.setLayout(layout)
|
||||
|
||||
self.populate_table()
|
||||
|
||||
return
|
||||
|
||||
def double_clicked(self, row, column):
|
||||
|
||||
ea = self.functions[row]
|
||||
idaapi.open_pseudocode(ea, True)
|
||||
|
||||
return
|
||||
|
||||
def get_decompiled_line(self, cfunc, ea):
|
||||
|
||||
print repr(ea)
|
||||
if ea not in cfunc.eamap:
|
||||
print 'strange, %x is not in %x eamap' % (ea, cfunc.entry_ea)
|
||||
return
|
||||
|
||||
insnvec = cfunc.eamap[ea]
|
||||
|
||||
lines = []
|
||||
for stmt in insnvec:
|
||||
|
||||
qs = idaapi.qstring()
|
||||
qp = idaapi.qstring_printer_t(cfunc.__deref__(), qs, False)
|
||||
|
||||
stmt._print(0, qp)
|
||||
s = str(qs).split('\n')[0]
|
||||
|
||||
#~ s = idaapi.tag_remove(s)
|
||||
lines.append(s)
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
def get_items_for_ea(self, ea):
|
||||
|
||||
frm = [x.frm for x in idautils.XrefsTo(self.__ea)]
|
||||
|
||||
items = []
|
||||
for ea in frm:
|
||||
try:
|
||||
cfunc = idaapi.decompile(ea)
|
||||
cfunc.refcnt += 1
|
||||
|
||||
self.functions.append(cfunc.entry_ea)
|
||||
self.items.append((ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, ea)))
|
||||
|
||||
except Exception as e:
|
||||
print 'could not decompile: %s' % (str(e), )
|
||||
raise
|
||||
|
||||
return
|
||||
|
||||
def get_items_for_type(self):
|
||||
|
||||
x = self.target.operands['x']
|
||||
m = self.target.operands['m']
|
||||
|
||||
xtype = typestring(x.type.u_str())
|
||||
xtype.remove_ptr_or_array()
|
||||
typename = str(xtype)
|
||||
|
||||
addresses = []
|
||||
for ea in idautils.Functions():
|
||||
|
||||
try:
|
||||
cfunc = idaapi.decompile(ea)
|
||||
cfunc.refcnt += 1
|
||||
except:
|
||||
print 'Decompilation of %x failed' % (ea, )
|
||||
continue
|
||||
|
||||
str(cfunc)
|
||||
|
||||
for citem in cfunc.treeitems:
|
||||
citem = citem.to_specific_type
|
||||
if not (type(citem) == idaapi.cexpr_t and citem.opname in ('memptr', 'memref')):
|
||||
continue
|
||||
|
||||
_x = citem.operands['x']
|
||||
_m = citem.operands['m']
|
||||
_xtype = typestring(_x.type.u_str())
|
||||
_xtype.remove_ptr_or_array()
|
||||
_typename = str(_xtype)
|
||||
|
||||
#~ print 'in', hex(cfunc.entry_ea), _typename, _m
|
||||
|
||||
if not (_typename == typename and _m == m):
|
||||
continue
|
||||
|
||||
parent = citem
|
||||
while parent:
|
||||
if type(parent.to_specific_type) == idaapi.cinsn_t:
|
||||
break
|
||||
parent = cfunc.body.find_parent_of(parent)
|
||||
|
||||
if not parent:
|
||||
print 'cannot find parent statement (?!)'
|
||||
continue
|
||||
|
||||
if parent.ea in addresses:
|
||||
continue
|
||||
|
||||
if parent.ea == idaapi.BADADDR:
|
||||
print 'parent.ea is BADADDR'
|
||||
continue
|
||||
|
||||
addresses.append(parent.ea)
|
||||
|
||||
self.functions.append(cfunc.entry_ea)
|
||||
self.items.append((parent.ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, int(parent.ea))))
|
||||
|
||||
|
||||
return []
|
||||
|
||||
def populate_table(self):
|
||||
|
||||
self.functions = []
|
||||
self.items = []
|
||||
|
||||
if self.__type == XREF_EA:
|
||||
self.get_items_for_ea(self.__ea)
|
||||
else:
|
||||
self.get_items_for_type()
|
||||
|
||||
self.table.setRowCount(len(self.items))
|
||||
|
||||
i = 0
|
||||
for item in self.items:
|
||||
address, func, line = item
|
||||
item = QtGui.QTableWidgetItem('0x%x' % (address, ))
|
||||
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
|
||||
self.table.setItem(i, 0, item)
|
||||
item = QtGui.QTableWidgetItem(func)
|
||||
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
|
||||
self.table.setItem(i, 1, item)
|
||||
item = QtGui.QTableWidgetItem(line)
|
||||
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
|
||||
self.table.setItem(i, 2, item)
|
||||
|
||||
i += 1
|
||||
|
||||
self.table.resizeRowsToContents()
|
||||
|
||||
return
|
||||
|
||||
def OnClose(self, form):
|
||||
pass
|
||||
|
||||
class hexrays_callback_info(object):
|
||||
|
||||
def __init__(self):
|
||||
self.vu = None
|
||||
return
|
||||
|
||||
def show_xrefs(self, vu):
|
||||
|
||||
vu.get_current_item(idaapi.USE_KEYBOARD)
|
||||
item = vu.item
|
||||
|
||||
sel = None
|
||||
if item.citype == idaapi.VDI_EXPR and item.it.to_specific_type.opname in ('obj', 'memref', 'memptr'):
|
||||
# if an expression is selected. verify that it's either a cot_obj, cot_memref or cot_memptr
|
||||
sel = item.it.to_specific_type
|
||||
|
||||
elif item.citype == idaapi.VDI_FUNC:
|
||||
# if the function itself is selected, show xrefs to it.
|
||||
sel = item.f
|
||||
else:
|
||||
return False
|
||||
|
||||
form = XrefsForm(sel)
|
||||
form.Show()
|
||||
return True
|
||||
|
||||
def menu_callback(self):
|
||||
self.show_xrefs(self.vu)
|
||||
return 0
|
||||
|
||||
def event_callback(self, event, *args):
|
||||
|
||||
try:
|
||||
if event == idaapi.hxe_keyboard:
|
||||
vu, keycode, shift = args
|
||||
|
||||
if idaapi.lookup_key_code(keycode, shift, True) == idaapi.get_key_code("X") and shift == 0:
|
||||
if self.show_xrefs(vu):
|
||||
return 1
|
||||
|
||||
elif event == idaapi.hxe_right_click:
|
||||
self.vu = args[0]
|
||||
idaapi.add_custom_viewer_popup_item(self.vu.ct, "Xrefs", "X", self.menu_callback)
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
return 0
|
||||
|
||||
if idaapi.init_hexrays_plugin():
|
||||
i = hexrays_callback_info()
|
||||
idaapi.install_hexrays_callback(i.event_callback)
|
||||
else:
|
||||
print 'invert-if: hexrays is not available.'
|
||||
""" Xref plugin for Hexrays Decompiler
|
||||
|
||||
Author: EiNSTeiN_ <einstein@g3nius.org>
|
||||
|
||||
Show decompiler-style Xref when the X key is pressed in the Decompiler window.
|
||||
|
||||
- It supports any global name: functions, strings, integers, etc.
|
||||
- It supports structure member.
|
||||
|
||||
"""
|
||||
|
||||
import idautils
|
||||
import idaapi
|
||||
import idc
|
||||
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from PyQt4 import QtCore, QtGui
|
||||
print 'Using PyQt'
|
||||
except:
|
||||
print 'PyQt not available'
|
||||
|
||||
try:
|
||||
from PySide import QtGui, QtCore
|
||||
print 'Using PySide'
|
||||
except:
|
||||
print 'PySide not available'
|
||||
|
||||
XREF_EA = 0
|
||||
XREF_STRUC_MEMBER = 1
|
||||
|
||||
class XrefsForm(idaapi.PluginForm):
|
||||
|
||||
def __init__(self, target):
|
||||
|
||||
idaapi.PluginForm.__init__(self)
|
||||
|
||||
self.target = target
|
||||
|
||||
if type(self.target) == idaapi.cfunc_t:
|
||||
|
||||
self.__type = XREF_EA
|
||||
self.__ea = self.target.entry_ea
|
||||
self.__name = 'Xrefs of %x' % (self.__ea, )
|
||||
|
||||
elif type(self.target) == idaapi.cexpr_t and self.target.opname == 'obj':
|
||||
|
||||
self.__type = XREF_EA
|
||||
self.__ea = self.target.obj_ea
|
||||
self.__name = 'Xrefs of %x' % (self.__ea, )
|
||||
|
||||
elif type(self.target) == idaapi.cexpr_t and self.target.opname in ('memptr', 'memref'):
|
||||
|
||||
self.__type = XREF_STRUC_MEMBER
|
||||
name = self.get_struc_name()
|
||||
self.__name = 'Xrefs of %s' % (name, )
|
||||
|
||||
else:
|
||||
raise ValueError('cannot show xrefs for this kind of target')
|
||||
|
||||
return
|
||||
|
||||
def get_struc_name(self):
|
||||
|
||||
x = self.target.operands['x']
|
||||
m = self.target.operands['m']
|
||||
|
||||
xtype = x.type
|
||||
xtype.remove_ptr_or_array()
|
||||
typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '')
|
||||
|
||||
sid = idc.GetStrucIdByName(typename)
|
||||
member = idc.GetMemberName(sid, m)
|
||||
|
||||
return '%s::%s' % (typename, member)
|
||||
|
||||
def OnCreate(self, form):
|
||||
|
||||
# Get parent widget
|
||||
try:
|
||||
self.parent = self.FormToPySideWidget(form)
|
||||
except:
|
||||
self.parent = self.FormToPyQtWidget(form)
|
||||
|
||||
self.populate_form()
|
||||
|
||||
return
|
||||
|
||||
def Show(self):
|
||||
idaapi.PluginForm.Show(self, self.__name)
|
||||
return
|
||||
|
||||
def populate_form(self):
|
||||
# Create layout
|
||||
layout = QtGui.QVBoxLayout()
|
||||
|
||||
layout.addWidget(QtGui.QLabel(self.__name))
|
||||
self.table = QtGui.QTableWidget()
|
||||
layout.addWidget(self.table)
|
||||
|
||||
self.table.setColumnCount(3)
|
||||
self.table.setHorizontalHeaderItem(0, QtGui.QTableWidgetItem("Address"))
|
||||
self.table.setHorizontalHeaderItem(1, QtGui.QTableWidgetItem("Function"))
|
||||
self.table.setHorizontalHeaderItem(2, QtGui.QTableWidgetItem("Line"))
|
||||
|
||||
self.table.setColumnWidth(0, 80)
|
||||
self.table.setColumnWidth(1, 150)
|
||||
self.table.setColumnWidth(2, 450)
|
||||
|
||||
self.table.cellDoubleClicked.connect(self.double_clicked)
|
||||
|
||||
#~ self.table.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows )
|
||||
self.parent.setLayout(layout)
|
||||
|
||||
self.populate_table()
|
||||
|
||||
return
|
||||
|
||||
def double_clicked(self, row, column):
|
||||
|
||||
ea = self.functions[row]
|
||||
idaapi.open_pseudocode(ea, True)
|
||||
|
||||
return
|
||||
|
||||
def get_decompiled_line(self, cfunc, ea):
|
||||
|
||||
print repr(ea)
|
||||
if ea not in cfunc.eamap:
|
||||
print 'strange, %x is not in %x eamap' % (ea, cfunc.entry_ea)
|
||||
return
|
||||
|
||||
insnvec = cfunc.eamap[ea]
|
||||
|
||||
lines = []
|
||||
for stmt in insnvec:
|
||||
|
||||
qp = idaapi.qstring_printer_t(cfunc.__deref__(), False)
|
||||
|
||||
stmt._print(0, qp)
|
||||
s = qp.s.split('\n')[0]
|
||||
|
||||
#~ s = idaapi.tag_remove(s)
|
||||
lines.append(s)
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
def get_items_for_ea(self, ea):
|
||||
|
||||
frm = [x.frm for x in idautils.XrefsTo(self.__ea)]
|
||||
|
||||
items = []
|
||||
for ea in frm:
|
||||
try:
|
||||
cfunc = idaapi.decompile(ea)
|
||||
|
||||
self.functions.append(cfunc.entry_ea)
|
||||
self.items.append((ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, ea)))
|
||||
|
||||
except Exception as e:
|
||||
print 'could not decompile: %s' % (str(e), )
|
||||
raise
|
||||
|
||||
return
|
||||
|
||||
def get_items_for_type(self):
|
||||
|
||||
x = self.target.operands['x']
|
||||
m = self.target.operands['m']
|
||||
|
||||
xtype = x.type
|
||||
xtype.remove_ptr_or_array()
|
||||
typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '')
|
||||
|
||||
addresses = []
|
||||
for ea in idautils.Functions():
|
||||
|
||||
try:
|
||||
cfunc = idaapi.decompile(ea)
|
||||
except:
|
||||
print 'Decompilation of %x failed' % (ea, )
|
||||
continue
|
||||
|
||||
str(cfunc)
|
||||
|
||||
for citem in cfunc.treeitems:
|
||||
citem = citem.to_specific_type
|
||||
if not (type(citem) == idaapi.cexpr_t and citem.opname in ('memptr', 'memref')):
|
||||
continue
|
||||
|
||||
_x = citem.operands['x']
|
||||
_m = citem.operands['m']
|
||||
_xtype = _x.type
|
||||
_xtype.remove_ptr_or_array()
|
||||
_typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, _xtype, '', '')
|
||||
|
||||
#~ print 'in', hex(cfunc.entry_ea), _typename, _m
|
||||
|
||||
if not (_typename == typename and _m == m):
|
||||
continue
|
||||
|
||||
parent = citem
|
||||
while parent:
|
||||
if type(parent.to_specific_type) == idaapi.cinsn_t:
|
||||
break
|
||||
parent = cfunc.body.find_parent_of(parent)
|
||||
|
||||
if not parent:
|
||||
print 'cannot find parent statement (?!)'
|
||||
continue
|
||||
|
||||
if parent.ea in addresses:
|
||||
continue
|
||||
|
||||
if parent.ea == idaapi.BADADDR:
|
||||
print 'parent.ea is BADADDR'
|
||||
continue
|
||||
|
||||
addresses.append(parent.ea)
|
||||
|
||||
self.functions.append(cfunc.entry_ea)
|
||||
self.items.append((parent.ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, int(parent.ea))))
|
||||
|
||||
|
||||
return []
|
||||
|
||||
def populate_table(self):
|
||||
|
||||
self.functions = []
|
||||
self.items = []
|
||||
|
||||
if self.__type == XREF_EA:
|
||||
self.get_items_for_ea(self.__ea)
|
||||
else:
|
||||
self.get_items_for_type()
|
||||
|
||||
self.table.setRowCount(len(self.items))
|
||||
|
||||
i = 0
|
||||
for item in self.items:
|
||||
address, func, line = item
|
||||
item = QtGui.QTableWidgetItem('0x%x' % (address, ))
|
||||
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
|
||||
self.table.setItem(i, 0, item)
|
||||
item = QtGui.QTableWidgetItem(func)
|
||||
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
|
||||
self.table.setItem(i, 1, item)
|
||||
item = QtGui.QTableWidgetItem(line)
|
||||
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
|
||||
self.table.setItem(i, 2, item)
|
||||
|
||||
i += 1
|
||||
|
||||
self.table.resizeRowsToContents()
|
||||
|
||||
return
|
||||
|
||||
def OnClose(self, form):
|
||||
pass
|
||||
|
||||
class hexrays_callback_info(object):
|
||||
|
||||
def __init__(self):
|
||||
self.vu = None
|
||||
return
|
||||
|
||||
def show_xrefs(self, vu):
|
||||
|
||||
vu.get_current_item(idaapi.USE_KEYBOARD)
|
||||
item = vu.item
|
||||
|
||||
sel = None
|
||||
if item.citype == idaapi.VDI_EXPR and item.it.to_specific_type.opname in ('obj', 'memref', 'memptr'):
|
||||
# if an expression is selected. verify that it's either a cot_obj, cot_memref or cot_memptr
|
||||
sel = item.it.to_specific_type
|
||||
|
||||
elif item.citype == idaapi.VDI_FUNC:
|
||||
# if the function itself is selected, show xrefs to it.
|
||||
sel = item.f
|
||||
else:
|
||||
return False
|
||||
|
||||
form = XrefsForm(sel)
|
||||
form.Show()
|
||||
return True
|
||||
|
||||
def menu_callback(self):
|
||||
self.show_xrefs(self.vu)
|
||||
return 0
|
||||
|
||||
def event_callback(self, event, *args):
|
||||
|
||||
try:
|
||||
if event == idaapi.hxe_keyboard:
|
||||
vu, keycode, shift = args
|
||||
|
||||
if idaapi.lookup_key_code(keycode, shift, True) == idaapi.get_key_code("X") and shift == 0:
|
||||
if self.show_xrefs(vu):
|
||||
return 1
|
||||
|
||||
elif event == idaapi.hxe_right_click:
|
||||
self.vu = args[0]
|
||||
idaapi.add_custom_viewer_popup_item(self.vu.ct, "Xrefs", "X", self.menu_callback)
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
return 0
|
||||
|
||||
if idaapi.init_hexrays_plugin():
|
||||
i = hexrays_callback_info()
|
||||
idaapi.install_hexrays_callback(i.event_callback)
|
||||
else:
|
||||
print 'invert-if: hexrays is not available.'
|
||||
|
||||
Reference in New Issue
Block a user