mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
IDA Pro 6.5 support
What's new: - Proper multi-threaded support - Better PyObject reference counting with ref_t and newref_t helper classes - Improved the pywraps/deployment script - Added IDAViewWrapper class and example - Added idc.GetDisasmEx() - Added idc.AddSegEx() - Added idc.GetLocalTinfo() - Added idc.ApplyType() - Updated type information implementation - Introduced the idaapi.require() - see http://www.hexblog.com/?p=749 - set REMOVE_CWD_SYS_PATH=1 by default in python.cfg (remove current directory from the import search path). Various bugfixes: - fixed various memory leaks - asklong/askaddr/asksel (and corresponding idc.py functions) were returning results truncated to 32 bits in IDA64 - fix wrong documentation for idc.SizeOf - GetFloat/GetDouble functions did not take into account endianness of the processor - idaapi.NO_PROCESS was not defined, and was causing GetProcessPid() to fail - idc.py: insert escape characters to string parameter when call Eval() - idc.SaveFile/savefile were always overwriting an existing file instead of writing only the new data - PluginForm.Close() wasn't passing its arguments to the delegate function, resulting in an error.
This commit is contained in:
@@ -15,11 +15,11 @@ def raw_main(p=True):
|
||||
|
||||
for ns in xrange(0, q.nsucc(n)):
|
||||
if p:
|
||||
print " %d->%d" % (n, q.succ(n, ns))
|
||||
print "SUCC: %d->%d" % (n, q.succ(n, ns))
|
||||
|
||||
for ns in xrange(0, q.npred(n)):
|
||||
if p:
|
||||
print " %d->%d" % (n, q.pred(n, ns))
|
||||
print "PRED: %d->%d" % (n, q.pred(n, ns))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Using the class
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to manipulate an existing IDA-provided
|
||||
# view (and thus its graph), in Python.
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
from idaapi import IDAViewWrapper
|
||||
from time import sleep
|
||||
import threading
|
||||
|
||||
class Worker(threading.Thread):
|
||||
def __init__(self, w):
|
||||
threading.Thread.__init__(self)
|
||||
self.w = w
|
||||
|
||||
def req_SetCurrentRendererType(self, switch_to):
|
||||
w = self.w
|
||||
def f():
|
||||
print "Switching.."
|
||||
w.SetCurrentRendererType(switch_to)
|
||||
idaapi.execute_sync(f, idaapi.MFF_FAST)
|
||||
|
||||
def req_SetNodeInfo(self, node, info, flags):
|
||||
w = self.w
|
||||
def f():
|
||||
print "Setting node info.."
|
||||
w.SetNodeInfo(node, info, flags)
|
||||
idaapi.execute_sync(f, idaapi.MFF_FAST)
|
||||
|
||||
def req_DelNodesInfos(self, *nodes):
|
||||
w = self.w
|
||||
def f():
|
||||
print "Deleting nodes infos.."
|
||||
w.DelNodesInfos(*nodes)
|
||||
idaapi.execute_sync(f, idaapi.MFF_FAST)
|
||||
|
||||
def run(self):
|
||||
# Note, in order to leave the UI available
|
||||
# to the user, we'll perform UI operations
|
||||
# in this thread.
|
||||
#
|
||||
# But.
|
||||
#
|
||||
# Qt expects that all UI operations be performed from
|
||||
# the main thread. Therefore, we'll have to use
|
||||
# 'idaapi.execute_sync' to send requests to the main thread.
|
||||
|
||||
# Switch back & forth to & from graph view
|
||||
for i in xrange(3):
|
||||
self.req_SetCurrentRendererType(idaapi.TCCRT_FLAT)
|
||||
sleep(1)
|
||||
self.req_SetCurrentRendererType(idaapi.TCCRT_GRAPH)
|
||||
sleep(1)
|
||||
|
||||
# Go to graph view, and set the first node's color
|
||||
self.req_SetCurrentRendererType(idaapi.TCCRT_GRAPH)
|
||||
ni = idaapi.node_info_t()
|
||||
ni.bg_color = 0x00ff00ff
|
||||
ni.frame_color = 0x0000ff00
|
||||
self.req_SetNodeInfo(0, ni, idaapi.NIF_BG_COLOR|idaapi.NIF_FRAME_COLOR)
|
||||
sleep(3)
|
||||
|
||||
# This was fun. But let's revert it.
|
||||
self.req_DelNodesInfos(0)
|
||||
sleep(3)
|
||||
|
||||
print "Done."
|
||||
|
||||
class MyIDAViewWrapper(IDAViewWrapper):
|
||||
# A wrapper around the standard IDA view wrapper.
|
||||
# We'll react to some events and print the parameters
|
||||
# that were sent to us, that's all.
|
||||
def __init__(self, viewName):
|
||||
IDAViewWrapper.__init__(self, viewName)
|
||||
|
||||
# Helper function, to be called by "On*" event handlers.
|
||||
# This will print all the arguments that were passed!
|
||||
def printPrevFrame(self):
|
||||
import inspect
|
||||
stack = inspect.stack()
|
||||
frame, _, _, _, _, _ = stack[1]
|
||||
args, _, _, values = inspect.getargvalues(frame)
|
||||
print "EVENT: %s: args=%s" % (
|
||||
inspect.getframeinfo(frame)[2],
|
||||
[(i, values[i]) for i in args[1:]])
|
||||
|
||||
def OnViewKeydown(self, key, state):
|
||||
self.printPrevFrame()
|
||||
|
||||
def OnViewClick(self, x, y, state):
|
||||
self.printPrevFrame()
|
||||
|
||||
def OnViewDblclick(self, x, y, state):
|
||||
self.printPrevFrame()
|
||||
|
||||
def OnViewSwitched(self, rt):
|
||||
self.printPrevFrame()
|
||||
|
||||
def OnViewMouseOver(self, x, y, state, over_type, over_data):
|
||||
self.printPrevFrame()
|
||||
|
||||
|
||||
|
||||
viewName = "IDA View-A"
|
||||
w = MyIDAViewWrapper(viewName)
|
||||
if w.Bind():
|
||||
print "Succesfully bound to %s" % viewName
|
||||
|
||||
# We'll launch the sequence of operations in another thread,
|
||||
# so that sleep() calls don't freeze the UI
|
||||
worker = Worker(w)
|
||||
worker.start()
|
||||
|
||||
else:
|
||||
print "Couldn't bind to view %s. Is it available?" % viewName
|
||||
+19
-19
@@ -1,27 +1,27 @@
|
||||
import idaapi
|
||||
|
||||
def main():
|
||||
if not idaapi.init_hexrays_plugin():
|
||||
return False
|
||||
if not idaapi.init_hexrays_plugin():
|
||||
return False
|
||||
|
||||
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
|
||||
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
|
||||
|
||||
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();
|
||||
idaapi.term_hexrays_plugin();
|
||||
|
||||
+50
-49
@@ -5,9 +5,9 @@ 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
|
||||
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
|
||||
|
||||
"""
|
||||
@@ -21,23 +21,23 @@ 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:
|
||||
@@ -47,39 +47,39 @@ class hexrays_callback_info(object):
|
||||
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)
|
||||
@@ -87,15 +87,15 @@ class hexrays_callback_info(object):
|
||||
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
|
||||
@@ -103,48 +103,48 @@ class hexrays_callback_info(object):
|
||||
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:
|
||||
@@ -152,40 +152,40 @@ class hexrays_callback_info(object):
|
||||
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():
|
||||
@@ -193,3 +193,4 @@ if idaapi.init_hexrays_plugin():
|
||||
idaapi.install_hexrays_callback(i.event_callback)
|
||||
else:
|
||||
print 'invert-if: hexrays is not available.'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user