Skip to content
This repository was archived by the owner on Dec 24, 2025. It is now read-only.

Commit 78c79f8

Browse files
author
elias.bachaalany@gmail.com
committed
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.
1 parent c88a77e commit 78c79f8

77 files changed

Lines changed: 8937 additions & 5305 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AUTHORS.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ The IDAPython Team:
88
* Hex-Rays - http://www.hex-rays.com/ - <support@hex-rays.com>
99

1010
Hex-Rays joined the IDAPython project in September 2009 and started contributing.
11-
It is primarily maintained by Elias Bachaalany.
11+
It is primarily maintained by Arnaud Diederen.
1212

13+
* Elias Bachaalany - http://0xeb.wordpress.com/
14+
15+
Current project owner and maintainer
1316

1417
* Ero Carrera - http://dkbza.org/
1518

Scripts/callstack_test.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import sys
2+
import os
3+
4+
def __sys(cmd, fmt=None, echo=True):
5+
"""Executes a string of OS commands and returns the a list of tuples (return code,command executed)"""
6+
if not fmt:
7+
fmt = {}
8+
r = []
9+
for cmd in [x for x in (cmd % fmt).split("\n") if len(x)]:
10+
if echo:
11+
print ">>>", cmd
12+
r.append((os.system(cmd), cmd))
13+
return r
14+
15+
body = r"""/// Autogenerated file
16+
#include <stdio.h>
17+
#include <conio.h>
18+
#include <ctype.h>
19+
#include <windows.h>
20+
21+
void want_break(int n)
22+
{
23+
printf("do you want to DebugBreak in func%d()?", n);
24+
char ch = _toupper(_getch());
25+
printf("\n");
26+
if (ch == 'Y')
27+
DebugBreak();
28+
else if (ch == 'X')
29+
ExitProcess(n);
30+
}
31+
%FUNCS%
32+
int main(int /*argc*/, char * /*argv[]*/)
33+
{
34+
func1();
35+
return 0;
36+
}
37+
"""
38+
39+
funcs_body = []
40+
41+
func_body = r"""
42+
void func%(n)d()
43+
{
44+
printf("%(ident)senter %(n)d\n");%(pause)s
45+
func%(n1)d();
46+
printf("%(ident)sleave %(n)d\n");
47+
}
48+
"""
49+
50+
if len(sys.argv) < 2:
51+
print "usage: gen nb_calls pause_frequency"
52+
sys.exit(0)
53+
54+
n = int(sys.argv[1])
55+
if n < 1:
56+
print "at least one call should be passed!"
57+
sys.exit(1)
58+
59+
m = int(sys.argv[2])
60+
61+
func_params = {'n': 0, 'n1': 0, 'ident': '', 'pause' : ''}
62+
63+
for i in xrange(1, n + 1):
64+
func_params['n'] = i
65+
func_params['n1'] = i+1
66+
func_params['ident'] = " " * i
67+
func_params['pause'] = ("\n want_break(%d);" % i) if (i % m) == 0 else ''
68+
69+
funcs_body.append(func_body % func_params)
70+
funcs_body.append(r"""
71+
void func%(n)d()
72+
{
73+
printf("that's it #%(n)d!\n");
74+
}
75+
""" % {'n':i+1})
76+
funcs_body.reverse()
77+
78+
# write the file
79+
body = body.replace('%FUNCS%', ''.join(funcs_body))
80+
f = file('src.cpp', 'w')
81+
f.write(body)
82+
f.close()
83+
84+
85+
__sys("""
86+
if exist src.exe del src.exe
87+
bcc32 src
88+
if exist src.exe move src.exe src_bcc.exe
89+
if exist src.obj del src.obj
90+
cl32 src.cpp /Zi /Od
91+
""")

build.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
VERBOSE = True
2525

2626
IDA_MAJOR_VERSION = 6
27-
IDA_MINOR_VERSION = 4
27+
IDA_MINOR_VERSION = 5
2828

2929
if 'IDA' in os.environ:
3030
IDA_SDK = os.environ['IDA']
@@ -35,8 +35,8 @@
3535

3636
# IDAPython version
3737
VERSION_MAJOR = 1
38-
VERSION_MINOR = 5
39-
VERSION_PATCH = 6
38+
VERSION_MINOR = 6
39+
VERSION_PATCH = 0
4040

4141
# Determine Python version
4242
PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
@@ -50,7 +50,7 @@
5050
S_NO_OPT = 'no-opt'
5151

5252
# Swig command-line parameters
53-
SWIG_OPTIONS = '-modern -python -c++ -w451 -shadow -D__GNUC__ -DNO_OBSOLETE_FUNCS'
53+
SWIG_OPTIONS = '-modern -python -threads -c++ -w451 -shadow -D__GNUC__'
5454

5555
# Common macros for all compilations
5656
COMMON_MACROS = [
@@ -169,8 +169,8 @@ def parse_options(args):
169169
with_hexrays = '--' + S_WITH_HEXRAYS in sys.argv
170170

171171
return {
172-
S_EA64: ea64,
173-
S_WITH_HEXRAYS: with_hexrays,
172+
S_EA64: ea64,
173+
S_WITH_HEXRAYS: with_hexrays,
174174
S_NO_OPT: no_opt
175175
}
176176

@@ -335,9 +335,9 @@ def build_distribution(manifest, distrootdir, ea64, nukeold):
335335

336336
# -----------------------------------------------------------------------
337337
def build_plugin(
338-
platform,
339-
idasdkdir,
340-
plugin_name,
338+
platform,
339+
idasdkdir,
340+
plugin_name,
341341
options):
342342

343343
# Get the arguments
@@ -401,7 +401,7 @@ def build_plugin(
401401
platform_macros.append("PLUGINFIX")
402402

403403
# Turn off obsolete functions
404-
platform_macros.append("NO_OBSOLETE_FUNCS")
404+
#platform_macros.append("NO_OBSOLETE_FUNCS")
405405

406406
# Build the wrapper from the interface files
407407
ea64flag = ea64 and "-D__EA64__" or ""
@@ -467,17 +467,17 @@ def build_binary_package(options, nukeold):
467467
platform_string)
468468
# Build the plugin
469469
build_plugin(platform_string, IDA_SDK, plugin_name, options)
470-
470+
471471
# Build the binary distribution
472472
binmanifest = []
473473
if nukeold:
474474
binmanifest.extend(BINDIST_MANIFEST)
475-
475+
476476
if not ea64 or nukeold:
477477
binmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py", "idaapi.py"])
478-
478+
479479
binmanifest.append((plugin_name, "plugins"))
480-
480+
481481
build_distribution(binmanifest, BINDISTDIR, ea64, nukeold)
482482

483483

examples/ex_gdl_qflow_chart.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ def raw_main(p=True):
1515

1616
for ns in xrange(0, q.nsucc(n)):
1717
if p:
18-
print " %d->%d" % (n, q.succ(n, ns))
18+
print "SUCC: %d->%d" % (n, q.succ(n, ns))
1919

2020
for ns in xrange(0, q.npred(n)):
2121
if p:
22-
print " %d->%d" % (n, q.pred(n, ns))
22+
print "PRED: %d->%d" % (n, q.pred(n, ns))
2323

2424
# -----------------------------------------------------------------------
2525
# Using the class

examples/ex_idagraph.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# -----------------------------------------------------------------------
2+
# This is an example illustrating how to manipulate an existing IDA-provided
3+
# view (and thus its graph), in Python.
4+
# (c) Hex-Rays
5+
#
6+
from idaapi import IDAViewWrapper
7+
from time import sleep
8+
import threading
9+
10+
class Worker(threading.Thread):
11+
def __init__(self, w):
12+
threading.Thread.__init__(self)
13+
self.w = w
14+
15+
def req_SetCurrentRendererType(self, switch_to):
16+
w = self.w
17+
def f():
18+
print "Switching.."
19+
w.SetCurrentRendererType(switch_to)
20+
idaapi.execute_sync(f, idaapi.MFF_FAST)
21+
22+
def req_SetNodeInfo(self, node, info, flags):
23+
w = self.w
24+
def f():
25+
print "Setting node info.."
26+
w.SetNodeInfo(node, info, flags)
27+
idaapi.execute_sync(f, idaapi.MFF_FAST)
28+
29+
def req_DelNodesInfos(self, *nodes):
30+
w = self.w
31+
def f():
32+
print "Deleting nodes infos.."
33+
w.DelNodesInfos(*nodes)
34+
idaapi.execute_sync(f, idaapi.MFF_FAST)
35+
36+
def run(self):
37+
# Note, in order to leave the UI available
38+
# to the user, we'll perform UI operations
39+
# in this thread.
40+
#
41+
# But.
42+
#
43+
# Qt expects that all UI operations be performed from
44+
# the main thread. Therefore, we'll have to use
45+
# 'idaapi.execute_sync' to send requests to the main thread.
46+
47+
# Switch back & forth to & from graph view
48+
for i in xrange(3):
49+
self.req_SetCurrentRendererType(idaapi.TCCRT_FLAT)
50+
sleep(1)
51+
self.req_SetCurrentRendererType(idaapi.TCCRT_GRAPH)
52+
sleep(1)
53+
54+
# Go to graph view, and set the first node's color
55+
self.req_SetCurrentRendererType(idaapi.TCCRT_GRAPH)
56+
ni = idaapi.node_info_t()
57+
ni.bg_color = 0x00ff00ff
58+
ni.frame_color = 0x0000ff00
59+
self.req_SetNodeInfo(0, ni, idaapi.NIF_BG_COLOR|idaapi.NIF_FRAME_COLOR)
60+
sleep(3)
61+
62+
# This was fun. But let's revert it.
63+
self.req_DelNodesInfos(0)
64+
sleep(3)
65+
66+
print "Done."
67+
68+
class MyIDAViewWrapper(IDAViewWrapper):
69+
# A wrapper around the standard IDA view wrapper.
70+
# We'll react to some events and print the parameters
71+
# that were sent to us, that's all.
72+
def __init__(self, viewName):
73+
IDAViewWrapper.__init__(self, viewName)
74+
75+
# Helper function, to be called by "On*" event handlers.
76+
# This will print all the arguments that were passed!
77+
def printPrevFrame(self):
78+
import inspect
79+
stack = inspect.stack()
80+
frame, _, _, _, _, _ = stack[1]
81+
args, _, _, values = inspect.getargvalues(frame)
82+
print "EVENT: %s: args=%s" % (
83+
inspect.getframeinfo(frame)[2],
84+
[(i, values[i]) for i in args[1:]])
85+
86+
def OnViewKeydown(self, key, state):
87+
self.printPrevFrame()
88+
89+
def OnViewClick(self, x, y, state):
90+
self.printPrevFrame()
91+
92+
def OnViewDblclick(self, x, y, state):
93+
self.printPrevFrame()
94+
95+
def OnViewSwitched(self, rt):
96+
self.printPrevFrame()
97+
98+
def OnViewMouseOver(self, x, y, state, over_type, over_data):
99+
self.printPrevFrame()
100+
101+
102+
103+
viewName = "IDA View-A"
104+
w = MyIDAViewWrapper(viewName)
105+
if w.Bind():
106+
print "Succesfully bound to %s" % viewName
107+
108+
# We'll launch the sequence of operations in another thread,
109+
# so that sleep() calls don't freeze the UI
110+
worker = Worker(w)
111+
worker.start()
112+
113+
else:
114+
print "Couldn't bind to view %s. Is it available?" % viewName

examples/vds1.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
import idaapi
22

33
def main():
4-
if not idaapi.init_hexrays_plugin():
5-
return False
4+
if not idaapi.init_hexrays_plugin():
5+
return False
66

7-
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
7+
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
88

9-
f = idaapi.get_func(idaapi.get_screen_ea());
10-
if f is None:
11-
print "Please position the cursor within a function"
12-
return True
13-
14-
cfunc = idaapi.decompile(f);
15-
if cfunc is None:
16-
print "Failed to decompile!"
17-
return True
18-
19-
sv = cfunc.get_pseudocode();
20-
for i in xrange(0, sv.size()):
21-
line = idaapi.tag_remove(str(sv[i]));
22-
print line
9+
f = idaapi.get_func(idaapi.get_screen_ea());
10+
if f is None:
11+
print "Please position the cursor within a function"
12+
return True
13+
14+
cfunc = idaapi.decompile(f);
15+
if cfunc is None:
16+
print "Failed to decompile!"
17+
return True
2318

24-
return True
19+
sv = cfunc.get_pseudocode();
20+
for i in xrange(0, sv.size()):
21+
line = idaapi.tag_remove(str(sv[i]));
22+
print line
23+
24+
return True
2525

2626
if main():
27-
idaapi.term_hexrays_plugin();
27+
idaapi.term_hexrays_plugin();

0 commit comments

Comments
 (0)