mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
IDAPython for IDA 7.5
This commit is contained in:
@@ -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
@@ -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).
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
"""
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+889
-248
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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.")
|
||||
|
||||
@@ -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
@@ -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")
|
||||
|
||||
@@ -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!")
|
||||
|
||||
@@ -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))
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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...")
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -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?")
|
||||
|
||||
@@ -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")
|
||||
@@ -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!")
|
||||
|
||||
|
||||
@@ -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]))
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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.')
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
@@ -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")
|
||||
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
+1
-1
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ida_exclude+=fuzzer.hpp
|
||||
@@ -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 \
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
-esym(4100, obj) // unreferenced formal parameter
|
||||
Binary file not shown.
+23692
-12166
File diff suppressed because it is too large
Load Diff
+24372
-12280
File diff suppressed because it is too large
Load Diff
+7
-6
@@ -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
@@ -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):
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user