IDAPython for IDA 7.5

This commit is contained in:
Arnaud Diederen
2020-05-27 14:34:02 +02:00
parent fc05f78e37
commit 604de9cfad
177 changed files with 102110 additions and 53038 deletions
+2
View File
@@ -53,6 +53,8 @@ so we don't have to do it ourselves.
When it comes to other types of pull requests (e.g., documentation),
it should usually not be necessary to write a test.
See also [the best practices for tests & examples](examples/README.md)
### How to write tests?
+31 -26
View File
@@ -1,43 +1,48 @@
IDAPython comes in two flavors:
* IDAPython-for-Python2
* IDAPython-for-Python3
* IDAPython-for-Python2.7
* IDAPython-for-Python3.x
# Switching between Python 2 and Python 3.
# Switching between IDAPython-for-Python2.7, and IDAPython-for-Python3.x.
Depending on your choice at the install time, your "plugins" directory will have
one version of plugin installed as idapython.[dll|so|dylib] (and/or idapython64) and
the other will be present with the ".disabled" extension. To switch, just rename the
current version to .disabled and the disabled one back to the .dll/.so/.dylib
(depending on your OS)
IDA ships with two versions of IDAPython:
* one that runs using the Python2.7 runtime
* one that runs using the Python3.x runtime
For example, to swith from Python 3 to Python 2 on Windows:
By default, IDA will load the one that runs using the Python3.x runtime.
In order to have IDA use IDAPython-on-Python2.7, the file
'use_python2' needs to be present in the 'python' subdirectory.
1. rename idapython.dll to idapython.3.disabled and idapython64.dll to idapython64.3.disabled
2. rename idapython2.disabled to idapython.dll and idapython642.disabled to idapython64.dll
That file will be looked for in the following places:
* IDA's install path: path/to/ida_install/python/use_python2
* The 'IDAUSR' directory:
+ ~/.idapro/python/use_python2 (on Linux/OSX)
+ %APPDATA%\Hex-Rays\IDA Pro\python\use_python2 (on Windows)
+ [...or any other directory if the environment variable $IDAUSR is set]
# Selecting which Python3.x install runtime to use
# Selecting a Python install to use
The situation for IDAPython-for-Python2 is simple: it uses Python 2.7,
and will expect that [lib]python2.7.[dll|so|dylib] is present in the system
The situation for IDAPython-for-Python2.7 is simple: it uses Python 2.7,
and will expect that [lib]python2.7.[dll|so|dylib] is present in the system
library path so that IDA can find it.
When it comes to IDAPython-for-Python3, it gets more complex: because
different users might have different (and possibly multiple) versions
of Python3 installed, IDA comes with a tool called `idapyswitch`, that
can be run to select the desired Python3 runtime to tailor
IDAPython-for-Python3 to.
But when it comes to IDAPython-for-Python3.x, things gets more complex:
because different users might have different (and possibly multiple)
versions of Python3.x installed, IDA comes with a tool called `idapyswitch`
that can be run to select the desired Python3.x runtime.
If you selected IDAPython-for-Python3 at installation-time,
`idapyswitch` utility should already have been run, and selected
the most appropriate Python3 version.
If you selected IDAPython-for-Python3.x at the installation time,
the `idapyswitch` utility should already have been run and selected
the most appropriate Python3.x version.
Should you want to switch to another Python3 install after installation,
please run `idapyswitch` from IDA's directory. It will scan for Python
installs present in the system's standard locations and offer you to choose one.
Should you want to switch to another Python3.x install after installation,
please run `idapyswitch` from the IDA directory. It will scan for Python
installs present in the system's standard locations and offer you to choose one.
It also supports optional command-line switches to handle non-standard installs.
Run `idapyswitch -h` to see them.
On Windows, you may need to run it as administrator
so it can patch sip.pyd (library required for PyQt bindings).
+1 -1
View File
@@ -4,7 +4,7 @@ A script that tries to determine the call stack
Run the application with the debugger, suspend the debugger, select a thread and finally run the script.
Copyright (c) 1990-2019 Hex-Rays
Copyright (c) 1990-2020 Hex-Rays
ALL RIGHTS RESERVED.
"""
import ida_ua
+1 -1
View File
@@ -2,7 +2,7 @@
A script to demonstrate how to send commands to the debugger and then parse and use the output in IDA
Copyright (c) 1990-2019 Hex-Rays
Copyright (c) 1990-2020 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2019 Hex-Rays
Copyright (c) 1990-2020 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -13,7 +13,7 @@ The general syntax is:
* To specify in which context the instructions should be assembled, pass asm_where=ea:
find("jmp dword ptr [esp]", asm_where=here())
Copyright (c) 1990-2019 Hex-Rays
Copyright (c) 1990-2020 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
+1 -1
View File
@@ -4,7 +4,7 @@ A script that graphs all the exception handlers in a given process
It will be easy to see what thread uses what handler and what handlers are commonly used between threads
Copyright (c) 1990-2019 Hex-Rays
Copyright (c) 1990-2020 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2019 Hex-Rays
Copyright (c) 1990-2020 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@ from __future__ import print_function
# -----------------------------------------------------------------------
# VirusTotal IDA Plugin
# By Elias Bachaalany <elias at hex-rays.com>
# (c) Hex-Rays 2011-2019
# (c) Hex-Rays 2011-2020
#
# Special thanks:
# - VirusTotal team
+886 -247
View File
File diff suppressed because it is too large Load Diff
+889 -248
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -26,7 +26,7 @@ What follows, are example build commands
python2 build.py \\
--with-hexrays \\
--swig-home C:/swigwin-2.0.12 \\
--idc "c:/Program\ Files/IDA_7.0-171130-tests/idc/idc.idc"
--ida-install "c:/Program\ Files/IDA_7.0-171130-tests"
### Linux/OSX (assume SWiG is installed in /opt/swiglinux-2.0.12, and IDA is in /opt/my-ida-install)
@@ -34,7 +34,7 @@ What follows, are example build commands
python2 build.py \\
--with-hexrays \\
--swig-home /opt/swiglinux-2.0.12 \\
--idc /opt/my-ida-install/idc/idc.idc
--ida-install /opt/my-ida-install
""",
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("--swig-home", type=str, help="Path to the SWIG installation", default=None)
@@ -42,7 +42,7 @@ parser.add_argument("--with-hexrays", help="Build Hex-Rays decompiler bindings (
parser.add_argument("--debug", help="Build debug version of the plugin", default=False, action="store_true")
parser.add_argument("-j", "--parallel", action="store_true", help="Build in parallel", default=False)
parser.add_argument("-v", "--verbose", help="Verbose mode", default=False, action="store_true")
parser.add_argument("-I", "--idc", required=True, help="IDA's idc.idc file (necessary for generating 6.95 compat API layer)", type=str)
parser.add_argument("-I", "--ida-install", required=True, help="IDA's installation directory", type=str)
args = parser.parse_args()
_probe = os.path.join("..", "..", "include", "pro.h")
@@ -76,7 +76,7 @@ def main():
env["NDEBUG"] = "1"
if args.verbose:
argv.append("-d")
env["IDC_BC695_IDC_SOURCE"] = args.idc.replace('\\', '/')
env["IDA_INSTALL"] = args.ida_install.replace('\\', '/')
for ea64 in [True, False]:
if ea64:
env["__EA64__"] = "1"
+32
View File
@@ -0,0 +1,32 @@
# IDAPython examples
This directory contains a variety of examples demonstrating
how IDA can be scripted using IDAPython.
## Adding a new example (for Hex-Rays developers)
When adding an example, the author (i.e., a Hex-Rays developer)
must add a corresponding test, making sure the example is properly
tested, and doesn't regress over time (see `idapython-examples`,
and `idapython_hr-examples` test suites.) This has the added benefit
that this ensures our APIs remain stable.
Also, any significant addition to IDAPython APIs should come
with one or many examples, and those should be also put under test
(in other words: it's better if a test relies on a real example,
rather than if it consists of a bunch of IDAPython code our
users will never see, and cannot be inspired from.)
## Helping our customers, teaching IDAPython in the process
In addition, when a customer asks for help on support@ (or the forums)
and we end up sending a significant body of IDAPython code as a reply,
since that body of code should be tested anyway, it's better to make
a real example out of it ... and, of course, put that example under
test as well.
## Maintaining quality
There should be no such thing as a non-tested example.
+98
View File
@@ -0,0 +1,98 @@
# get information about function(s)
import binascii
import ida_kernwin
import ida_funcs
def dump_flags(fn):
"dump some flags of the func_t object"
print("Function flags: %08X" % fn.flags)
if fn.is_far():
print(" Far function")
if not fn.does_return():
print(" Function does not return")
if fn.flags & ida_funcs.FUNC_FRAME:
print(" Function uses frame pointer")
if fn.flags & ida_funcs.FUNC_THUNK:
print(" Thunk function")
if fn.flags & ida_funcs.FUNC_LUMINA:
print(" Function info is provided by Lumina")
def dump_regvars(pfn):
"dump renamed registers information"
assert ida_funcs.is_func_entry(pfn)
print("Function has %d renamed registers" % pfn.regvarqty)
for rv in pfn.regvars:
print("%08X..%08X '%s'->'%s'" % (rv.start_ea, rv.end_ea, rv.canon, rv.user))
def dump_regargs(pfn):
"dump register arguments information"
assert ida_funcs.is_func_entry(pfn)
print("Function has %d register arguments" % pfn.regargqty)
for ra in pfn.regargs:
print(" register #=%d, argument name=\"%s\", (serialized) type=\"%s\"" % (
ra.reg,
ra.name,
binascii.hexlify(ra.type)))
def dump_tails(pfn):
"dump function tails for entry chunk pfn"
assert ida_funcs.is_func_entry(pfn)
print("Function has %d tails" % pfn.tailqty)
for i in range(pfn.tailqty):
ft = pfn.tails[i]
print(" tail %i: %08X..%08X" % (i, ft.start_ea, ft.end_ea))
def dump_stkpnts(pfn):
"dump function stack points"
print("Function has %d stack points" % pfn.pntqty)
for i in range(pfn.pntqty):
pnt = pfn.points[i]
print(" stkpnt %i @%08X: %d" % (i, pnt.ea, pnt.spd))
def dump_frame(fn):
"dump function frame info"
assert ida_funcs.is_func_entry(fn)
print("frame structure id: %08X" % fn.frame)
print("local variables area size: %8X" % fn.frsize)
print("saved registers area size: %8X" % fn.frregs)
print("bytes purged on return : %8X" % fn.argsize)
print("frame pointer delta : %8X" % fn.fpd)
def dump_parents(fn):
"dump parents of a function tail"
assert ida_funcs.is_func_tail(fn)
print("owner function: %08X" % fn.owner)
print("tail has %d referers" % fn.refqty)
for i in range(fn.refqty):
print(" referer %i: %08X" % (i, fn.referers[i]))
def dump_func_info(ea):
"dump info about function chunk at address 'ea'"
pfn = ida_funcs.get_fchunk(ea)
if pfn is None:
print("No function at %08X!" % ea)
return
print("current chunk boundaries: %08X..%08X" % (pfn.start_ea, pfn.end_ea))
dump_flags(pfn)
if (ida_funcs.is_func_entry(pfn)):
print ("This is an entry chunk")
dump_tails(pfn)
dump_frame(pfn)
dump_regvars(pfn)
dump_regargs(pfn)
dump_stkpnts(pfn)
elif (ida_funcs.is_func_tail(pfn)):
print ("This is a tail chunk")
dump_parents(pfn)
ea = ida_kernwin.get_screen_ea()
dump_func_info(ea)
+16 -15
View File
@@ -1,9 +1,10 @@
from __future__ import print_function
import idaapi
class SayHi(idaapi.action_handler_t):
import ida_kernwin
class SayHi(ida_kernwin.action_handler_t):
def __init__(self, message):
idaapi.action_handler_t.__init__(self)
ida_kernwin.action_handler_t.__init__(self)
self.message = message
def activate(self, ctx):
@@ -13,7 +14,7 @@ class SayHi(idaapi.action_handler_t):
# You can implement update(), to inform IDA when:
# * your action is enabled
# * update() should queried again
# E.g., returning 'idaapi.AST_ENABLE_FOR_WIDGET' will
# E.g., returning 'ida_kernwin.AST_ENABLE_FOR_WIDGET' will
# tell IDA that this action is available while the
# user is in the current widget, and that update()
# must be queried again once the user gives focus
@@ -25,7 +26,7 @@ class SayHi(idaapi.action_handler_t):
# querying update() anymore until the user has moved
# to another view..
def update(self, ctx):
return idaapi.AST_ENABLE_FOR_WIDGET if ctx.widget_type == idaapi.BWN_DISASM else idaapi.AST_DISABLE_FOR_WIDGET
return ida_kernwin.AST_ENABLE_FOR_WIDGET if ctx.widget_type == ida_kernwin.BWN_DISASM else ida_kernwin.AST_DISABLE_FOR_WIDGET
print("Creating a custom icon from raw data!")
@@ -49,12 +50,12 @@ icon_data = b"".join([
b"\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",
b"\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",
b"\x2E\xF8\x0B\x2F\x3D\xE5\xC3\x97\x06\xCF\xCF\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"])
act_icon = idaapi.load_custom_icon(data=icon_data, format="png")
act_icon = ida_kernwin.load_custom_icon(data=icon_data, format="png")
hooks = None
act_name = "example:add_action"
if idaapi.register_action(idaapi.action_desc_t(
if ida_kernwin.register_action(ida_kernwin.action_desc_t(
act_name, # Name. Acts as an ID. Must be unique.
"Say hi!", # Label. That's what users see.
SayHi("developer"), # Handler. Called when activated, and for updating
@@ -64,13 +65,13 @@ if idaapi.register_action(idaapi.action_desc_t(
print("Action registered. Attaching to menu.")
# Insert the action in the menu
if idaapi.attach_action_to_menu("Edit/Export data", act_name, idaapi.SETMENU_APP):
if ida_kernwin.attach_action_to_menu("Edit/Export data", act_name, ida_kernwin.SETMENU_APP):
print("Attached to menu.")
else:
print("Failed attaching to menu.")
# Insert the action in a toolbar
if idaapi.attach_action_to_toolbar("AnalysisToolBar", act_name):
if ida_kernwin.attach_action_to_toolbar("AnalysisToolBar", act_name):
print("Attached to toolbar.")
else:
print("Failed attaching to toolbar.")
@@ -81,7 +82,7 @@ if idaapi.register_action(idaapi.action_desc_t(
# To do that, we could in theory retrieve a reference to "IDA View-A", and
# then request to "permanently" attach the action to it, using something
# like this:
# idaapi.attach_action_to_popup(ida_view_a, None, act_name, None)
# ida_kernwin.attach_action_to_popup(ida_view_a, None, act_name, None)
#
# but alas, that won't do: widgets in IDA are very "volatile", and
# can be deleted & re-created on some occasions (e.g., starting a
@@ -92,17 +93,17 @@ if idaapi.register_action(idaapi.action_desc_t(
# Instead, we can opt for a different method: attach our action on-the-fly,
# when the popup for "IDA View-A" is being populated, right before
# it is displayed.
class Hooks(idaapi.UI_Hooks):
class Hooks(ida_kernwin.UI_Hooks):
def finish_populating_widget_popup(self, widget, popup):
# We'll add our action to all "IDA View-*"s.
# If we wanted to add it only to "IDA View-A", we could
# also discriminate on the widget's title:
#
# if idaapi.get_widget_title(widget) == "IDA View-A":
# if ida_kernwin.get_widget_title(widget) == "IDA View-A":
# ...
#
if idaapi.get_widget_type(widget) == idaapi.BWN_DISASM:
idaapi.attach_action_to_popup(widget, popup, act_name, None)
if ida_kernwin.get_widget_type(widget) == ida_kernwin.BWN_DISASM:
ida_kernwin.attach_action_to_popup(widget, popup, act_name, None)
hooks = Hooks()
hooks.hook()
@@ -110,7 +111,7 @@ else:
print("Action found; unregistering.")
# No need to call detach_action_from_menu(); it'll be
# done automatically on destruction of the action.
if idaapi.unregister_action(act_name):
if ida_kernwin.unregister_action(act_name):
print("Unregistered.")
else:
print("Failed to unregister action.")
+5 -3
View File
@@ -2,23 +2,25 @@ from __future__ import print_function
#---------------------------------------------------------------------
# This script demonstrates the usage of hotkeys.
#
# 'ida_kernwin.add_hotkey' offers a simpler alternative to
# 'ida_kernwin.register_action', but is much less flexible.
#
# Author: IDAPython team
#---------------------------------------------------------------------
import idaapi
import ida_kernwin
def hotkey_pressed():
print("hotkey pressed!")
try:
hotkey_ctx
if idaapi.del_hotkey(hotkey_ctx):
if ida_kernwin.del_hotkey(hotkey_ctx):
print("Hotkey unregistered!")
del hotkey_ctx
else:
print("Failed to delete hotkey!")
except:
hotkey_ctx = idaapi.add_hotkey("Shift-A", hotkey_pressed)
hotkey_ctx = ida_kernwin.add_hotkey("Shift-A", hotkey_pressed)
if hotkey_ctx is None:
print("Failed to register hotkey!")
del hotkey_ctx
@@ -1,25 +1,27 @@
from __future__ import print_function
#---------------------------------------------------------------------
# This script demonstrates the usage of hotkeys.
#
# Note: Hotkeys only work with the GUI version of IDA and not in
# text mode.
# This script demonstrates the usage of hotkeys, using an alternative API.
# See also:
# add_hotkey.py
# actions.py
#
# Author: Gergely Erdelyi <gergely.erdelyi@d-dome.net>
#---------------------------------------------------------------------
import idaapi
def foo():
print("Hotkey activated!")
import ida_expr
import ida_kernwin
def say_hi():
print("Hotkey activated!")
# IDA binds hotkeys to IDC functions so a trampoline IDC function must be created
ida_expr.compile_idc_text('static key_2() { RunPythonStatement("say_hi()"); }')
# IDA binds hotkeys to IDC functions so a trampoline IDC function
# must be created
idaapi.compile_idc_text('static key_2() { RunPythonStatement("foo()"); }')
# Add the hotkey
add_idc_hotkey("2", 'key_2')
ida_kernwin.add_idc_hotkey("2", 'key_2')
# Press 2 to activate foo()
# The hotkey can be removed with
# del_idc_hotkey('2')
# ida_kernwin.del_idc_hotkey('2')
@@ -7,44 +7,54 @@ from __future__ import print_function
#
# Author: Gergely Erdelyi <gergely.erdelyi@d-dome.net>
#---------------------------------------------------------------------
from idaapi import stroffflag, offflag
sid = get_struc_id("mystr1")
import ida_struct
import ida_idaapi
import ida_bytes
import ida_nalt
import idc
sid = ida_struct.get_struc_id("mystr1")
if sid != -1:
del_struc(sid)
sid = add_struc(-1, "mystr1", 0)
idc.del_struc(sid)
sid = ida_struct.add_struc(ida_idaapi.BADADDR, "mystr1", 0)
print("%x" % sid)
# Test simple data types
simple_types = [ FF_BYTE, FF_WORD, FF_DWORD, FF_QWORD, FF_TBYTE, FF_OWORD, FF_FLOAT, FF_DOUBLE, FF_PACKREAL ]
simple_sizes = [ 1, 2, 4, 8, 10, 16, 4, 8, 10 ]
i = 0
for t,nsize in zip(simple_types, simple_sizes):
print("t%x:"% ((t|FF_DATA)&0xFFFFFFFF), add_struc_member(sid, "t%02d"%i, BADADDR, (t|FF_DATA )&0xFFFFFFFF, -1, nsize))
i+=1
simple_types_data = [
(ida_bytes.FF_BYTE, 1),
(ida_bytes.FF_WORD, 2),
(ida_bytes.FF_DWORD, 4),
(ida_bytes.FF_QWORD, 8),
(ida_bytes.FF_TBYTE, 10),
(ida_bytes.FF_OWORD, 16),
(ida_bytes.FF_FLOAT, 4),
(ida_bytes.FF_DOUBLE, 8),
(ida_bytes.FF_PACKREAL, 10),
]
for i, tpl in enumerate(simple_types_data):
t, nsize = tpl
print("t%x:"% ((t|ida_bytes.FF_DATA) & 0xFFFFFFFF),
idc.add_struc_member(sid, "t%02d"%i, ida_idaapi.BADADDR, (t|ida_bytes.FF_DATA )&0xFFFFFFFF, -1, nsize))
# Test ASCII type
print("ASCII:", add_struc_member(sid, "tascii", -1, FF_STRLIT|FF_DATA, STRTYPE_C, 8))
# Test enum type - Add a defined enum name or load MACRO_WMI from a type library.
#eid = get_enum("MACRO_WMI")
#print("Enum:", add_struc_member(sid, "tenum", BADADDR, FF_0ENUM|FF_DATA|FF_DWORD, eid, 4))
print("ASCII:", idc.add_struc_member(sid, "tascii", -1, ida_bytes.FF_STRLIT|ida_bytes.FF_DATA, ida_nalt.STRTYPE_C, 8))
# Test struc member type
msid = get_struc_id("mystr2")
msid = ida_struct.get_struc_id("mystr2")
if msid != -1:
del_struc(msid)
msid = add_struc(-1, "mystr2", 0)
print(add_struc_member(msid, "member1", -1, (FF_DWORD|FF_DATA )&0xFFFFFFFF, -1, 4))
print(add_struc_member(msid, "member2", -1, (FF_DWORD|FF_DATA )&0xFFFFFFFF, -1, 4))
idc.del_struc(msid)
msid = idc.add_struc(-1, "mystr2", 0)
print(idc.add_struc_member(msid, "member1", -1, (ida_bytes.FF_DWORD|ida_bytes.FF_DATA )&0xFFFFFFFF, -1, 4))
print(idc.add_struc_member(msid, "member2", -1, (ida_bytes.FF_DWORD|ida_bytes.FF_DATA )&0xFFFFFFFF, -1, 4))
msize = get_struc_size(msid)
print("Struct:", add_struc_member(sid, "tstruct", -1, FF_STRUCT|FF_DATA, msid, msize))
print("Stroff:", add_struc_member(sid, "tstroff", -1, stroffflag()|FF_DWORD, msid, 4))
msize = ida_struct.get_struc_size(msid)
print("Struct:", idc.add_struc_member(sid, "tstruct", -1, ida_bytes.FF_STRUCT|ida_bytes.FF_DATA, msid, msize))
print("Stroff:", idc.add_struc_member(sid, "tstroff", -1, ida_bytes.stroff_flag()|ida_bytes.FF_DWORD, msid, 4))
# Test offset types
print("Offset:", add_struc_member(sid, "toffset", -1, offflag()|FF_DATA|FF_DWORD, 0, 4))
print("Offset:", set_member_type(sid, 0, offflag()|FF_DATA|FF_DWORD, 0, 4))
print("Offset:", idc.add_struc_member(sid, "toffset", -1, ida_bytes.off_flag()|ida_bytes.FF_DATA|ida_bytes.FF_DWORD, 0, 4))
print("Offset:", idc.set_member_type(sid, 0, ida_bytes.off_flag()|ida_bytes.FF_DATA|ida_bytes.FF_DWORD, 0, 4))
print("Done")
+25 -47
View File
@@ -1,77 +1,54 @@
from __future__ import print_function
# -----------------------------------------------------------------------
# This is an example illustrating how to implement a CLI
# (c) Hex-Rays
#
from idaapi import NW_OPENIDB, NW_CLOSEIDB, NW_TERMIDA, NW_REMOVE, COLSTR, cli_t
# A trivial example is also provided for tab completion. To try it,
# type "bon" in the input field, and then press <Tab> multiple times.
#
# (c) Hex-Rays
class mycli_t(cli_t):
import ida_kernwin
import ida_idaapi
class mycli_t(ida_kernwin.cli_t):
flags = 0
sname = "pycli"
lname = "Python CLI"
hint = "pycli hint"
def OnExecuteLine(self, line):
"""
The user pressed Enter. The CLI is free to execute the line immediately or ask for more lines.
This callback is mandatory.
@param line: typed line(s)
@return Boolean: True-executed line, False-ask for more lines
"""
print("OnExecute:", line)
return True
def OnKeydown(self, line, x, sellen, vkey, shift):
"""
A keyboard key has been pressed
This is a generic callback and the CLI is free to do whatever it wants.
This callback is optional.
@param line: current input line
@param x: current x coordinate of the cursor
@param sellen: current selection length (usually 0)
@param vkey: virtual key code. if the key has been handled, it should be returned as zero
@param shift: shift state
@return:
None - Nothing was changed
tuple(line, x, sellen, vkey): if either of the input line or the x coordinate or the selection length has been modified.
It is possible to return a tuple with None elements to preserve old values. Example: tuple(new_line, None, None, None) or tuple(new_line)
"""
print("Onkeydown: line=%s x=%d sellen=%d vkey=%d shift=%d" % (line, x, sellen, vkey, shift))
return None
completions = [
"bonnie & clyde",
"bonfire of the vanities",
"bongiorno",
]
def OnCompleteLine(self, prefix, n, line, prefix_start):
"""
The user pressed Tab. Find a completion number N for prefix PREFIX
This callback is optional.
@param prefix: Line prefix at prefix_start (string)
@param n: completion number (int)
@param line: the current line (string)
@param prefix_start: the index where PREFIX starts in LINE (int)
@return: None if no completion could be generated otherwise a String with the completion suggestion
"""
print("OnCompleteLine: prefix=%s n=%d line=%s prefix_start=%d" % (prefix, n, line, prefix_start))
if prefix == "bon":
if n < len(self.completions):
return self.completions[n]
return None
# -----------------------------------------------------------------------
def nw_handler(code, old=0):
if code == NW_OPENIDB:
if code == ida_idaapi.NW_OPENIDB:
print("nw_handler(): installing CLI")
mycli.register()
elif code == NW_CLOSEIDB:
elif code == ida_idaapi.NW_CLOSEIDB:
print("nw_handler(): removing CLI")
mycli.unregister()
elif code == NW_TERMIDA:
elif code == ida_idaapi.NW_TERMIDA:
print("nw_handler(): uninstalled nw handler")
idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB | NW_REMOVE, nw_handler)
when = ida_idaapi.NW_TERMIDA | ida_idaapi.NW_OPENIDB | ida_idaapi.NW_CLOSEIDB | ida_idaapi.NW_REMOVE
ida_idaapi.notify_when(when, nw_handler)
# -----------------------------------------------------------------------
@@ -82,7 +59,7 @@ try:
mycli.unregister()
del mycli
# remove previous handler
nw_handler(NW_TERMIDA)
nw_handler(ida_idaapi.NW_TERMIDA)
except:
pass
finally:
@@ -92,7 +69,8 @@ finally:
if mycli.register():
print("CLI installed")
# install new handler
idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB, nw_handler)
when = ida_idaapi.NW_TERMIDA | ida_idaapi.NW_OPENIDB | ida_idaapi.NW_CLOSEIDB
ida_idaapi.notify_when(when, nw_handler)
else:
del mycli
print("Failed to install CLI")
+41 -33
View File
@@ -3,7 +3,13 @@ from __future__ import print_function
# This is an example illustrating how to use custom data types in Python
# (c) Hex-Rays
#
from idaapi import data_type_t, data_format_t, NW_OPENIDB, NW_CLOSEIDB, NW_TERMIDA, NW_REMOVE, COLSTR
import ida_bytes
import ida_idaapi
import ida_lines
import ida_struct
import ida_netnode
import ida_nalt
import sys
import struct
@@ -11,9 +17,9 @@ import ctypes
import platform
# -----------------------------------------------------------------------
class pascal_data_type(data_type_t):
class pascal_data_type(ida_bytes.data_type_t):
def __init__(self):
data_type_t.__init__(
ida_bytes.data_type_t.__init__(
self,
"py_pascal_string",
2,
@@ -24,11 +30,11 @@ class pascal_data_type(data_type_t):
def calc_item_size(self, ea, maxsize):
# Custom data types may be used in structure definitions. If this case
# ea is a member id. Check for this situation and return 1
if idaapi.is_member_id(ea):
if ida_struct.is_member_id(ea):
return 1
# get the length byte
n = idaapi.get_byte(ea)
n = ida_bytes.get_byte(ea)
# string too big?
if n > maxsize:
@@ -36,10 +42,10 @@ class pascal_data_type(data_type_t):
# ok, accept the string
return n + 1
class pascal_data_format(data_format_t):
class pascal_data_format(ida_bytes.data_format_t):
FORMAT_NAME = "py_pascal_string_pstr"
def __init__(self):
data_format_t.__init__(
ida_bytes.data_format_t.__init__(
self,
pascal_data_format.FORMAT_NAME)
@@ -57,7 +63,7 @@ class pascal_data_format(data_format_t):
return "".join(o)
# -----------------------------------------------------------------------
class simplevm_data_type(data_type_t):
class simplevm_data_type(ida_bytes.data_type_t):
ASM_KEYWORD = "svm_emit"
def __init__(
self,
@@ -65,7 +71,7 @@ class simplevm_data_type(data_type_t):
value_size=1,
menu_name="SimpleVM",
asm_keyword=ASM_KEYWORD):
data_type_t.__init__(
ida_bytes.data_type_t.__init__(
self,
name,
value_size,
@@ -74,22 +80,22 @@ class simplevm_data_type(data_type_t):
asm_keyword)
def calc_item_size(self, ea, maxsize):
if idaapi.is_member_id(ea):
if ida_struct.is_member_id(ea):
return 1
# get the opcode and see if it has an imm
n = 5 if (idaapi.get_byte(ea) & 3) == 0 else 1
n = 5 if (ida_bytes.get_byte(ea) & 3) == 0 else 1
# string too big?
if n > maxsize:
return 0
# ok, accept
return n
class simplevm_data_format(data_format_t):
class simplevm_data_format(ida_bytes.data_format_t):
def __init__(
self,
name="py_simple_vm_format",
menu_name="SimpleVM"):
data_format_t.__init__(
ida_bytes.data_format_t.__init__(
self,
name,
0,
@@ -116,9 +122,9 @@ class simplevm_data_format(data_format_t):
imm = None
sz = 1
text = "%s %s, %s" % (
COLSTR(simplevm_data_format.INST[op], idaapi.SCOLOR_INSN),
COLSTR(simplevm_data_format.REGS[r1], idaapi.SCOLOR_REG),
COLSTR("0x%08X" % imm, idaapi.SCOLOR_NUMBER) if imm is not None else COLSTR(simplevm_data_format.REGS[r2], idaapi.SCOLOR_REG))
ida_lines.COLSTR(simplevm_data_format.INST[op], ida_lines.SCOLOR_INSN),
ida_lines.COLSTR(simplevm_data_format.REGS[r1], ida_lines.SCOLOR_REG),
ida_lines.COLSTR("0x%08X" % imm, ida_lines.SCOLOR_NUMBER) if imm is not None else ida_lines.COLSTR(simplevm_data_format.REGS[r2], ida_lines.SCOLOR_REG))
return (sz, text)
def printf(self, value, current_ea, operand_num, dtid):
@@ -131,9 +137,9 @@ class simplevm_data_format(data_format_t):
# -----------------------------------------------------------------------
# This format will display DWORD values as MAKE_DWORD(0xHI, 0xLO)
class makedword_data_format(data_format_t):
class makedword_data_format(ida_bytes.data_format_t):
def __init__(self):
data_format_t.__init__(
ida_bytes.data_format_t.__init__(
self,
"py_makedword",
4,
@@ -156,14 +162,14 @@ class makedword_data_format(data_format_t):
#
# The get_rsrc_string() is not optimal since it loads/unloads the
# DLL each time for a new string. It can be improved in many ways.
class rsrc_string_format(data_format_t):
class rsrc_string_format(ida_bytes.data_format_t):
def __init__(self):
data_format_t.__init__(
ida_bytes.data_format_t.__init__(
self,
"py_w32rsrcstring",
1,
"Resource string")
self.cache_node = idaapi.netnode("$ py_w32rsrcstring", 0, 1)
self.cache_node = ida_netnode.netnode("$ py_w32rsrcstring", 0, 1)
def get_rsrc_string(self, fn, id):
"""
@@ -188,8 +194,8 @@ class rsrc_string_format(data_format_t):
# Not cached?
if val == None:
# Retrieve it
num = idaapi.struct_unpack(value)
val = self.get_rsrc_string(idaapi.get_input_file_path(), num)
num = ida_idaapi.struct_unpack(value)
val = self.get_rsrc_string(ida_nalt.get_input_file_path(), num)
# Cache it
self.cache_node.supset(current_ea, val)
@@ -197,7 +203,7 @@ class rsrc_string_format(data_format_t):
if val == "" or val == "\x00":
return None
# Return the format
return "RSRC_STR(\"%s\")" % COLSTR(val, idaapi.SCOLOR_IMPNAME)
return "RSRC_STR(\"%s\")" % ida_lines.COLSTR(val, ida_lines.SCOLOR_IMPNAME)
# -----------------------------------------------------------------------
# Table of formats and types to be registered/unregistered
@@ -219,21 +225,23 @@ except:
# -----------------------------------------------------------------------
def nw_handler(code, old=0):
# delete notifications
if code == NW_OPENIDB:
if not idaapi.register_data_types_and_formats(new_formats):
if code == ida_idaapi.NW_OPENIDB:
if not ida_bytes.register_data_types_and_formats(new_formats):
print("Failed to register types!")
elif code == NW_CLOSEIDB:
idaapi.unregister_data_types_and_formats(new_formats)
elif code == NW_TERMIDA:
idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB | NW_REMOVE, nw_handler)
elif code == ida_idaapi.NW_CLOSEIDB:
ida_bytes.unregister_data_types_and_formats(new_formats)
elif code == ida_idaapi.NW_TERMIDA:
f = ida_idaapi.NW_TERMIDA | ida_idaapi.NW_OPENIDB | ida_idaapi.NW_CLOSEIDB | ida_idaapi.NW_REMOVE
ida_idaapi.notify_when(f, nw_handler)
# -----------------------------------------------------------------------
# Check if already installed
if idaapi.find_custom_data_type(pascal_data_format.FORMAT_NAME) == -1:
if not idaapi.register_data_types_and_formats(new_formats):
if ida_bytes.find_custom_data_type(pascal_data_format.FORMAT_NAME) == -1:
if not ida_bytes.register_data_types_and_formats(new_formats):
print("Failed to register types!")
else:
idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB, nw_handler)
f = ida_idaapi.NW_TERMIDA | ida_idaapi.NW_OPENIDB | ida_idaapi.NW_CLOSEIDB
ida_idaapi.notify_when(f, nw_handler)
print("Formats installed!")
else:
print("Formats already installed!")
+65
View File
@@ -0,0 +1,65 @@
from __future__ import print_function
# -----------------------------------------------------------------------
# This example illustrates how to use the 'get_extra_cmt' API,
# to retrieve anterior and posterior extra comments.
#
# After running this script, use Ctrl+Shift+Y when in the disassembly
# view to print previous extra comment, and Ctrl+Shift+Z to print next
# extra comments.
#
# (c) Hex-Rays
import ida_lines
import ida_kernwin
# -----------------------------------------------------------------------
class dump_at_point_handler_t(ida_kernwin.action_handler_t):
def __init__(self, anchor):
ida_kernwin.action_handler_t.__init__(self)
self.anchor = anchor
def activate(self, ctx):
ea = ida_kernwin.get_screen_ea()
index = self.anchor
while True:
cmt = ida_lines.get_extra_cmt(ea, index)
if cmt is None:
break
print("Got: '%s'" % cmt)
index += 1
def update(self, ctx):
return ida_kernwin.AST_ENABLE_FOR_WIDGET \
if ctx.widget_type == ida_kernwin.BWN_DISASM \
else ida_kernwin.AST_DISABLE_FOR_WIDGET
@staticmethod
def compose_action_name(v):
return "dump_extra_comments:%s" % v
# -----------------------------------------------------------------------
# create actions (and attach them to IDA View-A's context menu if possible)
widget_title = "IDA View-A"
ida_view = ida_kernwin.find_widget(widget_title)
actions_variants = [
("previous", ida_lines.E_PREV, "Ctrl+Shift+Y"),
("next", ida_lines.E_NEXT, "Ctrl+Shift+Z"),
]
for label, anchor, shortcut in actions_variants:
actname = dump_at_point_handler_t.compose_action_name(label)
if ida_kernwin.unregister_action(actname):
print("Unregistered previously-registered action \"%s\"" % actname)
desc = ida_kernwin.action_desc_t(
actname,
"Dump %s extra comments" % label,
dump_at_point_handler_t(anchor),
shortcut)
if ida_kernwin.register_action(desc):
print("Registered action \"%s\"" % actname)
if ida_view and ida_kernwin.attach_action_to_popup(ida_view, None, actname):
print("Permanently attached action \"%s\" to \"%s\"" % (actname, widget_title))
+43 -28
View File
@@ -1,44 +1,59 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
import idaapi
import ida_gdl
import ida_funcs
import ida_kernwin
def out(p, msg):
if p:
print(msg)
def out_succ(p, start_ea, end_ea):
out(p, " SUCC: %x - %x" % (start_ea, end_ea))
def out_pred(p, start_ea, end_ea):
out(p, " PRED: %x - %x" % (start_ea, end_ea))
# -----------------------------------------------------------------------
# Using raw IDAAPI
def raw_main(p=True):
f = idaapi.get_func(here())
# Using ida_gdl.qflow_chart_t
def using_qflow_chart_t(ea, p=True):
f = ida_funcs.get_func(ea)
if not f:
return
q = idaapi.qflow_chart_t("The title", f, 0, 0, idaapi.FC_PREDS)
for n in range(0, q.size()):
q = ida_gdl.qflow_chart_t("The title", f, 0, 0, 0)
for n in range(q.size()):
b = q[n]
if p:
print("%x - %x [%d]:" % (b.start_ea, b.end_ea, n))
out(p, "%x - %x [%d]:" % (b.start_ea, b.end_ea, n))
for ns in range(q.nsucc(n)):
b2 = q[q.succ(n, ns)]
out_succ(p, b2.start_ea, b2.end_ea)
for ns in range(0, q.nsucc(n)):
if p:
print("SUCC: %d->%d" % (n, q.succ(n, ns)))
for ns in range(0, q.npred(n)):
if p:
print("PRED: %d->%d" % (n, q.pred(n, ns)))
for ns in range(q.npred(n)):
b2 = q[q.pred(n, ns)]
out_pred(p, b2.start_ea, b2.end_ea)
# -----------------------------------------------------------------------
# Using the class
def cls_main(p=True):
f = idaapi.FlowChart(idaapi.get_func(here()))
# Using ida_gdl.FlowChart
def using_FlowChart(ea, p=True):
f = ida_gdl.FlowChart(ida_funcs.get_func(ea))
for block in f:
if p:
print("%x - %x [%d]:" % (block.start_ea, block.end_ea, block.id))
out(p, "%x - %x [%d]:" % (block.start_ea, block.end_ea, block.id))
for succ_block in block.succs():
if p:
print(" %x - %x [%d]:" % (succ_block.start_ea, succ_block.end_ea, succ_block.id))
out_succ(p, succ_block.start_ea, succ_block.end_ea)
for pred_block in block.preds():
if p:
print(" %x - %x [%d]:" % (pred_block.start_ea, pred_block.end_ea, pred_block.id))
out_pred(p, pred_block.start_ea, pred_block.end_ea)
q = None
f = None
raw_main(False)
cls_main(True)
ea = ida_kernwin.get_screen_ea()
print(">>> Dumping flow chart using ida_gdl.qflow_chart_t")
using_qflow_chart_t(ea)
print(">>> Dumping flow chart using the higher-level ida_gdl.FlowChart")
using_FlowChart(ea)
+6 -12
View File
@@ -3,19 +3,13 @@ from __future__ import print_function
# This is an example illustrating how to extend IDC from Python
# (c) Hex-Rays
#
from idaapi import add_idc_func
def py_power(n, e):
return n ** e
import ida_expr
desc = ext_idcfunc_t
desc.name = "pow"
desc.func = py_power,
desc.args = (idaapi.VT_LONG, idaapi.VT_LONG),
desc.defvals = ()
desc.flags = 0
ok = add_idc_func(desc)
if ok:
print("Now the pow() will be present IDC!")
if ida_expr.add_idc_func(
"pow",
lambda n, e: n ** e,
(ida_expr.VT_LONG, ida_expr.VT_LONG)):
print("The pow() function is now available in IDC")
else:
print("Failed to register pow() IDC function")
+6 -4
View File
@@ -4,16 +4,18 @@
# Place this script to ~/.idapro/ or to
# %APPDATA%\Hex-Rays\IDA Pro
#---------------------------------------------------------------------
import idaapi
# Add your favourite script to ScriptBox for easy access
# scriptbox.addscript("/here/is/my/favourite/script.py")
# Uncomment if you want to set Python as default interpreter in IDA
# idaapi.enable_extlang_python(True)
# import ida_idaapi
# ida_idaapi.enable_extlang_python(True)
# Disable the Python from interactive command-line
# idaapi.enable_python_cli(False)
# import ida_idaapi
# ida_idaapi.enable_python_cli(False)
# Set the timeout for the script execution cancel dialog
# idaapi.set_script_timeout(10)
# import ida_idaapi
# ida_idaapi.set_script_timeout(10)
+20 -22
View File
@@ -1,41 +1,39 @@
from __future__ import print_function
import idaapi
PREFIX = idaapi.SCOLOR_INV + ' ' + idaapi.SCOLOR_INV
import ida_lines
import ida_idaapi
class prefix_plugin_t(idaapi.plugin_t):
flags = 0
comment = "This is a user defined prefix sample plugin"
help = "This is help"
wanted_name = "user defined prefix"
wanted_hotkey = ""
def user_prefix(self, ea, lnnum, indent, line, bufsize):
#print("ea=%x lnnum=%d indent=%d line=%s bufsize=%d" % (ea, lnnum, indent, line, bufsize))
PREFIX = ida_lines.SCOLOR_INV + ' ' + ida_lines.SCOLOR_INV
class my_user_prefix_t(ida_lines.user_defined_prefix_t):
def get_user_defined_prefix(self, ea, insn, lnnum, indent, line):
if (ea % 2 == 0) and indent == -1:
return PREFIX
else:
return ""
class prefix_plugin_t(ida_idaapi.plugin_t):
flags = 0
comment = "This is a user defined prefix sample plugin"
help = "This is help"
wanted_name = "user defined prefix"
wanted_hotkey = ""
def __init__(self):
self.prefix = None
def init(self):
self.prefix_installed = idaapi.set_user_defined_prefix(8, self.user_prefix)
if self.prefix_installed:
print("prefix installed")
return idaapi.PLUGIN_KEEP
self.prefix = my_user_prefix_t(8)
print("prefix installed")
return ida_idaapi.PLUGIN_KEEP
def run(self, arg):
pass
def term(self):
if self.prefix_installed:
idaapi.set_user_defined_prefix(0, None)
print("prefix uninstalled!")
self.prefix = None
print("prefix uninstalled!")
def PLUGIN_ENTRY():
+15 -16
View File
@@ -3,28 +3,27 @@ from __future__ import print_function
# This is an example illustrating how to enumerate imports
# (c) Hex-Rays
#
import idaapi
import ida_nalt
def imp_cb(ea, name, ord):
if not name:
print("%08x: ord#%d" % (ea, ord))
else:
print("%08x: %s (ord#%d)" % (ea, name, ord))
# True -> Continue enumeration
# False -> Stop enumeration
return True
nimps = idaapi.get_import_module_qty()
nimps = ida_nalt.get_import_module_qty()
print("Found %d import(s)..." % nimps)
for i in range(0, nimps):
name = idaapi.get_import_module_name(i)
for i in range(nimps):
name = ida_nalt.get_import_module_name(i)
if not name:
print("Failed to get import module name for #%d" % i)
continue
name = "<unnamed>"
print("Walking-> %s" % name)
idaapi.enum_import_names(i, imp_cb)
print("Walking imports for module %s" % name)
def imp_cb(ea, name, ordinal):
if not name:
print("%08x: ordinal #%d" % (ea, ordinal))
else:
print("%08x: %s (ordinal #%d)" % (ea, name, ordinal))
# True -> Continue enumeration
# False -> Stop enumeration
return True
ida_nalt.enum_import_names(i, imp_cb)
print("All done...")
+5 -4
View File
@@ -3,7 +3,8 @@ from __future__ import print_function
# This is an example illustrating how to visit all patched bytes in Python
# (c) Hex-Rays
import idaapi
import ida_bytes
import ida_idaapi
# -------------------------------------------------------------------------
class patched_bytes_visitor(object):
@@ -14,7 +15,7 @@ class patched_bytes_visitor(object):
def __call__(self, ea, fpos, o, v, cnt=()):
if fpos == -1:
self.skip += 1
print(" ea: %x o: %x v: %x...skipped" % (ea, fpos, o, v))
print(" ea: %x o: %x v: %x...skipped" % (ea, o, v))
else:
self.patch += 1
print(" ea: %x fpos: %x o: %x v: %x" % (ea, fpos, o, v))
@@ -25,7 +26,7 @@ class patched_bytes_visitor(object):
def main():
print("Visiting all patched bytes:")
v = patched_bytes_visitor()
r = idaapi.visit_patched_bytes(0, idaapi.BADADDR, v)
r = ida_bytes.visit_patched_bytes(0, ida_idaapi.BADADDR, v)
if r != 0:
print("visit_patched_bytes() returned %d" % r)
else:
@@ -34,4 +35,4 @@ def main():
# -------------------------------------------------------------------------
if __name__ == '__main__':
main()
main()
+30
View File
@@ -0,0 +1,30 @@
import ida_ida
import ida_idaapi
import ida_problems
for ptype in [
ida_problems.PR_NOBASE,
ida_problems.PR_NONAME,
ida_problems.PR_NOFOP,
ida_problems.PR_NOCMT,
ida_problems.PR_NOXREFS,
ida_problems.PR_JUMP,
ida_problems.PR_DISASM,
ida_problems.PR_HEAD,
ida_problems.PR_ILLADDR,
ida_problems.PR_MANYLINES,
ida_problems.PR_BADSTACK,
ida_problems.PR_ATTN,
ida_problems.PR_FINAL,
ida_problems.PR_ROLLED,
ida_problems.PR_COLLISION,
ida_problems.PR_DECIMP,
]:
plistdesc = ida_problems.get_problem_name(ptype)
ea = ida_ida.inf_get_min_ea()
while True:
ea = ida_problems.get_problem(ptype, ea+1)
if ea == ida_idaapi.BADADDR:
break
print("0x%08x: %s" % (ea, plistdesc))
+17 -12
View File
@@ -6,36 +6,41 @@ from __future__ import print_function
#
# Implemented using direct IDA Plugin API calls
#
from idaapi import *
import ida_kernwin
import ida_segment
import ida_funcs
import ida_xref
import ida_idaapi
def main():
# Get current ea
ea = get_screen_ea()
ea = ida_kernwin.get_screen_ea()
# Get segment class
seg = getseg(ea)
seg = ida_segment.getseg(ea)
# Loop from segment start to end
func_ea = seg.startEA
func_ea = seg.start_ea
# Get a function at the start of the segment (if any)
func = get_func(func_ea)
func = ida_funcs.get_func(func_ea)
if func is None:
# No function there, try to get the next one
func = get_next_func(func_ea)
func = ida_funcs.get_next_func(func_ea)
seg_end = seg.end_ea
while func is not None and func.start_ea < seg_end:
funcea = func.start_ea
print("Function %s at 0x%x" % (get_func_name(funcea), funcea))
print("Function %s at 0x%x" % (ida_funcs.get_func_name(funcea), funcea))
ref = get_first_cref_to(funcea)
ref = ida_xref.get_first_cref_to(funcea)
while ref != BADADDR:
print(" called from %s(0x%x)" % (get_func_name(ref), ref))
ref = get_next_cref_to(funcea, ref)
while ref != ida_idaapi.BADADDR:
print(" called from %s(0x%x)" % (ida_funcs.get_func_name(ref), ref))
ref = ida_xref.get_next_cref_to(funcea, ref)
func = get_next_func(funcea)
func = ida_funcs.get_next_func(funcea)
main()
@@ -6,23 +6,32 @@ from __future__ import print_function
#
# Implemented with the idautils module
#
from idautils import *
import ida_kernwin
import ida_idaapi
import ida_segment
import ida_funcs
import idautils
def main():
# Get current ea
ea = get_screen_ea()
if ea == idaapi.BADADDR:
ea = ida_kernwin.get_screen_ea()
if ea == ida_idaapi.BADADDR:
print("Could not get get_screen_ea()")
return
# Loop from start to end in the current segment
for funcea in Functions(get_segm_start(ea), get_segm_end(ea)):
print("Function %s at 0x%x" % (get_func_name(funcea), funcea))
# Find all code references to funcea
for ref in CodeRefsTo(funcea, 1):
print(" called from %s(0x%x)" % (get_func_name(ref), ref))
seg = ida_segment.getseg(ea)
if seg:
# Loop from start to end in the current segment
for funcea in idautils.Functions(seg.start_ea, seg.end_ea):
print("Function %s at 0x%x" % (ida_funcs.get_func_name(funcea), funcea))
# Find all code references to funcea
for ref in idautils.CodeRefsTo(funcea, 1):
print(" called from %s(0x%x)" % (ida_funcs.get_func_name(ref), ref))
else:
print("Please position the cursor within a segment")
if __name__=='__main__':
main()
main()
+69
View File
@@ -0,0 +1,69 @@
#
# This example demonstrates how to retrieve all xrefs to
# a stack variable within a function.
# Contrary to (in-memory) data & code xrefs, retrieving
# stack variables xrefs require a bit more work than just
# using ida_xref's first_to(), next_to() (or higher level
# utilities such as idautils.XrefsTo)
#
# Press Ctrl+Shift+F7 to invoke the action that will print xrefs
# to the variable name that's under the cursor.
#
ACTION_NAME = "list_stkvar_xrefs:list"
ACTION_SHORTCUT = "Ctrl+Shift+F7"
import ida_bytes
import ida_frame
import ida_funcs
import ida_ida
import ida_kernwin
import ida_struct
import ida_ua
class list_stkvar_xrefs_ah_t(ida_kernwin.action_handler_t):
def activate(self, ctx):
cur_ea = ida_kernwin.get_screen_ea()
pfn = ida_funcs.get_func(cur_ea)
if pfn:
v = ida_kernwin.get_current_viewer()
result = ida_kernwin.get_highlight(v)
if result:
stkvar_name, _ = result
frame = ida_frame.get_frame(cur_ea)
sptr = ida_struct.get_struc(frame.id)
mptr = ida_struct.get_member_by_name(sptr, stkvar_name)
if mptr:
fii = ida_funcs.func_item_iterator_t()
ok = fii.set(pfn)
while ok:
ea = fii.current()
F = ida_bytes.get_flags(ea)
for n in range(ida_ida.UA_MAXOP):
if not ida_bytes.is_stkvar(F, n):
continue
insn = ida_ua.insn_t()
if not ida_ua.decode_insn(insn, ea):
continue
v = ida_frame.calc_stkvar_struc_offset(pfn, insn, n)
if v >= mptr.soff and v < mptr.eoff:
print("Found xref at 0x%08x, operand #%d" % (ea, n))
ok = fii.next_code()
else:
print("No stack variable named \"%s\"" % stkvar_name)
else:
print("Please position the cursor within a function")
def update(self, ctx):
return ida_kernwin.AST_ENABLE_FOR_WIDGET \
if ctx.widget_type == ida_kernwin.BWN_DISASM \
else ida_kernwin.AST_DISABLE_FOR_WIDGET
adesc = ida_kernwin.action_desc_t(
ACTION_NAME,
"List stack variable xrefs",
list_stkvar_xrefs_ah_t(),
ACTION_SHORTCUT)
if ida_kernwin.register_action(adesc):
print("Action registered. Please press \"%s\" to use" % ACTION_SHORTCUT)
+32
View File
@@ -0,0 +1,32 @@
"""
This example demonstrates how one can automate IDA to perform auto-analysis
on a file and, as soon as it is finished, produce a .c file containing the
decompilation of all the functions that the file contains.
Run like so:
ida -A "-S...path/to/produce_c_file.py" <binary-file>
where:
-A instructs IDA to run in non-interactive mode
-S holds a path to the script to run (note this is a single token;
there is no space between '-S' and its path.)
"""
import ida_pro
import ida_auto
import ida_loader
import ida_hexrays
# derive output file name
idb_path = ida_loader.get_path(ida_loader.PATH_TYPE_IDB)
c_path = "%s.c" % idb_path
ida_auto.auto_wait() # wait for end of auto-analysis
ida_hexrays.decompile_many( # generate .c file
c_path,
None,
ida_hexrays.VDRUN_NEWFILE
|ida_hexrays.VDRUN_SILENT
|ida_hexrays.VDRUN_MAYSTOP)
ida_pro.qexit(0)
+38
View File
@@ -0,0 +1,38 @@
"""
This example demonstrates how one can automate IDA to perform auto-analysis
on a file and, as soon as it is finished, produce a .lst file containing the
disassembly.
Run like so:
ida -A "-S...path/to/produce_lst_file.py" <binary-file>
where:
-A instructs IDA to run in non-interactive mode
-S holds a path to the script to run (note this is a single token;
there is no space between '-S' and its path.)
"""
import ida_auto
import ida_fpro
import ida_ida
import ida_loader
import ida_pro
# derive output file name
idb_path = ida_loader.get_path(ida_loader.PATH_TYPE_IDB)
lst_path = "%s.lst" % idb_path
ida_auto.auto_wait() # wait for end of auto-analysis
fptr = ida_fpro.qfile_t() # FILE * wrapper
if fptr.open(lst_path, "wt"):
try:
ida_loader.gen_file( # generate .lst file
ida_loader.OFILE_LST,
fptr.get_fp(),
ida_ida.inf_get_min_ea(),
ida_ida.inf_get_max_ea(),
0)
finally:
fptr.close()
ida_pro.qexit(0)
+6 -6
View File
@@ -3,13 +3,13 @@ from __future__ import print_function
# This is an example illustrating how to use timers
# (c) Hex-Rays
import idaapi
import ida_kernwin
# -------------------------------------------------------------------------
class timercallback_t(object):
def __init__(self):
self.interval = 1000
self.obj = idaapi.register_timer(self.interval, self)
self.obj = ida_kernwin.register_timer(self.interval, self)
if self.obj is None:
raise RuntimeError("Failed to register timer")
self.times = 5
@@ -21,19 +21,19 @@ class timercallback_t(object):
return -1 if self.times == 0 else self.interval
def __del__(self):
print("Timer object disposed %s" % id(self))
print("Timer object disposed %s" % self)
# -------------------------------------------------------------------------
def main():
try:
t = timercallback_t()
# No need to unregister the timer.
# It will unregister itself in the callback when it returns -1
# No need to unregister the timer.
# It will unregister itself in the callback when it returns -1
except Exception as e:
print("Error: %s" % e)
# -------------------------------------------------------------------------
if __name__ == '__main__':
main()
main()
@@ -1,12 +1,17 @@
from __future__ import print_function
# -----------------------------------------------------------------------
# This is an example illustrating how to use the execute_ui_requests()
# and the idautils.ProcessUiActions()
# This is an example illustrating how to use
# * ida_kernwin.execute_ui_requests()
# * ida_kernwin.process_ui_action()
#
# Ideally, this script should be run through the "File > Script file..."
# menu, so as to keep focus on "IDA View-A" and have the
# 'ProcessUiActions' part work as intended.
#
# (c) Hex-Rays
#
import idaapi
import idautils
import idc
import ida_kernwin
# --------------------------------------------------------------------------
class __process_ui_actions_helper(object):
@@ -34,9 +39,9 @@ class __process_ui_actions_helper(object):
return False
# Execute one action
idaapi.process_ui_action(
self.__action_list[self.__idx],
self.__flags)
aname = self.__action_list[self.__idx]
print("executing: %s (flags=0x%x)" % (aname, self.__flags))
print("=> %s" % ida_kernwin.process_ui_action(aname, self.__flags))
# Move to next action
self.__idx += 1
@@ -55,7 +60,7 @@ def ProcessUiActions(actions, flags=0):
# Instantiate a helper
helper = __process_ui_actions_helper(actions, flags)
return False if len(helper) < 1 else idaapi.execute_ui_requests((helper,))
return False if len(helper) < 1 else ida_kernwin.execute_ui_requests((helper,))
# --------------------------------------------------------------------------
@@ -63,14 +68,15 @@ class print_req_t(object):
def __init__(self, s):
self.s = s
def __call__(self):
idaapi.msg("%s" % self.s)
ida_kernwin.msg("%s" % self.s)
return False # Don't reschedule
if idc.ask_yn(1,("HIDECANCEL\nDo you want to run execute_ui_requests() example?\n"
"Press NO to execute ProcessUiActions() example\n")):
idaapi.execute_ui_requests(
(print_req_t("Hello"), print_req_t(" world\n")) )
if ida_kernwin.ask_yn(
1, ("HIDECANCEL\nDo you want to run execute_ui_requests() example?\n"
"Press NO to execute ProcessUiActions() example\n")):
ida_kernwin.execute_ui_requests(
(print_req_t("Hello"),
print_req_t(" world\n")) )
else:
ProcessUiActions("JumpQ;JumpName")
ProcessUiActions("JumpQ;Breakpoints")
@@ -0,0 +1,46 @@
import ida_dbg
import ida_idaapi
import ida_idd
import ida_kernwin
import ida_typeinf
import ida_name
def log(msg):
print(">>> %s" % msg)
class appcall_hooks_t(ida_dbg.DBG_Hooks):
def __init__(self, name_funcs=[]):
ida_dbg.DBG_Hooks.__init__(self) # important
for ea, func_name in name_funcs:
log("Renaming 0x%08x to \"%s\"" % (ea, func_name))
ida_name.set_name(ea, func_name)
for func_name, func_proto in [
("ref4", "int ref4(int *);"),
("ref8", "int ref8(long long int *);"),
]:
log("Setting '%s's prototype" % func_name)
func_ea = ida_name.get_name_ea(ida_idaapi.BADADDR, func_name)
assert(ida_typeinf.apply_cdecl(None, func_ea, func_proto))
def dbg_run_to(self, pid, tid, ea):
log("'run_to' reached its target location. Performing appcalls.")
for func_name in ["ref4", "ref8"]:
int_value = ida_idd.Appcall.int64(5)
int_ptr = ida_idd.Appcall.byref(int_value)
if ida_idd.Appcall[func_name](int_ptr):
log("Appcall (%s) succeeded: int_value.value=%s, int_ptr.value=%s" % (
func_name,
int_value.value,
int_ptr.value))
else:
log("Appcall (%s) failed" % func_name)
def run(self):
log("Running program up to current address, and letting the hooks do the rest")
assert(ida_dbg.run_to(ida_kernwin.get_screen_ea()))
@@ -0,0 +1,26 @@
from __future__ import print_function
#
# This sample illustrates how to use appcall, with the
# 'simple_appcall_linux32' or 'simple_appcall_linux64' test
# programs (see subdirectories.)
#
# This example will run the test program and stop wherever
# the cursor currently is, and then perform an appcall to
# `ref4` and `ref8`
#
# To use this example:
# * run `ida64` on test program `simple_appcall_linux64`, or
# `ida` on test program `simple_appcall_linux32`, and wait for
# auto-analysis to finish
# * select the 'linux debugger' (either local, or remote)
# * run this script
#
import os
import sys
sys.path.append(os.path.dirname(__file__))
import simple_appcall_common
appcall_hooks = simple_appcall_common.appcall_hooks_t()
appcall_hooks.hook()
appcall_hooks.run()
@@ -0,0 +1,42 @@
from __future__ import print_function
#
# This sample illustrates how to use appcall, with the
# 'simple_appcall_win32.exe' or 'simple_appcall_win64.exe' test
# programs (see subdirectories.)
#
# This example will run the test program and stop wherever
# the cursor currently is, and then perform an appcall to
# `ref4` and `ref8`
#
# To use this example:
# * run `ida64` on test program `simple_appcall_win64.exe`, or
# `ida` on test program `simple_appcall_win32.exe`, and wait for
# auto-analysis to finish
# * select the 'windows debugger' (either local, or remote)
# * run this script
#
import os
import sys
sys.path.append(os.path.dirname(__file__))
# Windows binaries don't have any symbols, thus we'll have
# to assign names to addresses of interest before we can
# appcall them by name.
import ida_ida
if ida_ida.inf_is_64bit():
ref4_ea = 0x140001000
ref8_ea = 0x140001060
else:
ref4_ea = 0x401000
ref8_ea = 0x401050
import simple_appcall_common
appcall_hooks = simple_appcall_common.appcall_hooks_t(
name_funcs=[
(ref4_ea, "ref4"),
(ref8_ea, "ref8"),
])
appcall_hooks.hook()
appcall_hooks.run()
@@ -0,0 +1,47 @@
ifdef __NT__
EA32_TARGET:=simple_appcall_win32.exe
EA64_TARGET:=simple_appcall_win64.exe
else
ifdef __LINUX__
EA32_TARGET:=simple_appcall_linux32
EA64_TARGET:=simple_appcall_linux64
else
$(error Not implemented for OSX)
endif
endif
all: $(EA32_TARGET) $(EA64_TARGET)
simple_appcall_win32.exe: simple_appcall_win32.obj
C:/PROGRA~2/MIB055~1/2017/PROFES~1/VC/Tools/MSVC/1415~1.267/bin/HostX86/x86/link.exe \
/LIBPATH:C:/PROGRA~2/MIB055~1/2017/PROFES~1/VC/Tools/MSVC/1415~1.267/lib/x86 \
/LIBPATH:C:/PROGRA~2/WI3CF2~1/10/Lib/100171~1.0/ucrt/x86 \
/LIBPATH:C:/idasrc/THIRD_~1/mssdk/8.1/Lib/x86 \
/OUT:$@ $<
simple_appcall_win32.obj: simple_appcall.c
C:/PROGRA~2/MIB055~1/2017/PROFES~1/VC/Tools/MSVC/1415~1.267/bin/HostX86/x86/cl.exe \
/IC:/PROGRA~2/MIB055~1/2017/PROFES~1/VC/Tools/MSVC/1415~1.267/Include \
/IC:/PROGRA~2/WI3CF2~1/10/Include/100171~1.0/ucrt \
/Zi /D__NT__ /DNDEBUG /DWIN32 /D_CONSOLE /D__VC__ /c /MD $< /Fo$@
simple_appcall_win64.exe: simple_appcall_win64.obj
C:/PROGRA~2/MIB055~1/2017/PROFES~1/VC/Tools/MSVC/1415~1.267/bin/HostX86/x86/link.exe \
/LIBPATH:C:/PROGRA~2/MIB055~1/2017/PROFES~1/VC/Tools/MSVC/1415~1.267/lib/x64 \
/LIBPATH:C:/PROGRA~2/WI3CF2~1/10/Lib/100171~1.0/ucrt/x64 \
/LIBPATH:C:/idasrc/THIRD_~1/mssdk/8.1/Lib/x64 \
/OUT:$@ $<
simple_appcall_win64.obj: simple_appcall.c
C:/PROGRA~2/MIB055~1/2017/PROFES~1/VC/Tools/MSVC/1415~1.267/bin/HostX64/x64/cl.exe \
/IC:/PROGRA~2/MIB055~1/2017/PROFES~1/VC/Tools/MSVC/1415~1.267/Include \
/IC:/PROGRA~2/WI3CF2~1/10/Include/100171~1.0/ucrt \
/Zi /D__NT__ /DNDEBUG /DWIN32 /D_CONSOLE /D__VC__ /c /MD $< /Fo$@
simple_appcall_linux32: simple_appcall.c
gcc -m32 -o $@ $<
simple_appcall_linux64: simple_appcall.c
gcc -m64 -o $@ $<
@@ -0,0 +1,35 @@
#include <stdio.h>
typedef int int32;
int ref4(int32 *a)
{
if (a == NULL)
{
printf("ref4: no number passed!");
return -1;
}
printf("ref4: entered with %d\n", *a);
(*a)++;
return 1;
}
typedef long long int int64;
int ref8(int64 *a)
{
if (a == NULL)
{
printf("ref8: no number passed!");
return -1;
}
printf("ref8: entered with %lld\n", *a);
(*a)++;
return 1;
}
int main()
{
int32 x;
int res = ref4(&x);
int64 y;
return res + ref8(&y);
}
+38 -33
View File
@@ -10,33 +10,41 @@ from __future__ import print_function
# Maintained By: IDAPython Team
#
#---------------------------------------------------------------------
from idaapi import *
class MyDbgHook(DBG_Hooks):
import ida_dbg
import ida_ida
import ida_lines
class MyDbgHook(ida_dbg.DBG_Hooks):
""" Own debug hook class that implementd the callback functions """
def __init__(self):
ida_dbg.DBG_Hooks.__init__(self) # important
self.steps = 0
def log(self, msg):
print(">>> %s" % msg)
def dbg_process_start(self, pid, tid, ea, name, base, size):
print("Process started, pid=%d tid=%d name=%s" % (pid, tid, name))
self.log("Process started, pid=%d tid=%d name=%s" % (pid, tid, name))
def dbg_process_exit(self, pid, tid, ea, code):
print("Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code))
self.log("Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code))
def dbg_library_unload(self, pid, tid, ea, info):
print("Library unloaded: pid=%d tid=%d ea=0x%x info=%s" % (pid, tid, ea, info))
return 0
self.log("Library unloaded: pid=%d tid=%d ea=0x%x info=%s" % (pid, tid, ea, info))
def dbg_process_attach(self, pid, tid, ea, name, base, size):
print("Process attach pid=%d tid=%d ea=0x%x name=%s base=%x size=%x" % (pid, tid, ea, name, base, size))
self.log("Process attach pid=%d tid=%d ea=0x%x name=%s base=%x size=%x" % (pid, tid, ea, name, base, size))
def dbg_process_detach(self, pid, tid, ea):
print("Process detached, pid=%d tid=%d ea=0x%x" % (pid, tid, ea))
return 0
self.log("Process detached, pid=%d tid=%d ea=0x%x" % (pid, tid, ea))
def dbg_library_load(self, pid, tid, ea, name, base, size):
print("Library loaded: pid=%d tid=%d name=%s base=%x" % (pid, tid, name, base))
self.log("Library loaded: pid=%d tid=%d name=%s base=%x" % (pid, tid, name, base))
def dbg_bpt(self, tid, ea):
print("Break point at 0x%x pid=%d" % (ea, tid))
self.log("Break point at 0x%x pid=%d" % (ea, tid))
# return values:
# -1 - to display a breakpoint warning dialog
# if the process is suspended.
@@ -45,11 +53,11 @@ class MyDbgHook(DBG_Hooks):
return 0
def dbg_suspend_process(self):
print("Process suspended")
self.log("Process suspended")
def dbg_exception(self, pid, tid, ea, exc_code, exc_can_cont, exc_ea, exc_info):
print("Exception: pid=%d tid=%d ea=0x%x exc_code=0x%x can_continue=%d exc_ea=0x%x exc_info=%s" % (
pid, tid, ea, exc_code & idaapi.BADADDR, exc_can_cont, exc_ea, exc_info))
self.log("Exception: pid=%d tid=%d ea=0x%x exc_code=0x%x can_continue=%d exc_ea=0x%x exc_info=%s" % (
pid, tid, ea, exc_code & ida_idaapi.BADADDR, exc_can_cont, exc_ea, exc_info))
# return values:
# -1 - to display an exception warning dialog
# if the process is suspended.
@@ -58,30 +66,32 @@ class MyDbgHook(DBG_Hooks):
return 0
def dbg_trace(self, tid, ea):
print("Trace tid=%d ea=0x%x" % (tid, ea))
self.log("Trace tid=%d ea=0x%x" % (tid, ea))
# return values:
# 1 - do not log this trace event;
# 0 - log it
return 0
def dbg_step_into(self):
print("Step into")
self.log("Step into")
self.dbg_step_over()
def dbg_run_to(self, pid, tid=0, ea=0):
print("Runto: tid=%d" % tid)
idaapi.continue_process()
self.log("Runto: tid=%d, ea=%x" % (tid, ea))
ida_dbg.request_step_over()
def dbg_step_over(self):
eip = get_reg_value("EIP")
print("0x%x %s" % (eip, GetDisasm(eip)))
eip = ida_dbg.get_reg_val("EIP")
disasm = ida_lines.tag_remove(
ida_lines.generate_disasm_line(
eip))
self.log("Step over: EIP=0x%x, disassembly=%s" % (eip, disasm))
self.steps += 1
if self.steps >= 5:
request_exit_process()
ida_dbg.request_exit_process()
else:
request_step_over()
ida_dbg.request_step_over()
# Remove an existing debug hook
@@ -95,14 +105,9 @@ except:
# Install the debug hook
debughook = MyDbgHook()
debughook.hook()
debughook.steps = 0
# Stop at the entry point
ep = get_inf_attr(INF_START_IP)
request_run_to(ep)
# Step one instruction
request_step_over()
# Start debugging
run_requests()
ep = ida_ida.inf_get_start_ip()
if ida_dbg.request_run_to(ep): # Request stop at entry point
ida_dbg.run_requests() # Launch process
else:
print("Impossible to prepare debugger requests. Is a debugger selected?")
+110
View File
@@ -0,0 +1,110 @@
"""
This script demonstrates using the low-level tracing hook (dbg_trace)
It can be run like: ida[t].exe -B -Sdbg_trace.py -Ltrace.log file.exe
"""
import time
import ida_dbg
import ida_ida
import ida_pro
import ida_ua
from ida_allins import NN_callni, NN_call, NN_callfi
from ida_lines import generate_disasm_line, GENDSM_FORCE_CODE, GENDSM_REMOVE_TAGS
# Note: this try/except block below is just there to
# let us (at Hex-Rays) test this script in various
# situations.
try:
import idc
print(idc.ARGV[1])
under_test = bool(idc.ARGV[1])
except:
under_test = False
class TraceHook(ida_dbg.DBG_Hooks):
def __init__(self):
ida_dbg.DBG_Hooks.__init__(self)
self.traces = 0
self.epReached = False
def _log(self, msg):
print(">>> %s" % msg)
def dbg_trace(self, tid, ea):
# Log all traced addresses
if ea < ida_ida.inf_get_min_ea() or ea > ida_ida.inf_get_max_ea():
raise Exception(
"Received a trace callback for an address outside this database!"
)
self._log("trace %08X" % ea)
self.traces += 1
insn = ida_ua.insn_t()
insnlen = ida_ua.decode_insn(insn, ea)
# log disassembly and ESP for call instructions
if insnlen > 0 and insn.itype in [NN_callni, NN_call, NN_callfi]:
self._log(
"call insn: %s"
% generate_disasm_line(ea, GENDSM_FORCE_CODE | GENDSM_REMOVE_TAGS)
)
self._log("ESP=%08X" % ida_dbg.get_reg_val("ESP"))
return 1
def dbg_run_to(self, pid, tid=0, ea=0):
# this hook is called once execution reaches temporary breakpoint set by run_to(ep) below
if not self.epReached:
ida_dbg.refresh_debugger_memory()
self._log("reached entry point at 0x%X" % ida_dbg.get_reg_val("EIP"))
self._log("current step trace options: %x" % ida_dbg.get_step_trace_options())
self.epReached = True
# enable step tracing (single-step the program and generate dbg_trace events)
ida_dbg.request_enable_step_trace(1)
# change options to only "over debugger segments" (i.e. library functions will be traced)
ida_dbg.request_set_step_trace_options(ida_dbg.ST_OVER_DEBUG_SEG)
ida_dbg.request_continue_process()
ida_dbg.run_requests()
def dbg_process_exit(self, pid, tid, ea, code):
self._log("process exited with %d" % code)
self._log("traced %d instructions" % self.traces)
return 0
def do_trace(then_quit_ida=True):
debugHook = TraceHook()
debugHook.hook()
# Start tracing when entry point is hit
ep = ida_ida.inf_get_start_ip()
ida_dbg.enable_step_trace(1)
ida_dbg.set_step_trace_options(ida_dbg.ST_OVER_DEBUG_SEG | ida_dbg.ST_OVER_LIB_FUNC)
print("Running to %x" % ep)
ida_dbg.run_to(ep)
while ida_dbg.get_process_state() != 0:
ida_dbg.wait_for_next_event(1, 0)
if not debugHook.epReached:
raise Exception("Entry point wasn't reached!")
if not debugHook.unhook():
raise Exception("Error uninstalling hooks!")
del debugHook
if then_quit_ida:
# we're done; exit IDA
ida_pro.qexit(0)
# load the debugger module depending on the file type
if ida_ida.inf_get_filetype() == ida_ida.f_PE:
ida_dbg.load_debugger("win32", 0)
elif ida_ida.inf_get_filetype() == ida_ida.f_ELF:
ida_dbg.load_debugger("linux", 0)
elif ida_ida.inf_get_filetype() == ida_ida.f_MACHO:
ida_dbg.load_debugger("mac", 0)
if not under_test:
do_trace()
@@ -0,0 +1,48 @@
import ida_dbg
import ida_idd
import ida_kernwin
import ida_ua
ACTION_NAME = "registers_context_menu:dump_reg"
class dump_reg_ah_t(ida_kernwin.action_handler_t):
def activate(self, ctx):
name = ctx.regname
value = ida_dbg.get_reg_val(name)
rtype = "integer"
rinfo = ida_idd.register_info_t()
if ida_dbg.get_dbg_reg_info(name, rinfo):
if rinfo.dtype == ida_ua.dt_byte:
value = "0x%02x" % value
elif rinfo.dtype == ida_ua.dt_word:
value = "0x%04x" % value
elif rinfo.dtype == ida_ua.dt_dword:
value = "0x%08x" % value
elif rinfo.dtype == ida_ua.dt_qword:
value = "0x%016x" % value
else:
rtype = "float"
print("> Register %s (of type %s): %s" % (name, rtype, value))
def update(self, ctx):
return ida_kernwin.AST_ENABLE_FOR_WIDGET \
if ctx.widget_type == ida_kernwin.BWN_CPUREGS \
else ida_kernwin.AST_DISABLE_FOR_WIDGET
if ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTION_NAME,
"Dump register info",
dump_reg_ah_t())):
class registers_hooks_t(ida_kernwin.UI_Hooks):
def finish_populating_widget_popup(self, form, popup):
if ida_kernwin.get_widget_type(form) == ida_kernwin.BWN_CPUREGS:
ida_kernwin.attach_action_to_popup(form, popup, ACTION_NAME)
hooks = registers_hooks_t()
hooks.hook()
else:
print("Failed to register action")
-35
View File
@@ -1,35 +0,0 @@
from __future__ import print_function
from tempo import *;
def test_getmeminfo():
L = tempo.getmeminfo()
out = []
# start_ea end_ea name sclass sbase bitness perm
for (start_ea, end_ea, name, sclass, sbase, bitness, perm) in L:
out.append("%x: %x name=<%s> sclass=<%s> sbase=%x bitness=%2x perm=%2x" % (start_ea, end_ea, name, sclass, sbase, bitness, perm))
f = file(r"d:\temp\out.log", "w")
f.write(("\n".join(out)).encode("UTF-8"))
f.close()
print("dumped meminfo!")
def test_getregs():
# name flags class dtype bit_strings bit_strings_default_mask
L = tempo.getregs()
out = []
for (name, flags, cls, dtype, bit_strings, bit_strings_default_mask) in L:
out.append("name=<%s> flags=%x class=%x dtype=%x bit_strings_mask=%x" % (name, flags, cls, dtype, bit_strings_default_mask))
if bit_strings:
for s in bit_strings:
out.append(" %s" % s)
f = file(r"d:\temp\out.log", "w")
f.write(("\n".join(out)).encode("UTF-8"))
f.close()
print("dumped regs!")
+9 -4
View File
@@ -1,15 +1,20 @@
from __future__ import print_function
import idaapi
import ida_dbg
import ida_ida
import ida_name
def main():
if not idaapi.is_debugger_on():
if not ida_dbg.is_debugger_on():
print("Please run the process first!")
return
if idaapi.get_process_state() != -1:
if ida_dbg.get_process_state() != -1:
print("Please suspend the debugger first!")
return
dn = idaapi.get_debug_names(idaapi.cvar.inf.min_ea, idaapi.cvar.inf.max_ea)
dn = ida_name.get_debug_names(
ida_ida.inf_get_min_ea(),
ida_ida.inf_get_max_ea())
for i in dn:
print("%08x: %s" % (i, dn[i]))
+3 -2
View File
@@ -17,8 +17,9 @@ import ida_entry
ida_auto.auto_wait()
ALL_DECOMPILERS = {
ida_idp.PLFM_386 : ("hexrays", "hexx64"),
ida_idp.PLFM_ARM : ("hexarm", "hexarm64"),
ida_idp.PLFM_PPC : ("hexppc", "hexppc64"),
ida_idp.PLFM_ARM : ("hexarm", "hexarm64"),
ida_idp.PLFM_PPC : ("hexppc", "hexppc64"),
ida_idp.PLFM_MIPS: ("hexmips", "hexmips64"),
}
pair = ALL_DECOMPILERS.get(ida_idp.ph.id, None)
if pair:
+10 -6
View File
@@ -1,25 +1,29 @@
from __future__ import print_function
import idaapi
import ida_hexrays
import ida_lines
import ida_funcs
import ida_kernwin
def main():
if not idaapi.init_hexrays_plugin():
if not ida_hexrays.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" % ida_hexrays.get_hexrays_version())
f = idaapi.get_func(idaapi.get_screen_ea());
f = ida_funcs.get_func(ida_kernwin.get_screen_ea());
if f is None:
print("Please position the cursor within a function")
return True
cfunc = idaapi.decompile(f);
cfunc = ida_hexrays.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));
print(ida_lines.tag_remove(sline.line));
return True
+25 -7
View File
@@ -1,6 +1,6 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
@@ -19,9 +19,10 @@ import ida_range
import ida_kernwin
import ida_hexrays
import ida_typeinf
import ida_idaapi
class nt_assert_optimizer_t(ida_hexrays.optinsn_t):
def func(self, blk, ins):
def func(self, blk, ins, optflags):
if self.handle_nt_assert(ins):
return 1
return 0
@@ -55,10 +56,27 @@ class nt_assert_optimizer_t(ida_hexrays.optinsn_t):
fa.size = fa.type.get_size()
return True
# --------------------------------------------------------------------------
# a plugin interface, boilerplate code
class my_plugin_t(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_HIDE
wanted_name = "Optimize DbgRaiseAssertionFailure (IDAPython)"
wanted_hotkey = ""
comment = "Sample plugin10 for Hex-Rays decompiler"
help = ""
def init(self):
if ida_hexrays.init_hexrays_plugin():
self.optimizer = nt_assert_optimizer_t()
self.optimizer.install()
return ida_idaapi.PLUGIN_KEEP # keep us in the memory
def term(self):
self.optimizer.remove()
def run(self, arg):
if arg == 1:
return self.optimizer.remove()
elif arg == 2:
return self.optimizer.install()
if ida_hexrays.init_hexrays_plugin():
optimizer = nt_assert_optimizer_t()
optimizer.install()
else:
print('vds10: Hex-rays is not available.')
def PLUGIN_ENTRY():
return my_plugin_t()
+25 -6
View File
@@ -1,6 +1,6 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
@@ -22,6 +22,7 @@ import ida_range
import ida_kernwin
import ida_hexrays
import ida_typeinf
import ida_idaapi
class goto_optimizer_t(ida_hexrays.optblock_t):
def func(self, blk):
@@ -71,9 +72,27 @@ class goto_optimizer_t(ida_hexrays.optblock_t):
mba.verify(True);
return True
# --------------------------------------------------------------------------
# a plugin interface, boilerplate code
class my_plugin_t(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_HIDE
wanted_name = "Optimize goto chains (IDAPython)"
wanted_hotkey = ""
comment = "Sample plugin11 for Hex-Rays decompiler"
help = ""
def init(self):
if ida_hexrays.init_hexrays_plugin():
self.optimizer = goto_optimizer_t()
self.optimizer.install()
return ida_idaapi.PLUGIN_KEEP # keep us in the memory
def term(self):
self.optimizer.remove()
def run(self, arg):
if arg == 1:
return self.optimizer.remove()
elif arg == 2:
return self.optimizer.install()
def PLUGIN_ENTRY():
return my_plugin_t()
if ida_hexrays.init_hexrays_plugin():
optimizer = goto_optimizer_t()
optimizer.install()
else:
print('vds11: Hex-rays is not available.')
+2 -2
View File
@@ -1,9 +1,9 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
# Sample script for Hex-Rays Decompiler.
# It shows list of direct references to a register from the current
# instruction.
#
+2 -2
View File
@@ -1,9 +1,9 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
# Sample script for Hex-Rays Decompiler.
# It generates microcode for selection and dumps it to the output window.
#
# This is a rewrite in Python of the vds13 example that comes with hexrays sdk.
+32 -13
View File
@@ -1,6 +1,6 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
@@ -15,6 +15,7 @@ import ida_idaapi
import ida_hexrays
import ida_lines
import ida_typeinf
import ida_kernwin
# --------------------------------------------------------------------------
class func_stroff_ah_t(ida_kernwin.action_handler_t):
@@ -26,14 +27,16 @@ class func_stroff_ah_t(ida_kernwin.action_handler_t):
vu = ida_hexrays.get_widget_vdui(ctx.widget)
vu.get_current_item(ida_hexrays.USE_KEYBOARD)
# REGION1, will be referenced latter
# REGION1, will be referenced later
# check that the current item is a union field
if not vu.item.is_citem():
ida_kernwin.warning("Please position the cursor on a union member")
return 0
e = vu.item.e
while True:
op = e.op
if op != ida_hexrays.cot_memptr and op != ida_hexrays.cot_memref:
ida_kernwin.warning("Please position the cursor on a union member")
return 0
e = e.x
if op == ida_hexrays.cot_memptr:
@@ -43,6 +46,7 @@ class func_stroff_ah_t(ida_kernwin.action_handler_t):
if ida_typeinf.remove_pointer(e.type).is_union():
break
if not e.type.is_udt():
ida_kernwin.warning("Please position the cursor on a union member")
return 0
# END REGION1
@@ -98,6 +102,7 @@ class func_stroff_ah_t(ida_kernwin.action_handler_t):
# the item itself may be unaddressable.
# TODO: find its addressable parent
if ea == ida_idaapi.BADADDR:
ida_kernwin.warning("Sorry, the current item is not addressable")
return 0
# END REGION4
@@ -126,7 +131,7 @@ class func_stroff_ah_t(ida_kernwin.action_handler_t):
def apply(self, opnum, path, top_tif, spath):
typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, top_tif, '', '')
idaapi.msg("User selected %s of type %s\n" % (spath, typename))
ida_kernwin.msg("User selected %s of type %s\n" % (spath, typename))
if path.empty():
return False
vu.cfunc.set_user_union_selection(self.ea, path)
@@ -151,16 +156,30 @@ class func_stroff_ah_t(ida_kernwin.action_handler_t):
# --------------------------------------------------------------------------
if ida_hexrays.init_hexrays_plugin():
print("Hex-rays version %s has been detected, Structure offsets ready to use" % ida_hexrays.get_hexrays_version())
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
"vds17:strchoose",
"Structure offsets",
func_stroff_ah_t(),
"Shift+T"))
else:
print('vds17: Hex-rays is not available.')
# a plugin interface, boilerplate code
class my_plugin_t(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_HIDE
wanted_name = "Structure offsets (IDAPython)"
wanted_hotkey = ""
comment = "Sample plugin17 for Hex-Rays decompiler"
help = ""
def init(self):
if ida_hexrays.init_hexrays_plugin():
print("Hex-rays version %s has been detected, Structure offsets ready to use" % ida_hexrays.get_hexrays_version())
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
"vds17:strchoose",
"Structure offsets",
func_stroff_ah_t(),
"Shift+T"))
return ida_idaapi.PLUGIN_KEEP # keep us in the memory
def term(self):
pass
def run(self, arg):
pass
def PLUGIN_ENTRY():
return my_plugin_t()
"""
# A few notes about the VDS17 sample
+64
View File
@@ -0,0 +1,64 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
# It installs a custom microcode optimization rule:
# x | ~x => -1
#
# To see this plugin in action please use be_ornot_be.idb
#
import ida_hexrays
import ida_idaapi
# recognize "x | ~x" and replace by -1
class subinsn_optimizer_t(ida_hexrays.minsn_visitor_t):
cnt = 0
def visit_minsn(self): # for each instruction...
ins = self.curins # take a reference to the current instruction
# THE CORE OF THE PLUGIN IS HERE:
# check the pattern "x | ~x"
if ins.opcode == ida_hexrays.m_or and ins.r.is_insn(ida_hexrays.m_bnot) and ins.l == ins.r.d.l:
if not ins.l.has_side_effects(): # avoid destroying side effects
# pattern matched, convert to "mov -1, ..."
ins.opcode = ida_hexrays.m_mov
ins.l.make_number(-1, ins.r.size)
ins.r = ida_hexrays.mop_t()
self.cnt = self.cnt + 1 # number of changes we made
return 0 # continue traversal
# a custom instruction optimizer, boilerplate code
class sample_optimizer_t(ida_hexrays.optinsn_t):
def func(self, blk, ins, optflags):
opt = subinsn_optimizer_t()
ins.for_all_insns(opt)
if opt.cnt != 0: # if we modified microcode,
blk.mba.verify(True) # run the verifier
return opt.cnt # report the number of changes
# a plugin interface, boilerplate code
class my_plugin_t(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_HIDE
wanted_name = "optimize x|~x"
wanted_hotkey = ""
comment = ""
help = ""
def init(self):
if ida_hexrays.init_hexrays_plugin():
self.optimizer = sample_optimizer_t()
self.optimizer.install()
print("Installed sample optimizer for 'x | ~x'")
return ida_idaapi.PLUGIN_KEEP # keep us in the memory
def term(self):
self.optimizer.remove()
def run(self, arg):
if arg == 1:
return self.optimizer.remove()
elif arg == 2:
return self.optimizer.install()
def PLUGIN_ENTRY():
return my_plugin_t()
+53 -38
View File
@@ -7,8 +7,11 @@ This is a rewrite in Python of the vds3 example that comes with hexrays sdk.
from __future__ import print_function
import idautils
import idaapi
import idc
import ida_kernwin
import ida_hexrays
import ida_netnode
import ida_idaapi
import traceback
@@ -16,20 +19,20 @@ NETNODE_NAME = '$ hexrays-inverted-if'
inverter_actname = "vds3:invert"
class invert_action_handler_t(idaapi.action_handler_t):
class invert_action_handler_t(ida_kernwin.action_handler_t):
def __init__(self, inverter):
idaapi.action_handler_t.__init__(self)
ida_kernwin.action_handler_t.__init__(self)
self.inverter = inverter
def activate(self, ctx):
vdui = idaapi.get_widget_vdui(ctx.widget)
vdui = ida_hexrays.get_widget_vdui(ctx.widget)
self.inverter.invert_if_event(vdui)
return 1
def update(self, ctx):
return idaapi.AST_ENABLE_FOR_WIDGET if \
ctx.widget_type == idaapi.BWN_PSEUDOCODE else \
idaapi.AST_DISABLE_FOR_WIDGET
return ida_kernwin.AST_ENABLE_FOR_WIDGET if \
ctx.widget_type == ida_kernwin.BWN_PSEUDOCODE else \
ida_kernwin.AST_DISABLE_FOR_WIDGET
class hexrays_callback_info(object):
@@ -37,7 +40,7 @@ class hexrays_callback_info(object):
def __init__(self):
self.vu = None
self.node = idaapi.netnode()
self.node = ida_netnode.netnode()
if not self.node.create(NETNODE_NAME):
# node exists
self.load()
@@ -83,12 +86,12 @@ class hexrays_callback_info(object):
if not cif.ithen or not cif.ielse:
return False
idaapi.qswap(cif.ithen, cif.ielse)
ida_hexrays.qswap(cif.ithen, cif.ielse)
# Make a copy of 'cif.expr': 'lnot' might destroy its toplevel
# cexpr_t and return a pointer to its direct child (but we'll want to
# 'swap' it later, the 'cif.expr' cexpr_t object must remain valid.)
cond = idaapi.cexpr_t(cif.expr)
notcond = idaapi.lnot(cond)
cond = ida_hexrays.cexpr_t(cif.expr)
notcond = ida_hexrays.lnot(cond)
cif.expr.swap(notcond)
@@ -104,26 +107,26 @@ class hexrays_callback_info(object):
def find_if_statement(self, vu):
vu.get_current_item(idaapi.USE_KEYBOARD)
vu.get_current_item(ida_hexrays.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:
if item.is_citem() and item.it.op == ida_hexrays.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:
if vu.tail.citype == ida_hexrays.VDI_TAIL and vu.tail.loc.itp == ida_hexrays.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):
class if_finder_t(ida_hexrays.ctree_visitor_t):
def __init__(self, ea):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
ida_hexrays.ctree_visitor_t.__init__(self, ida_hexrays.CV_FAST | ida_hexrays.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:
if i.op == ida_hexrays.cit_if and i.ea == self.ea:
self.found = i
return 1 # stop enumeration
return 0
@@ -149,17 +152,17 @@ class hexrays_callback_info(object):
def restore(self, cfunc):
class visitor(idaapi.ctree_visitor_t):
class visitor(ida_hexrays.ctree_visitor_t):
def __init__(self, inverter, cfunc):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
ida_hexrays.ctree_visitor_t.__init__(self, ida_hexrays.CV_FAST | ida_hexrays.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:
if i.op == ida_hexrays.cit_if and i.ea in self.inverter.stored:
self.inverter.invert_if(self.cfunc, i)
except:
traceback.print_exc()
@@ -170,31 +173,43 @@ class hexrays_callback_info(object):
return
class vds3_hooks_t(idaapi.Hexrays_Hooks):
class vds3_hooks_t(ida_hexrays.Hexrays_Hooks):
def __init__(self, i):
idaapi.Hexrays_Hooks.__init__(self)
ida_hexrays.Hexrays_Hooks.__init__(self)
self.i = i
def populating_popup(self, widget, phandle, vu):
idaapi.attach_action_to_popup(vu.ct, None, inverter_actname)
ida_kernwin.attach_action_to_popup(vu.ct, None, inverter_actname)
return 0
def maturity(self, cfunc, maturity):
if maturity == idaapi.CMAT_FINAL:
if maturity == ida_hexrays.CMAT_FINAL:
self.i.restore(cfunc)
return 0
# a plugin interface, boilerplate code
class my_plugin_t(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_HIDE
wanted_name = "Hex-Rays if-inverter (IDAPython)"
wanted_hotkey = ""
comment = "Sample plugin3 for Hex-Rays decompiler"
help = ""
def init(self):
if ida_hexrays.init_hexrays_plugin():
i = hexrays_callback_info()
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
inverter_actname,
"Invert then/else",
invert_action_handler_t(i),
"I"))
self.vds3_hooks = vds3_hooks_t(i)
self.vds3_hooks.hook()
return ida_idaapi.PLUGIN_KEEP # keep us in the memory
def term(self):
self.vds3_hooks.unhook()
def run(self, arg):
pass
if idaapi.init_hexrays_plugin():
i = hexrays_callback_info()
idaapi.register_action(
idaapi.action_desc_t(
inverter_actname,
"Invert then/else",
invert_action_handler_t(i),
"I"))
vds3_hooks = vds3_hooks_t(i)
vds3_hooks.hook()
else:
print('invert-if: hexrays is not available.')
def PLUGIN_ENTRY():
return my_plugin_t()
+17 -19
View File
@@ -6,15 +6,13 @@ This is a rewrite in Python of the vds4 example that comes with hexrays sdk.
"""
from __future__ import print_function
import idautils
import idaapi
import idc
import traceback
import ida_kernwin
import ida_hexrays
import ida_bytes
def run():
cfunc = idaapi.decompile(idaapi.get_screen_ea())
cfunc = ida_hexrays.decompile(ida_kernwin.get_screen_ea())
if not cfunc:
print('Please move the cursor into a function.')
return
@@ -23,31 +21,31 @@ def run():
print("Dump of user-defined information for function at %x" % (entry_ea, ))
# Display user defined labels.
labels = idaapi.restore_user_labels(entry_ea);
labels = ida_hexrays.restore_user_labels(entry_ea);
if labels is not None:
print("------- %u user defined labels" % (len(labels), ))
for org_label, name in labels.items():
print("Label %d: %s" % (org_label, str(name)))
idaapi.user_labels_free(labels)
ida_hexrays.user_labels_free(labels)
# Display user defined comments
cmts = idaapi.restore_user_cmts(entry_ea);
cmts = ida_hexrays.restore_user_cmts(entry_ea);
if cmts is not None:
print("------- %u user defined comments" % (len(cmts), ))
for tl, cmt in cmts.items():
print("Comment at %x, preciser %x:\n%s\n" % (tl.ea, tl.itp, str(cmt)))
idaapi.user_cmts_free(cmts)
ida_hexrays.user_cmts_free(cmts)
# Display user defined citem iflags
iflags = idaapi.restore_user_iflags(entry_ea)
iflags = ida_hexrays.restore_user_iflags(entry_ea)
if iflags is not None:
print("------- %u user defined citem iflags" % (len(iflags), ))
for cl, f in iflags.items():
print("%x(%d): %08X%s" % (cl.ea, cl.op, f, " CIT_COLLAPSED" if f & idaapi.CIT_COLLAPSED else ""))
idaapi.user_iflags_free(iflags)
print("%x(%d): %08X%s" % (cl.ea, cl.op, f, " CIT_COLLAPSED" if f & ida_hexrays.CIT_COLLAPSED else ""))
ida_hexrays.user_iflags_free(iflags)
# Display user defined number formats
numforms = idaapi.restore_user_numforms(entry_ea)
numforms = ida_hexrays.restore_user_numforms(entry_ea)
if numforms is not None:
print("------- %u user defined number formats" % (len(numforms), ))
for ol, nf in numforms.items():
@@ -64,13 +62,13 @@ def run():
print("struct offset %s" % (str(nf.type_name), ))
else:
print("number base=%d" % (idaapi.get_radix(nf.flags, ol.opnum), ))
print("number base=%d" % (ida_bytes.get_radix(nf.flags, ol.opnum), ))
idaapi.user_numforms_free(numforms)
ida_hexrays.user_numforms_free(numforms)
# Display user-defined local variable information
lvinf = idaapi.lvar_uservec_t()
if idaapi.restore_user_lvar_settings(lvinf, entry_ea):
lvinf = ida_hexrays.lvar_uservec_t()
if ida_hexrays.restore_user_lvar_settings(lvinf, entry_ea):
print("------- User defined local variable information\n")
for lv in lvinf.lvvec:
print("Lvar defined at %x" % (lv.ll.defea, ))
@@ -89,7 +87,7 @@ def run():
return
if idaapi.init_hexrays_plugin():
if ida_hexrays.init_hexrays_plugin():
run()
else:
print('dump user info: hexrays is not available.')
+26 -13
View File
@@ -1,11 +1,11 @@
from __future__ import print_function
import ida_idaapi
import ida_pro
import ida_hexrays
import ida_kernwin
import ida_gdl
import ida_lines
import ida_idaapi
ACTION_NAME = "vds5.py:displaygraph"
ACTION_SHORTCUT = "Ctrl+Shift+G"
@@ -296,18 +296,31 @@ class display_graph_ah_t(ida_kernwin.action_handler_t):
class vds5_hooks_t(ida_hexrays.Hexrays_Hooks):
def populating_popup(self, widget, handle, vu):
idaapi.attach_action_to_popup(vu.ct, None, ACTION_NAME)
ida_kernwin.attach_action_to_popup(vu.ct, None, ACTION_NAME)
return 0
if ida_hexrays.init_hexrays_plugin():
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTION_NAME,
"Hex-Rays show C graph (IDAPython)",
display_graph_ah_t(),
ACTION_SHORTCUT))
vds5_hooks = vds5_hooks_t()
vds5_hooks.hook()
else:
print('hexrays-graph: hexrays is not available.')
# a plugin interface, boilerplate code
class my_plugin_t(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_HIDE
wanted_name = "Hex-Rays show C graph (IDAPython)"
wanted_hotkey = ""
comment = "Sample plugin5 for Hex-Rays decompiler"
help = ""
def init(self):
if ida_hexrays.init_hexrays_plugin():
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTION_NAME,
"Hex-Rays show C graph (IDAPython)",
display_graph_ah_t(),
ACTION_SHORTCUT))
self.vds5_hooks = vds5_hooks_t()
self.vds5_hooks.hook()
return ida_idaapi.PLUGIN_KEEP # keep us in the memory
def term(self):
self.vds5_hooks.unhook()
def run(self, arg):
pass
def PLUGIN_ENTRY():
return my_plugin_t()
+22 -8
View File
@@ -51,6 +51,9 @@ def remove_spaces(sl):
last = None # last seen character
while True:
# go until comments
if l.startswith("//"):
push(l)
break
dbg("-" * 60)
nchars = ida_lines.tag_advance(l, 1)
push(l[0:nchars])
@@ -58,9 +61,6 @@ def remove_spaces(sl):
l = my_tag_skipcodes(l, out)
if not l:
break
if l.startswith("//"):
push(l)
break
c = l[0]
dbg("c: '%s', last: '%s', l: '%s'" % (c, last, l))
if delim:
@@ -89,8 +89,22 @@ class vds6_hooks_t(ida_hexrays.Hexrays_Hooks):
remove_spaces(sl);
return 0
if ida_hexrays.init_hexrays_plugin():
vds6_hooks = vds6_hooks_t()
vds6_hooks.hook()
else:
print('remove spaces: hexrays is not available.')
# a plugin interface, boilerplate code
class my_plugin_t(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_HIDE
wanted_name = "Hex-Rays space remover (IDAPython)"
wanted_hotkey = ""
comment = "Sample plugin6 for Hex-Rays decompiler"
help = ""
def init(self):
if ida_hexrays.init_hexrays_plugin():
self.vds6_hooks = vds6_hooks_t()
self.vds6_hooks.hook()
return ida_idaapi.PLUGIN_KEEP # keep us in the memory
def term(self):
self.vds6_hooks.unhook()
def run(self, arg):
pass
def PLUGIN_ENTRY():
return my_plugin_t()
+8 -20
View File
@@ -6,26 +6,16 @@ This is a rewrite in Python of the vds7 example that comes with hexrays sdk.
"""
from __future__ import print_function
import idautils
import idaapi
import idc
import ida_hexrays
import traceback
class cblock_visitor_t(idaapi.ctree_visitor_t):
class cblock_visitor_t(ida_hexrays.ctree_visitor_t):
def __init__(self):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST)
return
ida_hexrays.ctree_visitor_t.__init__(self, ida_hexrays.CV_FAST)
def visit_insn(self, ins):
try:
if ins.op == idaapi.cit_block:
self.dump_block(ins.ea, ins.cblock)
except:
traceback.print_exc()
if ins.op == ida_hexrays.cit_block:
self.dump_block(ins.ea, ins.cblock)
return 0
def dump_block(self, ea, b):
@@ -34,18 +24,16 @@ class cblock_visitor_t(idaapi.ctree_visitor_t):
for ins in b:
print(" %x: insn %s" % (ins.ea, ins.opname))
return
class vds7_hooks_t(idaapi.Hexrays_Hooks):
class vds7_hooks_t(ida_hexrays.Hexrays_Hooks):
def maturity(self, cfunc, maturity):
if maturity == idaapi.CMAT_BUILT:
if maturity == ida_hexrays.CMAT_BUILT:
cbv = cblock_visitor_t()
cbv.apply_to(cfunc.body, None)
return 0
if idaapi.init_hexrays_plugin():
if ida_hexrays.init_hexrays_plugin():
vds7_hooks = vds7_hooks_t()
vds7_hooks.hook()
else:
+1 -1
View File
@@ -1,6 +1,6 @@
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample script for Hex-Rays Decompiler usage of udc_filter_t
+44 -38
View File
@@ -10,9 +10,14 @@ Show decompiler-style Xref when the X key is pressed in the Decompiler window.
"""
from __future__ import print_function
import ida_kernwin
import ida_hexrays
import ida_typeinf
import ida_idaapi
import ida_struct
import ida_funcs
import idautils
import idaapi
import idc
import traceback
@@ -21,27 +26,27 @@ from PyQt5 import QtCore, QtWidgets
XREF_EA = 0
XREF_STRUC_MEMBER = 1
class XrefsForm(idaapi.PluginForm):
class XrefsForm(ida_kernwin.PluginForm):
def __init__(self, target):
idaapi.PluginForm.__init__(self)
ida_kernwin.PluginForm.__init__(self)
self.target = target
if type(self.target) == idaapi.cfunc_t:
if type(self.target) == ida_hexrays.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':
elif type(self.target) == ida_hexrays.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'):
elif type(self.target) == ida_hexrays.cexpr_t and self.target.opname in ('memptr', 'memref'):
self.__type = XREF_STRUC_MEMBER
name = self.get_struc_name()
@@ -59,10 +64,11 @@ class XrefsForm(idaapi.PluginForm):
xtype = x.type
xtype.remove_ptr_or_array()
typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '')
typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, xtype, '', '')
sid = idc.get_struc_id(typename)
member = idc.get_member_name(sid, m)
sid = ida_struct.get_struc_id(typename)
sptr = ida_struct.get_struc(sid)
member = ida_struct.get_member(sptr, m)
return '%s::%s' % (typename, member)
@@ -76,7 +82,7 @@ class XrefsForm(idaapi.PluginForm):
return
def Show(self):
idaapi.PluginForm.Show(self, self.__name)
ida_kernwin.PluginForm.Show(self, self.__name)
return
def populate_form(self):
@@ -109,7 +115,7 @@ class XrefsForm(idaapi.PluginForm):
def double_clicked(self, row, column):
ea = self.functions[row]
idaapi.open_pseudocode(ea, True)
ida_hexrays.open_pseudocode(ea, True)
return
@@ -125,12 +131,12 @@ class XrefsForm(idaapi.PluginForm):
lines = []
for stmt in insnvec:
qp = idaapi.qstring_printer_t(cfunc.__deref__(), False)
qp = ida_hexrays.qstring_printer_t(cfunc.__deref__(), False)
stmt._print(0, qp)
s = qp.s.split('\n')[0]
#~ s = idaapi.tag_remove(s)
#~ s = ida_lines.tag_remove(s)
lines.append(s)
return '\n'.join(lines)
@@ -142,10 +148,10 @@ class XrefsForm(idaapi.PluginForm):
items = []
for ea in frm:
try:
cfunc = idaapi.decompile(ea)
cfunc = ida_hexrays.decompile(ea)
self.functions.append(cfunc.entry_ea)
self.items.append((ea, idc.get_func_name(cfunc.entry_ea), self.get_decompiled_line(cfunc, ea)))
self.items.append((ea, ida_funcs.get_func_name(cfunc.entry_ea) or "", self.get_decompiled_line(cfunc, ea)))
except Exception as e:
print('could not decompile: %s' % (str(e), ))
@@ -160,13 +166,13 @@ class XrefsForm(idaapi.PluginForm):
xtype = x.type
xtype.remove_ptr_or_array()
typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '')
typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, xtype, '', '')
addresses = []
for ea in idautils.Functions():
try:
cfunc = idaapi.decompile(ea)
cfunc = ida_hexrays.decompile(ea)
except:
print('Decompilation of %x failed' % (ea, ))
continue
@@ -175,21 +181,21 @@ class XrefsForm(idaapi.PluginForm):
for citem in cfunc.treeitems:
citem = citem.to_specific_type
if not (type(citem) == idaapi.cexpr_t and citem.opname in ('memptr', 'memref')):
if not (type(citem) == ida_hexrays.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, '', '')
_typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, _xtype, '', '')
if not (_typename == typename and _m == m):
continue
parent = citem
while parent:
if type(parent.to_specific_type) == idaapi.cinsn_t:
if type(parent.to_specific_type) == ida_hexrays.cinsn_t:
break
parent = cfunc.body.find_parent_of(parent)
@@ -200,7 +206,7 @@ class XrefsForm(idaapi.PluginForm):
if parent.ea in addresses:
continue
if parent.ea == idaapi.BADADDR:
if parent.ea == ida_idaapi.BADADDR:
print('parent.ea is BADADDR')
continue
@@ -209,7 +215,7 @@ class XrefsForm(idaapi.PluginForm):
self.functions.append(cfunc.entry_ea)
self.items.append((
parent.ea,
idc.get_func_name(cfunc.entry_ea),
ida_funcs.get_func_name(cfunc.entry_ea) or "",
self.get_decompiled_line(cfunc, parent.ea)))
@@ -250,13 +256,13 @@ class XrefsForm(idaapi.PluginForm):
pass
class show_xrefs_ah_t(idaapi.action_handler_t):
class show_xrefs_ah_t(ida_kernwin.action_handler_t):
def __init__(self):
idaapi.action_handler_t.__init__(self)
ida_kernwin.action_handler_t.__init__(self)
self.sel = None
def activate(self, ctx):
vu = idaapi.get_widget_vdui(ctx.widget)
vu = ida_hexrays.get_widget_vdui(ctx.widget)
if not vu or not self.sel:
print("No vdui? Strange, since this action should be enabled only for pseudocode views.")
return 0
@@ -266,32 +272,32 @@ class show_xrefs_ah_t(idaapi.action_handler_t):
return 1
def update(self, ctx):
if ctx.widget_type != idaapi.BWN_PSEUDOCODE:
return idaapi.AST_DISABLE_FOR_WIDGET
vu = idaapi.get_widget_vdui(ctx.widget)
vu.get_current_item(idaapi.USE_KEYBOARD)
if ctx.widget_type != ida_kernwin.BWN_PSEUDOCODE:
return ida_kernwin.AST_DISABLE_FOR_WIDGET
vu = ida_hexrays.get_widget_vdui(ctx.widget)
vu.get_current_item(ida_hexrays.USE_KEYBOARD)
item = vu.item
self.sel = None
if item.citype == idaapi.VDI_EXPR and item.it.to_specific_type.opname in ('obj', 'memref', 'memptr'):
if item.citype == ida_hexrays.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
self.sel = item.it.to_specific_type
elif item.citype == idaapi.VDI_FUNC:
elif item.citype == ida_hexrays.VDI_FUNC:
# if the function itself is selected, show xrefs to it.
self.sel = item.f
return idaapi.AST_ENABLE if self.sel else idaapi.AST_DISABLE
return ida_kernwin.AST_ENABLE if self.sel else ida_kernwin.AST_DISABLE
class vds_xrefs_hooks_t(idaapi.Hexrays_Hooks):
class vds_xrefs_hooks_t(ida_hexrays.Hexrays_Hooks):
def populating_popup(self, widget, phandle, vu):
idaapi.attach_action_to_popup(widget, phandle, "vdsxrefs:show", None)
ida_kernwin.attach_action_to_popup(widget, phandle, "vdsxrefs:show", None)
return 0
if idaapi.init_hexrays_plugin():
adesc = idaapi.action_desc_t('vdsxrefs:show', 'Show xrefs', show_xrefs_ah_t(), "Ctrl+X")
if idaapi.register_action(adesc):
if ida_hexrays.init_hexrays_plugin():
adesc = ida_kernwin.action_desc_t('vdsxrefs:show', 'Show xrefs', show_xrefs_ah_t(), "Ctrl+X")
if ida_kernwin.register_action(adesc):
vds_xrefs_hooks = vds_xrefs_hooks_t()
vds_xrefs_hooks.hook()
else:
+66
View File
@@ -0,0 +1,66 @@
"""
This example shows notifications whenever the user changes
an instruction's operand, or a data item.
"""
import binascii
import ida_idp
import ida_bytes
import ida_nalt
import ida_struct
import ida_enum
class operand_changed_t(ida_idp.IDB_Hooks):
def log(self, msg):
print(">>> %s" % msg)
def op_type_changed(self, ea, n):
flags = ida_bytes.get_flags(ea)
self.log("op_type_changed(ea=0x%08X, n=%d). Flags now: 0x%08X" % (ea, n, flags))
buf = ida_nalt.opinfo_t()
opi = ida_bytes.get_opinfo(buf, ea, n, flags)
if opi:
if ida_bytes.is_struct(flags):
self.log("New struct: 0x%08X (name=%s)" % (
opi.tid,
ida_struct.get_struc_name(opi.tid)))
elif ida_bytes.is_strlit(flags):
encidx = ida_nalt.get_str_encoding_idx(opi.strtype)
if encidx == ida_nalt.STRENC_DEFAULT:
encidx = ida_nalt.get_default_encoding_idx(ida_nalt.get_strtype_bpu(opi.strtype))
encname = ida_nalt.get_encoding_name(encidx)
strlen = ida_bytes.get_max_strlit_length(
ea,
opi.strtype,
ida_bytes.ALOPT_IGNHEADS | ida_bytes.ALOPT_IGNCLT)
raw = ida_bytes.get_strlit_contents(ea, strlen, opi.strtype) or b""
self.log("New strlit: 0x%08X, raw hex=%s (encoding=%s)" % (
opi.strtype,
binascii.hexlify(raw),
encname))
elif ida_bytes.is_off(flags, n):
self.log("New offset: refinfo={target=0x%08X, base=0x%08X, tdelta=0x%08X, flags=0x%X}" % (
opi.ri.target,
opi.ri.base,
opi.ri.tdelta,
opi.ri.flags))
elif ida_bytes.is_enum(flags, n):
self.log("New enum: 0x%08X (enum=%s), serial=%d" % (
opi.ec.tid,
ida_enum.get_enum_name(opi.ec.tid),
opi.ec.serial))
pass
elif ida_bytes.is_stroff(flags, n):
parts = []
for i in range(opi.path.len):
tid = opi.path.ids[i]
parts.append("0x%08X (name=%s)" % (tid, ida_struct.get_struc_name(tid)))
self.log("New stroff: path=[%s] (len=%d, delta=0x%08X)" % (
", ".join(parts),
opi.path.len,
opi.path.delta))
elif ida_bytes.is_custom(flags) or ida_bytes.is_custfmt(flags, n):
self.log("New custom data type") # unimplemented
else:
print("Cannot retrieve opinfo_t")
@@ -0,0 +1,78 @@
"""
This is a sample script, that will record (in memory) all changes in
functions prototypes, in order to re-apply them later.
To use this script:
- open an IDB (say, "test.idb")
- modify some functions prototypes (e.g., by triggering the 'Y'
shortcut when the cursor is placed on the first address of a
function)
- reload that IDB, *without saving it first*
- call rpc.replay(), to re-apply the modifications.
Note: 'ti_changed' is also called for changes to the function
frames, but we'll only record function prototypes changes.
"""
import ida_idp
import ida_funcs
import ida_typeinf
class replay_prototypes_changes_t(ida_idp.IDB_Hooks):
def __init__(self):
ida_idp.IDB_Hooks.__init__(self)
# we'll store tuples (ea, typ, fields). We cannot store
# tinfo_t instances in there, because tinfo_t's are only
# valid while the IDB is opened.
# Since the very purpose of this example is to re-apply
# types after the IDB has been closed & re-opened, we
# must therefore keep the serialized version only.
self.memo = []
self.replaying = False
def _deser(self, typ, fields):
tif = ida_typeinf.tinfo_t()
if not tif.deserialize(ida_typeinf.get_idati(), typ, fields):
tif = None
return tif
def ti_changed(self, ea, typ, fields):
if not self.replaying:
pfn = ida_funcs.get_func(ea)
if pfn and pfn.start_ea == ea:
self.memo.append((ea, typ, fields))
# de-serialize, just for the sake of printing
tif = self._deser(typ, fields)
if tif:
print("%x: type changed: %s" % (
ea,
tif._print(None, ida_typeinf.PRTYPE_1LINE)))
def replay(self):
self.replaying = True
try:
for ea, typ, fields in self.memo:
tif = self._deser(typ, fields)
if tif:
print("%x: applying type: %s" % (
ea,
tif._print(None, ida_typeinf.PRTYPE_1LINE)))
# Since that type information was remembered from a change
# the user made, we'll re-apply it as a definite type (i.e.,
# can't be overriden by IDA's auto-analysis/heuristics.)
apply_flags = ida_typeinf.TINFO_DEFINITE
if not ida_typeinf.apply_tinfo(ea, tif, apply_flags):
print("FAILED")
finally:
self.replaying = False
rpc = replay_prototypes_changes_t()
if rpc.hook():
print("""
Please modify some functions prototypes (press 'Y' when the
cursor is on the function name, or first address), and when
you are done reload this IDB, *WITHOUT* saving it first,
and type 'rpc.replay()'
""")
else:
print("Couldn't create hooks")
Binary file not shown.
+14 -11
View File
@@ -3,30 +3,34 @@ from __future__ import print_function
# normally it's architecturally undefined and is not disassembled by IDA's ARM module
# see Linux/arch/arm/include/asm/bug.h
import idaapi
import ida_idp
import ida_bytes
import ida_segregs
ITYPE_BUGINSN = idaapi.CUSTOM_CMD_ITYPE + 10
ITYPE_BUGINSN = ida_idp.CUSTOM_INSN_ITYPE + 10
MNEM_WIDTH = 16
class MyHooks(idaapi.IDP_Hooks):
class MyHooks(ida_idp.IDP_Hooks):
def __init__(self):
idaapi.IDP_Hooks.__init__(self)
ida_idp.IDP_Hooks.__init__(self)
self.reported = []
def ev_ana_insn(self, insn):
t = get_sreg(insn.ea, "T")
if t==0 and get_wide_dword(insn.ea) == 0xE7F001F2:
t_reg = ida_idp.str2reg("T")
t = ida_segregs.get_sreg(insn.ea, t_reg)
if t==0 and ida_bytes.get_wide_dword(insn.ea) == 0xE7F001F2:
insn.itype = ITYPE_BUGINSN
insn.size = 4
elif t!=0 and get_wide_word(insn.ea) == 0xde02:
elif t!=0 and ida_bytes.get_wide_word(insn.ea) == 0xde02:
insn.itype = ITYPE_BUGINSN
insn.size = 2
return insn.size
def ev_emu_insn(self, insn):
if insn.ea == ITYPE_BUGINSN:
return 1
if insn.itype == ITYPE_BUGINSN:
return 1 # do not add any xrefs (stop code flow)
# use default processing for all other functions
return 0
def ev_out_mnem(self, outctx):
@@ -35,10 +39,9 @@ class MyHooks(idaapi.IDP_Hooks):
return 1
return 0
if idaapi.ph.id == idaapi.PLFM_ARM:
if ida_idp.ph.id == ida_idp.PLFM_ARM:
bahooks = MyHooks()
bahooks.hook()
print("BUG_INSTR processor extension installed")
else:
warning("This script only supports ARM files")
+2 -2
View File
@@ -1,5 +1,5 @@
from __future__ import print_function
import idaapi
import ida_idp
import idautils
"""
@@ -14,7 +14,7 @@ import idautils
"""
#--------------------------------------------------------------------------
class assemble_idp_hook_t(idaapi.IDP_Hooks):
class assemble_idp_hook_t(ida_idp.IDP_Hooks):
def assemble(self, ea, cs, ip, use32, line):
line = line.strip()
if line == "xor eax, eax":
+87
View File
@@ -0,0 +1,87 @@
#
# This example illustrates how one can execute commands in the
# "Output window", from their own widgets.
#
# In order to do so, we have to be careful that:
# - the original, underlying 'cli:Execute' action, that has to be
# triggered for the code present in the input field to execute
# and be placed in the history, requires that the input field
# has focus (otherwise it simply won't do anything.)
# - this, in turn, forces us to do "delayed" execution of that action,
# hence the need for a QTimer
# - the IDA/SWiG 'TWidget' type that we retrieve through
# `ida_kernwin.find_widget`, is not the same type as a
# `QtWidgets.QWidget`. We therefore need to convert it using
# `ida_kernwin.PluginForm.TWidgetToPyQtWidget`
#
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import QtWidgets
import ida_kernwin
import ida_segment
import idc
delayed_exec_timer = QtCore.QTimer()
def show_dialog():
dialog = QtWidgets.QDialog()
dialog.setWindowTitle("Inject command")
dialog.setMinimumSize(600, 480)
run_text = "Run"
buttons_box = QtWidgets.QDialogButtonBox()
button = buttons_box.addButton(run_text, QtWidgets.QDialogButtonBox.AcceptRole)
button.setDefault(True)
button.clicked.connect(dialog.accept)
text_edit = QtWidgets.QPlainTextEdit()
text_edit.setPlaceholderText(
"Type an expression, and press '%s' to execute through the regular input" % run_text)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(text_edit)
layout.addWidget(buttons_box)
dialog.setLayout(layout)
# disable script timeout, otherwise a "Please wait ..." dialog
# might briefly show after the dialog was accepted/rejected
with ida_kernwin.disabled_script_timeout_t():
if dialog.exec_() == QtWidgets.QDialog.Accepted:
# We'll now have to schedule a call to the standard
# 'execute' action. We can't call it right away, because
# the "Output window" doesn't have focus, and thus
# the action will fail to execute since it requires
# the "Output window" as context.
text = text_edit.toPlainText()
def delayed_exec(*args):
output_window_title = "Output window"
tw = ida_kernwin.find_widget(output_window_title)
if not tw:
raise Exception("Couldn't find widget '%s'" % output_window_title)
# convert from a SWiG 'TWidget*' facade,
# into an object that PyQt will understand
w = ida_kernwin.PluginForm.TWidgetToPyQtWidget(tw)
line_edit = w.findChild(QtWidgets.QLineEdit)
if not line_edit:
raise Exception("Couldn't find input")
line_edit.setFocus() # ensure it has focus
QtWidgets.QApplication.instance().processEvents() # and that it received the focus event
# inject text into widget
line_edit.setText(text)
# and execute the standard 'execute' action
ida_kernwin.process_ui_action("cli:Execute")
delayed_exec_timer.singleShot(0, delayed_exec)
show_dialog()
@@ -1,9 +1,7 @@
from idaapi import PluginForm
from PyQt5 import QtCore, QtGui, QtWidgets
import sip
class MyPluginFormClass(PluginForm):
class MyPluginFormClass(ida_kernwin.PluginForm):
def OnCreate(self, form):
"""
Called when the widget is created
+122
View File
@@ -0,0 +1,122 @@
"""
This example shows how one can dynamically alter the lines background
rendering (as opposed to, say, using ida_nalt.set_item_color()), and
also shows how that rendering can be limited to just a few glyphs,
not the whole line.
"""
import ida_kernwin
import ida_bytes
class lines_rendering_hooks_t(ida_kernwin.UI_Hooks):
def __init__(self):
ida_kernwin.UI_Hooks.__init__(self)
# We'll color all lines starting with the current
# one, with all available highlights...
self.instantiated_at = ida_kernwin.get_screen_ea()
self.color_info = []
data = [
ida_kernwin.CK_EXTRA1,
ida_kernwin.CK_EXTRA2,
ida_kernwin.CK_EXTRA3,
ida_kernwin.CK_EXTRA4,
ida_kernwin.CK_EXTRA5,
ida_kernwin.CK_EXTRA6,
ida_kernwin.CK_EXTRA7,
ida_kernwin.CK_EXTRA8,
ida_kernwin.CK_EXTRA9,
ida_kernwin.CK_EXTRA10,
ida_kernwin.CK_EXTRA11,
ida_kernwin.CK_EXTRA12,
ida_kernwin.CK_EXTRA13,
ida_kernwin.CK_EXTRA14,
ida_kernwin.CK_EXTRA15,
ida_kernwin.CK_EXTRA16,
# let's also try these colors keys, because why not
ida_kernwin.CK_TRACE,
ida_kernwin.CK_TRACE_OVL,
[
ida_kernwin.CK_TRACE,
ida_kernwin.CK_TRACE_OVL,
],
]
ea = self.instantiated_at
for one in data:
self.color_info.append((ea, one))
ea = ida_bytes.next_head(ea, ida_idaapi.BADADDR)
# ...and then we'll a few more things, such as
# overriding parts of a previously-specified overlay,
# and restricting the override to a few glyphs
self.color_info.append(
(
self.color_info[6][0],
[
(ida_kernwin.CK_EXTRA2, 7, 3),
(ida_kernwin.CK_EXTRA4, 2, 1),
(ida_kernwin.CK_EXTRA10, 2, 0),
(ida_kernwin.CK_EXTRA10, 20, 10),
]
))
self.color_info.append(
(
self.color_info[7][0],
[
(ida_kernwin.CK_EXTRA1, 1, 1),
(ida_kernwin.CK_EXTRA2, 3, 1),
(ida_kernwin.CK_EXTRA3, 5, 1),
(ida_kernwin.CK_EXTRA4, 7, 1),
(ida_kernwin.CK_EXTRA5, 9, 1),
(ida_kernwin.CK_EXTRA6, 11, 1),
(ida_kernwin.CK_EXTRA7, 13, 1),
(ida_kernwin.CK_EXTRA8, 15, 1),
(ida_kernwin.CK_EXTRA9, 17, 1),
(ida_kernwin.CK_EXTRA10, 19, 1),
(ida_kernwin.CK_EXTRA11, 21, 1),
(ida_kernwin.CK_EXTRA12, 23, 1),
(ida_kernwin.CK_EXTRA13, 25, 1),
(ida_kernwin.CK_EXTRA14, 27, 1),
(ida_kernwin.CK_EXTRA15, 29, 1),
(ida_kernwin.CK_EXTRA16, 31, 1),
]
))
self.color_info.append(
(
self.color_info[8][0],
[
(ida_kernwin.CK_EXTRA1, 16, 45),
(ida_kernwin.CK_EXTRA2, 19, 45),
(ida_kernwin.CK_EXTRA3, 22, 45),
(ida_kernwin.CK_EXTRA4, 25, 45),
]
))
def get_lines_rendering_info(self, out, widget, rin):
for section_lines in rin.sections_lines:
for line in section_lines:
line_ea = line.at.toea()
for ea, directives in self.color_info:
if ea == line_ea:
if not isinstance(directives, list):
directives = [directives]
for directive in directives:
e = ida_kernwin.line_rendering_output_entry_t(line)
if isinstance(directive, tuple):
color, cpx, nchars = directive
e.bg_color = color
e.cpx = cpx
e.nchars = nchars
e.flags |= ida_kernwin.LROEF_CPS_RANGE
else:
e.bg_color = directive
out.entries.push_back(e)
lrh = lines_rendering_hooks_t()
lrh.hook()
# Force a refresh of IDA View-A
ida_kernwin.refresh_idaview_anyway()
+3 -3
View File
@@ -8,11 +8,11 @@ from __future__ import print_function
#
#---------------------------------------------------------------------
import idaapi
import ida_kernwin
class MyUiHook(idaapi.UI_Hooks):
class MyUiHook(ida_kernwin.UI_Hooks):
def __init__(self):
idaapi.UI_Hooks.__init__(self)
ida_kernwin.UI_Hooks.__init__(self)
self.cmdname = "<no command>"
def _log(self, msg):
@@ -10,6 +10,9 @@ import ida_graph
import ida_ua
import ida_idp
import ida_funcs
import ida_xref
import idautils
class _base_graph_action_handler_t(ida_kernwin.action_handler_t):
def __init__(self, graph):
@@ -117,17 +120,17 @@ class MyGraph(ida_graph.GraphViewer):
def show_graph():
f = ida_funcs.get_func(here())
f = ida_funcs.get_func(ida_kernwin.get_screen_ea())
if not f:
print("Must be in a function")
return
# Iterate through all function instructions and take only call instructions
result = []
tmp = ida_ua.insn_t()
for x in [x for x in FuncItems(f.start_ea) if (ida_ua.decode_insn(tmp, x) and ida_idp.is_call_insn(tmp))]:
for xref in XrefsFrom(x, idaapi.XREF_FAR):
for x in [x for x in idautils.FuncItems(f.start_ea) if (ida_ua.decode_insn(tmp, x) and ida_idp.is_call_insn(tmp))]:
for xref in idautils.XrefsFrom(x, ida_xref.XREF_FAR):
if not xref.iscode: continue
t = get_func_name(xref.to)
t = ida_funcs.get_func_name(xref.to)
if not t:
t = hex(xref.to)
result.append(t)
+20 -18
View File
@@ -1,6 +1,8 @@
from __future__ import print_function
from idaapi import *
import ida_kernwin
import ida_moves
import ida_graph
#
# Cleanup (in case the script is run more than once)
@@ -16,9 +18,9 @@ wrap_a = None
#
# The IDA View-A "monitor": changes will be reported into IDA View-B
#
class IDAViewA_monitor_t(IDAViewWrapper):
class IDAViewA_monitor_t(ida_kernwin.IDAViewWrapper):
def __init__(self):
IDAViewWrapper.__init__(self, "IDA View-A")
ida_kernwin.IDAViewWrapper.__init__(self, "IDA View-A")
def OnViewLocationChanged(self, now, was):
self.update_widget_b()
@@ -26,40 +28,40 @@ class IDAViewA_monitor_t(IDAViewWrapper):
def update_widget_b(self):
# Make sure we are in the same function
place_a, _, _ = get_custom_viewer_place(widget_a, False)
jumpto(widget_b, place_a, -1, -1)
place_a, _, _ = ida_kernwin.get_custom_viewer_place(widget_a, False)
ida_kernwin.jumpto(widget_b, place_a, -1, -1)
# and that we show the right place (slightly zoomed out)
widget_a_center_gli = graph_location_info_t()
if viewer_get_gli(widget_a_center_gli, widget_a, GLICTL_CENTER):
widget_b_center_gli = graph_location_info_t()
widget_a_center_gli = ida_moves.graph_location_info_t()
if ida_graph.viewer_get_gli(widget_a_center_gli, widget_a, ida_graph.GLICTL_CENTER):
widget_b_center_gli = ida_moves.graph_location_info_t()
widget_b_center_gli.orgx = widget_a_center_gli.orgx
widget_b_center_gli.orgy = widget_a_center_gli.orgy
widget_b_center_gli.zoom = widget_a_center_gli.zoom * 0.5
viewer_set_gli(widget_b, widget_b_center_gli, GLICTL_CENTER)
ida_graph.viewer_set_gli(widget_b, widget_b_center_gli, ida_graph.GLICTL_CENTER)
#
# Make sure both views are opened...
#
for label in ["A", "B"]:
title = "IDA View-%s" % label
if not find_widget(title):
if not ida_kernwin.find_widget(title):
print("View %s not available. Opening." % title)
open_disasm_window(label)
ida_kernwin.open_disasm_window(label)
#
# ...and that they are both in graph mode
#
widget_a = find_widget("IDA View-A")
set_view_renderer_type(widget_a, TCCRT_GRAPH)
widget_a = ida_kernwin.find_widget("IDA View-A")
ida_kernwin.set_view_renderer_type(widget_a, ida_kernwin.TCCRT_GRAPH)
widget_b = find_widget("IDA View-B")
set_view_renderer_type(widget_b, TCCRT_GRAPH)
widget_b = ida_kernwin.find_widget("IDA View-B")
ida_kernwin.set_view_renderer_type(widget_b, ida_kernwin.TCCRT_GRAPH)
#
# Put view B to the right of view A
#
set_dock_pos("IDA View-B", "IDA View-A", DP_RIGHT)
ida_kernwin.set_dock_pos("IDA View-B", "IDA View-A", ida_kernwin.DP_RIGHT)
#
# Start monitoring IDA View-A
@@ -77,7 +79,7 @@ wrap_a.Bind()
#
def fit_widget_a():
def do_fit_widget_a():
viewer_fit_window(widget_a)
execute_sync(do_fit_widget_a, MFF_FAST)
ida_graph.viewer_fit_window(widget_a)
ida_kernwin.execute_sync(do_fit_widget_a, ida_kernwin.MFF_FAST)
import threading
threading.Timer(0.25, fit_widget_a).start()
+23 -16
View File
@@ -4,35 +4,41 @@ from __future__ import print_function
# view (and thus its graph), in Python.
# (c) Hex-Rays
#
from idaapi import IDAViewWrapper
from time import sleep
import threading
import ida_kernwin
import ida_graph
class Worker(threading.Thread):
def __init__(self, w):
threading.Thread.__init__(self)
self.w = w
def log(self, msg):
print(">>> thread: %s" % msg)
def req_SetCurrentRendererType(self, switch_to):
w = self.w
def f():
print("Switching..")
self.log("Switching to %s" % switch_to)
w.SetCurrentRendererType(switch_to)
idaapi.execute_sync(f, idaapi.MFF_FAST)
ida_kernwin.execute_sync(f, ida_kernwin.MFF_FAST)
def req_SetNodeInfo(self, node, info, flags):
w = self.w
def f():
print("Setting node info..")
self.log("Setting node info..")
w.SetNodeInfo(node, info, flags)
idaapi.execute_sync(f, idaapi.MFF_FAST)
ida_kernwin.execute_sync(f, ida_kernwin.MFF_FAST)
def req_DelNodesInfos(self, *nodes):
w = self.w
def f():
print("Deleting nodes infos..")
self.log("Deleting nodes infos..")
w.DelNodesInfos(*nodes)
idaapi.execute_sync(f, idaapi.MFF_FAST)
ida_kernwin.execute_sync(f, ida_kernwin.MFF_FAST)
def run(self):
# Note, in order to leave the UI available
@@ -43,35 +49,36 @@ class Worker(threading.Thread):
#
# 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.
# 'ida_kernwin.execute_sync' to send requests to the main thread.
# Switch back & forth to & from graph view
for i in range(3):
self.req_SetCurrentRendererType(idaapi.TCCRT_FLAT)
self.req_SetCurrentRendererType(ida_kernwin.TCCRT_FLAT)
sleep(1)
self.req_SetCurrentRendererType(idaapi.TCCRT_GRAPH)
self.req_SetCurrentRendererType(ida_kernwin.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()
self.req_SetCurrentRendererType(ida_kernwin.TCCRT_GRAPH)
ni = ida_graph.node_info_t()
ni.bg_color = 0x00ff00ff
ni.frame_color = 0x0000ff00
self.req_SetNodeInfo(0, ni, idaapi.NIF_BG_COLOR|idaapi.NIF_FRAME_COLOR)
self.req_SetNodeInfo(0, ni, ida_graph.NIF_BG_COLOR|ida_graph.NIF_FRAME_COLOR)
sleep(3)
# This was fun. But let's revert it.
self.req_DelNodesInfos(0)
sleep(3)
print("Done.")
self.log("Done.")
class MyIDAViewWrapper(IDAViewWrapper):
class MyIDAViewWrapper(ida_kernwin.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)
ida_kernwin.IDAViewWrapper.__init__(self, viewName)
# Helper function, to be called by "On*" event handlers.
# This will print all the arguments that were passed!
+15 -16
View File
@@ -3,21 +3,20 @@ from __future__ import print_function
# This is an example illustrating how to use customview in Python
# (c) Hex-Rays
#
import idaapi
import idc
from idaapi import simplecustviewer_t
import ida_kernwin
import ida_lines
# -----------------------------------------------------------------------
class say_something_handler_t(idaapi.action_handler_t):
class say_something_handler_t(ida_kernwin.action_handler_t):
def __init__(self, thing):
idaapi.action_handler_t.__init__(self)
ida_kernwin.action_handler_t.__init__(self)
self.thing = thing
def activate(self, ctx):
print(self.thing)
def update(self, ctx):
return idaapi.AST_ENABLE_ALWAYS
return ida_kernwin.AST_ENABLE_ALWAYS
@staticmethod
def compose_action_name(v):
@@ -38,7 +37,7 @@ for av in actions_variants:
# -----------------------------------------------------------------------
class mycv_t(simplecustviewer_t):
class mycv_t(ida_kernwin.simplecustviewer_t):
def Create(self, sn=None, use_colors=True):
# Form the title
title = "Simple custom view test"
@@ -47,16 +46,16 @@ class mycv_t(simplecustviewer_t):
self.use_colors = use_colors
# Create the customviewer
if not simplecustviewer_t.Create(self, title):
if not ida_kernwin.simplecustviewer_t.Create(self, title):
return False
for i in range(0, 100):
prefix, bg = idaapi.COLOR_DEFAULT, None
prefix, bg = ida_lines.COLOR_DEFAULT, None
# make every 10th line a bit special
if i % 10 == 0:
prefix = idaapi.COLOR_DNAME # i.e., dark yellow...
prefix = ida_lines.COLOR_DNAME # i.e., dark yellow...
bg = 0xFFFF00 # ...on cyan
pfx = idaapi.COLSTR("%3d" % i, idaapi.SCOLOR_PREFIX)
pfx = ida_lines.COLSTR("%3d" % i, ida_lines.SCOLOR_PREFIX)
if self.use_colors:
self.AddLine("%s: Line %d" % (pfx, i), fgcolor=prefix, bgcolor=bg)
else:
@@ -120,7 +119,7 @@ class mycv_t(simplecustviewer_t):
elif vkey == ord('G'):
n = self.GetLineNo()
if n is not None:
v = idaapi.ask_long(self.GetLineNo(), "Where to go?")
v = ida_kernwin.ask_long(self.GetLineNo(), "Where to go?")
if v:
self.Jump(v, 0, 5)
elif vkey == ord('R'):
@@ -130,7 +129,7 @@ class mycv_t(simplecustviewer_t):
print("refreshing current line...")
self.RefreshCurrent()
elif vkey == ord('A'):
s = idaapi.ask_str("NewLine%d" % self.Count(), 0, "Append new line")
s = ida_kernwin.ask_str("NewLine%d" % self.Count(), 0, "Append new line")
self.AddLine(s)
self.Refresh()
elif vkey == ord('X'):
@@ -139,7 +138,7 @@ class mycv_t(simplecustviewer_t):
self.Refresh()
elif vkey == ord('I'):
n = self.GetLineNo()
s = idaapi.ask_str("InsertedLine%d" % n, 0, "Insert new line")
s = ida_kernwin.ask_str("InsertedLine%d" % n, 0, "Insert new line")
self.InsertLine(n, s)
self.Refresh()
elif vkey == ord('E'):
@@ -148,7 +147,7 @@ class mycv_t(simplecustviewer_t):
return False
n = self.GetLineNo()
print("curline=<%s>" % l)
l = l + idaapi.COLSTR("*", idaapi.SCOLOR_VOIDOP)
l = l + ida_lines.COLSTR("*", ida_lines.SCOLOR_VOIDOP)
self.EditLine(n, l)
self.RefreshCurrent()
print("Edited line %d" % n)
@@ -167,7 +166,7 @@ class mycv_t(simplecustviewer_t):
return (1, "OnHint, line=%d" % lineno)
def Show(self, *args):
ok = simplecustviewer_t.Show(self, *args)
ok = ida_kernwin.simplecustviewer_t.Show(self, *args)
if ok:
# permanently attach actions to this viewer's popup menu
for av in actions_variants:
@@ -22,6 +22,14 @@ class MyChoose(Choose):
self.deflt = n # save current selection
return (Choose.NOTHING_CHANGED, )
def OnDeleteLine(self, indices):
new_items = []
for idx, item in enumerate(self.items):
if idx not in indices:
new_items.append(item)
self.items = new_items
return [Choose.ALL_CHANGED] + indices
def show(self, num):
self.deflt = [x
for x in range(len(self.items))
+68 -21
View File
@@ -36,6 +36,12 @@
# undef minor
#endif
#ifdef __NT__
# define PY_MODULE_EXT ".pyd"
#else
# define PY_MODULE_EXT ".so"
#endif
//-------------------------------------------------------------------------
struct user_args_t
{
@@ -217,17 +223,21 @@ struct pylib_entries_t
return nullptr;
}
pylib_entry_t &get_or_create_entry_for_version(const pylib_version_t &version)
pylib_entry_t &add_entry(const pylib_version_t &version, const qstrvec_t &paths)
{
pylib_entry_t *e = get_entry_for_version(version);
if ( e == nullptr )
{
pylib_entry_t ne(version);
entries.push_back(ne);
e = &entries.back();
}
pylib_entry_t ne(version);
ne.paths = paths;
entries.push_back(ne);
pylib_entry_t *e = &entries.back();
return *e;
}
pylib_entry_t &add_entry(const pylib_version_t &version, const char *path)
{
qstrvec_t paths;
paths.push_back(path);
return add_entry(version, paths);
}
};
#ifdef __UNIX__
@@ -238,8 +248,8 @@ static void set_preferred_pylib_version(pylib_entries_t *result);
struct pyver_tool_t
{
static bool reverse_compare_entries(
const pylib_entry_t &e0,
const pylib_entry_t &e1)
const pylib_entry_t &e0,
const pylib_entry_t &e1)
{
if ( e0.preferred )
return true;
@@ -252,15 +262,14 @@ struct pyver_tool_t
}
bool path_to_pylib_entry(
pylib_entry_t *out,
const char *path,
qstring *errbuf) const
pylib_entry_t *out,
const char *path,
qstring *errbuf) const
{
return do_path_to_pylib_entry(out, path, errbuf);
}
void find_python_libs(
pylib_entries_t *result) const
void find_python_libs(pylib_entries_t *result) const
{
do_find_python_libs(result);
@@ -280,10 +289,11 @@ struct pyver_tool_t
}
bool apply_version(
const pylib_entry_t &entry,
qstring *errbuf) const
const pylib_entry_t &entry,
qstring *errbuf) const
{
return do_apply_version(entry, errbuf);
return do_pick_sip(entry, errbuf)
&& do_apply_version(entry, errbuf);
}
private:
@@ -298,12 +308,47 @@ private:
// Python3 version and produce an entry with it.
bool do_path_to_pylib_entry(pylib_entry_t *entry, const char *path, qstring *errbuf) const;
// Pick the right sip.so for the selected version, and
// copy it in the PyQt5 directory
bool do_pick_sip(const pylib_entry_t &entry, qstring *errbuf) const;
// Do patch the idapython.[so|dylib] binary (or the
// registry on Windows) so that they refer to the right
// Python3 version.
bool do_apply_version(const pylib_entry_t &entry, qstring *errbuf) const;
};
//-------------------------------------------------------------------------
bool pyver_tool_t::do_pick_sip(
const pylib_entry_t &entry,
qstring *errbuf) const
{
const char *src_sip_subdir = entry.version.minor >= 8 ? "python_3.8" : "python_3.4";
char src_sip_path[QMAXPATH];
qmakepath(src_sip_path, sizeof(src_sip_path), idadir(""),
"python", "3", "PyQt5", src_sip_subdir, "sip" PY_MODULE_EXT, nullptr);
if ( !qfileexist(src_sip_path) )
{
errbuf->sprnt("File not found: \"%s\"", src_sip_path);
return false;
}
char dst_sip_path[QMAXPATH];
qmakepath(dst_sip_path, sizeof(dst_sip_path), idadir(""),
"python", "3", "PyQt5", "sip" PY_MODULE_EXT, nullptr);
out_verb("Copying \"%s\" to \"%s\"\n", src_sip_path, dst_sip_path);
const int code = qcopyfile(src_sip_path, dst_sip_path, /*overwrite=*/ true);
if ( code != 0 )
{
errbuf->sprnt("Couldn't copy file \"%s\" to \"%s\": %s",
src_sip_path, dst_sip_path, qstrerror(-1));
return false;
}
return true;
}
//-------------------------------------------------------------------------
// Accepts:
// "3.7"
@@ -473,7 +518,9 @@ static int for_all_plugin_files(file_visitor_t &dv, qstring *errbuf)
if ( qfileexist(path) )
{
found++;
qmakepath(path, sizeof(path), idadir(""), "plugins", is_ea64 ? "idapython64." SOSFX : "idapython." SOSFX, nullptr);
char fname[QMAXPATH];
qsnprintf(fname, sizeof(fname), "idapython%d%s.%s", args.major_version, is_ea64 ? "_64" : "", SOSFX);
qmakepath(path, sizeof(path), idadir(""), "plugins", fname, nullptr);
int ret = dv.visit_file(path);
if ( ret != 0 )
return ret;
@@ -543,7 +590,7 @@ static const cliopt_t _opts[] =
},
#ifdef __UNIX__
{ 'k', "ignore-python-config", "Don't use python-config to find out the preferred version number", set_ignore_python_config, 0 },
{ 'k', "ignore-python-config", "Do not use python-config to find out the preferred version number", set_ignore_python_config, 0 },
#endif
#ifdef __LINUX__
{ 'x', "split-debug-and-expand-libpython3-dtneeded-room", "Expand the DT_NEEDED room to N bytes, using the local `patchelf` (needed at build-time only)", set_split_debug_expand_libpython3_dtneeded_room, 1 },
@@ -576,7 +623,7 @@ static const char usage_epilog[] =
"\n"
" 2) The 'automatic' way\n"
" ----------------------\n"
" > $ idapyswitch --auto\n"
" > $ idapyswitch --auto-apply\n"
" will look on the filesystem for available Python3 installations,\n"
" and automatically pick the one it deemed the most preferable.\n"
"\n"
+2 -3
View File
@@ -43,8 +43,7 @@ void pyver_tool_t::do_find_python_libs(pylib_entries_t *result) const
{
qmakepath(path, sizeof(path), d, fb.ff_name, nullptr);
out_verb("Found: \"%s\" (version: %s)\n", path, version.str(&verbuf));
pylib_entry_t &e = result->get_or_create_entry_for_version(version);
e.paths.push_back(path);
result->add_entry(version, path);
}
}
}
@@ -333,7 +332,7 @@ bool pyver_tool_t::do_apply_version(
patcher_t(const qstring &_soname, qstring *_errbuf)
: lsoname(_soname), lerrbuf(_errbuf) {}
virtual int visit_file(const char *path)
virtual int visit_file(const char *path) override
{
return patch_dt_needed(path, lsoname, lerrbuf) ? 0 : -1;
}
+12 -6
View File
@@ -82,7 +82,10 @@ static bool get_pylib_entry_for_macho(
{
pylib_entry_t *entry;
lcid_finder_t(pylib_entry_t *_entry) : entry(_entry) {}
virtual int visit_dylib(const struct dylib_command *dl, const char *begin, const char *end)
virtual int visit_dylib(
const struct dylib_command *dl,
const char *begin,
const char *end) override
{
if ( dl->cmd == LC_ID_DYLIB )
{
@@ -119,7 +122,7 @@ static int extract_pylib_bin(pylib_entries_t *result, const char *version_dir)
{
pylib_entries_t *result;
pylib_finder_t(pylib_entries_t *_result) : result(_result) {}
virtual int visit_file(const char *bin)
virtual int visit_file(const char *bin) override
{
qstring errbuf;
pylib_version_t dummy;
@@ -150,7 +153,7 @@ static void extract_pylib_versions(pylib_entries_t *result, const char *framewor
{
pylib_entries_t *result;
version_visitor_t(pylib_entries_t *_result) : result(_result) {}
virtual int visit_file(const char *version_dir)
virtual int visit_file(const char *version_dir) override
{
extract_pylib_bin(result, version_dir);
return 0;
@@ -182,7 +185,7 @@ void pyver_tool_t::do_find_python_libs(pylib_entries_t *result) const
{
pylib_entries_t *result;
python_framework_finder_t(pylib_entries_t *_result) : result(_result) {}
virtual int visit_file(const char *framework)
virtual int visit_file(const char *framework) override
{
extract_pylib_versions(result, framework);
return 0;
@@ -277,7 +280,10 @@ static bool get_python_lc_info(python_lc_info_t *plc, const char *path, qstring
{
plc->off = sizeof(mach_header_64);
}
virtual int visit_any_load_command(const struct load_command *lc, const char *begin, const char *end)
virtual int visit_any_load_command(
const struct load_command *lc,
const char *begin,
const char *end) override
{
if ( lc->cmd == LC_LOAD_DYLIB )
{
@@ -433,7 +439,7 @@ bool pyver_tool_t::do_apply_version(
const pylib_entry_t &entry;
qstring *lerrbuf;
patcher_t(const pylib_entry_t &_entry, qstring *_errbuf) : entry(_entry), lerrbuf(_errbuf) {}
virtual int visit_file(const char *path)
virtual int visit_file(const char *path) override
{
return patch_python_dylib_cmd(path, entry, lerrbuf) ? 0 : -1;
}
+3 -4
View File
@@ -401,8 +401,7 @@ static void enum_python_key(pylib_entries_t *result, const HKEY hkey, qstring *_
&errbuf) )
{
out("Found: \"%s\" (version: %s)\n", install_path.c_str(), version.str(&verbuf));
pylib_entry_t &e = result->get_or_create_entry_for_version(version);
e.paths.insert(e.paths.end(), paths.begin(), paths.end());
pylib_entry_t &e = result->add_entry(version, paths);
e.display_name = displayname;
}
else
@@ -587,9 +586,9 @@ bool pyver_tool_t::do_apply_version(
}
// Now, let's handle sip.pyd
out_verb("Handling sip.pyd\n");
out_verb("Handling sip" PY_MODULE_EXT "\n");
char path[QMAXPATH];
qmakepath(path, sizeof(path), idadir(""), "python", "3", "PyQt5", "sip.pyd", nullptr);
qmakepath(path, sizeof(path), idadir(""), "python", "3", "PyQt5", "sip" PY_MODULE_EXT, nullptr);
linput_t *linput = open_linput(path, /*remote=*/ false);
if ( linput == nullptr )
{
+1230 -1286
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

+1 -1
View File
@@ -29,6 +29,7 @@ global:
idapython_hide_wait_box;
idcvar_to_pyvar;
is_api695_compat_enabled;
get_plugin_instance;
lookup_info_t_commit;
lookup_info_t_del_by_py_view;
lookup_info_t_find_by_py_view;
@@ -43,7 +44,6 @@ global:
py_customidamemo_t_delete_groups;
py_customidamemo_t_set_groups_visibility;
py_customidamemo_t_unbind;
pycim_lookup_info;
pylong_to_byte_array;
pyobj_get_clink;
python_timer_del;
+1 -1
View File
@@ -22,6 +22,7 @@ EXPORTS
enable_extlang_python
enable_python_cli
is_api695_compat_enabled
get_plugin_instance
idcvar_to_pyvar
lookup_info_t_commit
lookup_info_t_del_by_py_view
@@ -65,4 +66,3 @@ EXPORTS
idapython_hide_wait_box
register_module_lifecycle_callbacks
prepare_programmatic_plugin_load
pycim_lookup_info DATA
+1
View File
@@ -0,0 +1 @@
ida_exclude+=fuzzer.hpp
+202 -97
View File
@@ -1,8 +1,8 @@
ifeq ($(PYTHON_VERSION_MAJOR),3)
OBJDIR=obj/$(SYSDIR)/3
else
ifeq ($(PYTHON_VERSION_MAJOR),2)
OBJDIR=obj/$(SYSDIR)/2
else
OBJDIR=obj/$(SYSDIR)/3
endif
include ../../allmake.mak
@@ -24,8 +24,8 @@ include ../../allmake.mak
#----------------------------------------------------------------------
# default goals
.PHONY: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections public_tree test_idc docs bins
all: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections bins # public_tree test_idc docs
.PHONY: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections pyqt sip bins public_tree test_idc docs
all: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections pyqt sip bins # public_tree test_idc docs
ifeq ($(OUT_OF_TREE_BUILD),)
BINS += $(IDAPYSWITCH)
@@ -59,18 +59,14 @@ endif
# HACK HIJACK the $(I) variable to point to our staging SDK
# (but don't let mkdep know about it)
IDA_INCLUDE = ../../include
ifeq ($(OUT_OF_TREE_BUILD),)
ST_SDK = $(F)idasdk
else
ST_SDK = $(IDA_INCLUDE)
endif
ST_SDK = $(F)idasdk
ifndef __MKDEP__
I = $(ST_SDK)/
endif
# HACK HIJACK the $(LIBDIR) variable to point to our staging SDK
ifneq ($(OUT_OF_TREE_BUILD),)
LIBDIR = $(IDA)lib/$(TARGET_PROCESSOR_NAME)_$(SYSNAME)_$(COMPILER_NAME)_$(ADRSIZE)$(STATSUF)
LIBDIR = $(IDA)lib/$(TARGET_PROCESSOR_NAME)_$(SYSNAME)_$(COMPILER_NAME)_$(ADRSIZE)$(EXTRASUF)
endif
# HACK for mkdep to add dependencies for $(F)idapython$(O)
@@ -92,7 +88,20 @@ CONFIGS += idapython.cfg
#----------------------------------------------------------------------
# the 'modules' target is in $(IDA)module.mak
MODULE = $(call module_dll,idapython)
ifeq ($(PYTHON_VERSION_MAJOR),3)
ifdef __EA64__
MODULE_NAME_STEM:=idapython3_
else
MODULE_NAME_STEM:=idapython3
endif
else
ifdef __EA64__
MODULE_NAME_STEM:=idapython2_
else
MODULE_NAME_STEM:=idapython2
endif
endif
MODULE = $(call module_dll,$(MODULE_NAME_STEM))
MODULES += $(MODULE)
#----------------------------------------------------------------------
@@ -110,9 +119,9 @@ else
IDAPYSWITCH_MODULE_DEP := $(IDAPYSWITCH)
ifndef __CODE_CHECKER__
# this is for idapython[64].so
POSTACTION=$(IDAPYSWITCH) --split-debug-and-expand-libpython3-dtneeded-room $(MODULE)
POSTACTION=$(Q)$(IDAPYSWITCH) --split-debug-and-expand-libpython3-dtneeded-room $(MODULE)
# and this for _ida_*.so
POSTACTION_IDA_X_SO=$(IDAPYSWITCH) --split-debug-and-expand-libpython3-dtneeded-room
POSTACTION_IDA_X_SO=$(Q)$(IDAPYSWITCH) --split-debug-and-expand-libpython3-dtneeded-room
endif
endif
endif
@@ -121,18 +130,16 @@ endif
#----------------------------------------------------------------------
# we explicitly added our module targets
NO_DEFAULT_MODULE = 1
NO_DEFAULT_TARGETS = 1
DONT_ERASE_LIB = 1
# NOTE: all MODULES must be defined before including plugin.mak.
include ../plugin.mak
include ../pyplg.mak
# NOTE: target-specific rules and dependencies that use variable
# expansion to name the target (such as "$(MODULE): [...]") must
# come after including plugin.mak
# setup PYTHON_{C,LD}FLAGS (from allmake.mak)
$(eval $(call setup_python_flags))
#----------------------------------------------------------------------
PYTHON_OBJS += $(F)idapython$(O)
$(MODULE): MODULE_OBJS += $(PYTHON_OBJS)
@@ -173,7 +180,6 @@ ifdef DO_IDAMAKE_SIMPLIFY
endif
#----------------------------------------------------------------------
IDA_CMD=TVHEADLESS=1 $(R)idat$(SUFF64)
ST_SWIG=$(F)swig
ST_PYW=$(F)pywraps
ST_WRAP=$(F)wrappers
@@ -197,51 +203,73 @@ endif
ifeq ($(OUT_OF_TREE_BUILD),)
TEST_IDC=test_idc
IDC_BC695_IDC_SOURCE?=$(DEPLOY_PYDIR)/../../idc/idc.idc
IDAT_PATH?=$(R)/idat
else
IDC_BC695_IDC_SOURCE?=$(IDA_INSTALL)/idc/idc.idc
IDAT_PATH?=$(IDA_INSTALL)/idat
endif
IDAT_CMD=TVHEADLESS=1 $(IDAT_PATH)$(SUFF64)
ifneq ($(OUT_OF_TREE_BUILD),)
# envvar HAS_HEXRAYS must have been set by build.py if needed
else
ifeq ($(BUILD_VD),1)
HAS_HEXRAYS=1 # force hexrays bindings
endif
endif
#
ifeq ($(OUT_OF_TREE_BUILD),)
include ../../etc/sdk/sdk_files.mak
SDK_SOURCES=$(sort $(foreach v,$(SDK_FILES),$(if $(findstring include/,$(v)),$(addprefix $(IDA_INCLUDE)/,$(notdir $(v))))))
SDK_SOURCES+=$(IDA_INCLUDE)/hexrays.hpp
ifneq ($(HAS_HEXRAYS),)
SDK_SOURCES+=$(IDA_INCLUDE)/hexrays.hpp
endif
SDK_SOURCES+=$(IDA_INCLUDE)/lumina.hpp
ST_SDK_TARGETS = $(SDK_SOURCES:$(IDA_INCLUDE)/%=$(ST_SDK)/%)
SDK_SOURCES+=$(IDA_INCLUDE)/dirtree.hpp
else
SDK_SOURCES=$(wildcard $(IDA_INCLUDE)/*.h) $(wildcard $(IDA_INCLUDE)/*.hpp)
ST_SDK_TARGETS = $(SDK_SOURCES)
endif
ST_SDK_TARGETS = $(SDK_SOURCES:$(IDA_INCLUDE)/%=$(ST_SDK)/%)
# Python 2-3
ifeq ($(PYTHON_VERSION_MAJOR),3)
_SWIGPY3FLAG := -py3 -py3-stable-abi -DPY3=1
CC_DEFS += PY3=1
CC_DEFS += Py_LIMITED_API=0x03040000 # we should make sure we use the same version as SWiG
else
USE_PYTHON2_ENVVAR := USE_PYTHON2=1
endif
DYNLOAD_SUBDIR := python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)
DEPLOY_LIBDIR=$(DEPLOY_PYDIR)/ida_$(ADRSIZE)
ifdef __NT__
MODULE_SFX = .pyd
PYDLL_EXT = .pyd
else
MODULE_SFX = .so
PYDLL_EXT = .so
endif
ifneq ($(OUT_OF_TREE_BUILD),)
# envvar HAS_HEXRAYS must have been set by build.py if needed
else
HAS_HEXRAYS=1 # force hexrays bindings
endif
ifneq ($(HAS_HEXRAYS),)
WITH_HEXRAYS_DEF = WITH_HEXRAYS
WITH_HEXRAYS_CHKAPI=--with-hexrays
HEXRAYS_MODNAME=hexrays
ifdef BC695
CMP_API = 1
endif
# Warning: adding an empty HEXRAYS_MODNAME will lead to idaapy trying to load
# a module called ida_.
MODULES_NAMES += $(HEXRAYS_MODNAME)
endif
ifeq ($(CMP_API),)
NO_CMP_API := 1
endif
#----------------------------------------------------------------------
MODULES_NAMES += $(HEXRAYS_MODNAME)
MODULES_NAMES += allins
MODULES_NAMES += auto
MODULES_NAMES += bitrange
MODULES_NAMES += bytes
MODULES_NAMES += dbg
MODULES_NAMES += diskio
@@ -264,6 +292,10 @@ MODULES_NAMES += lines
MODULES_NAMES += loader
ifdef TESTABLE_BUILD
MODULES_NAMES += lumina
# when dirtree.hpp makes it into the SDK, add all relevant scripts
# that are currently in tests/ui/, into plugins/idapython/examples/.
# Grep for 'dirtree' and 'dirspec' to spot those.
MODULES_NAMES += dirtree
endif
MODULES_NAMES += moves
MODULES_NAMES += nalt
@@ -286,9 +318,9 @@ MODULES_NAMES += xref
ALL_ST_WRAP_CPP = $(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/$(mod).cpp)
ALL_ST_WRAP_PY = $(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/ida_$(mod).py)
DEPLOYED_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_LIBDIR)/_ida_$(mod)$(MODULE_SFX))
DEPLOYED_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_LIBDIR)/_ida_$(mod)$(PYDLL_EXT))
IDAPYTHON_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_PYDIR)/ida_$(mod).py)
PYTHON_BINARY_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_LIBDIR)/_ida_$(mod)$(MODULE_SFX))
PYTHON_BINARY_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_LIBDIR)/_ida_$(mod)$(PYDLL_EXT))
#----------------------------------------------------------------------
idapython_modules: $(IDAPYTHON_MODULES)
@@ -331,6 +363,79 @@ pyfiles: $(DEPLOY_IDAUTILS_PY) \
$(DEPLOY_IDADEX_PY) \
$(DEPLOY_LUMINA_MODEL_PY)
ifeq ($(OUT_OF_TREE_BUILD),)
ifndef NDEBUG
SRC_PYQT_BUNDLE:=$(PYQT5_DEBUG)
else
SRC_PYQT_BUNDLE:=$(PYQT5_RELEASE)
endif
DEST_PYQT_DIR:=$(R)python/$(PYTHON_VERSION_MAJOR)/PyQt5
$(DEST_PYQT_DIR):
-$(Q)if [ ! -d "$(DEST_PYQT_DIR)" ] ; then mkdir -p 2>/dev/null $(DEST_PYQT_DIR) ; fi
# PyQt5
DEST_PYQT_QTCORE:=$(DEST_PYQT_DIR)/QtCore$(PYDLL_EXT)
$(DEST_PYQT_QTCORE): $(SRC_PYQT_BUNDLE) | $(DEST_PYQT_DIR)
$(Q)tar -xf $(SRC_PYQT_BUNDLE) -C $(dir $(DEST_PYQT_DIR)) --strip 1
$(Q)touch $@
DEST_PYQT += $(DEST_PYQT_QTCORE)
SIP_PYDLL_FNAME:=sip$(PYDLL_EXT)
SIP_PYI_FNAME:=sip.pyi
ifeq ($(PYTHON_VERSION_MAJOR),3)
# sip for Python < 3.8
DEST_SIP34_DIR:=$(DEST_PYQT_DIR)/python_3.4
$(DEST_SIP34_DIR):
-$(Q)if [ ! -d "$(DEST_SIP34_DIR)" ] ; then mkdir -p 2>/dev/null $(DEST_SIP34_DIR) ; fi
DEST_SIP34_PYDLL:=$(DEST_SIP34_DIR)/$(SIP_PYDLL_FNAME)
DEST_SIP34_PYI:=$(DEST_SIP34_DIR)/$(SIP_PYI_FNAME)
$(DEST_SIP34_PYDLL): $(wildcard $(SIP34_TREE)/lib/python*/PyQt5/$(SIP_PYDLL_FNAME)) | $(DEST_SIP34_DIR)
$(Q)$(CP) $? $@
$(DEST_SIP34_PYI): $(wildcard $(SIP34_TREE)/lib/python*/PyQt5/$(SIP_PYI_FNAME)) | $(DEST_SIP34_DIR)
$(Q)$(CP) $? $@
DEST_SIP += $(DEST_SIP34_PYDLL) $(DEST_SIP34_PYI)
# sip for Python >= 3.8
DEST_SIP38_DIR:=$(DEST_PYQT_DIR)/python_3.8
$(DEST_SIP38_DIR):
-$(Q)if [ ! -d "$(DEST_SIP38_DIR)" ] ; then mkdir -p 2>/dev/null $(DEST_SIP38_DIR) ; fi
DEST_SIP38_PYDLL:=$(DEST_SIP38_DIR)/$(SIP_PYDLL_FNAME)
DEST_SIP38_PYI:=$(DEST_SIP38_DIR)/$(SIP_PYI_FNAME)
$(DEST_SIP38_PYDLL): $(wildcard $(SIP38_TREE)/lib/python*/PyQt5/$(SIP_PYDLL_FNAME)) | $(DEST_SIP38_DIR)
$(Q)$(CP) $? $@
$(DEST_SIP38_PYI): $(wildcard $(SIP38_TREE)/lib/python*/PyQt5/$(SIP_PYI_FNAME)) | $(DEST_SIP38_DIR)
$(Q)$(CP) $? $@
DEST_SIP += $(DEST_SIP38_PYDLL) $(DEST_SIP38_PYI)
else
# sip for Python 2.7
DEST_SIP27_DIR:=$(DEST_PYQT_DIR)
DEST_SIP27_PYDLL:=$(DEST_SIP27_DIR)/$(SIP_PYDLL_FNAME)
DEST_SIP27_PYI:=$(DEST_SIP27_DIR)/$(SIP_PYI_FNAME)
$(DEST_SIP27_PYDLL): $(wildcard $(SIP27_TREE)/lib/python*/PyQt5/$(SIP_PYDLL_FNAME)) | $(DEST_SIP27_DIR)
$(Q)$(CP) $? $@
$(DEST_SIP27_PYI): $(wildcard $(SIP27_TREE)/lib/python*/PyQt5/$(SIP_PYI_FNAME)) | $(DEST_SIP27_DIR)
$(Q)$(CP) $? $@
DEST_SIP += $(DEST_SIP27_PYDLL) $(DEST_SIP27_PYI)
endif
# And pick the right sip.so now (Python3 only; for Python2, we already put it in the right place)
ifeq ($(PYTHON_VERSION_MAJOR),3)
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 7; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP38_PYDLL)
else
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP34_PYDLL)
endif
$(DEST_PYQT_DIR)/$(SIP_PYDLL_FNAME): $(DEST_INSTALL_SIP_PYDLL)
$(Q)$(CP) $? $@
$(Q)chmod +w $@
DEST_SIP += $(DEST_PYQT_DIR)/$(SIP_PYDLL_FNAME)
endif
endif
pyqt: $(DEST_PYQT)
sip: $(DEST_SIP)
GENHOOKS=tools/genhooks/
$(DEPLOY_INIT_PY): python/init.py
@@ -399,14 +504,17 @@ $(foreach d,$(sort $(DIRLIST)),$(if $(wildcard $(d)),,$(shell mkdir -p $(d))))
# template incantation, and finally '%include "hexrays_notemplates.hpp"'
# to actually generate wrappers.
ifeq ($(OUT_OF_TREE_BUILD),)
$(ST_SDK)/%.h: $(IDA_INCLUDE)/%.h
$(QUPDATE_SDK) perl ../../etc/sdk/filter_src.pl $^ $@
$(ST_SDK)/%.hpp: $(IDA_INCLUDE)/%.hpp
$(QUPDATE_SDK) perl ../../etc/sdk/filter_src.pl $^ $@
HEXRAYS_HPP_SPLIT_DIR:=$(ST_SDK)
$(ST_SDK)/%.h: $(IDA_INCLUDE)/%.h ../../etc/sdk/filter_src.pl tools/preprocess_sdk_header.py
$(QUPDATE_SDK) perl ../../etc/sdk/filter_src.pl $< - | $(PYTHON) tools/preprocess_sdk_header.py --input - --output $@ --metadata $@.metadata
$(ST_SDK)/%.hpp: $(IDA_INCLUDE)/%.hpp ../../etc/sdk/filter_src.pl tools/preprocess_sdk_header.py
$(QUPDATE_SDK) perl ../../etc/sdk/filter_src.pl $< - | $(PYTHON) tools/preprocess_sdk_header.py --input - --output $@ --metadata $@.metadata
else
HEXRAYS_HPP_SPLIT_DIR:=$(F)
$(ST_SDK)/%.h: $(IDA_INCLUDE)/%.h tools/preprocess_sdk_header.py
$(QUPDATE_SDK) $(PYTHON) tools/preprocess_sdk_header.py --input $< --output $@ --metadata $@.metadata
$(ST_SDK)/%.hpp: $(IDA_INCLUDE)/%.hpp tools/preprocess_sdk_header.py
$(QUPDATE_SDK) $(PYTHON) tools/preprocess_sdk_header.py --input $< --output $@ --metadata $@.metadata
endif
HEXRAYS_HPP_SPLIT_DIR:=$(ST_SDK)
$(HEXRAYS_HPP_SPLIT_DIR)/hexrays_notemplates.hpp: $(ST_SDK)/hexrays.hpp tools/split_hexrays_templates.py
$(QSPLIT_HEXRAYS_TEMPLATES)$(PYTHON) tools/split_hexrays_templates.py \
@@ -432,64 +540,58 @@ $(ST_PYW)/py_idp.hpp: pywraps/py_idp.hpp \
$(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c IDP_Hooks \
-x $(ST_PARSED_HEADERS)/structprocessor__t.xml -e event_t \
-r int -n 0 -m hookgenIDP -q "processor_t::" \
-R $(GENHOOKS)recipe_idphooks.py
-x $(ST_PARSED_HEADERS) \
-m hookgenIDP \
-q "processor_t::"
$(ST_PYW)/py_idp_idbhooks.hpp: pywraps/py_idp_idbhooks.hpp \
$(I)idp.hpp \
$(GENHOOKS)recipe_idbhooks.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c IDB_Hooks \
-x $(ST_PARSED_HEADERS)/namespaceidb__event.xml -e event_code_t \
-r void -n 0 -m hookgenIDB -q "idb_event::" \
-R $(GENHOOKS)recipe_idbhooks.py
-x $(ST_PARSED_HEADERS) \
-m hookgenIDB \
-q "idb_event::"
$(ST_PYW)/py_dbg.hpp: pywraps/py_dbg.hpp \
$(I)dbg.hpp \
$(GENHOOKS)recipe_dbghooks.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c DBG_Hooks \
-x $(ST_PARSED_HEADERS)/dbg_8hpp.xml -q "dbg_notification_t::" -e dbg_notification_t \
-r void -n 0 -m hookgenDBG \
-R $(GENHOOKS)recipe_dbghooks.py
-x $(ST_PARSED_HEADERS) \
-m hookgenDBG \
-q "dbg_notification_t::"
$(ST_PYW)/py_kernwin.hpp: pywraps/py_kernwin.hpp \
$(I)kernwin.hpp \
$(GENHOOKS)recipe_uihooks.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c UI_Hooks \
-x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e ui_notification_t \
-x $(ST_PARSED_HEADERS) \
-q "ui_notification_t::" \
-r void -n 0 -m hookgenUI \
-R $(GENHOOKS)recipe_uihooks.py \
-d "ui_dbg_,ui_obsolete" -D "ui:" -s "ui_"
-m hookgenUI
$(ST_PYW)/py_kernwin_viewhooks.hpp: pywraps/py_kernwin_viewhooks.hpp \
$(I)kernwin.hpp \
$(GENHOOKS)recipe_viewhooks.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c View_Hooks \
-x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e view_notification_t \
-x $(ST_PARSED_HEADERS) \
-q "view_notification_t::" \
-r void -n 0 -m hookgenVIEW \
-R $(GENHOOKS)recipe_viewhooks.py
-m hookgenVIEW
$(ST_PYW)/py_hexrays_hooks.hpp: pywraps/py_hexrays_hooks.hpp \
$(HEXRAYS_HPP_SPLIT_DIR)/hexrays_notemplates.hpp \
$(GENHOOKS)recipe_hexrays.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c Hexrays_Hooks \
-x $(ST_PARSED_HEADERS)/hexrays_8hpp.xml -e hexrays_event_t \
-x $(ST_PARSED_HEADERS) \
-q "hexrays_event_t::" \
-r int -n 0 -m hookgenHEXRAYS \
-R $(GENHOOKS)recipe_hexrays.py \
-s "hxe_,lxe_"
-m hookgenHEXRAYS
#----------------------------------------------------------------------
CFLAGS += $(PYTHON_CFLAGS)
CC_DEFS += PYTHON_ABIFLAGS=$(PYTHON_ABIFLAGS)
CC_DEFS += $(BC695_CC_DEF)
CC_DEFS += $(DEF_TYPE_TABLE)
CC_DEFS += $(WITH_HEXRAYS_DEF)
@@ -499,10 +601,8 @@ CC_DEFS += VER_MINOR="4"
CC_DEFS += VER_PATCH="0"
CC_DEFS += __EXPR_SRC
CC_INCP += $(F)
CC_INCP += $(IDA_INCLUDE)
CC_INCP += $(ST_SWIG)
CC_INCP += ../../ldr/mach-o/h
CC_INCP += $(IRRXML)
CC_INCP += .
ifdef __UNIX__
@@ -565,10 +665,14 @@ SWIG_IFACE_funcs=range
SWIG_IFACE_gdl=range
SWIG_IFACE_hexrays=pro typeinf xref
SWIG_IFACE_idd=range
SWIG_IFACE_idp=bitrange
SWIG_IFACE_segment=range
SWIG_IFACE_segregs=range
SWIG_IFACE_typeinf=idp
SWIG_IFACE_tryblks=range
# ifdef TESTABLE_BUILD
# SWIG_IFACE_kernwin=dirtree
# endif
MODULE_LIFECYCLE_hexrays=--lifecycle-aware
MODULE_LIFECYCLE_bytes=--lifecycle-aware
@@ -624,7 +728,6 @@ define make-module-rules
-outdir $(ST_WRAP) -o $$@.in1 -oh $(ST_WRAP)/$(1).h -I$(ST_SDK) -DIDAPYTHON_MODULE_$(1)=1 $$<
$(call PATCH_CONST,$(ST_WRAP)/$(1).cpp.in1,$(ST_WRAP)/$(1).cpp.in2)
$(QPATCH_CODEGEN)$(PYTHON) tools/patch_codegen.py \
--apply-valist-patches \
--input $(ST_WRAP)/$(1).cpp.in2 \
--output $(ST_WRAP)/$(1).cpp \
--module $(1) \
@@ -671,7 +774,7 @@ $(X_O):
endif
# obj/x86_linux_gcc/_ida_X.so
_IDA_X_SO = $(addprefix $(F)_ida_,$(addsuffix $(MODULE_SFX),$(MODULES_NAMES)))
_IDA_X_SO = $(addprefix $(F)_ida_,$(addsuffix $(PYDLL_EXT),$(MODULES_NAMES)))
ifdef __NT__
$(_IDA_X_SO): STDLIBS += user32.lib
endif
@@ -685,14 +788,14 @@ endif
# See Python's dynload_win.c:GetPythonImport() for more details.
$(_IDA_X_SO): STDLIBS += $(LINKIDAPYTHON)
$(_IDA_X_SO): LDFLAGS += $(PYTHON_LDFLAGS) $(PYTHON_LDFLAGS_RPATH_MODULE) $(OUTMAP)$(F)$(@F).map
$(F)_ida_%$(MODULE_SFX): $(F)%$(O) $(MODULE) $(IDAPYTHON_IMPLIB_DEF) $(IDAPYSWITCH_MODULE_DEP)
$(F)_ida_%$(PYDLL_EXT): $(F)%$(O) $(MODULE) $(IDAPYTHON_IMPLIB_DEF) $(IDAPYSWITCH_MODULE_DEP)
$(call link_dll, $<, $(LINKIDA))
ifdef __NT__
$(Q)$(RM) $(@:$(MODULE_SFX)=.exp) $(@:$(MODULE_SFX)=.lib)
$(Q)$(RM) $(@:$(PYDLL_EXT)=.exp) $(@:$(PYDLL_EXT)=.lib)
endif
# ../../bin/x64_linux_gcc/python/2/ida_32/_ida_X.so
$(DEPLOY_LIBDIR)/_ida_%$(MODULE_SFX): $(F)_ida_%$(MODULE_SFX)
$(DEPLOY_LIBDIR)/_ida_%$(PYDLL_EXT): $(F)_ida_%$(PYDLL_EXT)
$(Q)$(CP) $< $@
ifdef __LINUX__
ifndef __CODE_CHECKER__
@@ -715,7 +818,7 @@ api_contents: $(ST_API_CONTENTS)
$(ST_API_CONTENTS): $(ALL_ST_WRAP_CPP)
$(QCHKAPI)$(PYTHON) tools/chkapi.py $(WITH_HEXRAYS_CHKAPI) -i $(subst $(space),$(comma),$(ALL_ST_WRAP_CPP)) -p $(subst $(space),$(comma),$(ALL_ST_WRAP_PY)) -r $(ST_API_CONTENTS)
ifeq ($(OUT_OF_TREE_BUILD),)
ifdef BC695 # turn off comparison when bw-compat is off, or api_contents will differ
ifdef CMP_API # turn off comparison when bw-compat is off, or api_contents will differ
$(Q)(diff -w $(API_CONTENTS) $(ST_API_CONTENTS)) > /dev/null || \
(echo "API CONTENTS CHANGED! update $(API_CONTENTS) or fix the API" && \
echo "(New API: $(ST_API_CONTENTS)) ***" && \
@@ -733,22 +836,24 @@ endif
ST_PYDOC_INJECTIONS = $(F)$(PYDOC_INJECTIONS)
.PRECIOUS: $(ST_PYDOC_INJECTIONS)
PYDOC_INJECTIONS_IDA_CMD=$(IDA_CMD) $(BATCH_SWITCH) -OIDAPython:AUTOIMPORT_COMPAT_IDA695=NO -S"$< $@ $(ST_WRAP)" -t -L$(F)dumpdoc.log >/dev/null
ifdef __EA64__
DUMPDOC_IS_64:=True
else
DUMPDOC_IS_64:=False
endif
PYDOC_INJECTIONS_IDAT_CMD=$(USE_PYTHON2_ENVVAR) $(IDAT_CMD) $(BATCH_SWITCH) "-OIDAPython:AUTOIMPORT_COMPAT_IDA695=NO" -S"$< $@ $(ST_WRAP) $(DUMPDOC_IS_64)" -t -L$(F)dumpdoc.log >/dev/null
pydoc_injections: $(ST_PYDOC_INJECTIONS)
$(ST_PYDOC_INJECTIONS): tools/dumpdoc.py $(IDAPYTHON_MODULES) $(PYTHON_BINARY_MODULES)
ifdef __CODE_CHECKER__
$(Q)touch $@
else
ifeq ($(OUT_OF_TREE_BUILD),)
$(QPYDOC_INJECTIONS)$(PYDOC_INJECTIONS_IDA_CMD) || \
(echo "Command \"$(PYDOC_INJECTIONS_IDA_CMD)\" failed. Check \"$(F)dumpdoc.log\" for details." && false)
ifeq ($(or $(__CODE_CHECKER__),$(NO_CMP_API),$(__ASAN__)),)
$(QPYDOC_INJECTIONS)$(PYDOC_INJECTIONS_IDAT_CMD) || \
(echo "Command \"$(PYDOC_INJECTIONS_IDAT_CMD)\" failed. Check \"$(F)dumpdoc.log\" for details." && false)
$(Q)(diff -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS)) > /dev/null || \
(echo "PYDOC INJECTION CHANGED! update $(PYDOC_INJECTIONS) or fix .. what needs fixing" && \
echo "(New API: $(ST_PYDOC_INJECTIONS)) ***" && \
(diff -U 1 -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS) && false))
else
else
$(Q)touch $@
endif
endif
#----------------------------------------------------------------------
@@ -759,7 +864,7 @@ tools/docs/hrdoc.cfg: tools/docs/hrdoc.cfg.in
# the html files are produced in docs\hr-html directory
docs: tools/docs/hrdoc.py tools/docs/hrdoc.cfg tools/docs/hrdoc.css
ifndef __NT__
TVHEADLESS=1 $(R)idat -Stools/docs/hrdoc.py -t > /dev/null
$(IDAT_CMD) -Stools/docs/hrdoc.py -t > /dev/null
else
$(R)ida -Stools/docs/hrdoc.py -t
endif
@@ -781,7 +886,7 @@ $(TEST_IDC): $(F)idctest.log
$(F)idctest.log: $(RS)idc/idc.idc | $(MODULE) pyfiles
ifneq ($(wildcard ../../tests),)
$(Q)$(RM) $(F)idctest.log
$(Q)$(IDA_CMD) $(BATCH_SWITCH) -S"test_idc.py $^" -t -L$(F)idctest.log >/dev/null || \
$(Q)$(IDAT_CMD) $(BATCH_SWITCH) -S"test_idc.py $^" -t -L$(F)idctest.log >/dev/null || \
(echo "ERROR: The IDAPython IDC interface is incomplete. IDA log:" && cat $(F)idctest.log && false)
endif
@@ -801,18 +906,18 @@ ifeq ($(OUT_OF_TREE_BUILD),)
(cd $(F) && zip -r ../../../$(PUBTREE_DIR)/out_of_tree/parsed_notifications.zip parsed_notifications)
endif
#----------------------------------------------------------------------
IDAPYSWITCH_OBJS += $(F)idapyswitch$(O)
ifdef __NT__
ifneq ($(OUT_OF_TREE_BUILD),)
# SDK provides only MT libraries
$(F)idapyswitch$(O): RUNTIME_LIBSW=/MT
else
ifndef NDEBUG
$(F)idapyswitch$(O): CFLAGS := $(filter-out /U_DEBUG,$(CFLAGS))
ifneq ($(OUT_OF_TREE_BUILD),)
# SDK provides only MT libraries
$(F)idapyswitch$(O): RUNTIME_LIBSW=/MT
else
ifndef NDEBUG
$(F)idapyswitch$(O): CFLAGS := $(filter-out /U_DEBUG,$(CFLAGS))
endif
endif
endif
endif
$(R)idapyswitch$(B): $(call dumb_target, pro, $(IDAPYSWITCH_OBJS))
#----------------------------------------------------------------------
@@ -830,19 +935,18 @@ $(MODULE): LDFLAGS += $(PYTHON_LDFLAGS) $(PYTHON_LDFLAGS_RPATH_MAIN)
# MAKEDEP dependency list ------------------
$(F)idapyswitch$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)err.h \
$(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)exehdr.h $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \
$(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)network.hpp $(I)offset.hpp $(I)pro.h \
$(I)prodir.h $(I)range.hpp $(I)segment.hpp \
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \
../../ldr/ar/aixar.hpp \
../../ldr/ar/ar.hpp ../../ldr/ar/arcmn.cpp \
../../ldr/elf/../idaldr.h ../../ldr/elf/elf.h \
../../ldr/elf/elfbase.h ../../ldr/elf/elfr_arm.h \
../../ldr/elf/elfr_ia64.h ../../ldr/elf/elfr_mips.h \
../../ldr/elf/elfr_ppc.h ../../ldr/elf/reader.cpp \
../../ldr/mach-o/../ar/ar.hpp \
../../ldr/ar/aixar.hpp ../../ldr/ar/ar.hpp \
../../ldr/ar/arcmn.cpp ../../ldr/elf/../idaldr.h \
../../ldr/elf/elf.h ../../ldr/elf/elfbase.h \
../../ldr/elf/elfr_arm.h ../../ldr/elf/elfr_ia64.h \
../../ldr/elf/elfr_mips.h ../../ldr/elf/elfr_ppc.h \
../../ldr/elf/reader.cpp ../../ldr/mach-o/../ar/ar.hpp \
../../ldr/mach-o/../idaldr.h ../../ldr/mach-o/base.cpp \
../../ldr/mach-o/common.cpp ../../ldr/mach-o/common.h \
../../ldr/mach-o/h/architecture/byte_order.h \
@@ -901,9 +1005,10 @@ $(F)idapyswitch$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
../../ldr/mach-o/h/sys/_posix_availability.h \
../../ldr/mach-o/h/sys/_symbol_aliasing.h \
../../ldr/mach-o/h/sys/cdefs.h \
../../ldr/mach-o/macho_node.h idapyswitch.cpp \
idapyswitch_linux.cpp idapyswitch_mac.cpp \
idapyswitch_win.cpp
../../ldr/mach-o/macho_node.h ../../ldr/pe/../idaldr.h \
../../ldr/pe/common.cpp ../../ldr/pe/common.h \
../../ldr/pe/pe.h idapyswitch.cpp idapyswitch_linux.cpp \
idapyswitch_mac.cpp idapyswitch_win.cpp
$(F)idapython$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \
$(I)diskio.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \
+1
View File
@@ -0,0 +1 @@
-esym(4100, obj) // unreferenced formal parameter
Binary file not shown.
+23692 -12166
View File
File diff suppressed because it is too large Load Diff
+24372 -12280
View File
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -26,6 +26,7 @@ import ida_name
import ida_netnode
import ida_segment
import ida_strlist
import ida_struct
import ida_ua
import ida_xref
@@ -359,14 +360,14 @@ def StructMembers(sid):
@note: This will not return 'holes' in structures/stack frames;
it only returns defined structure members.
"""
m = idc.get_first_member(sid)
if m == -1:
sptr = ida_struct.get_struc(sid)
if sptr is None:
raise Exception("No structure with ID: 0x%x" % sid)
while (m != ida_idaapi.BADADDR):
name = idc.get_member_name(sid, m)
for m in sptr.members:
name = idc.get_member_name(sid, m.soff)
if name:
yield (m, name, idc.get_member_size(sid, m))
m = idc.get_next_offset(sid, m)
size = ida_struct.get_member_size(m)
yield (m.soff, name, size)
def DecodePrecedingInstruction(ea):
+4 -23
View File
@@ -1087,7 +1087,7 @@ def gen_file(filetype, path, ea1, ea2, flags):
-1 if an error occurred
OFILE_EXE: 0-can't generate exe file, 1-ok
"""
f = ida_diskio.fopenWT(path)
f = ida_diskio.fopenWB(path)
if f:
retval = ida_loader.gen_file(filetype, f, ea1, ea2, flags)
@@ -1787,13 +1787,9 @@ def find_binary(ea, flag, searchstr, radix=16, from_bc695=False):
#----------------------------------------------------------------------------
def process_config_line(directive):
"""
Parse one or more ida.cfg config directives
@param directive: directives to process, for example: PACK_DATABASE=2
@note: If the directives are erroneous, a fatal error will be generated.
The settings are permanent: effective for the current session and the next ones
Obsolete. Please use ida_idp.process_config_directive().
"""
return eval_idc('process_config_line("%s")' % ida_kernwin.str2user(directive))
return eval_idc('process_config_directive("%s")' % ida_kernwin.str2user(directive))
# The following functions allow you to set/get common parameters.
@@ -5675,22 +5671,7 @@ define_exception = ida_dbg.define_exception
EXC_BREAK = 0x0001 # break on the exception
EXC_HANDLE = 0x0002 # should be handled by the debugger?
def get_reg_value(name):
"""
Get register value
@param name: the register name
@note: The debugger should be running. otherwise the function fails
the register name should be valid.
It is not necessary to use this function to get register values
because a register name in the script will do too.
@return: register value (integer or floating point)
"""
return ida_dbg.get_reg_val(name)
get_reg_value = ida_dbg.get_reg_val
def set_reg_value(value, name):
"""
+8 -1
View File
@@ -1,4 +1,6 @@
import sys
import ida_pro
import ida_funcs
import ida_lumina
@@ -9,12 +11,17 @@ 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, long]:
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()
+1 -4
View File
@@ -831,7 +831,7 @@ int ida_export idcvar_to_pyvar(
if ( *py_var == NULL )
{
double x;
if ( ph.realcvt(&x, (uint16 *)idc_var.e, (sizeof(x)/2-1)|010) != 1 )
if ( processor_t::realcvt(&x, (uint16 *)idc_var.e, (sizeof(x)/2-1)|010) != 1 )
INTERR(30160);
*py_var = newref_t(PyFloat_FromDouble(x));
@@ -1556,9 +1556,6 @@ bool ida_export lookup_info_t_del_by_py_view(
return false;
}
//-------------------------------------------------------------------------
lookup_info_t pycim_lookup_info;
//-------------------------------------------------------------------------
// py_customidamemo_t
//-------------------------------------------------------------------------
+325 -34
View File
@@ -38,7 +38,7 @@ struct switch_info_t;
// "A pointer can be explicitly converted to any integral type large
// enough to hold it. The mapping function is implementation-defined."
// C++03
// - C++03
// => G++ (and probably MSVC) will typically first sign-extend the pointer.
//
// int bar(void *p) { return foo(uint64(p)); }
@@ -116,6 +116,8 @@ static const char S_ON_GET_ICON[] = "OnGetIcon";
static const char S_ON_GET_LINE_ATTR[] = "OnGetLineAttr";
static const char S_ON_GET_SIZE[] = "OnGetSize";
static const char S_ON_GETTEXT[] = "OnGetText";
static const char S_ON_GET_DIRTREE[] = "OnGetDirTree";
static const char S_ON_INDEX_TO_INODE[] = "OnIndexToInode";
static const char S_ON_ACTIVATE[] = "OnActivate";
static const char S_ON_DEACTIVATE[] = "OnDeactivate";
static const char S_ON_SELECT[] = "OnSelect";
@@ -585,8 +587,6 @@ private:
#define plugin_export_data __attribute__((visibility("default")))
#endif
extern lookup_info_t plugin_export_data pycim_lookup_info;
//-------------------------------------------------------------------------
struct pycim_callback_id_t
{
@@ -669,10 +669,10 @@ class py_customidamemo_t
// View events that are bound with 'set_custom_viewer_handler()'.
static void idaapi s_on_view_mouse_moved(
TWidget *cv,
int shift,
view_mouse_event_t *e,
void *ud);
TWidget *cv,
int shift,
view_mouse_event_t *e,
void *ud);
DECL_CIM_HELPERS(friend);
@@ -689,19 +689,8 @@ protected:
friend TWidget *pycim_get_widget(PyObject *self);
public:
py_customidamemo_t()
: cb_flags(0),
self(newref_t(NULL)),
view(NULL)
{
PYGLOG("%p: py_customidamemo_t()\n", this);
}
virtual ~py_customidamemo_t()
{
PYGLOG("%p: ~py_customidamemo_t()\n", this);
unbind(true);
pycim_lookup_info.del_by_py_view(this);
}
py_customidamemo_t();
virtual ~py_customidamemo_t();
virtual void refresh()
{
@@ -783,8 +772,294 @@ struct new_execution_t
};
//-------------------------------------------------------------------------
enum run_script_when_t
{
RSW_UNKNOWN = 0,
RSW_ui_database_inited, // run script after opening database (default)
RSW_ui_ready_to_run, // run script when UI is ready
RSW_on_init, // run script immediately on plugin load (shortly after IDA starts)
};
//-------------------------------------------------------------------------
struct idapython_plugin_config_t
{
struct run_script_t
{
qstring path;
run_script_when_t when;
run_script_t() : when(RSW_UNKNOWN) {}
};
run_script_t run_script;
uint32 execution_timeout;
bool alert_auto_scripts;
bool remove_cwd_sys_path;
bool autoimport_compat_idaapi;
bool autoimport_compat_ida695;
bool namespace_aware;
bool repl_use_sys_displayhook;
idapython_plugin_config_t()
: execution_timeout(0),
alert_auto_scripts(true),
remove_cwd_sys_path(false),
autoimport_compat_idaapi(true),
autoimport_compat_ida695(false),
namespace_aware(true),
repl_use_sys_displayhook(true) {}
};
//-------------------------------------------------------------------------
struct idapython_plugin_t : public plugmod_t, public event_listener_t
{
idapython_plugin_config_t config;
lookup_info_t pycim_lookup_info;
qstring idapython_dir;
qstring requested_plugin_path;
#ifdef __MAC__
# ifdef PY3
qvector<wchar_t> pyhomepath;
# else
qstring pyhomepath;
# endif
#endif
bool initialized;
bool ui_ready;
#ifdef TESTABLE_BUILD
int user_code_lenient;
#endif
idapython_plugin_t();
~idapython_plugin_t();
bool init();
void parse_plugin_options();
ref_t get_sys_displayhook();
#ifdef TESTABLE_BUILD
bool is_user_code_lenient();
#endif
virtual bool idaapi run(size_t arg) override;
virtual ssize_t idaapi on_event(ssize_t code, va_list va) override;
static ssize_t idaapi on_idb_notification(void *, int code, va_list va);
static idapython_plugin_t *get_instance() { return instance; }
static bool idaapi extlang_compile_file(
const char *path,
qstring *errbuf)
{
return get_instance()->_extlang_compile_file(path, errbuf);
}
static bool idaapi extlang_compile_expr(
const char *name,
ea_t current_ea,
const char *expr,
qstring *errbuf)
{
return get_instance()->_extlang_compile_expr(name, current_ea, expr, errbuf);
}
static bool idaapi extlang_eval_expr(
idc_value_t *rv,
ea_t current_ea,
const char *expr,
qstring *errbuf)
{
return get_instance()->_extlang_eval_expr(rv, current_ea, expr, errbuf);
}
static bool idaapi extlang_load_procmod(
idc_value_t *procobj,
const char *path,
qstring *errbuf)
{
return get_instance()->_extlang_load_procmod(procobj, path, errbuf);
}
static bool idaapi extlang_unload_procmod(
const char *path,
qstring *errbuf)
{
return get_instance()->_extlang_unload_procmod(path, errbuf);
}
static bool idaapi extlang_create_object(
idc_value_t *result,
const char *name,
const idc_value_t args[],
size_t nargs,
qstring *errbuf)
{
return get_instance()->_extlang_create_object(result, name, args, nargs, errbuf);
}
static bool idaapi extlang_eval_snippet(
const char *str,
qstring *errbuf)
{
return get_instance()->_extlang_eval_snippet(str, errbuf);
}
static bool idaapi extlang_call_func(
idc_value_t *result,
const char *name,
const idc_value_t args[],
size_t nargs,
qstring *errbuf)
{
return get_instance()->_extlang_call_func(result, name, args, nargs, errbuf);
}
static bool idaapi extlang_call_method(
idc_value_t *result,
const idc_value_t *idc_obj,
const char *method_name,
const idc_value_t args[],
size_t nargs,
qstring *errbuf)
{
return get_instance()->_extlang_call_method(result, idc_obj, method_name, args, nargs, errbuf);
}
static bool idaapi extlang_get_attr(
idc_value_t *result,
const idc_value_t *obj,
const char *attr)
{
return get_instance()->_extlang_get_attr(result, obj, attr);
}
static bool idaapi extlang_set_attr(
idc_value_t *obj,
const char *attr,
const idc_value_t &value)
{
return get_instance()->_extlang_set_attr(obj, attr, value);
}
static bool idaapi cli_execute_line(
const char *line)
{
return get_instance()->_cli_execute_line(line);
}
static bool idaapi cli_find_completions(
qstrvec_t *out_completions,
int *out_match_start,
int *out_match_end,
const char *line,
int x)
{
return get_instance()->_cli_find_completions(out_completions, out_match_start, out_match_end, line, x);
}
private:
bool _extlang_compile_file(
const char *path,
qstring *errbuf);
bool _extlang_compile_expr(
const char *name,
ea_t current_ea,
const char *expr,
qstring *errbuf);
bool _extlang_eval_expr(
idc_value_t *rv,
ea_t current_ea,
const char *expr,
qstring *errbuf);
bool _extlang_load_procmod(
idc_value_t *procobj,
const char *path,
qstring *errbuf);
bool _extlang_unload_procmod(
const char *path,
qstring *errbuf);
bool _extlang_create_object(
idc_value_t *result,
const char *name,
const idc_value_t args[],
size_t nargs,
qstring *errbuf);
bool _extlang_eval_snippet(
const char *str,
qstring *errbuf);
bool _extlang_call_func(
idc_value_t *result,
const char *name,
const idc_value_t args[],
size_t nargs,
qstring *errbuf);
bool _extlang_call_method(
idc_value_t *result,
const idc_value_t *idc_obj,
const char *method_name,
const idc_value_t args[],
size_t nargs,
qstring *errbuf);
bool _extlang_get_attr(
idc_value_t *result,
const idc_value_t *obj,
const char *attr);
bool _extlang_set_attr(
idc_value_t *obj,
const char *attr,
const idc_value_t &value);
bool _cli_execute_line(
const char *line);
bool _cli_find_completions(
qstrvec_t *out_completions,
int *out_match_start,
int *out_match_end,
const char *line,
int x);
bool _handle_file(
const char *path,
PyObject *globals,
qstring *errbuf,
const char *idaapi_executor_func_name = S_IDAAPI_EXECSCRIPT,
idc_value_t *second_res = NULL,
bool want_tuple = false);
bool _run_user_script();
bool _check_python_dir();
void _prepare_sys_path();
bool _run_init_py();
PyObject *_get_module_globals(const char *modname=nullptr);
PyObject *_get_module_globals_from_path_with_kind(
const char *path,
const char *kind);
PyObject *_get_module_globals_from_path(
const char *path);
static idapython_plugin_t *instance;
};
idaman idapython_plugin_t *ida_export get_plugin_instance();
idaman bool ida_export is_api695_compat_enabled();
//-------------------------------------------------------------------------
py_customidamemo_t::py_customidamemo_t()
: cb_flags(0),
self(newref_t(NULL)),
view(NULL)
{
PYGLOG("%p: py_customidamemo_t()\n", this);
}
//-------------------------------------------------------------------------
py_customidamemo_t::~py_customidamemo_t()
{
PYGLOG("%p: ~py_customidamemo_t()\n", this);
unbind(true);
get_plugin_instance()->pycim_lookup_info.del_by_py_view(this);
}
//-------------------------------------------------------------------------
idaman bool ida_export idapython_hook_to_notification_point(
hook_type_t hook_type,
@@ -811,8 +1086,8 @@ struct hooks_base_t
typedef std::map<int,uchar> has_nondef_map_t;
has_nondef_map_t has_nondef;
bool hook() { return cb != NULL ? idapython_hook_to_notification_point(type, cb, this, true) : false; }
bool unhook() { return cb != NULL ? idapython_unhook_from_notification_point(type, cb, this) : false; }
bool hook() { return cb != NULL && idapython_hook_to_notification_point(type, cb, this, true); }
bool unhook() { return cb != NULL && idapython_unhook_from_notification_point(type, cb, this); }
bool call_requires_new_execution() const { return (flags & HBF_CALL_WITH_NEW_EXEC) != 0; }
bool has_fixed_method_set() const { return (flags & HBF_VOLATILE_METHOD_SET) == 0; }
@@ -837,9 +1112,9 @@ struct hooks_base_t
protected:
void init_director_hooks(
PyObject *self,
const event_code_to_method_name_t *mappings,
size_t count)
PyObject *self,
const event_code_to_method_name_t *mappings,
size_t count)
{
// identifier
{
@@ -885,14 +1160,25 @@ protected:
{
#ifdef BC695
if ( PyObject_HasAttrString(py_def_meth.o, "bc695_trampoline") > 0 )
_has_nondef = 2;
{
_has_nondef = 3;
}
else
#endif
{
if ( PyObject_HasAttrString(py_def_meth.o, "__trampoline") > 0 )
{
_has_nondef = 2;
}
else
{
#ifdef PY3
_has_nondef = PyObject_RichCompareBool(py_this_meth.o, py_def_meth.o, Py_EQ) == 0 ? 1 : 0;
_has_nondef = PyObject_RichCompareBool(py_this_meth.o, py_def_meth.o, Py_EQ) == 0 ? 1 : 0;
#else
_has_nondef = PyObject_Compare(py_this_meth.o, py_def_meth.o) != 0 ? 1 : 0;
_has_nondef = PyObject_Compare(py_this_meth.o, py_def_meth.o) != 0 ? 1 : 0;
#endif
}
}
}
has_nondef[cur.code] = _has_nondef;
}
@@ -901,9 +1187,9 @@ protected:
}
void ensure_no_method_when_no_695_compat(
PyObject *self,
const char *forbidden_method_name,
const char *replacement_method_name)
PyObject *self,
const char *forbidden_method_name,
const char *replacement_method_name)
{
if ( !is_api695_compat_enabled() )
{
@@ -935,9 +1221,14 @@ protected:
const hooks_base_t::event_code_to_method_name_t &m = mappings[i];
has_nondef_map_t::const_iterator it = has_nondef.find(m.code);
if ( it != has_nondef.end() && it->second > 0 )
buf.cat_sprnt("\n\treimplements \"%s\"%s",
m.method_name,
it->second > 1 ? " (as 6.95 bw-compat)" : "");
{
const char *how = "";
if ( it->second == 2 )
how = " (as compat trampoline)";
else if ( it->second == 3 )
how = " (as 6.95 bw-compat)";
buf.cat_sprnt("\n\treimplements \"%s\"%s", m.method_name, how);
}
}
}
else
+40 -40
View File
@@ -16,9 +16,9 @@ class py_custom_data_type_t : public data_type_t
// may create data? NULL means always may
static bool idaapi s_may_create_at(
void *ud, // user-defined data
ea_t ea, // address of the future item
size_t nbytes) // size of the future item
void *ud, // user-defined data
ea_t ea, // address of the future item
size_t nbytes) // size of the future item
{
py_custom_data_type_t *_this = (py_custom_data_type_t *)ud;
PYW_GIL_GET;
@@ -36,11 +36,11 @@ class py_custom_data_type_t : public data_type_t
// !=NULL means variable size datatype
static asize_t idaapi s_calc_item_size(
// This function is used to determine
// size of the (possible) item at 'ea'
void *ud, // user-defined data
ea_t ea, // address of the item
asize_t maxsize) // maximal size of the item
// This function is used to determine
// size of the (possible) item at 'ea'
void *ud, // user-defined data
ea_t ea, // address of the item
asize_t maxsize) // maximal size of the item
{
PYW_GIL_GET;
// Returns: 0-no such item can be created/displayed
@@ -136,8 +136,8 @@ public:
// dtor to be called, which in turn will call this 'do_unregister' a
// second time, but this is no problem since the dtid has already been
// unregistered and thus we won't end up in this Py_XDECREF block.
dtid = -1; // modify the object now, otherwise it may get deleted
Py_XDECREF(py_self);
dtid = -1;
}
return ok;
}
@@ -176,14 +176,14 @@ private:
PyObject *py_self;
qstring df_name, df_menu_name, df_hotkey;
static bool idaapi s_print( // convert to colored string
void *ud, // user-defined data
qstring *out, // output buffer. may be NULL
const void *value, // value to print. may not be NULL
asize_t size, // size of value in bytes
ea_t current_ea, // current address (BADADDR if unknown)
int operand_num, // current operand number
int dtid) // custom data type id
static bool idaapi s_print( // convert to colored string
void *ud, // user-defined data
qstring *out, // output buffer. may be NULL
const void *value, // value to print. may not be NULL
asize_t size, // size of value in bytes
ea_t current_ea, // current address (BADADDR if unknown)
int operand_num, // current operand number
int dtid) // custom data type id
{
PYW_GIL_GET;
@@ -218,13 +218,13 @@ private:
return ok;
}
static bool idaapi s_scan( // convert from uncolored string
void *ud, // user-defined data
bytevec_t *value, // output buffer. may be NULL
const char *input, // input string. may not be NULL
ea_t current_ea, // current address (BADADDR if unknown)
int operand_num, // current operand number (-1 if unknown)
qstring *errstr) // buffer for error message
static bool idaapi s_scan( // convert from uncolored string
void *ud, // user-defined data
bytevec_t *value, // output buffer. may be NULL
const char *input, // input string. may not be NULL
ea_t current_ea, // current address (BADADDR if unknown)
int operand_num, // current operand number (-1 if unknown)
qstring *errstr) // buffer for error message
{
PYW_GIL_GET;
@@ -286,10 +286,10 @@ private:
return ok;
}
static void idaapi s_analyze( // analyze custom data format occurrence
void *ud, // user-defined data
ea_t current_ea, // current address (BADADDR if unknown)
int operand_num) // current operand number
static void idaapi s_analyze( // analyze custom data format occurrence
void *ud, // user-defined data
ea_t current_ea, // current address (BADADDR if unknown)
int operand_num) // current operand number
// this callback can be used to create
// xrefs from the current item.
// this callback may be missing.
@@ -309,13 +309,13 @@ private:
}
public:
py_custom_data_format_t(
PyObject *py_df,
const char *name,
asize_t value_size,
const char *menu_name,
int props,
const char *hotkey,
int32 text_width)
PyObject *py_df,
const char *name,
asize_t value_size,
const char *menu_name,
int props,
const char *hotkey,
int32 text_width)
{
memset(this, 0, sizeof(data_format_t));
cbsize = sizeof(data_format_t);
@@ -381,8 +381,8 @@ public:
if ( ok )
{
// see comment in py_custom_data_type_t::do_unregister()
Py_XDECREF(py_self);
dfid = -1;
Py_XDECREF(py_self);
}
return ok;
}
@@ -408,10 +408,10 @@ static int py_custom_data_format_t_get_id(data_format_t *_df)
static void clear_custom_data_types_and_formats()
{
PYW_GIL_GET;
for ( size_t n = py_custom_data_types.size(); n > 0; --n )
py_custom_data_types[n-1]->do_unregister();
for ( size_t n = py_custom_data_formats.size(); n > 0; --n )
py_custom_data_formats[n-1]->do_unregister();
for ( ssize_t i=py_custom_data_types.size()-1; i >= 0; --i )
py_custom_data_types[i]->do_unregister();
for ( ssize_t i=py_custom_data_formats.size()-1; i >= 0; --i )
py_custom_data_formats[i]->do_unregister();
}
//</code(py_bytes_custdata)>
+7 -1
View File
@@ -447,7 +447,7 @@ static ea_t py_internal_get_sreg_base(thid_t tid, int sreg_value)
static ssize_t py_write_dbg_memory(ea_t ea, PyObject *py_buf, size_t size=size_t(-1))
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !dbg_can_query() || !IDAPyBytes_Check(py_buf) )
if ( !dbg_can_query(dbg) || !IDAPyBytes_Check(py_buf) )
return -1;
char *buf = NULL;
Py_ssize_t sz;
@@ -474,6 +474,12 @@ def dbg_can_query():
#</pydoc>
*/
//-------------------------------------------------------------------------
static bool py_dbg_can_query()
{
return dbg_can_query(dbg);
}
//-------------------------------------------------------------------------
static PyObject *py_set_reg_val(const char *regname, PyObject *o)
{
+3 -2
View File
@@ -75,14 +75,15 @@ def del_idc_func(name):
return _ida_expr.pyw_unregister_idc_func(f.ctxptr)
# --------------------------------------------------------------------------
def add_idc_func(name, fp, args, defvals=None, flags=0):
def add_idc_func(name, fp, args, defvals=(), flags=0):
"""
Extends the IDC language by exposing a new IDC function that is backed up by a Python function
@param name: IDC function name to expose
@param fp: Python callable that will receive the arguments and return a tuple.
@param args: Arguments. A tuple of idaapi.VT_XXX constants
@param flags: IDC function flags. A combination of EXTFUN_XXX constants
@param defvals: default argument values (optional)
@param flags: IDC function flags. A combination of EXTFUN_XXX constants (optional)
@return: Boolean
"""

Some files were not shown because too many files have changed in this diff Show More