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

Commit bbf628d

Browse files
author
elias.bachaalany@gmail.com
committed
IDA Pro 6.7 support
1 parent 49dcdc5 commit bbf628d

69 files changed

Lines changed: 5059 additions & 1791 deletions

Some content is hidden

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

BUILDING.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ REQUIREMENTS
1616
- Python [2.5.1, 2.6.1, 2.7]
1717
http://www.python.org/
1818

19-
- Simplified Wrapper Interface Generator (SWIG) [2.0]
19+
- Simplified Wrapper Interface Generator (SWIG) [2.0.12]
2020
http://www.swig.org/
21+
Hex-Rays cannot guarantee support for IDAPython
22+
versions built with other versions of SWIG.
2123

2224
- Unix utilities (GNU patch on Windows):
2325
http://www.research.att.com/sw/tools/uwin/ or

build.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,23 @@
2424
VERBOSE = True
2525

2626
IDA_MAJOR_VERSION = 6
27-
IDA_MINOR_VERSION = 6
27+
IDA_MINOR_VERSION = 7
2828

2929
if 'IDA' in os.environ:
3030
IDA_SDK = os.environ['IDA']
3131
else:
32-
IDA_SDK = os.path.join("..", "swigsdk-versions", ("%d.%d" % (IDA_MAJOR_VERSION, IDA_MINOR_VERSION)))
32+
IDA_SDK = os.path.join("..", "..", "include")
33+
if not os.path.exists(IDA_SDK):
34+
IDA_SDK = os.path.join("..", "swigsdk-versions", ("%d.%d" % (IDA_MAJOR_VERSION, IDA_MINOR_VERSION)))
35+
assert os.path.exists(IDA_SDK), "Could not find IDA SDK include path"
36+
3337

3438
# End of user configurable options
3539

3640
# IDAPython version
3741
VERSION_MAJOR = 1
3842
VERSION_MINOR = 7
39-
VERSION_PATCH = 0
43+
VERSION_PATCH = 1
4044

4145
# Determine Python version
4246
PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
@@ -89,7 +93,7 @@
8993
"examples/structure.py",
9094
"examples/ex_gdl_qflow_chart.py",
9195
"examples/ex_strings.py",
92-
"examples/ex_add_menu_item.py",
96+
"examples/ex_actions.py",
9397
"examples/ex_func_chooser.py",
9498
"examples/ex_choose2.py",
9599
"examples/ex_debug_names.py",
@@ -157,7 +161,6 @@
157161
"swig/graph.i",
158162
"swig/fpro.i",
159163
"swig/hexrays.i",
160-
"tools/gendocs.py",
161164
]
162165

163166
# -----------------------------------------------------------------------
@@ -396,7 +399,8 @@ def build_plugin(
396399
platform_macros.append("WITH_HEXRAYS")
397400
SWIG_OPTIONS += ' -DWITH_HEXRAYS '
398401

399-
platform_macros.append("NDEBUG")
402+
platform_macros.append("DEBUG")
403+
# platform_macros.append("NDEBUG")
400404

401405
if not '--no-early-load' in sys.argv:
402406
platform_macros.append("PLUGINFIX")
@@ -411,6 +415,13 @@ def build_plugin(
411415
res = os.system(swigcmd)
412416
assert res == 0, "Failed to build the wrapper with SWIG"
413417

418+
# If we are running on windows, we have to patch some directors'
419+
# virtual methods, so they have the right calling convention.
420+
# Without that, compilation just won't succeed.
421+
if platform == "win32":
422+
res = os.system("python patch_directors_cc.py -f idaapi.h")
423+
assert res == 0, "Failed to patch directors' calling conventions"
424+
414425
# Compile the wrapper
415426
res = builder.compile("idaapi",
416427
includes=[ PYTHON_INCLUDE_DIRECTORY, ida_include_directory ],

examples/ex_actions.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import idaapi
2+
3+
class SayHi(idaapi.action_handler_t):
4+
def __init__(self, message):
5+
idaapi.action_handler_t.__init__(self)
6+
self.message = message
7+
8+
def activate(self, ctx):
9+
print "Hi, %s" % (self.message)
10+
return 1
11+
12+
# You can implement update(), to inform IDA when:
13+
# * your action is enabled
14+
# * update() should queried again
15+
# E.g., returning 'idaapi.AST_ENABLE_FOR_FORM' will
16+
# tell IDA that this action is available while the
17+
# user is in the current widget, and that update()
18+
# must be queried again once the user gives focus
19+
# to another widget.
20+
#
21+
# For example, the following update() implementation
22+
# will let IDA know that the action is available in
23+
# "IDA View-*" views, and that it's not even worth
24+
# querying update() anymore until the user has moved
25+
# to another view..
26+
def update(self, ctx):
27+
return idaapi.AST_ENABLE_FOR_FORM if ctx.form_type == idaapi.BWN_DISASM else idaapi.AST_DISABLE_FOR_FORM
28+
29+
30+
print "Creating a custom icon from raw data!"
31+
# Stunned panda face icon data.
32+
icon_data = "".join([
33+
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1F\xF3\xFF\x61\x00\x00\x02\xCA\x49\x44\x41\x54\x78\x5E\x65",
34+
"\x53\x6D\x48\x53\x6F\x14\x3F\xBA\xB5\xB7\xA0\x8D\x20\x41\xF2\xBA\x5D\xB6\x0F\x56\xF4\x41\xA2\xC0\x9C\xE9\xB4\x29\x4A\x7D\xB0\x22\x7A\x11\x02\x23\x48\x2A\xD4\x74\x53\x33\x3F\xD4",
35+
"\x3E\x4A\x50\x19\xE4\xB0\xD0\x22\xCD\x44\x45\x4A\x31\x8C\x92\xA2\x3E\x65\x0A\x4D\xCB\x96\x7E\xE8\xD5\x97\xCC\xFE\xFE\x37\xA7\x77\xDB\xBD\xA7\xE7\x3C\xBE\x05\x9E\xED\xB7\xB3\xF3",
36+
"\x7B\x39\xF7\xEE\x19\x17\xA8\xAC\x56\xDB\x54\x82\x60\x41\xB3\x59\xBC\xFF\xAC\xF9\xCA\xB5\xAE\x86\xCA\xF9\x4E\xAF\x1B\x3B\xEA\x5D\x48\x9D\x66\xE2\x49\x27\x9F\xD5\x66\x9B\xA2\x1C",
37+
"\x22\x02\xD0\x40\xE4\x81\x6C\x3B\x76\x37\x56\xE3\x37\x5F\x2F\x62\xE8\x0B\xD3\x66\x19\x7E\x53\xA7\x99\x78\xAE\x1F\x64\x3E\x21\x71\x69\x09\x5F\x20\x98\x2D\x58\x70\x24\x07\x07\x7B",
38+
"\x6F\xB0\x79\x82\x61\x81\x21\xCC\xDE\x21\x54\x16\x02\xD4\x69\x26\x9E\x74\xEE\xCB\xCF\x4D\xC7\x44\xB3\x88\x7C\x81\xC5\x22\xFE\x6C\xB9\xE9\x46\x67\x46\x1A\x8A\x16\x2B\x0A\x5B\x05",
39+
"\x74\x66\x65\xE1\x98\x6F\x00\x31\x32\x87\x9F\x59\x77\x66\x66\x61\x42\xBC\xC0\xF5\x6C\x47\x1A\x36\xD7\xB9\x51\x14\xC5\x1E\xBE\xA0\xC3\x5B\xD9\x98\x99\xE1\xC0\xCE\xBE\x57\x48\xD7",
40+
"\x9A\x63\x68\xEA\x7C\x8A\xF6\x14\x3B\x9F\xF6\xA6\xA4\x60\xEB\xE3\x3E\x9C\x5F\xD6\x5A\x7A\xFA\x71\xBF\xC3\x81\x3D\x4D\x35\x0D\x7C\xC1\xF3\x87\x57\x43\xF9\x87\x8F\x21\x95\x5E\xAB",
41+
"\x41\x83\x4E\x83\x54\xDB\x92\x76\x20\xCA\xBF\xD0\x99\x9D\xBB\x4E\xDB\xBD\xC7\x8E\x2F\x5A\x3D\x74\x3D\x50\x03\x80\x7E\x7A\x7A\x06\x46\x47\xFD\xA0\x33\x6C\x84\x18\x46\x0C\xBD\x1F",
42+
"\x86\x2D\x71\x71\x00\x52\x10\x16\x17\xE6\xC1\xE7\x1B\x61\x9A\x81\x69\x31\x30\xFC\x61\x14\xB4\x3A\x3D\x20\x82\x1E\x58\xA9\x15\x05\x41\x14\x05\xB8\x58\xEE\x82\x7D\xE9\x99\x20\xCB",
43+
"\x32\x94\x95\x95\xC3\xA5\xD2\x53\x00\x51\x09\xAA\x4B\x0B\xA1\xB8\xA4\x0C\x52\x53\x33\x40\xA5\x52\x81\xDB\x5D\x01\xA2\x45\x00\x45\x51\x80\x2A\x36\x12\x8D\x42\x49\x51\x01\x44\xE5",
44+
"\x18\x90\x22\x0A\x98\x8C\x46\xF0\x54\x14\x42\x6D\x7D\x3B\xE4\x1C\x75\x41\xAD\xB7\x1D\x3C\x55\x85\x60\x32\x19\x41\x8A\x2A\xDC\x57\x5C\x74\x12\x28\x47\xA5\x8E\x44\xE4\xF0\x76\x5B",
45+
"\x82\xA6\xCD\x5B\x0D\xB2\x12\xE6\xE4\x06\xB5\x1A\x66\xA7\x26\x41\x92\xC2\xA0\xD5\x6A\x60\x67\x92\x19\xAE\x7B\xCE\x70\x4D\x15\xAB\x01\xAD\xC1\x08\x3F\x46\x64\x6E\x8E\x9D\xF9\x13",
46+
"\xE8\x1A\xFF\xE4\x63\x8A\x0E\xE6\x02\x41\xF8\x3F\x18\x82\x40\x28\x04\xFD\xDD\x75\xF0\xB6\xFF\x2E\x75\x9A\x89\x27\x9D\xFB\xC8\x4F\x39\xBE\xE0\xB4\xAB\xCE\x35\xFE\x71\x00\x16\x17",
47+
"\x25\x76\x50\x26\x76\x6B\x61\x86\x08\xE4\x1D\xAF\x81\xBC\x13\x97\xA9\xD3\x4C\x3C\xE9\xDC\x47\x7E\xCA\xF1\x05\x0C\x5F\x7D\xFE\xEF\x35\x03\xAF\x9F\x00\xB0\x73\x30\x9A\xE2\x81\x0E",
48+
"\xF6\xC1\xED\x52\xB8\x77\xAB\x98\x3A\xCD\xC4\x73\x9D\x7C\x6F\xDE\xF9\xCF\x53\x0E\xFE\xA9\xCD\xAE\xB3\x87\xCE\x75\x35\x54\xE1\xD0\xCB\x47\x38\x39\x36\x88\xFF\x4D\xF8\x57\x41\x33",
49+
"\xF1\xA4\x93\x0F\x00\x36\xAD\x3E\x4C\x6B\xC5\xC9\x5D\x77\x6A\x2F\xB4\x31\xA3\xC4\x40\x4F\x21\x0F\xD1\x4C\x3C\xE9\x2B\xE1\xF5\x0B\xD6\x90\xC8\x90\x4C\xE6\x35\xD0\xCC\x79\x5E\xFF",
50+
"\x2E\xF8\x0B\x2F\x3D\xE5\xC3\x97\x06\xCF\xCF\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"])
51+
act_icon = idaapi.load_custom_icon(data=icon_data, format="png")
52+
53+
hooks = None
54+
act_name = "example:add_action"
55+
56+
if idaapi.register_action(idaapi.action_desc_t(
57+
act_name, # Name. Acts as an ID. Must be unique.
58+
"Say hi!", # Label. That's what users see.
59+
SayHi("developer"), # Handler. Called when activated, and for updating
60+
"Ctrl+F12", # Shortcut (optional)
61+
"Greets the user", # Tooltip (optional)
62+
act_icon)): # Icon ID (optional)
63+
print "Action registered. Attaching to menu."
64+
65+
# Insert the action in the menu
66+
if idaapi.attach_action_to_menu("Edit/Export data", act_name, idaapi.SETMENU_APP):
67+
print "Attached to menu."
68+
else:
69+
print "Failed attaching to menu."
70+
71+
# Insert the action in a toolbar
72+
if idaapi.attach_action_to_toolbar("AnalysisToolBar", act_name):
73+
print "Attached to toolbar."
74+
else:
75+
print "Failed attaching to toolbar."
76+
77+
# We will also want our action to be available in the context menu
78+
# for the "IDA View-A" widget.
79+
#
80+
# To do that, we could in theory retrieve a reference to "IDA View-A", and
81+
# then request to "permanently" attach the action to it, using something
82+
# like this:
83+
# idaapi.attach_action_to_popup(ida_view_a, None, act_name, None)
84+
#
85+
# but alas, that won't do: widgets in IDA are very "volatile", and
86+
# can be deleted & re-created on some occasions (e.g., starting a
87+
# debugging session), and our efforts to permanently register our
88+
# action on "IDA View-A" would be annihilated as soon as "IDA View-A"
89+
# is deleted.
90+
#
91+
# Instead, we can opt for a different method: attach our action on-the-fly,
92+
# when the popup for "IDA View-A" is being populated, right before
93+
# it is displayed.
94+
class Hooks(idaapi.UI_Hooks):
95+
def finish_populating_tform_popup(self, form, popup):
96+
# We'll add our action to all "IDA View-*"s.
97+
# If we wanted to add it only to "IDA View-A", we could
98+
# also discriminate on the widget's title:
99+
#
100+
# if idaapi.get_tform_title(form) == "IDA View-A":
101+
# ...
102+
#
103+
if idaapi.get_tform_type(form) == idaapi.BWN_DISASM:
104+
idaapi.attach_action_to_popup(form, popup, act_name, None)
105+
106+
hooks = Hooks()
107+
hooks.hook()
108+
else:
109+
print "Action found; unregistering."
110+
# No need to call detach_action_from_menu(); it'll be
111+
# done automatically on destruction of the action.
112+
if idaapi.unregister_action(act_name):
113+
print "Unregistered."
114+
else:
115+
print "Failed to unregister action."
116+
117+
if hooks is not None:
118+
hooks.unhook()
119+
hooks = None

examples/ex_askusingform.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ def OnFormChange(self, fid):
344344

345345
# --------------------------------------------------------------------------
346346
def test_dropdown(execute=True):
347-
"""Test the combobox controls"""
347+
"""Test the combobox controls, in a modal dialog"""
348348
f = MyForm3()
349349
f, args = f.Compile()
350350
if execute:
@@ -360,6 +360,18 @@ def test_dropdown(execute=True):
360360

361361
f.Free()
362362

363+
# --------------------------------------------------------------------------
364+
tdn_form = None
365+
def test_dropdown_nomodal():
366+
"""Test the combobox controls, in a non-modal form"""
367+
global tdn_form
368+
if tdn_form is None:
369+
tdn_form = MyForm3()
370+
tdn_form.modal = False
371+
tdn_form.openform_flags = idaapi.PluginForm.FORM_TAB
372+
tdn_form, _ = tdn_form.Compile()
373+
tdn_form.Open()
374+
363375
#</pycode(ex_askusingform)>
364376

365377

0 commit comments

Comments
 (0)