├── AUTHORS.txt ├── BUILDING.txt ├── CHANGES.txt ├── COPYING.txt ├── README.txt ├── STATUS.txt ├── Scripts ├── 3rd │ └── BboeVt.py ├── AsmViewer.py ├── CallStackWalk.py ├── DbgCmd.py ├── DrvsDispatch.py ├── ExchainDump.py ├── FindInstructions.py ├── ImpRef.py ├── ImportExportViewer.py ├── PteDump.py ├── SEHGraph.py ├── VaDump.py ├── VirusTotal.py ├── callstack_test.py └── msdnapihelp.py ├── basetsd.h ├── build.py ├── docs └── notes.txt ├── examples ├── chooser.py ├── colours.py ├── debughook.py ├── ex1.idc ├── ex1_idaapi.py ├── ex1_idautils.py ├── ex_actions.py ├── ex_add_menu_item.py ├── ex_askusingform.py ├── ex_choose2.py ├── ex_cli.py ├── ex_custdata.py ├── ex_custview.py ├── ex_dbg.py ├── ex_debug_names.py ├── ex_expr.py ├── ex_func_chooser.py ├── ex_gdl_qflow_chart.py ├── ex_graph.py ├── ex_hotkey.py ├── ex_idagraph.py ├── ex_idphook_asm.py ├── ex_imports.py ├── ex_patch.py ├── ex_prefix_plugin.py ├── ex_pyqt.py ├── ex_pyside.py ├── ex_strings.py ├── ex_timer.py ├── ex_uihook.py ├── ex_uirequests.py ├── hotkey.py ├── idapythonrc.py ├── structure.py ├── vds1.py ├── vds3.py ├── vds4.py ├── vds7.py └── vds_xrefs.py ├── hrdoc.cfg ├── hrdoc.css ├── hrdoc.py ├── idaapi.i ├── idapython.sln ├── idapython.vcxproj ├── idapython.vcxproj.filters ├── inject_pydoc.py ├── patch_directors_cc.py ├── python.cfg ├── python.cpp ├── python ├── idautils.py ├── idc.py └── init.py ├── pywraps.hpp ├── pywraps ├── deploy.bat ├── deploy.py ├── deploy_all.py ├── driver.cpp ├── driver_bytes.cpp ├── driver_chooser.cpp ├── driver_cli.cpp ├── driver_custdata.cpp ├── driver_custview.cpp ├── driver_dbg.cpp ├── driver_diskio.cpp ├── driver_expr.cpp ├── driver_graph.cpp ├── driver_kernwin.cpp ├── driver_nalt.cpp ├── driver_notifywhen.cpp ├── link_gen.py ├── py_appcall.py ├── py_askusingform.hpp ├── py_askusingform.py ├── py_bytes.hpp ├── py_choose.hpp ├── py_choose2.hpp ├── py_choose2.py ├── py_cli.hpp ├── py_cli.py ├── py_custdata.hpp ├── py_custdata.py ├── py_custview.hpp ├── py_custview.py ├── py_cvt.hpp ├── py_dbg.hpp ├── py_dbg.py ├── py_diskio.hpp ├── py_diskio.py ├── py_expr.hpp ├── py_expr.py ├── py_gdl.py ├── py_graph.hpp ├── py_graph.py ├── py_idaapi.hpp ├── py_idaapi.py ├── py_idaview.hpp ├── py_idaview.py ├── py_idp.hpp ├── py_kernwin.hpp ├── py_kernwin.py ├── py_lines.hpp ├── py_lines.py ├── py_linput.hpp ├── py_loader.hpp ├── py_nalt.hpp ├── py_nalt.py ├── py_name.hpp ├── py_name.py ├── py_notifywhen.hpp ├── py_notifywhen.py ├── py_plgform.hpp ├── py_plgform.py ├── py_qfile.hpp ├── py_registry.hpp ├── py_typeinf.hpp ├── py_typeinf.py ├── py_ua.hpp ├── py_ua.py ├── py_view_base.hpp ├── py_view_base.py ├── pywraps.hpp ├── pywraps.sln ├── pywraps.vcproj ├── pywraps.vcxproj ├── pywraps.vcxproj.filters ├── readme.txt ├── sidaapi.py ├── sidc.py ├── swig_stub.cpp └── swig_stub.h ├── swig ├── allins.i ├── area.i ├── auto.i ├── bytes.i ├── dbg.i ├── diskio.i ├── entry.i ├── enum.i ├── expr.i ├── fixup.i ├── fpro.i ├── frame.i ├── funcs.i ├── gdl.i ├── graph.i ├── hexrays.i ├── ida.i ├── idaapi.i ├── idd.i ├── idp.i ├── ints.i ├── kernwin.i ├── lines.i ├── loader.i ├── moves.i ├── nalt.i ├── name.i ├── netnode.i ├── offset.i ├── pro.i ├── queue.i ├── registry.i ├── search.i ├── segment.i ├── srarea.i ├── strlist.i ├── struct.i ├── typeconv.i ├── typeinf.i ├── ua.i ├── view.i └── xref.i └── tools ├── gendocs.py └── swigdocs.py /AUTHORS.txt: -------------------------------------------------------------------------------- 1 | The IDAPython Team: 2 | 3 | * Gergely Erdelyi - http://d-dome.net/idapython/ 4 | 5 | Original IDAPython author - The IDAPython Guy - 6 | 7 | 8 | * Hex-Rays - http://www.hex-rays.com/ - 9 | 10 | Hex-Rays joined the IDAPython project in September 2009 and started contributing. 11 | It is primarily maintained, updated and improved by Arnaud Diederen of Hex-Rays. 12 | 13 | * Elias Bachaalany - elias.bachaalany@gmail.com 14 | Maintains IDAPython online source code repository and coordinates patches/updates/contributions from Hex-Rays and 3rd party contributors 15 | 16 | 17 | * Ero Carrera - http://dkbza.org/ 18 | 19 | Project contributor 20 | 21 | 22 | * Special thanks to the following people for their contribution, suggestions and bug fixes: 23 | 24 | Igor Skochinsky 25 | Sebastian Muniz 26 | cbwhiz 27 | Arnaud Diederen 28 | -------------------------------------------------------------------------------- /BUILDING.txt: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------ 2 | IDAPython - Python plugin for Interactive Disassembler 3 | ------------------------------------------------------ 4 | Building From Source 5 | -------------------- 6 | 7 | REQUIREMENTS 8 | ------------ 9 | 10 | [Tested versions are in brackets] 11 | 12 | 13 | - IDA and IDA SDK [> 5.6] 14 | http://www.hex-rays.com/idapro/ 15 | 16 | - Python [2.5.1, 2.6.1, 2.7] 17 | http://www.python.org/ 18 | 19 | - Simplified Wrapper Interface Generator (SWIG) [2.0.12] 20 | http://www.swig.org/ 21 | Hex-Rays cannot guarantee support for IDAPython 22 | versions built with other versions of SWIG. 23 | 24 | - Unix utilities (GNU patch on Windows): 25 | http://www.research.att.com/sw/tools/uwin/ or 26 | http://unxutils.sourceforge.net/ or 27 | http://www.cygwin.com/ 28 | 29 | - GCC on Linux and Mac OS X [4.0.1, 4.1.3] 30 | Comes with your distribution 31 | 32 | - Microsoft Visual C on Windows [Microsoft Visual C++ 2008 Express Edition] 33 | http://msdn.microsoft.com/vstudio/express/visualc/ 34 | 35 | 36 | BUILDING 37 | -------- 38 | 39 | Make sure all the needed tools (compiler, swig) are on the PATH. 40 | 41 | 1. Unpack the IDAPython source and IDA SDK into the following 42 | directory structure: 43 | 44 | swigsdk-versions/x.y/ - A supported version of the IDA SDK 45 | idapython/ - IDAPython source code 46 | 47 | Note: To build with Hex-Rays decompiler support, please copy hexrays.hpp from 48 | the decompiler SDK folder into IDA's include folder (in the SDK). 49 | 50 | 2. On Mac OS X copy libida.dylib from the IDA install directory to 51 | swigsdk-versions/x.y/lib/x86_mac_gcc_32/ 52 | and libida64.dylib to 53 | swigsdk-versions/x.y/lib/x86_mac_gcc_64/ 54 | 55 | 3. Build the plugin 56 | 57 | python build.py 58 | 59 | It is possible to build the plugin for different Python versions by 60 | running build.py with the corresponding Python binary. 61 | 62 | Run 'build.py --help' for more information. 63 | 64 | 4. Install the components as described in README.txt 65 | 66 | See build.py for build details and possible tweaks. 67 | 68 | On 64 bits distributions, you may need to compile Python to generate a 32bit 69 | version of the interpreter: 70 | 71 | 1. tar xvf Python-2.6.6.tar.bz2 72 | 2. cd Python-2.6.6 73 | 3. CC="gcc -m32" CXX="c++ -m32" ./configure --prefix=/path/to/py32 --enable-shared 74 | 4. make 75 | 5. make install 76 | 6. cd /path/to/py32/lib 77 | 7. ln -s libpython2.6.so.1.0 libpython2.6.so.1 78 | 8. PYTHONHOME=/path/to/py32 LD_LIBRARY_PATH=/path/to/py32/lib idaq 79 | -------------------------------------------------------------------------------- /COPYING.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004-2010 Gergely Erdelyi . All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | 3. The name of the author may not be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 21 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 24 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 25 | OF SUCH DAMAGE. 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------ 2 | IDAPython - Python plugin for Interactive Disassembler 3 | ------------------------------------------------------ 4 | 5 | What is IDAPython? 6 | ------------------ 7 | 8 | IDAPython is an IDA plugin which makes it possible to write scripts 9 | for IDA in the Python programming language. IDAPython provides full 10 | access to both the IDA API and any installed Python module. 11 | 12 | Check the scripts in the examples directory to get an quick glimpse. 13 | 14 | 15 | Availability 16 | ------------ 17 | 18 | Latest stable versions of IDAPython are available from 19 | http://code.google.com/p/idapython/downloads/list 20 | 21 | Development builds are available from 22 | http://code.google.com/p/idapython/ 23 | 24 | 25 | Resources 26 | --------- 27 | 28 | The full function cross-reference is readable online at 29 | http://www.hex-rays.com/idapro/idapython_docs/ 30 | 31 | Bugs and enhancement requests should be submitted to 32 | http://code.google.com/p/idapython/issues/list 33 | 34 | Mailing list for the project is hosted by Google Groups at 35 | http://groups.google.com/group/idapython 36 | 37 | 38 | Installation from binaries 39 | -------------------------- 40 | 41 | 1. Install 2.6 or 2.7 from http://www.python.org/ 42 | 2. Copy the whole "python" directory to %IDADIR% 43 | 3. Copy the contents of the "plugins" directory to the %IDADIR%\plugins\ 44 | 4. Copy "python.cfg" to %IDADIR%\cfg 45 | 46 | Usage 47 | ----- 48 | 49 | - Run script: File / Script file (Alt-F7) 50 | - Execute Python statement(s) (Ctrl-F3) 51 | - Run previously executed script again: View / Recent Scripts (Alt+F9) 52 | 53 | 54 | * Batch mode execution: 55 | 56 | Start IDA with the following command line options: 57 | 58 | -A -OIDAPython:yourscript.py file_to_work_on 59 | or 60 | -Syourscript.py 61 | or 62 | -S"yourscript.py arg1 arg2 arg3" 63 | 64 | (Please see http://www.hexblog.com/?p=128) 65 | 66 | If you want fully unattended execution mode, make sure your script 67 | exits with a qexit() call. 68 | 69 | By default scripts run after the database is opened. Extended option 70 | format is: 71 | 72 | -OIDAPython:[N;]script.py 73 | 74 | Where N can be: 75 | 0: run script after opening database (default) 76 | 1: run script when UI is ready 77 | 2: run script immediately on plugin load (shortly after IDA starts and before processor modules and loaders) 78 | 79 | * User init file 80 | 81 | You can place your custom settings to a file called 'idapythonrc.py' 82 | that should be placed to 83 | 84 | ${HOME}/.idapro/ 85 | 86 | or 87 | 88 | %AppData%\Hex-Rays\IDA Pro 89 | 90 | The user init file is read and executed at the end of the init process. 91 | 92 | Please note that IDAPython can be configured with "python.cfg" file. 93 | 94 | * Invoking Python from IDC 95 | 96 | The IDAPython plugin exposes a new IDC function "RunPythonStatement(string idc_code)" that allows execution 97 | of Python code from IDC 98 | 99 | * Invoking IDC from Python 100 | 101 | It is possible to use the idc.Eval() to evaluate IDC expressions from Python 102 | 103 | * Making Python the default language 104 | 105 | By default, IDA will use IDC to evaluate expressions. It is possible to change the default language to use 106 | Python instead of IDC. 107 | 108 | In order to do that, please use the following IDC code: 109 | 110 | RunPlugin("python", 3) 111 | 112 | To disable Python language and revert back to IDC: 113 | RunPlugin("python", 4) 114 | 115 | -------------------------------------------------------------------------------- /STATUS.txt: -------------------------------------------------------------------------------- 1 | Status of the IDC layer 2 | ----------------------- 3 | 4 | The IDC emulation layer is complete and at par with IDA 5.1, 5 | although it would benefit from more testing. 6 | 7 | 8 | Status of IDA API wrappers 9 | -------------------------- 10 | 11 | COMPLETE: all possible functions wrapped, no SWIG ifdefs 12 | INCOMPLETE: some wrapping or SWIG ifdefs still left 13 | EXCLUDED: will not be wrapped 14 | 15 | allins.hpp - COMPLETE 16 | area.hpp - COMPLETE (necessary SWIGdefs) 17 | auto.hpp - COMPLETE 18 | bytes.hpp - COMPLETE (some minor unwrapped) 19 | compress.hpp - EXCLUDED 20 | dbg.hpp - INCOMPLETE (SWIGs and lot of fixing to do) 21 | demangle.hpp - EXCLUDED 22 | diskio.hpp - INCOMPLETE (no SWIGs, some unwrapped) 23 | entry.hpp - COMPLETE 24 | enum.hpp - COMPLETE 25 | err.h - EXCLUDED 26 | exehdr.h - EXCLUDED 27 | expr.hpp - COMPLETE (necessary SWIGs) 28 | fixup.hpp - COMPLETE 29 | fpro.h - EXCLUDED 30 | frame.hpp - COMPLETE 31 | funcs.hpp - COMPLETE (necessary SWIGs, minor FIXME) 32 | gdl.hpp - EXCLUDED 33 | graph.hpp - INCOMPLETE 34 | help.h - EXCLUDED 35 | ida.hpp - COMPLETE 36 | idd.hpp - COMPLETE (necessary SWIGs) 37 | idp.hpp - COMPLETE 38 | ieee.h - EXCLUDED 39 | intel.hpp - EXCLUDED 40 | ints.hpp - COMPLETE 41 | kernwin.hpp - INCOMPLETE (SWIGs and lot of fixing to do) 42 | lex.hpp - EXCLUDED 43 | lines.hpp - INCOMPLETE (few FIXMEs) 44 | llong.hpp - EXCLUDED 45 | loader.hpp - INCOMPLETE (few FIXMEs) 46 | md5.h - EXCLUDED 47 | moves.hpp - COMPLETE (some needed SWIGs) 48 | nalt.hpp - INCOMPLETE (SWIGs and lot of fixing to do) 49 | name.hpp - INCOMPLETE (few FIXMEs) 50 | netnode.hpp - COMPLETE 51 | offset.hpp - COMPLETE 52 | prodir.h - EXCLUDED 53 | pro.h - COMPLETE (some needed SWIGs) 54 | queue.hpp - INCOMPLETE (one FIXME) 55 | regex.h - EXCLUDED 56 | search.hpp - COMPLETE 57 | segment.hpp - COMPLETE 58 | sistack.hpp - EXCLUDED 59 | srarea.hpp - INCOMPLETE (not wrapped at all) 60 | strlist.hpp - COMPLETE 61 | struct.hpp - COMPLETE 62 | typeinf.hpp - INCOMPLETE (no SWIGs, lot of fixing to do) 63 | ua.hpp - INCOMPLETE (SWIGs and lot of fixing to do) 64 | va.hpp - EXCLUDED 65 | vm.hpp - EXCLUDED 66 | xref.hpp - COMPLETE 67 | -------------------------------------------------------------------------------- /Scripts/DbgCmd.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # Debugger command prompt with CustomViewers 3 | # (c) Hex-Rays 4 | # 5 | import idaapi 6 | import idc 7 | from idaapi import simplecustviewer_t 8 | 9 | def SendDbgCommand(cmd): 10 | """Sends a command to the debugger and returns the output string. 11 | An exception will be raised if the debugger is not running or the current debugger does not export 12 | the 'SendDbgCommand' IDC command. 13 | """ 14 | s = Eval('SendDbgCommand("%s");' % cmd) 15 | if s.startswith("IDC_FAILURE"): 16 | raise Exception, "Debugger command is available only when the debugger is active!" 17 | return s 18 | 19 | # ----------------------------------------------------------------------- 20 | class dbgcmd_t(simplecustviewer_t): 21 | def Create(self): 22 | # Form the title 23 | title = "Debugger command window" 24 | # Create the customview 25 | if not simplecustviewer_t.Create(self, title): 26 | return False 27 | self.last_cmd = "" 28 | self.menu_clear = self.AddPopupMenu("Clear") 29 | self.menu_cmd = self.AddPopupMenu("New command") 30 | 31 | self.ResetOutput() 32 | return True 33 | 34 | def IssueCommand(self): 35 | s = idaapi.askstr(0, self.last_cmd, "Please enter a debugger command") 36 | if not s: 37 | return 38 | 39 | # Save last command 40 | self.last_cmd = s 41 | 42 | # Add it using a different color 43 | self.AddLine("debugger>" + idaapi.COLSTR(s, idaapi.SCOLOR_VOIDOP)) 44 | 45 | try: 46 | r = SendDbgCommand(s).split("\n") 47 | for s in r: 48 | self.AddLine(idaapi.COLSTR(s, idaapi.SCOLOR_LIBNAME)) 49 | except: 50 | self.AddLine(idaapi.COLSTR("Debugger is not active or does not export SendDbgCommand()", idaapi.SCOLOR_ERROR)) 51 | self.Refresh() 52 | 53 | def ResetOutput(self): 54 | self.ClearLines() 55 | self.AddLine(idaapi.COLSTR("Please press INS to enter command; X to clear output", idaapi.SCOLOR_AUTOCMT)) 56 | self.Refresh() 57 | 58 | def OnKeydown(self, vkey, shift): 59 | # ESCAPE? 60 | if vkey == 27: 61 | self.Close() 62 | # VK_INSERT 63 | elif vkey == 45: 64 | self.IssueCommand() 65 | elif vkey == ord('X'): 66 | self.ResetOutput() 67 | else: 68 | return False 69 | return True 70 | 71 | def OnPopupMenu(self, menu_id): 72 | if menu_id == self.menu_clear: 73 | self.ResetOutput() 74 | elif menu_id == self.menu_cmd: 75 | self.IssueCommand() 76 | else: 77 | # Unhandled 78 | return False 79 | return True 80 | 81 | # ----------------------------------------------------------------------- 82 | def show_win(): 83 | x = dbgcmd_t() 84 | if not x.Create(): 85 | print "Failed to create debugger command line!" 86 | return None 87 | x.Show() 88 | return x 89 | 90 | try: 91 | # created already? 92 | dbgcmd 93 | dbgcmd.Close() 94 | del dbgcmd 95 | except: 96 | pass 97 | 98 | dbgcmd = show_win() 99 | if not dbgcmd: 100 | del dbgcmd 101 | 102 | -------------------------------------------------------------------------------- /Scripts/DrvsDispatch.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | A script to demonstrate how to send commands to the debugger and then parse and use the output in IDA 4 | 5 | Copyright (c) 1990-2009 Hex-Rays 6 | ALL RIGHTS RESERVED. 7 | 8 | """ 9 | 10 | import re 11 | from idaapi import Choose 12 | 13 | # ----------------------------------------------------------------------- 14 | def CmdDriverList(): 15 | s = Eval('WinDbgCommand("lm o");') 16 | if "IDC_FAILURE" in s: return False 17 | return s 18 | 19 | # ----------------------------------------------------------------------- 20 | def CmdDrvObj(drvname, flag=2): 21 | return Eval('WinDbgCommand("!drvobj %s %d");' % (drvname, flag)) 22 | 23 | # ----------------------------------------------------------------------- 24 | def CmdReloadForce(): 25 | s = Eval('WinDbgCommand(".reload /f");') 26 | if "IDC_FAILURE" in s: return False 27 | return True 28 | 29 | # ----------------------------------------------------------------------- 30 | # class to hold dispatch entry information 31 | class DispatchEntry: 32 | def __init__(self, addr, name): 33 | self.addr = addr 34 | self.name = name 35 | def __repr__(self): 36 | return "%08X: %s" % (self.addr, self.name) 37 | 38 | # ----------------------------------------------------------------------- 39 | def GetDriverDispatch(): 40 | 41 | # return a list of arrays of the form: [addr, name] 42 | ret_list = [] 43 | 44 | # build the RE for parsing output from the "lm o" command 45 | re_drv = re.compile('^[a-f0-9]+\s+[a-f0-9]+\s+(\S+)', re.I) 46 | 47 | # build the RE for parsing output from the "!drvobj DRV_NAME 2" command 48 | re_tbl = re.compile('^\[\d{2}\]\s+IRP_MJ_(\S+)\s+([0-9a-f]+)', re.I) 49 | 50 | # force reloading of module symbols 51 | if not CmdReloadForce(): 52 | print "Could not communicate with WinDbg, make sure the debugger is running!" 53 | return None 54 | 55 | # get driver list 56 | lm_out = CmdDriverList() 57 | if not lm_out: 58 | return "Failed to get driver list!" 59 | 60 | # for each line 61 | for line in lm_out.split("\n"): 62 | # parse 63 | r = re_drv.match(line) 64 | if not r: continue 65 | 66 | # extract driver name 67 | drvname = r.group(1).strip() 68 | 69 | # execute "drvobj" command 70 | tbl_out = CmdDrvObj(drvname) 71 | 72 | if not tbl_out: 73 | print "Failed to get driver object for", drvname 74 | continue 75 | 76 | # for each line 77 | for line in tbl_out.split("\n"): 78 | # parse 79 | r = re_tbl.match(line) 80 | if not r: continue 81 | disp_addr = int(r.group(2), 16) # convert hex string to number 82 | disp_name = "Dispatch" + r.group(1) 83 | ret_list.append(DispatchEntry(disp_addr, drvname + "_" + disp_name)) 84 | 85 | return ret_list 86 | 87 | # ----------------------------------------------------------------------- 88 | # Chooser class 89 | class DispatchChoose(Choose): 90 | def __init__(self, list, title): 91 | Choose.__init__(self, list, title) 92 | self.width = 250 93 | 94 | def enter(self, n): 95 | o = self.list[n-1] 96 | idc.Jump(o.addr) 97 | 98 | # ----------------------------------------------------------------------- 99 | # main 100 | r = GetDriverDispatch() 101 | if r: 102 | c = DispatchChoose(r, "Dispatch table browser") 103 | c.choose() 104 | else: 105 | print "Failed to retrieve dispatchers list!" -------------------------------------------------------------------------------- /Scripts/ExchainDump.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This script shows how to send debugger commands and use the result in IDA 4 | 5 | Copyright (c) 1990-2009 Hex-Rays 6 | ALL RIGHTS RESERVED. 7 | 8 | """ 9 | 10 | import idc 11 | import re 12 | 13 | # class to store parsed results 14 | class exchain: 15 | def __init__(self, m): 16 | self.name = m.group(1) 17 | self.addr = int(m.group(2), 16) 18 | 19 | def __str__(self): 20 | return "%x: %s" % (self.addr, self.name) 21 | 22 | # Chooser class 23 | class MyChoose(Choose): 24 | def __init__(self, list, title): 25 | Choose.__init__(self, list, title) 26 | self.width = 250 27 | 28 | def enter(self, n): 29 | o = self.list[n-1] 30 | idc.Jump(o.addr) 31 | 32 | # main 33 | def main(): 34 | s = idc.Eval('SendDbgCommand("!exchain")') 35 | if "IDC_FAILURE" in s: 36 | return (False, "Cannot execute the command") 37 | 38 | matches = re.finditer(r'[^:]+: ([^\(]+) \(([^\)]+)\)\n', s) 39 | L = [] 40 | for x in matches: 41 | L.append(exchain(x)) 42 | if not L: 43 | return (False, "Nothing to display: Could parse the result!") 44 | 45 | # Get a Choose instance 46 | chooser = MyChoose(L, "Exchain choose") 47 | # Run the chooser 48 | chooser.choose() 49 | return (True, "Success!") 50 | ok, r = main() 51 | if not ok: 52 | print r 53 | -------------------------------------------------------------------------------- /Scripts/ImpRef.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This is an example illustrating how to enumerate all addresses 3 | # that refer to all imported functions in a given module 4 | # 5 | # (c) Hex-Rays 6 | # 7 | 8 | import idaapi 9 | import idc 10 | import idautils 11 | import re 12 | 13 | # ----------------------------------------------------------------------- 14 | def find_imported_funcs(dllname): 15 | def imp_cb(ea, name, ord): 16 | if not name: 17 | name = '' 18 | imports.append([ea, name, ord]) 19 | return True 20 | 21 | imports = [] 22 | nimps = idaapi.get_import_module_qty() 23 | for i in xrange(0, nimps): 24 | name = idaapi.get_import_module_name(i) 25 | if re.match(dllname, name, re.IGNORECASE) is None: 26 | continue 27 | idaapi.enum_import_names(i, imp_cb) 28 | 29 | return imports 30 | 31 | 32 | # ----------------------------------------------------------------------- 33 | def find_import_ref(dllname): 34 | imports = find_imported_funcs(dllname) 35 | R = dict() 36 | for i, (ea, name,_) in enumerate(imports): 37 | #print "%x -> %s" % (ea, name) 38 | for xref in idautils.XrefsTo(ea): 39 | # check if referrer is a thunk 40 | ea = xref.frm 41 | f = idaapi.get_func(ea) 42 | if f and (f.flags & idaapi.FUNC_THUNK) != 0: 43 | imports.append([f.startEA, idaapi.get_func_name(f.startEA), 0]) 44 | #print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.startEA) 45 | continue 46 | 47 | # save results 48 | if not R.has_key(i): 49 | R[i] = [] 50 | 51 | R[i].append(ea) 52 | 53 | return (imports, R) 54 | 55 | # ----------------------------------------------------------------------- 56 | def main(): 57 | dllname = idc.AskStr('kernel32', "Enter module name") 58 | if not dllname: 59 | print("Cancelled") 60 | return 61 | 62 | imports, R = find_import_ref(dllname) 63 | for k, v in R.items(): 64 | print(imports[k][1]) 65 | for ea in v: 66 | print("\t%x" % ea) 67 | 68 | # ----------------------------------------------------------------------- 69 | main() -------------------------------------------------------------------------------- /Scripts/ImportExportViewer.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This is an example illustrating how to: 3 | # - enumerate imports 4 | # - enumerate entrypoints 5 | # - Use PluginForm class 6 | # - Use PySide with PluginForm to create a Python UI 7 | # 8 | # (c) Hex-Rays 9 | # 10 | import idaapi 11 | import idautils 12 | from idaapi import PluginForm 13 | from PySide import QtGui, QtCore 14 | 15 | # -------------------------------------------------------------------------- 16 | class ImpExpForm_t(PluginForm): 17 | 18 | def imports_names_cb(self, ea, name, ord): 19 | self.items.append((ea, '' if not name else name, ord)) 20 | # True -> Continue enumeration 21 | return True 22 | 23 | 24 | def BuildImports(self): 25 | tree = {} 26 | nimps = idaapi.get_import_module_qty() 27 | 28 | for i in xrange(0, nimps): 29 | name = idaapi.get_import_module_name(i) 30 | if not name: 31 | continue 32 | # Create a list for imported names 33 | self.items = [] 34 | 35 | # Enum imported entries in this module 36 | idaapi.enum_import_names(i, self.imports_names_cb) 37 | 38 | if name not in tree: 39 | tree[name] = [] 40 | tree[name].extend(self.items) 41 | 42 | return tree 43 | 44 | 45 | def BuildExports(self): 46 | return list(idautils.Entries()) 47 | 48 | 49 | def PopulateTree(self): 50 | # Clear previous items 51 | self.tree.clear() 52 | 53 | # Build imports 54 | root = QtGui.QTreeWidgetItem(self.tree) 55 | root.setText(0, "Imports") 56 | 57 | for dll_name, imp_entries in self.BuildImports().items(): 58 | imp_dll = QtGui.QTreeWidgetItem(root) 59 | imp_dll.setText(0, dll_name) 60 | 61 | for imp_ea, imp_name, imp_ord in imp_entries: 62 | item = QtGui.QTreeWidgetItem(imp_dll) 63 | item.setText(0, "%s [0x%08x]" %(imp_name, imp_ea)) 64 | 65 | 66 | # Build exports 67 | root = QtGui.QTreeWidgetItem(self.tree) 68 | root.setText(0, "Exports") 69 | 70 | for exp_i, exp_ord, exp_ea, exp_name in self.BuildExports(): 71 | item = QtGui.QTreeWidgetItem(root) 72 | item.setText(0, "%s [#%d] [0x%08x]" % (exp_name, exp_ord, exp_ea)) 73 | 74 | 75 | def OnCreate(self, form): 76 | """ 77 | Called when the plugin form is created 78 | """ 79 | 80 | # Get parent widget 81 | self.parent = self.FormToPySideWidget(form) 82 | 83 | # Create tree control 84 | self.tree = QtGui.QTreeWidget() 85 | self.tree.setHeaderLabels(("Names",)) 86 | self.tree.setColumnWidth(0, 100) 87 | 88 | # Create layout 89 | layout = QtGui.QVBoxLayout() 90 | layout.addWidget(self.tree) 91 | 92 | self.PopulateTree() 93 | # Populate PluginForm 94 | self.parent.setLayout(layout) 95 | 96 | 97 | def OnClose(self, form): 98 | """ 99 | Called when the plugin form is closed 100 | """ 101 | global ImpExpForm 102 | del ImpExpForm 103 | print "Closed" 104 | 105 | 106 | def Show(self): 107 | """Creates the form is not created or focuses it if it was""" 108 | return PluginForm.Show(self, 109 | "Imports / Exports viewer", 110 | options = PluginForm.FORM_PERSIST) 111 | 112 | # -------------------------------------------------------------------------- 113 | def main(): 114 | global ImpExpForm 115 | 116 | try: 117 | ImpExpForm 118 | except: 119 | ImpExpForm = ImpExpForm_t() 120 | 121 | ImpExpForm.Show() 122 | 123 | # -------------------------------------------------------------------------- 124 | main() -------------------------------------------------------------------------------- /Scripts/PteDump.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | import idc 3 | from idaapi import Choose2 4 | 5 | def parse_pte(str): 6 | try: 7 | parse_pte.re 8 | except: 9 | parse_pte.re = re.compile('PDE at ([0-9a-f]+)\s*PTE at ([0-9a-f]+)\ncontains ([0-9a-f]+)\s*contains ([0-9a-f]+)\npfn ([0-9]+)\s*([^ ]+)\s*pfn ([0-9a-f]+)\s*([^\r\n]+)', re.I | re.M) 10 | parse_pte.items = ('pde', 'pte', 'pdec', 'ptec', 'pdepfn', 'pdepfns', 'ptepfn', 'ptepfns') 11 | 12 | m = parse_pte.re.search(s) 13 | r = {} 14 | for i in range(0, len(parse_pte.items)): 15 | r[parse_pte.items[i]] = m.group(i+1) 16 | return r 17 | 18 | class MyChoose2(Choose2): 19 | 20 | def __init__(self, title, ea1, ea2): 21 | Choose2.__init__(self, title, [ ["VA", 10], ["PTE attr", 30] ]) 22 | self.ea1 = ea1 23 | self.ea2 = ea2 24 | self.n = 0 25 | self.icon = 5 26 | self.items = [] 27 | self.Refresh() 28 | self.selcount = 0 29 | 30 | def OnGetLine(self, n): 31 | print("getline %d" % n) 32 | return self.items[n] 33 | 34 | def OnGetSize(self): 35 | n = len(self.items) 36 | self.Refresh() 37 | return n 38 | 39 | def OnRefresh(self, n): 40 | print("refresh %d" % n) 41 | return n 42 | 43 | def Refresh(self): 44 | items = [] 45 | PG = 0x1000 46 | ea1 = self.ea1 47 | npages = (self.ea2 - ea1) / PG 48 | for i in range(npages): 49 | r = idc.SendDbgCommand("!pte %x" % ea1) 50 | if not r: 51 | return False 52 | r = parse_pte(r) 53 | items.append([hex(ea1), r['ptepfns']]) 54 | ea1 += PG 55 | 56 | self.items = items 57 | print(self.items) 58 | return True 59 | 60 | @staticmethod 61 | def Execute(ea1, ea2): 62 | c = MyChoose2("PTE Viewer [%x..%x]" % (ea1, ea2), ea1, ea2) 63 | return (c, c.Show()) 64 | 65 | 66 | def DumpPTE(ea1, ea2): 67 | items = [] 68 | PG = 0x1000 69 | npages = (ea2 - ea1) / PG 70 | for i in range(npages): 71 | r = idc.SendDbgCommand("!pte %x" % ea1) 72 | if not r: 73 | return False 74 | print r 75 | r = parse_pte(r) 76 | print("VA: %08X PTE: %s PDE: %s" % (ea1, r['ptepfns'], r['pdepfns'])) 77 | ea1 += PG 78 | 79 | def DumpSegPTE(ea): 80 | DumpPTE(idc.SegStart(ea), idc.SegEnd(ea)) 81 | 82 | DumpSegPTE(here()) 83 | 84 | #MyChoose2.Execute(0xF718F000, 0xF718F000+0x1000) 85 | 86 | -------------------------------------------------------------------------------- /Scripts/VaDump.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This script shows how to send debugger commands and use the result in IDA 4 | 5 | Copyright (c) 1990-2009 Hex-Rays 6 | ALL RIGHTS RESERVED. 7 | 8 | """ 9 | 10 | import idc 11 | from idaapi import Choose 12 | 13 | import re 14 | 15 | # class to store parsed results 16 | class memva: 17 | def __init__(self, m): 18 | self.base = int(m.group(1), 16) 19 | self.regionsize = int(m.group(2), 16) 20 | self.state = int(m.group(3), 16) 21 | self.statestr = m.group(4).strip() 22 | self.protect = int(m.group(5), 16) 23 | self.protectstr = m.group(6).strip() 24 | if m.group(7): 25 | self.type = int(m.group(8), 16) 26 | self.typestr = m.group(9).strip() 27 | else: 28 | self.type = 0 29 | self.typestr = "" 30 | def __str__(self): 31 | return "(Base %08X; RegionSize: %08X; State: %08X/%10s; protect: %08X/%10s; type: %08X/%10s)" % ( 32 | self.base, self.regionsize, self.state, 33 | self.statestr, self.protect, 34 | self.protectstr, self.type, self.typestr) 35 | 36 | # Chooser class 37 | class MemChoose(Choose): 38 | def __init__(self, list, title): 39 | Choose.__init__(self, list, title) 40 | self.width = 250 41 | 42 | def enter(self, n): 43 | o = self.list[n-1] 44 | idc.Jump(o.base) 45 | 46 | # main 47 | def main(): 48 | s = idc.Eval('SendDbgCommand("!vadump")') 49 | if "IDC_FAILURE" in s: 50 | return (False, "Cannot execute the command") 51 | 52 | matches = re.finditer(r'BaseAddress:\s*?(\w+?)\n' \ 53 | +'RegionSize:\s*?(\w*?)\n' \ 54 | +'State:\s*?(\w*?)\s*?(\w*?)\n' \ 55 | +'Protect:\s*?(\w*?)\s*?(\w*?)\n' \ 56 | +'(Type:\s*?(\w*?)\s*?(\w*?)\n)*', s) 57 | L = [] 58 | for x in matches: 59 | L.append(memva(x)) 60 | if not L: 61 | return (False, "Nothing to display: Could not parse the result!") 62 | 63 | # Get a Choose instance 64 | chooser = MemChoose(L, "Memory choose") 65 | # Run the chooser 66 | chooser.choose() 67 | return (True, "Success!") 68 | r = main() 69 | if not r[0]: 70 | print r[1] 71 | -------------------------------------------------------------------------------- /Scripts/callstack_test.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | def __sys(cmd, fmt=None, echo=True): 5 | """Executes a string of OS commands and returns the a list of tuples (return code,command executed)""" 6 | if not fmt: 7 | fmt = {} 8 | r = [] 9 | for cmd in [x for x in (cmd % fmt).split("\n") if len(x)]: 10 | if echo: 11 | print ">>>", cmd 12 | r.append((os.system(cmd), cmd)) 13 | return r 14 | 15 | body = r"""/// Autogenerated file 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | void want_break(int n) 22 | { 23 | printf("do you want to DebugBreak in func%d()?", n); 24 | char ch = _toupper(_getch()); 25 | printf("\n"); 26 | if (ch == 'Y') 27 | DebugBreak(); 28 | else if (ch == 'X') 29 | ExitProcess(n); 30 | } 31 | %FUNCS% 32 | int main(int /*argc*/, char * /*argv[]*/) 33 | { 34 | func1(); 35 | return 0; 36 | } 37 | """ 38 | 39 | funcs_body = [] 40 | 41 | func_body = r""" 42 | void func%(n)d() 43 | { 44 | printf("%(ident)senter %(n)d\n");%(pause)s 45 | func%(n1)d(); 46 | printf("%(ident)sleave %(n)d\n"); 47 | } 48 | """ 49 | 50 | if len(sys.argv) < 2: 51 | print "usage: gen nb_calls pause_frequency" 52 | sys.exit(0) 53 | 54 | n = int(sys.argv[1]) 55 | if n < 1: 56 | print "at least one call should be passed!" 57 | sys.exit(1) 58 | 59 | m = int(sys.argv[2]) 60 | 61 | func_params = {'n': 0, 'n1': 0, 'ident': '', 'pause' : ''} 62 | 63 | for i in xrange(1, n + 1): 64 | func_params['n'] = i 65 | func_params['n1'] = i+1 66 | func_params['ident'] = " " * i 67 | func_params['pause'] = ("\n want_break(%d);" % i) if (i % m) == 0 else '' 68 | 69 | funcs_body.append(func_body % func_params) 70 | funcs_body.append(r""" 71 | void func%(n)d() 72 | { 73 | printf("that's it #%(n)d!\n"); 74 | } 75 | """ % {'n':i+1}) 76 | funcs_body.reverse() 77 | 78 | # write the file 79 | body = body.replace('%FUNCS%', ''.join(funcs_body)) 80 | f = file('src.cpp', 'w') 81 | f.write(body) 82 | f.close() 83 | 84 | 85 | __sys(""" 86 | if exist src.exe del src.exe 87 | bcc32 src 88 | if exist src.exe move src.exe src_bcc.exe 89 | if exist src.obj del src.obj 90 | cl32 src.cpp /Zi /Od 91 | """) -------------------------------------------------------------------------------- /Scripts/msdnapihelp.py: -------------------------------------------------------------------------------- 1 | """ 2 | User contributed script: MSDN API HELP plugin 3 | 4 | This script fetches the API reference (from MSDN) of a given highlighted identifier 5 | and returns the results in a new web browser page. 6 | 7 | This script depends on the feedparser package: http://code.google.com/p/feedparser/ 8 | 9 | 10/05/2010 10 | - initial version 11 | 12 | 13 | """ 14 | 15 | import idaapi 16 | 17 | # ----------------------------------------------------------------------- 18 | class msdnapihelp_plugin_t(idaapi.plugin_t): 19 | flags = idaapi.PLUGIN_UNL 20 | comment = "Online MSDN API Help" 21 | help = "Help me" 22 | wanted_name = "MSDN API Help" 23 | wanted_hotkey = "F3" 24 | 25 | def init(self): 26 | return idaapi.PLUGIN_OK 27 | 28 | 29 | @staticmethod 30 | def sanitize_name(name): 31 | t = idaapi.FUNC_IMPORT_PREFIX 32 | if name.startswith(t): 33 | return name[len(t):] 34 | return name 35 | 36 | 37 | def run(self, arg): 38 | # Get the highlighted identifier 39 | id = idaapi.get_highlighted_identifier() 40 | if not id: 41 | print "No identifier was highlighted" 42 | return 43 | 44 | import webbrowser 45 | 46 | try: 47 | import feedparser 48 | except: 49 | idaapi.warning('Feedparser package not installed') 50 | return 51 | 52 | id = self.sanitize_name(id) 53 | print "Looking up '%s' in MSDN online" % id 54 | d = feedparser.parse("http://social.msdn.microsoft.com/Search/Feed.aspx?locale=en-us&format=RSS&Query=%s" % id) 55 | if len(d['entries']) > 0: 56 | url = d['entries'][0].link 57 | webbrowser.open_new_tab(url) 58 | else: 59 | print "API documentation not found for: %s" % id 60 | 61 | 62 | def term(self): 63 | pass 64 | 65 | 66 | # ----------------------------------------------------------------------- 67 | def PLUGIN_ENTRY(): 68 | return msdnapihelp_plugin_t() 69 | -------------------------------------------------------------------------------- /basetsd.h: -------------------------------------------------------------------------------- 1 | #ifndef _BASETSD_H 2 | #define _BASETSD_H 3 | /* Microsoft free compilers seem to lack this file and Python needs it */ 4 | #endif 5 | -------------------------------------------------------------------------------- /docs/notes.txt: -------------------------------------------------------------------------------- 1 | Assorted notes 2 | -------------- 3 | 4 | Wrapped functions and constants: 5 | 6 | All the symbols from the idaapi module are listed in symbollist.txt. 7 | Documentation for the plugin API functions functions is in the IDA 8 | SDK header files. All function and symbol names directly translate 9 | to the C++ counterparts. If you try to use a function that is not 10 | wrapped yet you will get an exception like this: 11 | 12 | Traceback (most recent call last): 13 | File "", line 1, in ? 14 | NameError: name 'foobar' is not defined 15 | 16 | If this happens you can check the function in symbollist.txt. If it 17 | is not included and it should be please report it to the author. 18 | 19 | 20 | Data types: 21 | 22 | All the C++ data types are mapped to corresponding Python data types. 23 | For example ea_t maps to a Python integer. Complex data types (like 24 | structures and classes) are mapped to Python classes that have the 25 | same attributes as the original type. 26 | 27 | 28 | Arguments and return values: 29 | 30 | Generally all function arguments should be the same type as specified 31 | by the original headers. Pointers to complex types (structures, classes) 32 | are checked and must match the original declarations. 33 | 34 | For example comment = get_func_comment("aa", 0) will raise an exception: 35 | 36 | Traceback (most recent call last): 37 | File "", line 1, in ? 38 | TypeError: Type error. Got aa, expected _p_func_t 39 | 40 | When calling functions that return a string in a buffer (usually with 41 | maximum size) the buffer and size parameter is omitted. These functions 42 | return either the result in a string or None if the call fails and returns 43 | NULL. The output buffers are maximized at MAXSTR. 44 | 45 | Example: 46 | 47 | C++: get_func_name(0x1234, buf, sizeof(buf)); 48 | Python: name = get_func_name(0x1234) 49 | 50 | Any function that should return a char * is going to return either a 51 | Python string (up to MAXSTR) or None. 52 | 53 | 54 | -------------------------------------------------------------------------------- /examples/chooser.py: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # Chooser test 3 | # 4 | # This script demonstrates the usage of the class-based chooser. 5 | # 6 | # Author: Gergely Erdelyi 7 | #--------------------------------------------------------------------- 8 | from idaapi import Choose 9 | 10 | # 11 | # Modal chooser 12 | # 13 | 14 | # Get a modal Choose instance 15 | chooser = Choose([], "MyChooser", 1) 16 | # List to choose from 17 | chooser.list = [ "First", "Second", "Third" ] 18 | # Set the width 19 | chooser.width = 50 20 | # Run the chooser 21 | ch = chooser.choose() 22 | # Print the results 23 | if ch > 0: 24 | print "You chose %d which is %s" % (ch, chooser.list[ch-1]) 25 | else: 26 | print "Escape from chooser" 27 | 28 | # 29 | # Normal chooser 30 | # 31 | class MyChoose(Choose): 32 | """ 33 | You have to subclass Chooser to override the enter() method 34 | """ 35 | def __init__(self, list=[], name="Choose"): 36 | Choose.__init__(self, list, name) 37 | # Set the width 38 | self.width = 50 39 | self.deflt = 1 40 | 41 | def enter(self, n): 42 | print "Enter called. Do some stuff here." 43 | print "The chosen item is %d = %s" % (n, self.list[n-1]) 44 | print "Now press ESC to leave." 45 | 46 | # Get a Choose instance 47 | chooser = MyChoose([ "First", "Second", "Third" ], "MyChoose") 48 | 49 | # Run the chooser 50 | ch = chooser.choose() 51 | -------------------------------------------------------------------------------- /examples/colours.py: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # Colour test 3 | # 4 | # This script demonstrates the usage of background colours. 5 | # 6 | # Author: Gergely Erdelyi 7 | #--------------------------------------------------------------------- 8 | 9 | # Set the colour of the current segment to BLUE 10 | SetColor(here(), CIC_SEGM, 0xc02020) 11 | # Set the colour of the current function to GREEN 12 | SetColor(here(), CIC_FUNC, 0x208020) 13 | # Set the colour of the current item to RED 14 | SetColor(here(), CIC_ITEM, 0x2020c0) 15 | 16 | # Print the colours just set 17 | print "%x" % GetColor(here(), CIC_SEGM) 18 | print "%x" % GetColor(here(), CIC_FUNC) 19 | print "%x" % GetColor(here(), CIC_ITEM) 20 | -------------------------------------------------------------------------------- /examples/debughook.py: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # Debug notification hook test 3 | # 4 | # This script start the executable and steps through the first five 5 | # instructions. Each instruction is disassembled after execution. 6 | # 7 | # Original Author: Gergely Erdelyi 8 | # 9 | # Maintained By: IDAPython Team 10 | # 11 | #--------------------------------------------------------------------- 12 | from idaapi import * 13 | 14 | class MyDbgHook(DBG_Hooks): 15 | """ Own debug hook class that implementd the callback functions """ 16 | 17 | def dbg_process_start(self, pid, tid, ea, name, base, size): 18 | print("Process started, pid=%d tid=%d name=%s" % (pid, tid, name)) 19 | 20 | def dbg_process_exit(self, pid, tid, ea, code): 21 | print("Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code)) 22 | 23 | def dbg_library_unload(self, pid, tid, ea, info): 24 | print("Library unloaded: pid=%d tid=%d ea=0x%x info=%s" % (pid, tid, ea, info)) 25 | return 0 26 | 27 | def dbg_process_attach(self, pid, tid, ea, name, base, size): 28 | print("Process attach pid=%d tid=%d ea=0x%x name=%s base=%x size=%x" % (pid, tid, ea, name, base, size)) 29 | 30 | def dbg_process_detach(self, pid, tid, ea): 31 | print("Process detached, pid=%d tid=%d ea=0x%x" % (pid, tid, ea)) 32 | return 0 33 | 34 | def dbg_library_load(self, pid, tid, ea, name, base, size): 35 | print "Library loaded: pid=%d tid=%d name=%s base=%x" % (pid, tid, name, base) 36 | 37 | def dbg_bpt(self, tid, ea): 38 | print "Break point at 0x%x pid=%d" % (ea, tid) 39 | # return values: 40 | # -1 - to display a breakpoint warning dialog 41 | # if the process is suspended. 42 | # 0 - to never display a breakpoint warning dialog. 43 | # 1 - to always display a breakpoint warning dialog. 44 | return 0 45 | 46 | def dbg_suspend_process(self): 47 | print "Process suspended" 48 | 49 | def dbg_exception(self, pid, tid, ea, exc_code, exc_can_cont, exc_ea, exc_info): 50 | print("Exception: pid=%d tid=%d ea=0x%x exc_code=0x%x can_continue=%d exc_ea=0x%x exc_info=%s" % ( 51 | pid, tid, ea, exc_code & idaapi.BADADDR, exc_can_cont, exc_ea, exc_info)) 52 | # return values: 53 | # -1 - to display an exception warning dialog 54 | # if the process is suspended. 55 | # 0 - to never display an exception warning dialog. 56 | # 1 - to always display an exception warning dialog. 57 | return 0 58 | 59 | def dbg_trace(self, tid, ea): 60 | print("Trace tid=%d ea=0x%x" % (tid, ea)) 61 | # return values: 62 | # 1 - do not log this trace event; 63 | # 0 - log it 64 | return 0 65 | 66 | def dbg_step_into(self): 67 | print("Step into") 68 | self.dbg_step_over() 69 | 70 | def dbg_run_to(self, pid, tid=0, ea=0): 71 | print "Runto: tid=%d" % tid 72 | idaapi.continue_process() 73 | 74 | 75 | def dbg_step_over(self): 76 | eip = GetRegValue("EIP") 77 | print("0x%x %s" % (eip, GetDisasm(eip))) 78 | 79 | self.steps += 1 80 | if self.steps >= 5: 81 | request_exit_process() 82 | else: 83 | request_step_over() 84 | 85 | 86 | # Remove an existing debug hook 87 | try: 88 | if debughook: 89 | print("Removing previous hook ...") 90 | debughook.unhook() 91 | except: 92 | pass 93 | 94 | # Install the debug hook 95 | debughook = MyDbgHook() 96 | debughook.hook() 97 | debughook.steps = 0 98 | 99 | # Stop at the entry point 100 | ep = GetLongPrm(INF_START_IP) 101 | request_run_to(ep) 102 | 103 | # Step one instruction 104 | request_step_over() 105 | 106 | # Start debugging 107 | run_requests() 108 | -------------------------------------------------------------------------------- /examples/ex1.idc: -------------------------------------------------------------------------------- 1 | // 2 | // Reference Lister 3 | // 4 | // List all functions and all references to them in the current section. 5 | // 6 | // Implemented in IDC 7 | // 8 | #include 9 | 10 | static main() 11 | { 12 | auto ea, func, ref; 13 | 14 | // Get current ea 15 | ea = ScreenEA(); 16 | 17 | // Loop from start to end in the current segment 18 | for (func=SegStart(ea); 19 | func != BADADDR && func < SegEnd(ea); 20 | func=NextFunction(func)) 21 | { 22 | // If the current address is function process it 23 | if (GetFunctionFlags(func) != -1) 24 | { 25 | Message("Function %s at 0x%x\n", GetFunctionName(func), func); 26 | 27 | // Find all code references to func 28 | for (ref=RfirstB(func); ref != BADADDR; ref=RnextB(func, ref)) 29 | { 30 | Message(" called from %s(0x%x)\n", GetFunctionName(ref), ref); 31 | } 32 | 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/ex1_idaapi.py: -------------------------------------------------------------------------------- 1 | # 2 | # Reference Lister 3 | # 4 | # List all functions and all references to them in the current section. 5 | # 6 | # Implemented using direct IDA Plugin API calls 7 | # 8 | from idaapi import * 9 | 10 | def main(): 11 | # Get current ea 12 | ea = get_screen_ea() 13 | 14 | # Get segment class 15 | seg = getseg(ea) 16 | 17 | # Loop from segment start to end 18 | func = get_next_func(seg.startEA) 19 | seg_end = seg.endEA 20 | while func is not None and func.startEA < seg_end: 21 | funcea = func.startEA 22 | print "Function %s at 0x%x" % (GetFunctionName(funcea), funcea) 23 | 24 | ref = get_first_cref_to(funcea) 25 | 26 | while ref != BADADDR: 27 | print " called from %s(0x%x)" % (get_func_name(ref), ref) 28 | ref = get_next_cref_to(funcea, ref) 29 | 30 | func = get_next_func(funcea) 31 | 32 | 33 | main() -------------------------------------------------------------------------------- /examples/ex1_idautils.py: -------------------------------------------------------------------------------- 1 | # 2 | # Reference Lister 3 | # 4 | # List all functions and all references to them in the current section. 5 | # 6 | # Implemented with the idautils module 7 | # 8 | from idautils import * 9 | 10 | def main(): 11 | # Get current ea 12 | ea = ScreenEA() 13 | if ea == idaapi.BADADDR: 14 | print("Could not get get_screen_ea()") 15 | return 16 | 17 | # Loop from start to end in the current segment 18 | for funcea in Functions(SegStart(ea), SegEnd(ea)): 19 | print("Function %s at 0x%x" % (GetFunctionName(funcea), funcea)) 20 | 21 | # Find all code references to funcea 22 | for ref in CodeRefsTo(funcea, 1): 23 | print(" called from %s(0x%x)" % (GetFunctionName(ref), ref)) 24 | 25 | 26 | if __name__=='__main__': 27 | main() -------------------------------------------------------------------------------- /examples/ex_add_menu_item.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | 3 | def cb(*args): 4 | print("Callback called!") 5 | return 1 6 | 7 | try: 8 | ex_addmenu_item_ctx 9 | idaapi.del_menu_item(ex_addmenu_item_ctx) 10 | print("Menu removed") 11 | del ex_addmenu_item_ctx 12 | except: 13 | ex_addmenu_item_ctx = idaapi.add_menu_item("Search/", "X", "", 0, cb, tuple("hello world")) 14 | if ex_addmenu_item_ctx is None: 15 | print("Failed to add menu!") 16 | del ex_addmenu_item_ctx 17 | else: 18 | print("Menu added successfully. Run the script again to delete the menu") -------------------------------------------------------------------------------- /examples/ex_choose2.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | from idaapi import Choose2 3 | 4 | # 5 | 6 | 7 | class chooser_handler_t(idaapi.action_handler_t): 8 | def __init__(self, thing): 9 | idaapi.action_handler_t.__init__(self) 10 | self.thing = thing 11 | 12 | def activate(self, ctx): 13 | sel = [] 14 | for i in xrange(len(ctx.chooser_selection)): 15 | sel.append(str(ctx.chooser_selection.at(i))) 16 | print "command %s selected @ %s" % (self.thing, ", ".join(sel)) 17 | 18 | def update(self, ctx): 19 | return idaapi.AST_ENABLE_FOR_FORM if idaapi.is_chooser_tform(ctx.form_type) else idaapi.AST_DISABLE_FOR_FORM 20 | 21 | 22 | class MyChoose2(Choose2): 23 | 24 | def __init__(self, title, nb = 5, flags=0, width=None, height=None, embedded=False, modal=False): 25 | Choose2.__init__( 26 | self, 27 | title, 28 | [ ["Address", 10], ["Name", 30] ], 29 | flags = flags, 30 | width = width, 31 | height = height, 32 | embedded = embedded) 33 | self.n = 0 34 | self.items = [ self.make_item() for x in xrange(0, nb+1) ] 35 | self.icon = 5 36 | self.selcount = 0 37 | self.modal = modal 38 | self.popup_names = ["Inzert", "Del leet", "Ehdeet", "Ree frech"] 39 | 40 | print("created %s" % str(self)) 41 | 42 | def OnClose(self): 43 | print "closed", str(self) 44 | 45 | def OnEditLine(self, n): 46 | self.items[n][1] = self.items[n][1] + "*" 47 | print("editing %d" % n) 48 | 49 | def OnInsertLine(self): 50 | self.items.append(self.make_item()) 51 | print("insert line") 52 | 53 | def OnSelectLine(self, n): 54 | self.selcount += 1 55 | Warning("[%02d] selectline '%s'" % (self.selcount, n)) 56 | 57 | def OnGetLine(self, n): 58 | print("getline %d" % n) 59 | return self.items[n] 60 | 61 | def OnGetSize(self): 62 | n = len(self.items) 63 | print("getsize -> %d" % n) 64 | return n 65 | 66 | def OnDeleteLine(self, n): 67 | print("del %d " % n) 68 | del self.items[n] 69 | return n 70 | 71 | def OnRefresh(self, n): 72 | print("refresh %d" % n) 73 | return n 74 | 75 | def OnGetIcon(self, n): 76 | r = self.items[n] 77 | t = self.icon + r[1].count("*") 78 | print "geticon", n, t 79 | return t 80 | 81 | def show(self): 82 | return self.Show(self.modal) >= 0 83 | 84 | def make_item(self): 85 | r = [str(self.n), "func_%04d" % self.n] 86 | self.n += 1 87 | return r 88 | 89 | def OnGetLineAttr(self, n): 90 | print("getlineattr %d" % n) 91 | if n == 1: 92 | return [0xFF0000, 0] 93 | 94 | 95 | # ----------------------------------------------------------------------- 96 | def test_choose2(modal=False): 97 | global c 98 | c = MyChoose2("Choose2 - sample 1", nb=10, modal=modal) 99 | r = c.show() 100 | form = idaapi.get_current_tform() 101 | for thing in ["A", "B"]: 102 | idaapi.attach_action_to_popup(form, None, "choose2:act%s" % thing) 103 | 104 | # ----------------------------------------------------------------------- 105 | def test_choose2_embedded(): 106 | global c 107 | c = MyChoose2("Choose2 - embedded", nb=12, embedded = True, width=123, height=222) 108 | r = c.Embedded() 109 | if r == 1: 110 | try: 111 | if test_embedded: 112 | o, sel = _idaapi.choose2_get_embedded(c) 113 | print("o=%s, type(o)=%s" % (str(o), type(o))) 114 | test_embedded(o) 115 | finally: 116 | c.Close() 117 | 118 | # ----------------------------------------------------------------------- 119 | if __name__ == '__main__': 120 | 121 | # Register actions 122 | for thing in ["A", "B"]: 123 | actname = "choose2:act%s" % thing 124 | idaapi.register_action( 125 | idaapi.action_desc_t( 126 | actname, 127 | "command %s" % thing, 128 | chooser_handler_t(thing))) 129 | 130 | #test_choose2_embedded() 131 | test_choose2(False) 132 | 133 | # 134 | -------------------------------------------------------------------------------- /examples/ex_cli.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This is an example illustrating how to implement a CLI 3 | # (c) Hex-Rays 4 | # 5 | from idaapi import NW_OPENIDB, NW_CLOSEIDB, NW_TERMIDA, NW_REMOVE, COLSTR, cli_t 6 | 7 | # 8 | class mycli_t(cli_t): 9 | flags = 0 10 | sname = "pycli" 11 | lname = "Python CLI" 12 | hint = "pycli hint" 13 | 14 | def OnExecuteLine(self, line): 15 | """ 16 | The user pressed Enter. The CLI is free to execute the line immediately or ask for more lines. 17 | 18 | This callback is mandatory. 19 | 20 | @param line: typed line(s) 21 | @return Boolean: True-executed line, False-ask for more lines 22 | """ 23 | print "OnExecute:", line 24 | return True 25 | 26 | def OnKeydown(self, line, x, sellen, vkey, shift): 27 | """ 28 | A keyboard key has been pressed 29 | This is a generic callback and the CLI is free to do whatever it wants. 30 | 31 | This callback is optional. 32 | 33 | @param line: current input line 34 | @param x: current x coordinate of the cursor 35 | @param sellen: current selection length (usually 0) 36 | @param vkey: virtual key code. if the key has been handled, it should be returned as zero 37 | @param shift: shift state 38 | 39 | @return: 40 | None - Nothing was changed 41 | tuple(line, x, sellen, vkey): if either of the input line or the x coordinate or the selection length has been modified. 42 | 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) 43 | """ 44 | print "Onkeydown: line=%s x=%d sellen=%d vkey=%d shift=%d" % (line, x, sellen, vkey, shift) 45 | return None 46 | 47 | def OnCompleteLine(self, prefix, n, line, prefix_start): 48 | """ 49 | The user pressed Tab. Find a completion number N for prefix PREFIX 50 | 51 | This callback is optional. 52 | 53 | @param prefix: Line prefix at prefix_start (string) 54 | @param n: completion number (int) 55 | @param line: the current line (string) 56 | @param prefix_start: the index where PREFIX starts in LINE (int) 57 | 58 | @return: None if no completion could be generated otherwise a String with the completion suggestion 59 | """ 60 | print "OnCompleteLine: prefix=%s n=%d line=%s prefix_start=%d" % (prefix, n, line, prefix_start) 61 | return None 62 | # 63 | 64 | 65 | # ----------------------------------------------------------------------- 66 | def nw_handler(code, old=0): 67 | if code == NW_OPENIDB: 68 | print "nw_handler(): installing CLI" 69 | mycli.register() 70 | elif code == NW_CLOSEIDB: 71 | print "nw_handler(): removing CLI" 72 | mycli.unregister() 73 | elif code == NW_TERMIDA: 74 | print "nw_handler(): uninstalled nw handler" 75 | idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB | NW_REMOVE, nw_handler) 76 | 77 | # ----------------------------------------------------------------------- 78 | 79 | # Already installed? 80 | try: 81 | mycli 82 | # remove previous CLI 83 | mycli.unregister() 84 | del mycli 85 | # remove previous handler 86 | nw_handler(NW_TERMIDA) 87 | except: 88 | pass 89 | finally: 90 | mycli = mycli_t() 91 | 92 | # register CLI 93 | if mycli.register(): 94 | print "CLI installed" 95 | # install new handler 96 | idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB, nw_handler) 97 | else: 98 | del mycli 99 | print "Failed to install CLI" 100 | 101 | -------------------------------------------------------------------------------- /examples/ex_dbg.py: -------------------------------------------------------------------------------- 1 | # 2 | # Demonstrates some functions from the "dbg" class 3 | # 4 | 5 | import idaapi 6 | #from idaapi import dbg_write_memory, dbg_read_memory, dbg_get_thread_sreg_base, dbg_get_registers, dbg_get_memory_info 7 | 8 | def dump_meminfo(L): 9 | # startEA, endEA, name, sclass, sbase, bitness, perm 10 | for (startEA, endEA, name, sclass, sbase, bitness, perm) in L: 11 | print "%x: %x name=<%s> sclass=<%s> sbase=%x bitness=%2x perm=%2x" % (startEA, endEA, name, sclass, sbase, bitness, perm) 12 | 13 | def test_getmeminfo(): 14 | L = idaapi.dbg_get_memory_info() 15 | dump_meminfo(L) 16 | 17 | def test_getregs(): 18 | L = idaapi.dbg_get_registers() 19 | # name flags class dtyp bit_strings bit_strings_default_mask 20 | for (name, flags, cls, dtype, bit_strings, bit_strings_default_mask) in L: 21 | print "name=<%s> flags=%x class=%x dtype=%x bit_strings_mask=%x" % (name, flags, cls, dtype, bit_strings_default_mask) 22 | if bit_strings: 23 | for s in bit_strings: 24 | print " %s" % s 25 | 26 | def test_manual_regions(): 27 | L = idaapi.get_manual_regions() 28 | if not L: 29 | print "no manual regions!" 30 | else: 31 | dump_meminfo(L) 32 | 33 | def test_readwrite(): 34 | ea = cpu.Eip 35 | buf = idaapi.dbg_read_memory(ea, 5) 36 | print "read: ", [hex(ord(x)) for x in buf] 37 | idaapi.dbg_write_memory(ea, buf) 38 | 39 | test_manual_regions() 40 | 41 | if idaapi.dbg_can_query(): 42 | print "%x: fs" % (idaapi.dbg_get_thread_sreg_base(idc.GetCurrentThreadId(), cpu.fs)) 43 | test_getmeminfo() 44 | test_getregs() 45 | test_readwrite() 46 | 47 | else: 48 | print "run and suspend the debugger first" -------------------------------------------------------------------------------- /examples/ex_debug_names.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | 3 | def main(): 4 | if not idaapi.is_debugger_on(): 5 | print "Please run the process first!" 6 | return 7 | if idaapi.get_process_state() != -1: 8 | print "Please suspend the debugger first!" 9 | return 10 | 11 | dn = idaapi.get_debug_names(idaapi.cvar.inf.minEA, idaapi.cvar.inf.maxEA) 12 | for i in dn: 13 | print "%08x: %s" % (i, dn[i]) 14 | 15 | main() 16 | -------------------------------------------------------------------------------- /examples/ex_expr.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This is an example illustrating how to extend IDC from Python 3 | # (c) Hex-Rays 4 | # 5 | from idaapi import set_idc_func_ex 6 | 7 | # 8 | def py_power(n, e): 9 | return n ** e 10 | 11 | ok = set_idc_func_ex("pow", py_power, (idaapi.VT_LONG, idaapi.VT_LONG), 0) 12 | if ok: 13 | print("Now the pow() will be present IDC!") 14 | else: 15 | print("Failed to register pow() IDC function") 16 | # 17 | -------------------------------------------------------------------------------- /examples/ex_func_chooser.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | import idautils 3 | import idc 4 | 5 | class MyChoose2(Choose2): 6 | 7 | def __init__(self, title): 8 | Choose2.__init__(self, title, [ ["Address", 10 | Choose2.CHCOL_HEX], ["Name", 30 | Choose2.CHCOL_PLAIN] ]) 9 | self.n = 0 10 | self.icon = 41 11 | self.PopulateItems() 12 | 13 | def PopulateItems(self): 14 | self.items = [ [hex(x), GetFunctionName(x), x] for x in idautils.Functions() ] 15 | 16 | def OnClose(self): 17 | print "closed ", self.title 18 | 19 | def OnSelectLine(self, n): 20 | idc.Jump(self.items[n][2]) 21 | 22 | def OnGetLine(self, n): 23 | return self.items[n] 24 | 25 | def OnGetSize(self): 26 | return len(self.items) 27 | 28 | def OnDeleteLine(self, n): 29 | ea = self.items[n][2] 30 | idc.DelFunction(ea) 31 | return n 32 | 33 | def OnRefresh(self, n): 34 | self.PopulateItems() 35 | return n 36 | 37 | c = MyChoose2("My functions list") 38 | c.Show() -------------------------------------------------------------------------------- /examples/ex_gdl_qflow_chart.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | 3 | # ----------------------------------------------------------------------- 4 | # Using raw IDAAPI 5 | def raw_main(p=True): 6 | f = idaapi.get_func(here()) 7 | if not f: 8 | return 9 | 10 | q = idaapi.qflow_chart_t("The title", f, 0, 0, idaapi.FC_PREDS) 11 | for n in xrange(0, q.size()): 12 | b = q[n] 13 | if p: 14 | print "%x - %x [%d]:" % (b.startEA, b.endEA, n) 15 | 16 | for ns in xrange(0, q.nsucc(n)): 17 | if p: 18 | print "SUCC: %d->%d" % (n, q.succ(n, ns)) 19 | 20 | for ns in xrange(0, q.npred(n)): 21 | if p: 22 | print "PRED: %d->%d" % (n, q.pred(n, ns)) 23 | 24 | # ----------------------------------------------------------------------- 25 | # Using the class 26 | def cls_main(p=True): 27 | f = idaapi.FlowChart(idaapi.get_func(here())) 28 | for block in f: 29 | if p: 30 | print "%x - %x [%d]:" % (block.startEA, block.endEA, block.id) 31 | for succ_block in block.succs(): 32 | if p: 33 | print " %x - %x [%d]:" % (succ_block.startEA, succ_block.endEA, succ_block.id) 34 | 35 | for pred_block in block.preds(): 36 | if p: 37 | print " %x - %x [%d]:" % (pred_block.startEA, pred_block.endEA, pred_block.id) 38 | 39 | q = None 40 | f = None 41 | raw_main(False) 42 | cls_main(True) 43 | 44 | -------------------------------------------------------------------------------- /examples/ex_graph.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This is an example illustrating how to use the user graphing functionality 3 | # in Python 4 | # (c) Hex-Rays 5 | # 6 | from idaapi import * 7 | 8 | class GraphCloser(action_handler_t): 9 | def __init__(self, graph): 10 | action_handler_t.__init__(self) 11 | self.graph = graph 12 | 13 | def activate(self, ctx): 14 | self.graph.Close() 15 | 16 | def update(self, ctx): 17 | return AST_ENABLE_ALWAYS 18 | 19 | 20 | class MyGraph(GraphViewer): 21 | def __init__(self, funcname, result): 22 | self.title = "call graph of " + funcname 23 | GraphViewer.__init__(self, self.title) 24 | self.funcname = funcname 25 | self.result = result 26 | 27 | def OnRefresh(self): 28 | self.Clear() 29 | id = self.AddNode(self.funcname) 30 | for x in self.result.keys(): 31 | callee = self.AddNode(x) 32 | self.AddEdge(id, callee) 33 | 34 | return True 35 | 36 | def OnGetText(self, node_id): 37 | return str(self[node_id]) 38 | 39 | def Show(self): 40 | if not GraphViewer.Show(self): 41 | return False 42 | actname = "graph_closer:%s" % self.title 43 | register_action(action_desc_t(actname, "Close %s" % self.title, GraphCloser(self))) 44 | attach_action_to_popup(self.GetTCustomControl(), None, actname) 45 | return True 46 | 47 | 48 | def show_graph(): 49 | f = idaapi.get_func(here()) 50 | if not f: 51 | print "Must be in a function" 52 | return 53 | # Iterate through all function instructions and take only call instructions 54 | result = {} 55 | for x in [x for x in FuncItems(f.startEA) if idaapi.is_call_insn(x)]: 56 | for xref in XrefsFrom(x, idaapi.XREF_FAR): 57 | if not xref.iscode: continue 58 | t = GetFunctionName(xref.to) 59 | if not t: 60 | t = hex(xref.to) 61 | result[t] = True 62 | g = MyGraph(GetFunctionName(f.startEA), result) 63 | if g.Show(): 64 | return g 65 | else: 66 | return None 67 | 68 | g = show_graph() 69 | if g: 70 | print "Graph created and displayed!" -------------------------------------------------------------------------------- /examples/ex_hotkey.py: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # This script demonstrates the usage of hotkeys. 3 | # 4 | # 5 | # Author: IDAPython team 6 | #--------------------------------------------------------------------- 7 | import idaapi 8 | 9 | def hotkey_pressed(): 10 | print("hotkey pressed!") 11 | 12 | try: 13 | hotkey_ctx 14 | if idaapi.del_hotkey(hotkey_ctx): 15 | print("Hotkey unregistered!") 16 | del hotkey_ctx 17 | else: 18 | print("Failed to delete hotkey!") 19 | except: 20 | hotkey_ctx = idaapi.add_hotkey("Shift-A", hotkey_pressed) 21 | if hotkey_ctx is None: 22 | print("Failed to register hotkey!") 23 | del hotkey_ctx 24 | else: 25 | print("Hotkey registered!") 26 | -------------------------------------------------------------------------------- /examples/ex_idagraph.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This is an example illustrating how to manipulate an existing IDA-provided 3 | # view (and thus its graph), in Python. 4 | # (c) Hex-Rays 5 | # 6 | from idaapi import IDAViewWrapper 7 | from time import sleep 8 | import threading 9 | 10 | class Worker(threading.Thread): 11 | def __init__(self, w): 12 | threading.Thread.__init__(self) 13 | self.w = w 14 | 15 | def req_SetCurrentRendererType(self, switch_to): 16 | w = self.w 17 | def f(): 18 | print "Switching.." 19 | w.SetCurrentRendererType(switch_to) 20 | idaapi.execute_sync(f, idaapi.MFF_FAST) 21 | 22 | def req_SetNodeInfo(self, node, info, flags): 23 | w = self.w 24 | def f(): 25 | print "Setting node info.." 26 | w.SetNodeInfo(node, info, flags) 27 | idaapi.execute_sync(f, idaapi.MFF_FAST) 28 | 29 | def req_DelNodesInfos(self, *nodes): 30 | w = self.w 31 | def f(): 32 | print "Deleting nodes infos.." 33 | w.DelNodesInfos(*nodes) 34 | idaapi.execute_sync(f, idaapi.MFF_FAST) 35 | 36 | def run(self): 37 | # Note, in order to leave the UI available 38 | # to the user, we'll perform UI operations 39 | # in this thread. 40 | # 41 | # But. 42 | # 43 | # Qt expects that all UI operations be performed from 44 | # the main thread. Therefore, we'll have to use 45 | # 'idaapi.execute_sync' to send requests to the main thread. 46 | 47 | # Switch back & forth to & from graph view 48 | for i in xrange(3): 49 | self.req_SetCurrentRendererType(idaapi.TCCRT_FLAT) 50 | sleep(1) 51 | self.req_SetCurrentRendererType(idaapi.TCCRT_GRAPH) 52 | sleep(1) 53 | 54 | # Go to graph view, and set the first node's color 55 | self.req_SetCurrentRendererType(idaapi.TCCRT_GRAPH) 56 | ni = idaapi.node_info_t() 57 | ni.bg_color = 0x00ff00ff 58 | ni.frame_color = 0x0000ff00 59 | self.req_SetNodeInfo(0, ni, idaapi.NIF_BG_COLOR|idaapi.NIF_FRAME_COLOR) 60 | sleep(3) 61 | 62 | # This was fun. But let's revert it. 63 | self.req_DelNodesInfos(0) 64 | sleep(3) 65 | 66 | print "Done." 67 | 68 | class MyIDAViewWrapper(IDAViewWrapper): 69 | # A wrapper around the standard IDA view wrapper. 70 | # We'll react to some events and print the parameters 71 | # that were sent to us, that's all. 72 | def __init__(self, viewName): 73 | IDAViewWrapper.__init__(self, viewName) 74 | 75 | # Helper function, to be called by "On*" event handlers. 76 | # This will print all the arguments that were passed! 77 | def printPrevFrame(self): 78 | import inspect 79 | stack = inspect.stack() 80 | frame, _, _, _, _, _ = stack[1] 81 | args, _, _, values = inspect.getargvalues(frame) 82 | print "EVENT: %s: args=%s" % ( 83 | inspect.getframeinfo(frame)[2], 84 | [(i, values[i]) for i in args[1:]]) 85 | 86 | def OnViewKeydown(self, key, state): 87 | self.printPrevFrame() 88 | 89 | def OnViewClick(self, x, y, state): 90 | self.printPrevFrame() 91 | 92 | def OnViewDblclick(self, x, y, state): 93 | self.printPrevFrame() 94 | 95 | def OnViewSwitched(self, rt): 96 | self.printPrevFrame() 97 | 98 | def OnViewMouseOver(self, x, y, state, over_type, over_data): 99 | self.printPrevFrame() 100 | 101 | 102 | 103 | viewName = "IDA View-A" 104 | w = MyIDAViewWrapper(viewName) 105 | if w.Bind(): 106 | print "Succesfully bound to %s" % viewName 107 | 108 | # We'll launch the sequence of operations in another thread, 109 | # so that sleep() calls don't freeze the UI 110 | worker = Worker(w) 111 | worker.start() 112 | 113 | else: 114 | print "Couldn't bind to view %s. Is it available?" % viewName 115 | -------------------------------------------------------------------------------- /examples/ex_idphook_asm.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | import idautils 3 | 4 | """ 5 | This is a sample plugin for extending the assemble(). 6 | 7 | We add support for assembling the following pseudo instructions: 8 | - "zero eax" -> xor eax, eax 9 | - "nothing" -> nop 10 | 11 | 12 | (c) Hex-Rays 13 | """ 14 | 15 | #-------------------------------------------------------------------------- 16 | class assemble_idp_hook_t(idaapi.IDP_Hooks): 17 | def __init__(self): 18 | idaapi.IDP_Hooks.__init__(self) 19 | 20 | def assemble(self, ea, cs, ip, use32, line): 21 | line = line.strip() 22 | if line == "xor eax, eax": 23 | return "\x33\xC0" 24 | elif line == "nop": 25 | # Decode current instruction to figure out its size 26 | cmd = idautils.DecodeInstruction(ea) 27 | if cmd: 28 | # NOP all the instruction bytes 29 | return "\x90" * cmd.size 30 | return None 31 | 32 | 33 | #--------------------------------------------------------------------- 34 | # Remove an existing hook on second run 35 | try: 36 | idp_hook_stat = "un" 37 | print("IDP hook: checking for hook...") 38 | idphook 39 | print("IDP hook: unhooking....") 40 | idphook.unhook() 41 | del idphook 42 | except: 43 | print("IDP hook: not installed, installing now....") 44 | idp_hook_stat = "" 45 | idphook = assemble_idp_hook_t() 46 | idphook.hook() 47 | 48 | print("IDP hook %sinstalled. Run the script again to %sinstall" % (idp_hook_stat, idp_hook_stat)) 49 | -------------------------------------------------------------------------------- /examples/ex_imports.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This is an example illustrating how to enumerate imports 3 | # (c) Hex-Rays 4 | # 5 | import idaapi 6 | 7 | def imp_cb(ea, name, ord): 8 | if not name: 9 | print "%08x: ord#%d" % (ea, ord) 10 | else: 11 | print "%08x: %s (ord#%d)" % (ea, name, ord) 12 | # True -> Continue enumeration 13 | # False -> Stop enumeration 14 | return True 15 | 16 | nimps = idaapi.get_import_module_qty() 17 | 18 | print "Found %d import(s)..." % nimps 19 | 20 | for i in xrange(0, nimps): 21 | name = idaapi.get_import_module_name(i) 22 | if not name: 23 | print "Failed to get import module name for #%d" % i 24 | continue 25 | 26 | print "Walking-> %s" % name 27 | idaapi.enum_import_names(i, imp_cb) 28 | 29 | print "All done..." -------------------------------------------------------------------------------- /examples/ex_patch.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------- 2 | # This is an example illustrating how to visit all patched bytes in Python 3 | # (c) Hex-Rays 4 | 5 | import idaapi 6 | 7 | # ------------------------------------------------------------------------- 8 | class patched_bytes_visitor(object): 9 | def __init__(self): 10 | self.skip = 0 11 | self.patch = 0 12 | 13 | def __call__(self, ea, fpos, o, v, cnt=()): 14 | if fpos == -1: 15 | self.skip += 1 16 | print(" ea: %x o: %x v: %x...skipped" % (ea, fpos, o, v)) 17 | else: 18 | self.patch += 1 19 | print(" ea: %x fpos: %x o: %x v: %x" % (ea, fpos, o, v)) 20 | return 0 21 | 22 | 23 | # ------------------------------------------------------------------------- 24 | def main(): 25 | print("Visiting all patched bytes:") 26 | v = patched_bytes_visitor() 27 | r = idaapi.visit_patched_bytes(0, idaapi.BADADDR, v) 28 | if r != 0: 29 | print("visit_patched_bytes() returned %d" % r) 30 | else: 31 | print("Patched: %d Skipped: %d" % (v.patch, v.skip)) 32 | 33 | 34 | # ------------------------------------------------------------------------- 35 | if __name__ == '__main__': 36 | main() -------------------------------------------------------------------------------- /examples/ex_prefix_plugin.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | 3 | PREFIX = idaapi.SCOLOR_INV + ' ' + idaapi.SCOLOR_INV 4 | 5 | class prefix_plugin_t(idaapi.plugin_t): 6 | flags = 0 7 | comment = "This is a user defined prefix sample plugin" 8 | help = "This is help" 9 | wanted_name = "user defined prefix" 10 | wanted_hotkey = "" 11 | 12 | 13 | def user_prefix(self, ea, lnnum, indent, line, bufsize): 14 | #print("ea=%x lnnum=%d indent=%d line=%s bufsize=%d" % (ea, lnnum, indent, line, bufsize)) 15 | 16 | if (ea % 2 == 0) and indent == -1: 17 | return PREFIX 18 | else: 19 | return "" 20 | 21 | 22 | def init(self): 23 | self.prefix_installed = idaapi.set_user_defined_prefix(8, self.user_prefix) 24 | if self.prefix_installed: 25 | print("prefix installed") 26 | 27 | return idaapi.PLUGIN_KEEP 28 | 29 | 30 | def run(self, arg): 31 | pass 32 | 33 | 34 | def term(self): 35 | if self.prefix_installed: 36 | idaapi.set_user_defined_prefix(0, None) 37 | print("prefix uninstalled!") 38 | 39 | 40 | def PLUGIN_ENTRY(): 41 | return prefix_plugin_t() 42 | 43 | -------------------------------------------------------------------------------- /examples/ex_pyqt.py: -------------------------------------------------------------------------------- 1 | from idaapi import PluginForm 2 | from PyQt4 import QtCore, QtGui 3 | import sip 4 | 5 | class MyPluginFormClass(PluginForm): 6 | def OnCreate(self, form): 7 | """ 8 | Called when the plugin form is created 9 | """ 10 | 11 | # Get parent widget 12 | self.parent = self.FormToPyQtWidget(form) 13 | self.PopulateForm() 14 | 15 | 16 | def PopulateForm(self): 17 | # Create layout 18 | layout = QtGui.QVBoxLayout() 19 | 20 | layout.addWidget( 21 | QtGui.QLabel("Hello from PyQt")) 22 | layout.addWidget( 23 | QtGui.QLabel("Hello from IDAPython")) 24 | 25 | self.parent.setLayout(layout) 26 | 27 | 28 | def OnClose(self, form): 29 | """ 30 | Called when the plugin form is closed 31 | """ 32 | pass 33 | 34 | plg = MyPluginFormClass() 35 | plg.Show("PyQt hello world") 36 | -------------------------------------------------------------------------------- /examples/ex_pyside.py: -------------------------------------------------------------------------------- 1 | from idaapi import PluginForm 2 | from PySide import QtGui, QtCore 3 | 4 | class MyPluginFormClass(PluginForm): 5 | def OnCreate(self, form): 6 | """ 7 | Called when the plugin form is created 8 | """ 9 | 10 | # Get parent widget 11 | self.parent = self.FormToPySideWidget(form) 12 | self.PopulateForm() 13 | 14 | 15 | def PopulateForm(self): 16 | # Create layout 17 | layout = QtGui.QVBoxLayout() 18 | 19 | layout.addWidget( 20 | QtGui.QLabel("Hello from PySide")) 21 | layout.addWidget( 22 | QtGui.QLabel("Hello from IDAPython")) 23 | 24 | self.parent.setLayout(layout) 25 | 26 | 27 | def OnClose(self, form): 28 | """ 29 | Called when the plugin form is closed 30 | """ 31 | pass 32 | 33 | plg = MyPluginFormClass() 34 | plg.Show("PySide hello world") 35 | -------------------------------------------------------------------------------- /examples/ex_strings.py: -------------------------------------------------------------------------------- 1 | import idautils 2 | 3 | s = idautils.Strings(False) 4 | s.setup(strtypes=Strings.STR_UNICODE | Strings.STR_C) 5 | for i, v in enumerate(s): 6 | if v is None: 7 | print("Failed to retrieve string index %d" % i) 8 | else: 9 | print("%x: len=%d type=%d index=%d-> '%s'" % (v.ea, v.length, v.type, i, str(v))) 10 | -------------------------------------------------------------------------------- /examples/ex_timer.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------- 2 | # This is an example illustrating how to use timers 3 | # (c) Hex-Rays 4 | 5 | import idaapi 6 | 7 | # ------------------------------------------------------------------------- 8 | class timercallback_t(object): 9 | def __init__(self): 10 | self.interval = 1000 11 | self.obj = idaapi.register_timer(self.interval, self) 12 | if self.obj is None: 13 | raise RuntimeError, "Failed to register timer" 14 | self.times = 5 15 | 16 | def __call__(self): 17 | print("Timer invoked. %d time(s) left" % self.times) 18 | self.times -= 1 19 | # Unregister the timer when the counter reaches zero 20 | return -1 if self.times == 0 else self.interval 21 | 22 | def __del__(self): 23 | print("Timer object disposed %s" % id(self)) 24 | 25 | 26 | # ------------------------------------------------------------------------- 27 | def main(): 28 | try: 29 | t = timercallback_t() 30 | # No need to unregister the timer. 31 | # It will unregister itself in the callback when it returns -1 32 | except Exception as e: 33 | print "Error: %s" % e 34 | 35 | 36 | # ------------------------------------------------------------------------- 37 | if __name__ == '__main__': 38 | main() -------------------------------------------------------------------------------- /examples/ex_uihook.py: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # UI hook example 3 | # 4 | # (c) Hex-Rays 5 | # 6 | # Maintained By: IDAPython Team 7 | # 8 | #--------------------------------------------------------------------- 9 | 10 | import idaapi 11 | 12 | class MyUiHook(idaapi.UI_Hooks): 13 | def __init__(self): 14 | idaapi.UI_Hooks.__init__(self) 15 | self.cmdname = "" 16 | 17 | def preprocess(self, name): 18 | print("IDA preprocessing command: %s" % name) 19 | self.cmdname = name 20 | return 0 21 | 22 | def postprocess(self): 23 | print("IDA finished processing command: %s" % self.cmdname) 24 | return 0 25 | 26 | def saving(self): 27 | """ 28 | The kernel is saving the database. 29 | 30 | @return: Ignored 31 | """ 32 | print("Saving....") 33 | 34 | def saved(self): 35 | """ 36 | The kernel has saved the database. 37 | 38 | @return: Ignored 39 | """ 40 | print("Saved") 41 | 42 | def term(self): 43 | """ 44 | IDA is terminated and the database is already closed. 45 | The UI may close its windows in this callback. 46 | 47 | This callback is best used with a plugin_t with flags PLUGIN_FIX 48 | """ 49 | print("IDA terminated") 50 | 51 | def get_ea_hint(self, ea): 52 | """ 53 | The UI wants to display a simple hint for an address in the navigation band 54 | 55 | @param ea: The address 56 | @return: String with the hint or None 57 | """ 58 | print("get_ea_hint(%x)" % ea) 59 | 60 | 61 | #--------------------------------------------------------------------- 62 | # Remove an existing hook on second run 63 | try: 64 | ui_hook_stat = "un" 65 | print("UI hook: checking for hook...") 66 | uihook 67 | print("UI hook: unhooking....") 68 | uihook.unhook() 69 | del uihook 70 | except: 71 | print("UI hook: not installed, installing now....") 72 | ui_hook_stat = "" 73 | uihook = MyUiHook() 74 | uihook.hook() 75 | 76 | print("UI hook %sinstalled. Run the script again to %sinstall" % (ui_hook_stat, ui_hook_stat)) 77 | -------------------------------------------------------------------------------- /examples/ex_uirequests.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This is an example illustrating how to use the execute_ui_requests() 3 | # and the idautils.ProcessUiActions() 4 | # (c) Hex-Rays 5 | # 6 | import idaapi 7 | import idautils 8 | import idc 9 | 10 | # -------------------------------------------------------------------------- 11 | class __process_ui_actions_helper(object): 12 | def __init__(self, actions, flags = 0): 13 | """Expect a list or a string with a list of actions""" 14 | if isinstance(actions, str): 15 | lst = actions.split(";") 16 | elif isinstance(actions, (list, tuple)): 17 | lst = actions 18 | else: 19 | raise ValueError, "Must pass a string, list or a tuple" 20 | 21 | # Remember the action list and the flags 22 | self.__action_list = lst 23 | self.__flags = flags 24 | 25 | # Reset action index 26 | self.__idx = 0 27 | 28 | def __len__(self): 29 | return len(self.__action_list) 30 | 31 | def __call__(self): 32 | if self.__idx >= len(self.__action_list): 33 | return False 34 | 35 | # Execute one action 36 | idaapi.process_ui_action( 37 | self.__action_list[self.__idx], 38 | self.__flags) 39 | 40 | # Move to next action 41 | self.__idx += 1 42 | print "index=%d" % self.__idx 43 | 44 | # Reschedule 45 | return True 46 | 47 | # -------------------------------------------------------------------------- 48 | def ProcessUiActions(actions, flags=0): 49 | """ 50 | @param actions: A string containing a list of actions separated by semicolon, a list or a tuple 51 | @param flags: flags to be passed to process_ui_action() 52 | @return: Boolean. Returns False if the action list was empty or execute_ui_requests() failed. 53 | """ 54 | 55 | # Instantiate a helper 56 | helper = __process_ui_actions_helper(actions, flags) 57 | return False if len(helper) < 1 else idaapi.execute_ui_requests((helper,)) 58 | 59 | 60 | # -------------------------------------------------------------------------- 61 | class print_req_t(object): 62 | def __init__(self, s): 63 | self.s = s 64 | def __call__(self): 65 | idaapi.msg("%s" % self.s) 66 | return False # Don't reschedule 67 | 68 | 69 | 70 | if idc.AskYN(1,("HIDECANCEL\nDo you want to run execute_ui_requests() example?\n" 71 | "Press NO to execute ProcessUiActions() example\n")): 72 | idaapi.execute_ui_requests( 73 | (print_req_t("Hello"), print_req_t(" world\n")) ) 74 | else: 75 | ProcessUiActions("JumpQ;JumpName") 76 | -------------------------------------------------------------------------------- /examples/hotkey.py: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # This script demonstrates the usage of hotkeys. 3 | # 4 | # Note: Hotkeys only work with the GUI version of IDA and not in 5 | # text mode. 6 | # 7 | # Author: Gergely Erdelyi 8 | #--------------------------------------------------------------------- 9 | import idaapi 10 | 11 | def foo(): 12 | print "Hotkey activated!" 13 | 14 | # IDA binds hotkeys to IDC functions so a trampoline IDC function 15 | # must be created 16 | idaapi.CompileLine('static key_2() { RunPythonStatement("foo()"); }') 17 | # Add the hotkey 18 | AddHotkey("2", 'key_2') 19 | 20 | # Press 2 to activate foo() 21 | 22 | # The hotkey can be removed with 23 | # DelHotkey('2') 24 | 25 | -------------------------------------------------------------------------------- /examples/idapythonrc.py: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # Example user initialisation script: idapythonrc.py 3 | # 4 | # Place this script to ~/.idapro/ or to 5 | # %APPDATA%\Hex-Rays\IDA Pro 6 | #--------------------------------------------------------------------- 7 | import idaapi 8 | 9 | # Add your favourite script to ScriptBox for easy access 10 | # scriptbox.addscript("/here/is/my/favourite/script.py") 11 | 12 | # Uncomment if you want to set Python as default interpreter in IDA 13 | # idaapi.enable_extlang_python(True) 14 | 15 | # Disable the Python from interactive command-line 16 | # idaapi.enable_python_cli(False) 17 | 18 | # Set the timeout for the script execution cancel dialog 19 | # idaapi.set_script_timeout(10) 20 | -------------------------------------------------------------------------------- /examples/structure.py: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # Structure test 3 | # 4 | # This script demonstrates how to create structures and populate them 5 | # with members of different types. 6 | # 7 | # Author: Gergely Erdelyi 8 | #--------------------------------------------------------------------- 9 | from idaapi import stroffflag, offflag 10 | 11 | sid = GetStrucIdByName("mystr1") 12 | if sid != -1: 13 | DelStruc(sid) 14 | sid = AddStrucEx(-1, "mystr1", 0) 15 | print "%x" % sid 16 | 17 | # Test simple data types 18 | simple_types = [ FF_BYTE, FF_WORD, FF_DWRD, FF_QWRD, FF_TBYT, FF_OWRD, FF_FLOAT, FF_DOUBLE, FF_PACKREAL ] 19 | simple_sizes = [ 1, 2, 4, 8, 10, 16, 4, 8, 10 ] 20 | 21 | i = 0 22 | for t,nsize in zip(simple_types, simple_sizes): 23 | print "t%x:"% ((t|FF_DATA)&0xFFFFFFFF), AddStrucMember(sid, "t%02d"%i, BADADDR, (t|FF_DATA )&0xFFFFFFFF, -1, nsize) 24 | i+=1 25 | 26 | # Test ASCII type 27 | print "ASCII:", AddStrucMember(sid, "tascii", -1, FF_ASCI|FF_DATA, ASCSTR_C, 8) 28 | 29 | # Test enum type - Add a defined enum name or load MACRO_WMI from a type library. 30 | #eid = GetEnum("MACRO_WMI") 31 | #print "Enum:", AddStrucMember(sid, "tenum", BADADDR, FF_0ENUM|FF_DATA|FF_DWRD, eid, 4) 32 | 33 | # Test struc member type 34 | msid = GetStrucIdByName("mystr2") 35 | if msid != -1: 36 | DelStruc(msid) 37 | msid = AddStrucEx(-1, "mystr2", 0) 38 | print AddStrucMember(msid, "member1", -1, (FF_DWRD|FF_DATA )&0xFFFFFFFF, -1, 4) 39 | print AddStrucMember(msid, "member2", -1, (FF_DWRD|FF_DATA )&0xFFFFFFFF, -1, 4) 40 | 41 | msize = GetStrucSize(msid) 42 | print "Struct:", AddStrucMember(sid, "tstruct", -1, FF_STRU|FF_DATA, msid, msize) 43 | print "Stroff:", AddStrucMember(sid, "tstroff", -1, stroffflag()|FF_DWRD, msid, 4) 44 | 45 | # Test offset types 46 | print "Offset:", AddStrucMember(sid, "toffset", -1, offflag()|FF_DATA|FF_DWRD, 0, 4) 47 | print "Offset:", SetMemberType(sid, 0, offflag()|FF_DATA|FF_DWRD, 0, 4) 48 | 49 | print "Done" 50 | -------------------------------------------------------------------------------- /examples/vds1.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | 3 | def main(): 4 | if not idaapi.init_hexrays_plugin(): 5 | return False 6 | 7 | print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version() 8 | 9 | f = idaapi.get_func(idaapi.get_screen_ea()); 10 | if f is None: 11 | print "Please position the cursor within a function" 12 | return True 13 | 14 | cfunc = idaapi.decompile(f); 15 | if cfunc is None: 16 | print "Failed to decompile!" 17 | return True 18 | 19 | sv = cfunc.get_pseudocode(); 20 | for sline in sv: 21 | print idaapi.tag_remove(sline.line); 22 | 23 | return True 24 | 25 | if main(): 26 | idaapi.term_hexrays_plugin(); 27 | -------------------------------------------------------------------------------- /examples/vds4.py: -------------------------------------------------------------------------------- 1 | """ Print user-defined details to the output window. 2 | 3 | Author: EiNSTeiN_ 4 | 5 | This is a rewrite in Python of the vds4 example that comes with hexrays sdk. 6 | """ 7 | 8 | import idautils 9 | import idaapi 10 | import idc 11 | 12 | import traceback 13 | 14 | def run(): 15 | 16 | cfunc = idaapi.decompile(idaapi.get_screen_ea()) 17 | if not cfunc: 18 | print 'Please move the cursor into a function.' 19 | return 20 | 21 | entry_ea = cfunc.entry_ea 22 | print "Dump of user-defined information for function at %x" % (entry_ea, ) 23 | 24 | # Display user defined labels. 25 | labels = idaapi.restore_user_labels(entry_ea); 26 | if labels is not None: 27 | print "------- %u user defined labels" % (len(labels), ) 28 | for org_label, name in labels.iteritems(): 29 | print "Label %d: %s" % (org_label, str(name)) 30 | idaapi.user_labels_free(labels) 31 | 32 | # Display user defined comments 33 | cmts = idaapi.restore_user_cmts(entry_ea); 34 | if cmts is not None: 35 | print "------- %u user defined comments" % (len(cmts), ) 36 | for tl, cmt in cmts.iteritems(): 37 | print "Comment at %x, preciser %x:\n%s\n" % (tl.ea, tl.itp, str(cmt)) 38 | idaapi.user_cmts_free(cmts) 39 | 40 | # Display user defined citem iflags 41 | iflags = idaapi.restore_user_iflags(entry_ea) 42 | if iflags is not None: 43 | print "------- %u user defined citem iflags" % (len(iflags), ) 44 | for cl, t in iflags.iteritems(): 45 | print "%a(%d): %08X%s" % (cl.ea, cl.op, f, " CIT_COLLAPSED" if f & CIT_COLLAPSED else "") 46 | idaapi.user_iflags_free(iflags) 47 | 48 | # Display user defined number formats 49 | numforms = idaapi.restore_user_numforms(entry_ea) 50 | if numforms is not None: 51 | print "------- %u user defined number formats" % (len(numforms), ) 52 | for ol, nf in numforms.iteritems(): 53 | 54 | print "Number format at %a, operand %d: %s" % (ol.ea, ol.opnum, "negated " if (nf.props & NF_NEGATE) != 0 else "") 55 | 56 | if nf.isEnum(): 57 | print "enum %s (serial %d)" % (str(nf.type_name), nf.serial) 58 | 59 | elif nf.isChar(): 60 | print "char" 61 | 62 | elif nf.isStroff(): 63 | print "struct offset %s" % (str(nf.type_name), ) 64 | 65 | else: 66 | print "number base=%d" % (idaapi.getRadix(nf.flags, ol.opnum), ) 67 | 68 | idaapi.user_numforms_free(numforms) 69 | 70 | # Display user-defined local variable information 71 | # First defined the visitor class 72 | class dump_lvar_info_t(idaapi.user_lvar_visitor_t): 73 | 74 | def __init__(self): 75 | idaapi.user_lvar_visitor_t.__init__(self) 76 | self.displayed_header = False 77 | return 78 | 79 | def get_info_qty_for_saving(self): 80 | return 0 81 | 82 | def get_info_for_saving(self, lv): 83 | return False 84 | 85 | def handle_retrieved_info(self, lv): 86 | 87 | try: 88 | if not self.displayed_header: 89 | self.displayed_header = True; 90 | print "------- User defined local variable information" 91 | 92 | print "Lvar defined at %x" % (lv.ll.defea, ) 93 | 94 | if len(str(lv.name)): 95 | print " Name: %s" % (str(lv.name), ) 96 | 97 | if len(str(lv.type)): 98 | #~ print_type_to_one_line(buf, sizeof(buf), idati, .c_str()); 99 | print " Type: %s" % (str(lv.type), ) 100 | 101 | if len(str(lv.cmt)): 102 | print " Comment: %s" % (str(lv.cmt), ) 103 | except: 104 | traceback.print_exc() 105 | return 0 106 | 107 | def handle_retrieved_mapping(self, lm): 108 | return 0 109 | 110 | def get_info_mapping_for_saving(self): 111 | return None 112 | 113 | # Now iterate over all user definitions 114 | dli = dump_lvar_info_t(); 115 | idaapi.restore_user_lvar_settings(entry_ea, dli) 116 | 117 | return 118 | 119 | 120 | if idaapi.init_hexrays_plugin(): 121 | run() 122 | else: 123 | print 'dump user info: hexrays is not available.' 124 | -------------------------------------------------------------------------------- /examples/vds7.py: -------------------------------------------------------------------------------- 1 | """ It demonstrates how to iterate a cblock_t object. 2 | 3 | Author: EiNSTeiN_ 4 | 5 | This is a rewrite in Python of the vds7 example that comes with hexrays sdk. 6 | """ 7 | 8 | import idautils 9 | import idaapi 10 | import idc 11 | 12 | import traceback 13 | 14 | class cblock_visitor_t(idaapi.ctree_visitor_t): 15 | 16 | def __init__(self): 17 | idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST) 18 | return 19 | 20 | def visit_insn(self, ins): 21 | 22 | try: 23 | if ins.op == idaapi.cit_block: 24 | self.dump_block(ins.ea, ins.cblock) 25 | except: 26 | traceback.print_exc() 27 | 28 | return 0 29 | 30 | def dump_block(self, ea, b): 31 | # iterate over all block instructions 32 | print "dumping block %x" % (ea, ) 33 | for ins in b: 34 | print " %x: insn %s" % (ins.ea, ins.opname) 35 | 36 | return 37 | 38 | class hexrays_callback_info(object): 39 | 40 | def __init__(self): 41 | return 42 | 43 | def event_callback(self, event, *args): 44 | 45 | try: 46 | if event == idaapi.hxe_maturity: 47 | cfunc, maturity = args 48 | 49 | if maturity == idaapi.CMAT_BUILT: 50 | cbv = cblock_visitor_t() 51 | cbv.apply_to(cfunc.body, None) 52 | 53 | except: 54 | traceback.print_exc() 55 | 56 | return 0 57 | 58 | if idaapi.init_hexrays_plugin(): 59 | i = hexrays_callback_info() 60 | idaapi.install_hexrays_callback(i.event_callback) 61 | else: 62 | print 'cblock visitor: hexrays is not available.' 63 | -------------------------------------------------------------------------------- /hrdoc.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import shutil 4 | from glob import glob 5 | 6 | # -------------------------------------------------------------------------- 7 | DOC_DIR = 'hr-html' 8 | PYWRAPS_FN = 'idaapi.py' 9 | 10 | # -------------------------------------------------------------------------- 11 | def add_footer(lines): 12 | S1 = 'Generated by Epydoc' 13 | S2 = '' 14 | p = lines.find(S1) 15 | 16 | if p == -1: 17 | return None 18 | 19 | p = lines.find(S2, p) 20 | if p == -1: 21 | return None 22 | 23 | p += len(S2) 24 | 25 | return lines[0:p] + '\n' + lines[p:] 26 | 27 | # -------------------------------------------------------------------------- 28 | def define_idaapi_resolver(): 29 | """ 30 | Whenever a module named \"idaapi_\" is 31 | spotted, turn it into \"idaapi\". 32 | """ 33 | import epydoc.apidoc 34 | dn = epydoc.apidoc.DottedName.__init__ 35 | def resolver(piece): 36 | if piece is not None and isinstance(piece, basestring) and piece.startswith("idaapi_"): 37 | return "idaapi" 38 | else: 39 | return piece 40 | def wrapper(self, *pieces, **options): 41 | return dn(self, *map(resolver, pieces), **options); 42 | epydoc.apidoc.DottedName.__init__ = wrapper 43 | 44 | # -------------------------------------------------------------------------- 45 | def gen_docs(): 46 | import epydoc.cli 47 | import swigdocs 48 | 49 | define_idaapi_resolver() 50 | 51 | swigdocs.gen_docs(outfn = 'pywraps.py') 52 | # append obj/x86_win_vc_32/idaapi.py to it 53 | # os.system(r'copy /b idaapi.py+..\obj\x86_win_vc_32\idaapi.py idaapi.py') 54 | 55 | # delete all output files 56 | for fn in glob('hr-html/*'): 57 | os.unlink(fn) 58 | 59 | epydoc.cli.optparse.sys.argv = [ 'epydoc', 60 | '--config', '../hrdoc.cfg', 61 | '--simple-term' 62 | ] 63 | 64 | # Generate the documentation 65 | epydoc.cli.cli() 66 | 67 | # -------------------------------------------------------------------------- 68 | def patch_docs(): 69 | shutil.copy('../../hrdoc.css', 'epydoc.css') 70 | os.system('chmod +w epydoc.css') 71 | 72 | for fn in glob('*.html'): 73 | f = open(fn, 'r') 74 | lines = f.read() 75 | f.close() 76 | 77 | r = add_footer(lines) 78 | if not r: 79 | print "-", 80 | continue 81 | 82 | f = open(fn, 'w') 83 | f.write(r) 84 | f.close() 85 | print "+", 86 | 87 | print "\nDocumentation patched!" 88 | 89 | # -------------------------------------------------------------------------- 90 | def main(): 91 | # Save old directory and adjust import path 92 | curdir = os.getcwd() + os.sep 93 | sys.path.append(curdir + 'python') 94 | sys.path.append(curdir + 'tools') 95 | sys.path.append(curdir + 'docs') 96 | 97 | old_dir = os.getcwd() 98 | 99 | try: 100 | print "Generating documentation....." 101 | 102 | os.chdir('docs') 103 | gen_docs() 104 | 105 | os.chdir(DOC_DIR) 106 | patch_docs() 107 | 108 | print "Documentation generated!" 109 | 110 | finally: 111 | os.chdir(old_dir) 112 | 113 | # -------------------------------------------------------------------------- 114 | if __name__ == '__main__': 115 | main() 116 | Exit(0) 117 | -------------------------------------------------------------------------------- /idaapi.i: -------------------------------------------------------------------------------- 1 | // We need this file just to avoid a warning from swig that the input file is not 2 | // specifed precisely and swig had to find it using the header path. 3 | 4 | %include "swig/idaapi.i" -------------------------------------------------------------------------------- /idapython.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "idapython", "idapython.vcxproj", "{F43D6BB8-B7D6-486A-82E5-BABBA9848525}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Debug64|Win32 = Debug64|Win32 10 | Release|Win32 = Release|Win32 11 | SemiDebug|Win32 = SemiDebug|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug|Win32.Build.0 = Debug|Win32 16 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug64|Win32.ActiveCfg = Debug64|Win32 17 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug64|Win32.Build.0 = Debug64|Win32 18 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release|Win32.ActiveCfg = Release|Win32 19 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release|Win32.Build.0 = Release|Win32 20 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebug|Win32.ActiveCfg = SemiDebug|Win32 21 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebug|Win32.Build.0 = SemiDebug|Win32 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /patch_directors_cc.py: -------------------------------------------------------------------------------- 1 | 2 | import os, shutil, sys, optparse 3 | 4 | if __name__ == "__main__": 5 | 6 | p = optparse.OptionParser(description='Patch calling conventions for some functions, so it builds on windows') 7 | p.add_option('-v', "--verbose", dest="verbose", action="store_true") 8 | p.add_option('-f', "--file", dest="path", type="string", help="File name, without extension.") 9 | opts, _ = p.parse_args(sys.argv[1:]) 10 | 11 | if not opts.path: 12 | p.print_help() 13 | sys.exit(1) 14 | 15 | patches = [ 16 | # user_lvar_visitor_t 17 | "virtual int idaapi handle_retrieved_info", 18 | "virtual int idaapi handle_retrieved_mapping", 19 | "virtual int idaapi get_info_qty_for_saving", 20 | "virtual bool idaapi get_info_for_saving", 21 | "virtual lvar_mapping_t const *idaapi get_info_mapping_for_saving", 22 | 23 | # ctree_visitor_t 24 | "virtual int idaapi visit_insn", 25 | "virtual int idaapi visit_expr", 26 | "virtual int idaapi leave_insn", 27 | "virtual int idaapi leave_expr", 28 | 29 | # ctree_parentee_t 30 | "virtual int idaapi visit_insn", 31 | "virtual int idaapi visit_expr", 32 | "virtual int idaapi leave_insn", 33 | "virtual int idaapi leave_expr", 34 | 35 | # cfunc_parentee_t 36 | "virtual int idaapi visit_insn", 37 | "virtual int idaapi visit_expr", 38 | "virtual int idaapi leave_insn", 39 | "virtual int idaapi leave_expr", 40 | ] 41 | 42 | path = opts.path 43 | outlines = [] 44 | outpath = "%s.cc" % path 45 | with open(path, "r") as f: 46 | lines = f.readlines() 47 | for line in lines: 48 | for patch in patches: 49 | from_text = patch.replace("idaapi ", "") 50 | if line.find(from_text) > -1: 51 | line = line.replace(from_text, patch) 52 | patches.remove(patch) 53 | break 54 | outlines.append(line) 55 | with open(outpath, "w") as f: 56 | f.writelines(outlines) 57 | shutil.move(outpath, path) 58 | -------------------------------------------------------------------------------- /python.cfg: -------------------------------------------------------------------------------- 1 | // Alert before loading automatic scripts found in current directory 2 | // swig_runtime_dataN, sitecustomize and usercustomize 3 | ALERT_AUTO_SCRIPTS = 1 4 | 5 | // Remove current directory from import search path 6 | REMOVE_CWD_SYS_PATH = 1 7 | 8 | // Script timeout (in seconds) 9 | // (A value of 0 disables the timeout) 10 | SCRIPT_TIMEOUT = 3 11 | 12 | // Use a local Python library 13 | // If enabled, the "lib" directory tree with modules must be present in IDADIR/python 14 | USE_LOCAL_PYTHON = 0 15 | -------------------------------------------------------------------------------- /python/init.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ----------------------------------------------------------------------- 3 | # IDAPython - Python plugin for Interactive Disassembler 4 | # 5 | # Copyright (c) The IDAPython Team 6 | # 7 | # All rights reserved. 8 | # 9 | # For detailed copyright information see the file COPYING in 10 | # the root of the distribution archive. 11 | # ----------------------------------------------------------------------- 12 | # init.py - Essential init routines 13 | # ----------------------------------------------------------------------- 14 | import os 15 | import sys 16 | import time 17 | import warnings 18 | import _idaapi 19 | 20 | # __EA64__ is set if IDA is running in 64-bit mode 21 | __EA64__ = _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL 22 | 23 | # ----------------------------------------------------------------------- 24 | # Take over the standard text outputs 25 | # ----------------------------------------------------------------------- 26 | class IDAPythonStdOut: 27 | """ 28 | Dummy file-like class that receives stout and stderr 29 | """ 30 | def write(self, text): 31 | # NB: in case 'text' is Unicode, msg() will decode it 32 | # and call umsg() to print it 33 | _idaapi.msg(text) 34 | 35 | def flush(self): 36 | pass 37 | 38 | def isatty(self): 39 | return False 40 | 41 | # ----------------------------------------------------------------------- 42 | def runscript(script): 43 | """ 44 | Executes a script. 45 | This function is present for backward compatiblity. Please use idaapi.IDAPython_ExecScript() instead 46 | 47 | @param script: script path 48 | 49 | @return: Error string or None on success 50 | """ 51 | 52 | import idaapi 53 | return idaapi.IDAPython_ExecScript(script, globals()) 54 | 55 | # ----------------------------------------------------------------------- 56 | def print_banner(): 57 | banner = [ 58 | "Python %s " % sys.version, 59 | "IDAPython" + (" 64-bit" if __EA64__ else "") + " v%d.%d.%d %s (serial %d) (c) The IDAPython Team " % IDAPYTHON_VERSION 60 | ] 61 | sepline = '-' * (max([len(s) for s in banner])+1) 62 | 63 | print(sepline) 64 | print("\n".join(banner)) 65 | print(sepline) 66 | 67 | # ----------------------------------------------------------------------- 68 | 69 | # Redirect stderr and stdout to the IDA message window 70 | _orig_stdout = sys.stdout; 71 | _orig_stderr = sys.stderr; 72 | sys.stdout = sys.stderr = IDAPythonStdOut() 73 | 74 | # ----------------------------------------------------------------------- 75 | # Initialize the help, with our own stdin wrapper, that'll query the user 76 | # ----------------------------------------------------------------------- 77 | import pydoc 78 | class IDAPythonHelpPrompter: 79 | def readline(self): 80 | return idaapi.askstr(0, '', 'Help topic?') 81 | help = pydoc.Helper(input = IDAPythonHelpPrompter(), output = sys.stdout) 82 | 83 | # Assign a default sys.argv 84 | sys.argv = [""] 85 | 86 | # Have to make sure Python finds our modules 87 | sys.path.append(_idaapi.idadir("python")) 88 | 89 | # Remove current directory from the top of the patch search 90 | if '' in sys.path: # On non Windows, the empty path is added 91 | sys.path.remove('') 92 | 93 | if os.getcwd() in sys.path: 94 | sys.path.remove(os.getcwd()) 95 | 96 | # ...and add it to the end if needed 97 | if not IDAPYTHON_REMOVE_CWD_SYS_PATH: 98 | sys.path.append(os.getcwd()) 99 | 100 | # Import all the required modules 101 | from idaapi import Choose, get_user_idadir, cvar, Choose2, Appcall, Form 102 | from idc import * 103 | from idautils import * 104 | import idaapi 105 | 106 | # Load the users personal init file 107 | userrc = os.path.join(get_user_idadir(), "idapythonrc.py") 108 | if os.path.exists(userrc): 109 | idaapi.IDAPython_ExecScript(userrc, globals()) 110 | 111 | # All done, ready to rock. -------------------------------------------------------------------------------- /pywraps/deploy.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | deploy_all.py 3 | -------------------------------------------------------------------------------- /pywraps/deploy.py: -------------------------------------------------------------------------------- 1 | """ 2 | Deploy code snips into swig interface files 3 | 4 | (c) Hex-Rays 5 | """ 6 | 7 | import sys 8 | import re 9 | import os 10 | 11 | # creates a regular expression 12 | def make_re(tag, mod_name, prefix): 13 | s = '%(p)s<%(tag)s\(%(m)s\)>(.+?)%(p)s' % {'m': mod_name, 'tag': tag, 'p': prefix} 14 | return (s, re.compile(s, re.DOTALL)) 15 | 16 | def convert_path(path_in): 17 | parts = path_in.split('/') 18 | return os.sep.join(parts) 19 | 20 | def deploy(mod_name, src_files, dest_file, silent = True): 21 | dest_file = convert_path(dest_file) 22 | src_files = map(convert_path, src_files) 23 | # create regular expressions 24 | templates = ( 25 | ('pycode', make_re('pycode', mod_name, '#')), 26 | ('code', make_re('code', mod_name, '//')), 27 | ('inline', make_re('inline', mod_name, '//')) 28 | ) 29 | 30 | if not os.path.exists(dest_file): 31 | print "File", dest_file, "does not exist and will be skipped" 32 | return 33 | 34 | if not os.access(dest_file, os.W_OK): 35 | print "File", dest_file, "is not writable and will be skipped" 36 | return 37 | 38 | # read dest file 39 | dest_lines = "".join(file(dest_file, "r").readlines()) 40 | 41 | # read all source files into one buffer 42 | src_lines = "".join(["".join(file(x, "r").readlines()) for x in src_files]) 43 | 44 | pcount = 0 45 | for desc, (expr_str, expr) in templates: 46 | # find source pattern 47 | matches = expr.findall(src_lines) 48 | if not matches: 49 | if not silent: 50 | print "Failed to match <%s> source expression against '%s', skipping...!" % (desc, expr_str) 51 | continue 52 | 53 | # find pattern in destination 54 | dest = expr.search(dest_lines) 55 | if not dest: 56 | if not silent: 57 | print "Failed to match <%s> destination expression against '%s', skipping..." % (desc, expr_str) 58 | print dest_lines 59 | sys.exit(0) 60 | continue 61 | 62 | # accumulate all the strings to be replaced 63 | replaces = [] 64 | for src in matches: 65 | replaces.append(src) 66 | 67 | dest_lines = dest_lines[:dest.start(1)] + "\n".join(replaces) + dest_lines[dest.end(1):] 68 | pcount += 1 69 | 70 | 71 | f = file(dest_file, 'w') 72 | if not f: 73 | print "Failed to open destination file:", dest_file 74 | return 75 | f.write(dest_lines) 76 | f.close() 77 | 78 | if pcount: 79 | print "Deployed successfully: %s (%d)" % (dest_file, pcount) 80 | else: 81 | print "Nothing was deployed in: %s" % dest_file 82 | 83 | 84 | def main(argv = None): 85 | if not argv: 86 | argv = sys.argv 87 | if len(argv) != 4: 88 | print "Usage deploy.py modname src_file1,src_file2,... dest_file" 89 | return 90 | 91 | mod_name = argv[1] 92 | src_files = argv[2].split(',') 93 | dest_file = argv[3] 94 | deploy(mod_name, src_files, dest_file) 95 | 96 | #main(['', 'py_graph', 'py_graph.hpp,py_graph.py', 'graph.i']) 97 | if __name__ == '__main__': 98 | main() 99 | -------------------------------------------------------------------------------- /pywraps/driver_bytes.cpp: -------------------------------------------------------------------------------- 1 | #include "py_bytes.hpp" 2 | 3 | //-------------------------------------------------------------------------- 4 | static PyObject *ex_nextthat(PyObject *self, PyObject *args) 5 | { 6 | PyObject *callback; 7 | pyul_t addr, bound; 8 | if ( !PyArg_ParseTuple(args, PY_FMT64 PY_FMT64 "O", &addr, &bound, &callback) ) 9 | return NULL; 10 | return Py_BuildValue("i", py_nextthat(pyul_t(addr), pyul_t(bound), callback)); 11 | } 12 | 13 | //-------------------------------------------------------------------------- 14 | static PyMethodDef py_methods_bytes[] = 15 | { 16 | {"nextthat", ex_nextthat, METH_VARARGS, ""}, 17 | {NULL, NULL, 0, NULL} 18 | }; 19 | DRIVER_INIT_METHODS(bytes); -------------------------------------------------------------------------------- /pywraps/driver_chooser.cpp: -------------------------------------------------------------------------------- 1 | #include "py_choose2.hpp" 2 | 3 | //------------------------------------------------------------------------- 4 | static PyObject *ex_choose2_find(PyObject *self, PyObject *args) 5 | { 6 | char *title; 7 | if ( !PyArg_ParseTuple(args, "s", &title) ) 8 | return NULL; 9 | else 10 | return choose2_find(title); 11 | } 12 | 13 | //------------------------------------------------------------------------- 14 | static PyObject *ex_choose2_create(PyObject *self, PyObject *args) 15 | { 16 | PyObject *obj; 17 | int embedded; 18 | if ( !PyArg_ParseTuple(args, "Oi", &obj, &embedded) ) 19 | return NULL; 20 | else 21 | return PyInt_FromLong(choose2_create(obj, embedded == 1 ? true : false)); 22 | } 23 | 24 | //------------------------------------------------------------------------- 25 | static PyObject *ex_choose2_activate(PyObject *self, PyObject *args) 26 | { 27 | PyObject *obj; 28 | if ( !PyArg_ParseTuple(args, "O", &obj) ) 29 | return NULL; 30 | 31 | choose2_activate(obj); 32 | Py_RETURN_NONE; 33 | } 34 | 35 | //------------------------------------------------------------------------- 36 | static PyObject *ex_choose2_close(PyObject *self, PyObject *args) 37 | { 38 | PyObject *obj; 39 | if ( !PyArg_ParseTuple(args, "O", &obj) ) 40 | return NULL; 41 | 42 | choose2_close(obj); 43 | Py_RETURN_NONE; 44 | } 45 | 46 | //------------------------------------------------------------------------- 47 | static PyObject *ex_choose2_refresh(PyObject *self, PyObject *args) 48 | { 49 | PyObject *obj; 50 | if ( !PyArg_ParseTuple(args, "O", &obj) ) 51 | return NULL; 52 | 53 | choose2_refresh(obj); 54 | Py_RETURN_NONE; 55 | } 56 | 57 | //------------------------------------------------------------------------- 58 | static PyObject *ex_choose2_add_command(PyObject *self, PyObject *args) 59 | { 60 | PyObject *obj; 61 | char *caption; 62 | int flags, menu_index, icon; 63 | if ( !PyArg_ParseTuple(args, "Osiii", &obj, &caption, &flags, &menu_index, &icon) ) 64 | return NULL; 65 | else 66 | return PyInt_FromLong(choose2_add_command(obj, caption, flags, menu_index, icon)); 67 | } 68 | 69 | //------------------------------------------------------------------------- 70 | static PyObject *ex_choose2_get_test_embedded(PyObject *self, PyObject *args) 71 | { 72 | return PyLong_FromSize_t(choose2_get_test_embedded()); 73 | } 74 | 75 | //------------------------------------------------------------------------- 76 | static PyObject *ex_choose2_get_embedded(PyObject *self, PyObject *args) 77 | { 78 | PyObject *obj; 79 | if ( !PyArg_ParseTuple(args, "O", &obj) ) 80 | return NULL; 81 | else 82 | return choose2_get_embedded(obj); 83 | } 84 | 85 | //------------------------------------------------------------------------- 86 | static PyObject *ex_choose2_get_embedded_selection(PyObject *self, PyObject *args) 87 | { 88 | PyObject *obj; 89 | if ( !PyArg_ParseTuple(args, "O", &obj) ) 90 | return NULL; 91 | else 92 | return choose2_get_embedded_selection(obj); 93 | } 94 | 95 | //------------------------------------------------------------------------- 96 | static PyMethodDef py_methods_chooser[] = 97 | { 98 | {"py_choose2_find", ex_choose2_find, METH_VARARGS, ""}, 99 | {"py_choose2_create", ex_choose2_create, METH_VARARGS, ""}, 100 | {"py_choose2_close", ex_choose2_close, METH_VARARGS, ""}, 101 | {"py_choose2_activate", ex_choose2_activate, METH_VARARGS, ""}, 102 | {"py_choose2_refresh", ex_choose2_refresh, METH_VARARGS, ""}, 103 | {"py_choose2_add_command", ex_choose2_add_command, METH_VARARGS, ""}, 104 | {"py_choose2_get_test_embedded", ex_choose2_get_test_embedded, METH_VARARGS, ""}, 105 | {"py_choose2_get_embedded", ex_choose2_get_embedded, METH_VARARGS, ""}, 106 | {"py_choose2_get_embedded_selection", ex_choose2_get_embedded_selection, METH_VARARGS, ""}, 107 | {NULL, NULL, 0, NULL} // End of methods 108 | }; 109 | DRIVER_INIT_METHODS(chooser); 110 | -------------------------------------------------------------------------------- /pywraps/driver_cli.cpp: -------------------------------------------------------------------------------- 1 | #include "py_custview.hpp" 2 | 3 | //------------------------------------------------------------------------- 4 | static PyObject *ex_install_command_interpreter(PyObject *self, PyObject *args) 5 | { 6 | PyObject *py_obj; 7 | if ( !PyArg_ParseTuple(args, "O", &py_obj) ) 8 | return NULL; 9 | return PyInt_FromLong(py_install_command_interpreter(py_obj)); 10 | } 11 | 12 | //------------------------------------------------------------------------- 13 | static PyObject *ex_remove_command_interpreter(PyObject *self, PyObject *args) 14 | { 15 | int cli_idx; 16 | if ( !PyArg_ParseTuple(args, "i", &cli_idx) ) 17 | return NULL; 18 | py_remove_command_interpreter(cli_idx); 19 | Py_RETURN_NONE; 20 | } 21 | 22 | //------------------------------------------------------------------------- 23 | static PyMethodDef py_methods_cli[] = 24 | { 25 | {"install_command_interpreter", ex_install_command_interpreter, METH_VARARGS, ""}, 26 | {"remove_command_interpreter", ex_remove_command_interpreter, METH_VARARGS, ""}, 27 | {NULL, NULL, 0, NULL} 28 | }; 29 | DRIVER_INIT_METHODS(cli); -------------------------------------------------------------------------------- /pywraps/driver_custdata.cpp: -------------------------------------------------------------------------------- 1 | #include "py_custdata.hpp" 2 | 3 | //------------------------------------------------------------------------- 4 | static PyObject *ex_register_custom_data_type(PyObject *self, PyObject *args) 5 | { 6 | PyObject *py_dt; 7 | if ( !PyArg_ParseTuple(args, "O", &py_dt) ) 8 | return NULL; 9 | return Py_BuildValue("i", py_register_custom_data_type(py_dt)); 10 | } 11 | 12 | //------------------------------------------------------------------------- 13 | static PyObject *ex_unregister_custom_data_type(PyObject *self, PyObject *args) 14 | { 15 | int dtid; 16 | if ( !PyArg_ParseTuple(args, "i", &dtid) ) 17 | return NULL; 18 | return Py_BuildValue("i", py_unregister_custom_data_type(dtid)); 19 | } 20 | 21 | //------------------------------------------------------------------------- 22 | static PyObject *ex_unregister_custom_data_format(PyObject *self, PyObject *args) 23 | { 24 | int dtid, dfid; 25 | if ( !PyArg_ParseTuple(args, "ii", &dtid, &dfid) ) 26 | return NULL; 27 | return Py_BuildValue("i", py_unregister_custom_data_format(dtid, dfid)); 28 | } 29 | 30 | //------------------------------------------------------------------------- 31 | static PyObject *ex_register_custom_data_format(PyObject *self, PyObject *args) 32 | { 33 | int dtid; 34 | PyObject *py_df; 35 | if ( !PyArg_ParseTuple(args, "iO", &dtid, &py_df) ) 36 | return NULL; 37 | return Py_BuildValue("i", py_register_custom_data_format(dtid, py_df)); 38 | } 39 | 40 | //------------------------------------------------------------------------- 41 | static PyObject *ex_get_custom_data_format(PyObject *self, PyObject *args) 42 | { 43 | int dtid, dfid; 44 | if ( !PyArg_ParseTuple(args, "ii", &dtid, &dfid) ) 45 | return NULL; 46 | return py_get_custom_data_format(dtid, dfid); 47 | } 48 | 49 | //------------------------------------------------------------------------- 50 | static PyObject *ex_get_custom_data_type(PyObject *self, PyObject *args) 51 | { 52 | int dtid; 53 | if ( !PyArg_ParseTuple(args, "i", &dtid) ) 54 | return NULL; 55 | return py_get_custom_data_type(dtid); 56 | } 57 | 58 | //------------------------------------------------------------------------- 59 | static PyMethodDef py_methods_custdata[] = 60 | { 61 | {"unregister_custom_data_format", ex_unregister_custom_data_format, METH_VARARGS, ""}, 62 | {"register_custom_data_format", ex_register_custom_data_format, METH_VARARGS, ""}, 63 | {"unregister_custom_data_type", ex_unregister_custom_data_type, METH_VARARGS, ""}, 64 | {"register_custom_data_type", ex_register_custom_data_type, METH_VARARGS, ""}, 65 | {"get_custom_data_format", ex_get_custom_data_format, METH_VARARGS, ""}, 66 | {"get_custom_data_type", ex_get_custom_data_type, METH_VARARGS, ""}, 67 | {NULL, NULL, 0, NULL} /* Sentinel */ 68 | }; 69 | //--------------------------------------------------------------------------- 70 | class init_custdata_driver_t 71 | { 72 | public: 73 | init_custdata_driver_t() 74 | { 75 | driver_add_methods(py_methods_custdata); 76 | } 77 | } init_custdata_driver; 78 | -------------------------------------------------------------------------------- /pywraps/driver_dbg.cpp: -------------------------------------------------------------------------------- 1 | #include "py_dbg.hpp" 2 | 3 | //------------------------------------------------------------------------- 4 | static PyObject *ex_getthreadsregbase(PyObject * /*self*/, PyObject *args) 5 | { 6 | PyObject *py_tid, *py_sreg_value; 7 | if ( !PyArg_ParseTuple(args, "OO", &py_tid, &py_sreg_value) ) 8 | return NULL; 9 | return dbg_get_thread_sreg_base(py_tid, py_sreg_value); 10 | } 11 | 12 | //------------------------------------------------------------------------- 13 | static PyObject *ex_readmemory(PyObject * /*self*/, PyObject *args) 14 | { 15 | PyObject *py_ea, *py_size; 16 | if ( !PyArg_ParseTuple(args, "OO", &py_ea, &py_size) ) 17 | return NULL; 18 | return dbg_read_memory(py_ea, py_size); 19 | } 20 | 21 | //------------------------------------------------------------------------- 22 | static PyObject *ex_writememory(PyObject * /*self*/, PyObject *args) 23 | { 24 | PyObject *py_ea, *py_buf; 25 | if ( !PyArg_ParseTuple(args, "OO", &py_ea, &py_buf) ) 26 | return NULL; 27 | return dbg_write_memory(py_ea, py_buf); 28 | } 29 | 30 | //------------------------------------------------------------------------- 31 | static PyObject *ex_getmeminfo(PyObject * /*self*/, PyObject *args) 32 | { 33 | return dbg_get_memory_info(); 34 | } 35 | 36 | //------------------------------------------------------------------------- 37 | static PyObject *ex_getregs(PyObject *self, PyObject *args) 38 | { 39 | return dbg_get_registers(); 40 | } 41 | 42 | //------------------------------------------------------------------------- 43 | static PyObject *ex_appcall(PyObject * /*self*/, PyObject *args) 44 | { 45 | PyObject *app_args, *type, *fields; 46 | int func_ea, tid; 47 | if ( !PyArg_ParseTuple(args, "iiOOO", &func_ea, &tid, &type, &fields, &app_args) ) 48 | return NULL; 49 | return py_appcall(func_ea, tid, type, fields, app_args); 50 | } 51 | 52 | //------------------------------------------------------------------------- 53 | static PyObject *ex_pytoidc( 54 | PyObject *self, 55 | PyObject *args) 56 | { 57 | if ( !PyArg_ParseTuple(args, "O", &self) ) 58 | return NULL; 59 | idc_value_t v; 60 | int sn = 0; 61 | borref_t self_ref(self); 62 | if ( pyvar_to_idcvar(self_ref, &v, &sn) < CIP_OK ) 63 | Py_RETURN_NONE; 64 | Py_RETURN_TRUE; 65 | } 66 | 67 | //------------------------------------------------------------------------- 68 | static PyMethodDef py_methods_dbg[] = 69 | { 70 | {"getregs", ex_getregs, METH_VARARGS, ""}, 71 | {"getmeminfo", ex_getmeminfo, METH_VARARGS, ""}, 72 | {"readmemory", ex_readmemory, METH_VARARGS, ""}, 73 | {"writememory", ex_writememory, METH_VARARGS, ""}, 74 | {"getthreadsregbase", ex_getthreadsregbase, METH_VARARGS, ""}, 75 | {"appcall", ex_appcall, METH_VARARGS, ""}, 76 | {"pytoidc", ex_pytoidc, METH_VARARGS, ""}, 77 | {NULL, NULL, 0, NULL} /* Sentinel */ 78 | }; 79 | DRIVER_INIT_METHODS(dbg); 80 | -------------------------------------------------------------------------------- /pywraps/driver_diskio.cpp: -------------------------------------------------------------------------------- 1 | #include "py_diskio.hpp" 2 | 3 | static PyObject *ex_enumfiles(PyObject * /*self*/, PyObject *args) 4 | { 5 | PyObject *path, *fname, *callback; 6 | if ( !PyArg_ParseTuple(args, "OOO", &path, &fname, &callback) ) 7 | return NULL; 8 | return py_enumerate_files(path, fname, callback); 9 | } 10 | 11 | // 12 | //static PyObject *ex_linput_close(PyObject * /*self*/, PyObject *args) 13 | //{ 14 | // PyObject *obj; 15 | // if ( !PyArg_ParseTuple(args, "O", &obj) ) 16 | // return NULL; 17 | // pyl_close(obj); 18 | // Py_RETURN_NONE; 19 | //} 20 | // 21 | //static PyObject *ex_linput_open(PyObject *self, PyObject *args) 22 | //{ 23 | // PyObject *obj, *py_filename, *py_remote; 24 | // if ( !PyArg_ParseTuple(args, "OOO", &obj, &py_filename, &py_remote) ) 25 | // return NULL; 26 | // return pyl_open(obj, py_filename, py_remote); 27 | //} 28 | // 29 | //static PyObject *ex_linput_read(PyObject *self, PyObject *args) 30 | //{ 31 | // PyObject *obj, *py_size; 32 | // if ( !PyArg_ParseTuple(args, "OO", &obj, &py_size) ) 33 | // return NULL; 34 | // return pyl_read(obj, py_size); 35 | //} 36 | 37 | static PyMethodDef py_methods_diskio[] = 38 | { 39 | {"enumfiles", ex_enumfiles, METH_VARARGS, ""}, 40 | //{"tell", ex_linput_tell, METH_VARARGS, ""}, 41 | //{"open", ex_linput_open, METH_VARARGS, ""}, 42 | //{"size", ex_linput_tell, METH_VARARGS, ""}, 43 | //{"read", ex_linput_read, METH_VARARGS, ""}, 44 | //{"close", ex_linput_close, METH_VARARGS, ""}, 45 | {NULL, NULL, 0, NULL} /* Sentinel */ 46 | }; 47 | DRIVER_INIT_METHODS(diskio); -------------------------------------------------------------------------------- /pywraps/driver_expr.cpp: -------------------------------------------------------------------------------- 1 | #include "py_expr.hpp" 2 | 3 | #pragma warning(push) 4 | #pragma warning(disable: 4244) 5 | 6 | //--------------------------------------------------------------------------- 7 | static PyObject *ex_pyw_register_idc_func(PyObject *self, PyObject *args) 8 | { 9 | char *name, *arg; 10 | PyObject *py_fp; 11 | if ( !PyArg_ParseTuple(args, "ssO", &name, &arg, &py_fp) ) 12 | return NULL; 13 | else 14 | return PyLong_FromUnsignedLongLong(pyw_register_idc_func(name, arg, py_fp)); 15 | } 16 | 17 | //--------------------------------------------------------------------------- 18 | static PyObject *ex_pyw_unregister_idc_func(PyObject *self, PyObject *args) 19 | { 20 | unsigned PY_LONG_LONG ctxptr; 21 | if ( !PyArg_ParseTuple(args, "K", &ctxptr) ) 22 | return NULL; 23 | return PyLong_FromLong(pyw_unregister_idc_func(ctxptr)); 24 | } 25 | 26 | static PyObject *ex_py_set_idc_func_ex(PyObject *self, PyObject *pyargs) 27 | { 28 | const char *name; 29 | unsigned PY_LONG_LONG fp_ptr; 30 | const char *args; 31 | int flags; 32 | if ( !PyArg_ParseTuple(pyargs, "sKsi", &name, &fp_ptr, &args, &flags) ) 33 | return NULL; 34 | else 35 | return PyLong_FromLong(py_set_idc_func_ex(name, fp_ptr, args, flags)); 36 | } 37 | 38 | //--------------------------------------------------------------------------- 39 | static PyObject *ex_py_get_call_idc_func(PyObject *self, PyObject *args) 40 | { 41 | return PyLong_FromUnsignedLongLong(py_get_call_idc_func()); 42 | } 43 | 44 | //------------------------------------------------------------------------- 45 | #pragma warning(pop) 46 | 47 | //------------------------------------------------------------------------- 48 | static PyMethodDef py_methods_expr[] = 49 | { 50 | {"pyw_register_idc_func", ex_pyw_register_idc_func, METH_VARARGS, ""}, 51 | {"pyw_unregister_idc_func", ex_pyw_unregister_idc_func, METH_VARARGS, ""}, 52 | {"py_get_call_idc_func", ex_py_get_call_idc_func, METH_VARARGS, ""}, 53 | {"py_set_idc_func_ex", ex_py_set_idc_func_ex, METH_VARARGS, ""}, 54 | {NULL, NULL, 0, NULL} // End of methods 55 | }; 56 | DRIVER_INIT_METHODS(expr); 57 | -------------------------------------------------------------------------------- /pywraps/driver_graph.cpp: -------------------------------------------------------------------------------- 1 | #include "py_graph.hpp" 2 | 3 | //-------------------------------------------------------------------------- 4 | //py_choose2_t *last_c2 = NULL; 5 | static PyObject *ex_graph_show(PyObject * /*self*/, PyObject *args) 6 | { 7 | PyObject *obj; 8 | if ( !PyArg_ParseTuple(args, "O", &obj) ) 9 | return NULL; 10 | 11 | py_graph_t *ret = py_graph_t::Show(obj); 12 | return PyBool_FromLong(ret == NULL ? 0 : 1); 13 | } 14 | 15 | //-------------------------------------------------------------------------- 16 | static PyObject *ex_graph_refresh(PyObject * /*self*/, PyObject *args) 17 | { 18 | PyObject *obj; 19 | if ( !PyArg_ParseTuple(args, "O", &obj) ) 20 | return NULL; 21 | py_graph_t::Refresh(obj); 22 | Py_RETURN_NONE; 23 | } 24 | 25 | //-------------------------------------------------------------------------- 26 | static PyObject *ex_graph_addcmd(PyObject *self, PyObject *args) 27 | { 28 | PyObject *obj; 29 | const char *title, *hotkey; 30 | if ( !PyArg_ParseTuple(args, "Oss", &obj, &title, &hotkey) ) 31 | return NULL; 32 | Py_ssize_t r = py_graph_t::AddCommand(obj, title, hotkey); 33 | return Py_BuildValue("n", r); 34 | } 35 | 36 | //-------------------------------------------------------------------------- 37 | static PyMethodDef py_methods_graph[] = 38 | { 39 | {"show", ex_graph_show, METH_VARARGS, ""}, 40 | {"refresh", ex_graph_refresh, METH_VARARGS, ""}, 41 | {"addcmd", ex_graph_addcmd, METH_VARARGS, ""}, 42 | {NULL, NULL, 0, NULL} /* Sentinel */ 43 | }; 44 | DRIVER_INIT_METHODS(graph); -------------------------------------------------------------------------------- /pywraps/driver_kernwin.cpp: -------------------------------------------------------------------------------- 1 | #include "py_kernwin.hpp" 2 | 3 | //------------------------------------------------------------------------- 4 | static PyObject *ex_add_menu_item(PyObject *self, PyObject *args) 5 | { 6 | const char *menupath, *name, *hotkey; 7 | PyObject *pyfunc, *pyargs; 8 | int flags; 9 | if ( !PyArg_ParseTuple(args, "sssiOO", &menupath, &name, &hotkey, &flags, &pyfunc, &pyargs) ) 10 | return NULL; 11 | return py_add_menu_item(menupath, name, hotkey, flags, pyfunc, pyargs); 12 | } 13 | 14 | //------------------------------------------------------------------------- 15 | static PyObject *ex_del_menu_item(PyObject *self, PyObject *args) 16 | { 17 | if ( !PyArg_ParseTuple(args, "O", &self) ) 18 | return NULL; 19 | if ( py_del_menu_item(self) ) 20 | Py_RETURN_TRUE; 21 | else 22 | Py_RETURN_FALSE; 23 | } 24 | 25 | //------------------------------------------------------------------------- 26 | static PyObject *ex_execute_sync(PyObject *self, PyObject *args) 27 | { 28 | PyObject *pycall; 29 | int reqf; 30 | if ( !PyArg_ParseTuple(args, "Oi", &pycall, &reqf) ) 31 | return NULL; 32 | return PyInt_FromLong(py_execute_sync(pycall, reqf)); 33 | } 34 | 35 | //------------------------------------------------------------------------- 36 | static PyObject *ex_add_hotkey(PyObject *self, PyObject *args) 37 | { 38 | PyObject *pyfunc; 39 | const char *hotkey; 40 | if ( !PyArg_ParseTuple(args, "sO", &hotkey, &pyfunc) ) 41 | return NULL; 42 | else 43 | return py_add_hotkey(hotkey, pyfunc); 44 | } 45 | 46 | //------------------------------------------------------------------------- 47 | static PyObject *ex_del_hotkey(PyObject *self, PyObject *args) 48 | { 49 | PyObject *pyctx; 50 | if ( !PyArg_ParseTuple(args, "O", &pyctx) ) 51 | return NULL; 52 | else 53 | return PyInt_FromLong(py_del_hotkey(pyctx) ? 1 : 0); 54 | } 55 | 56 | //------------------------------------------------------------------------- 57 | static PyObject *ex_execute_ui_request(PyObject *self, PyObject *args) 58 | { 59 | PyObject *py_list; 60 | if ( !PyArg_ParseTuple(args, "O", &py_list) ) 61 | return NULL; 62 | else 63 | return PyBool_FromLong(py_execute_ui_requests(py_list) ? 1 : 0); 64 | } 65 | 66 | 67 | //------------------------------------------------------------------------- 68 | static PyMethodDef py_methods_kernwin[] = 69 | { 70 | {"py_del_menu_item", ex_del_menu_item, METH_VARARGS, ""}, 71 | {"py_add_menu_item", ex_add_menu_item, METH_VARARGS, ""}, 72 | {"py_execute_sync", ex_execute_sync, METH_VARARGS, ""}, 73 | {"py_add_hotkey", ex_add_hotkey, METH_VARARGS, ""}, 74 | {"py_del_hotkey", ex_del_hotkey, METH_VARARGS, ""}, 75 | {"py_execute_ui_request", ex_execute_ui_request, METH_VARARGS, ""}, 76 | {NULL, NULL, 0, NULL} /* Sentinel */ 77 | }; 78 | DRIVER_INIT_METHODS(kernwin); -------------------------------------------------------------------------------- /pywraps/driver_nalt.cpp: -------------------------------------------------------------------------------- 1 | #include "py_nalt.hpp" 2 | 3 | //------------------------------------------------------------------------- 4 | static PyObject *ex_get_switch_info_ex(PyObject *self, PyObject *args) 5 | { 6 | pyul_t ea; 7 | if ( !PyArg_ParseTuple(args, PY_FMT64, &ea) ) 8 | return NULL; 9 | return py_get_switch_info_ex(ea_t(ea)); 10 | } 11 | 12 | //------------------------------------------------------------------------- 13 | static PyMethodDef py_methods_nalt[] = 14 | { 15 | {"get_switch_info_ex", ex_get_switch_info_ex, METH_VARARGS, ""}, 16 | {NULL, NULL, 0, NULL} 17 | }; 18 | DRIVER_INIT_METHODS(nalt); 19 | -------------------------------------------------------------------------------- /pywraps/driver_notifywhen.cpp: -------------------------------------------------------------------------------- 1 | #include "py_notifywhen.hpp" 2 | 3 | //------------------------------------------------------------------------- 4 | static PyObject *ex_notify_when(PyObject *self, PyObject *args) 5 | { 6 | int when; 7 | PyObject *py_callable; 8 | if ( !PyArg_ParseTuple(args, "IO", &when, &py_callable) ) 9 | return NULL; 10 | return Py_BuildValue("i", notify_when(when, py_callable)); 11 | } 12 | 13 | //------------------------------------------------------------------------- 14 | static PyMethodDef py_methods_nw[] = 15 | { 16 | {"notify_when", ex_notify_when, METH_VARARGS, ""}, 17 | {NULL, NULL, 0, NULL} /* Sentinel */ 18 | }; 19 | DRIVER_INIT_METHODS(nw); 20 | 21 | #define DRIVER_INIT 22 | int driver_init() 23 | { 24 | bool ok = pywraps_nw_init(); 25 | if ( !ok ) 26 | return PLUGIN_SKIP; 27 | pywraps_nw_notify(NW_INITIDA_SLOT); 28 | return PLUGIN_KEEP; 29 | } 30 | 31 | #define DRIVER_TERM 32 | void driver_term() 33 | { 34 | pywraps_nw_notify(NW_TERMIDA_SLOT); 35 | pywraps_nw_term(); 36 | } 37 | -------------------------------------------------------------------------------- /pywraps/py_choose.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __PY_CHOOSE__ 2 | #define __PY_CHOOSE__ 3 | 4 | //--------------------------------------------------------------------------- 5 | // 6 | //--------------------------------------------------------------------------- 7 | uint32 idaapi choose_sizer(void *self) 8 | { 9 | PYW_GIL_GET; 10 | newref_t pyres(PyObject_CallMethod((PyObject *)self, "sizer", "")); 11 | return PyInt_AsLong(pyres.o); 12 | } 13 | 14 | //--------------------------------------------------------------------------- 15 | char *idaapi choose_getl(void *self, uint32 n, char *buf) 16 | { 17 | PYW_GIL_GET; 18 | newref_t pyres( 19 | PyObject_CallMethod( 20 | (PyObject *)self, 21 | "getl", 22 | "l", 23 | n)); 24 | 25 | const char *res; 26 | if (pyres == NULL || (res = PyString_AsString(pyres.o)) == NULL ) 27 | qstrncpy(buf, "", MAXSTR); 28 | else 29 | qstrncpy(buf, res, MAXSTR); 30 | return buf; 31 | } 32 | 33 | //--------------------------------------------------------------------------- 34 | void idaapi choose_enter(void *self, uint32 n) 35 | { 36 | PYW_GIL_GET; 37 | newref_t res(PyObject_CallMethod((PyObject *)self, "enter", "l", n)); 38 | } 39 | 40 | //--------------------------------------------------------------------------- 41 | uint32 choose_choose( 42 | void *self, 43 | int flags, 44 | int x0,int y0, 45 | int x1,int y1, 46 | int width, 47 | int deflt, 48 | int icon) 49 | { 50 | PYW_GIL_CHECK_LOCKED_SCOPE(); 51 | newref_t pytitle(PyObject_GetAttrString((PyObject *)self, "title")); 52 | const char *title = pytitle != NULL ? PyString_AsString(pytitle.o) : "Choose"; 53 | 54 | int r = choose( 55 | flags, 56 | x0, y0, 57 | x1, y1, 58 | self, 59 | width, 60 | choose_sizer, 61 | choose_getl, 62 | title, 63 | icon, 64 | deflt, 65 | NULL, /* del */ 66 | NULL, /* inst */ 67 | NULL, /* update */ 68 | NULL, /* edit */ 69 | choose_enter, 70 | NULL, /* destroy */ 71 | NULL, /* popup_names */ 72 | NULL);/* get_icon */ 73 | 74 | return r; 75 | } 76 | // 77 | 78 | #endif // __PY_CHOOSE__ 79 | -------------------------------------------------------------------------------- /pywraps/py_dbg.py: -------------------------------------------------------------------------------- 1 | 2 | # 3 | NO_PROCESS = 0xFFFFFFFF 4 | NO_THREAD = 0 5 | # 6 | 7 | 8 | -------------------------------------------------------------------------------- /pywraps/py_diskio.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __PY_IDA_DISKIO__ 2 | #define __PY_IDA_DISKIO__ 3 | 4 | // 5 | //-------------------------------------------------------------------------- 6 | int idaapi py_enumerate_files_cb(const char *file, void *ud) 7 | { 8 | // No need to 'PYW_GIL_GET' here, as this is called synchronously 9 | // and from the same thread as the one that executes 10 | // 'py_enumerate_files'. 11 | PYW_GIL_CHECK_LOCKED_SCOPE(); 12 | newref_t py_file(PyString_FromString(file)); 13 | newref_t py_ret( 14 | PyObject_CallFunctionObjArgs( 15 | (PyObject *)ud, 16 | py_file.o, 17 | NULL)); 18 | return (py_ret == NULL || !PyNumber_Check(py_ret.o)) ? 1 /* stop enum on failure */ : PyInt_AsLong(py_ret.o); 19 | } 20 | // 21 | 22 | // 23 | //-------------------------------------------------------------------------- 24 | /* 25 | # 26 | def enumerate_files(path, fname, callback): 27 | """ 28 | Enumerate files in the specified directory while the callback returns 0. 29 | @param path: directory to enumerate files in 30 | @param fname: mask of file names to enumerate 31 | @param callback: a callable object that takes the filename as 32 | its first argument and it returns 0 to continue 33 | enumeration or non-zero to stop enumeration. 34 | @return: 35 | None in case of script errors 36 | tuple(code, fname) : If the callback returns non-zero 37 | """ 38 | pass 39 | # 40 | */ 41 | PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback) 42 | { 43 | PYW_GIL_CHECK_LOCKED_SCOPE(); 44 | 45 | do 46 | { 47 | if ( !PyString_Check(path) || !PyString_Check(fname) || !PyCallable_Check(callback) ) 48 | break; 49 | 50 | const char *_path = PyString_AsString(path); 51 | const char *_fname = PyString_AsString(fname); 52 | if ( _path == NULL || _fname == NULL ) 53 | break; 54 | 55 | char answer[MAXSTR]; 56 | answer[0] = '\0'; 57 | int r = enumerate_files(answer, sizeof(answer), _path, _fname, py_enumerate_files_cb, callback); 58 | return Py_BuildValue("(is)", r, answer); 59 | } while ( false ); 60 | Py_RETURN_NONE; 61 | } 62 | // 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /pywraps/py_diskio.py: -------------------------------------------------------------------------------- 1 | # 2 | def enumerate_system_files(subdir, fname, callback): 3 | """Similar to enumerate_files() however it searches inside IDA directory or its subdirectories""" 4 | return enumerate_files(idadir(subdir), fname, callback) 5 | # 6 | -------------------------------------------------------------------------------- /pywraps/py_expr.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __PY_EXPR__ 2 | #define __PY_EXPR__ 3 | 4 | // 5 | struct py_idcfunc_ctx_t 6 | { 7 | PyObject *py_func; 8 | qstring name; 9 | int nargs; 10 | py_idcfunc_ctx_t(PyObject *py_func, const char *name, int nargs): py_func(py_func), name(name), nargs(nargs) 11 | { 12 | PYW_GIL_CHECK_LOCKED_SCOPE(); 13 | Py_INCREF(py_func); 14 | } 15 | ~py_idcfunc_ctx_t() 16 | { 17 | PYW_GIL_CHECK_LOCKED_SCOPE(); 18 | Py_DECREF(py_func); 19 | } 20 | }; 21 | 22 | //--------------------------------------------------------------------------- 23 | static error_t py_call_idc_func( 24 | void *_ctx, 25 | idc_value_t *argv, 26 | idc_value_t *r) 27 | { 28 | // Convert IDC arguments to Python list 29 | py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)_ctx; 30 | int cvt; 31 | char errbuf[MAXSTR]; 32 | 33 | PYW_GIL_CHECK_LOCKED_SCOPE(); 34 | ref_vec_t pargs; 35 | if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, true, errbuf, sizeof(errbuf)) ) 36 | { 37 | // Error during conversion? Create an IDC exception 38 | return PyW_CreateIdcException(r, errbuf); 39 | } 40 | 41 | // Call the Python function 42 | newref_t py_result(PyObject_CallObject( 43 | ctx->py_func, 44 | pargs.empty() ? NULL : pargs[0].o)); 45 | 46 | error_t err; 47 | if ( PyW_GetError(errbuf, sizeof(errbuf)) ) 48 | { 49 | err = PyW_CreateIdcException(r, errbuf); 50 | } 51 | else 52 | { 53 | // Convert the result to IDC 54 | r->clear(); 55 | cvt = pyvar_to_idcvar(py_result, r); 56 | if ( cvt < CIP_OK ) 57 | err = PyW_CreateIdcException(r, "ERROR: bad return value"); 58 | else 59 | err = eOk; 60 | } 61 | 62 | return err; 63 | } 64 | 65 | // 66 | 67 | // 68 | 69 | //--------------------------------------------------------------------------- 70 | static size_t py_get_call_idc_func() 71 | { 72 | return (size_t)py_call_idc_func; 73 | } 74 | 75 | //--------------------------------------------------------------------------- 76 | // Internal function: 77 | // - capture the python callable 78 | // - return a C context as a numeric value 79 | static size_t pyw_register_idc_func( 80 | const char *name, 81 | const char *args, 82 | PyObject *py_fp) 83 | { 84 | return (size_t)new py_idcfunc_ctx_t(py_fp, name, strlen(args)); 85 | } 86 | 87 | //--------------------------------------------------------------------------- 88 | // Internal function: 89 | // - free the C context 90 | static bool pyw_unregister_idc_func(size_t ctxptr) 91 | { 92 | // Unregister the function 93 | py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)ctxptr; 94 | bool ok = set_idc_func_ex(ctx->name.c_str(), NULL, NULL, 0); 95 | 96 | // Delete the context 97 | delete ctx; 98 | 99 | return ok; 100 | } 101 | 102 | //--------------------------------------------------------------------------- 103 | static bool py_set_idc_func_ex( 104 | const char *name, 105 | size_t fp_ptr, 106 | const char *args, 107 | int flags) 108 | { 109 | return set_idc_func_ex(name, (idc_func_t *)fp_ptr, args, flags); 110 | } 111 | 112 | //--------------------------------------------------------------------------- 113 | // Compile* functions return false when error so the return 114 | // value must be negated for the error string to be returned 115 | bool CompileEx_wrap( 116 | const char *file, 117 | bool del_macros, 118 | char *errbuf, size_t errbufsize) 119 | { 120 | return !CompileEx(file, del_macros, errbuf, errbufsize); 121 | } 122 | 123 | bool Compile_wrap(const char *file, char *errbuf, size_t errbufsize) 124 | { 125 | return !Compile(file, errbuf, errbufsize); 126 | } 127 | 128 | bool calcexpr_wrap( 129 | ea_t where, 130 | const char *line, 131 | idc_value_t *rv, 132 | char *errbuf, size_t errbufsize) 133 | { 134 | return !calcexpr(where, line, rv, errbuf, errbufsize); 135 | } 136 | 137 | bool calc_idc_expr_wrap( 138 | ea_t where, 139 | const char *line, 140 | idc_value_t *rv, 141 | char *errbuf, size_t errbufsize) 142 | { 143 | return !calc_idc_expr(where, line, rv, errbuf, errbufsize); 144 | } 145 | 146 | bool CompileLine_wrap(const char *line, char *errbuf, size_t errbufsize) 147 | { 148 | return !CompileLineEx(line, errbuf, errbufsize); 149 | } 150 | 151 | // 152 | #endif 153 | -------------------------------------------------------------------------------- /pywraps/py_gdl.py: -------------------------------------------------------------------------------- 1 | # 2 | # ----------------------------------------------------------------------- 3 | class BasicBlock(object): 4 | """Basic block class. It is returned by the Flowchart class""" 5 | def __init__(self, id, bb, fc): 6 | self._fc = fc 7 | 8 | self.id = id 9 | """Basic block ID""" 10 | 11 | self.startEA = bb.startEA 12 | """startEA of basic block""" 13 | 14 | self.endEA = bb.endEA 15 | """endEA of basic block""" 16 | 17 | self.type = self._fc._q.calc_block_type(self.id) 18 | """Block type (check fc_block_type_t enum)""" 19 | 20 | 21 | def preds(self): 22 | """ 23 | Iterates the predecessors list 24 | """ 25 | q = self._fc._q 26 | for i in xrange(0, self._fc._q.npred(self.id)): 27 | yield self._fc[q.pred(self.id, i)] 28 | 29 | 30 | def succs(self): 31 | """ 32 | Iterates the successors list 33 | """ 34 | q = self._fc._q 35 | for i in xrange(0, q.nsucc(self.id)): 36 | yield self._fc[q.succ(self.id, i)] 37 | 38 | # ----------------------------------------------------------------------- 39 | class FlowChart(object): 40 | """ 41 | Flowchart class used to determine basic blocks. 42 | Check ex_gdl_qflow_chart.py for sample usage. 43 | """ 44 | def __init__(self, f=None, bounds=None, flags=0): 45 | """ 46 | Constructor 47 | @param f: A func_t type, use get_func(ea) to get a reference 48 | @param bounds: A tuple of the form (start, end). Used if "f" is None 49 | @param flags: one of the FC_xxxx flags. One interesting flag is FC_PREDS 50 | """ 51 | if (f is None) and (bounds is None or type(bounds) != types.TupleType): 52 | raise Exception("Please specifiy either a function or start/end pair") 53 | 54 | if bounds is None: 55 | bounds = (BADADDR, BADADDR) 56 | 57 | # Create the flowchart 58 | self._q = qflow_chart_t("", f, bounds[0], bounds[1], flags) 59 | 60 | size = property(lambda self: self._q.size()) 61 | """Number of blocks in the flow chart""" 62 | 63 | 64 | def refresh(): 65 | """Refreshes the flow chart""" 66 | self._q.refresh() 67 | 68 | 69 | def _getitem(self, index): 70 | return BasicBlock(index, self._q[index], self) 71 | 72 | 73 | def __iter__(self): 74 | return (self._getitem(index) for index in xrange(0, self.size)) 75 | 76 | 77 | def __getitem__(self, index): 78 | """ 79 | Returns a basic block 80 | 81 | @return: BasicBlock 82 | """ 83 | if index >= self.size: 84 | raise KeyError 85 | else: 86 | return self._getitem(index) 87 | 88 | # 89 | -------------------------------------------------------------------------------- /pywraps/py_idaview.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __PY_IDA_VIEW__ 2 | #define __PY_IDA_VIEW__ 3 | 4 | // 5 | class py_idaview_t : public py_customidamemo_t 6 | { 7 | typedef py_customidamemo_t inherited; 8 | 9 | public: 10 | static bool Bind(PyObject *self); 11 | static bool Unbind(PyObject *self); 12 | }; 13 | 14 | //------------------------------------------------------------------------- 15 | bool py_idaview_t::Bind(PyObject *self) 16 | { 17 | // Already a py_idaview_t associated to this object? 18 | py_idaview_t *_this = view_extract_this(self); 19 | if ( _this != NULL ) 20 | return false; 21 | 22 | qstring title; 23 | if ( !PyW_GetStringAttr(self, S_M_TITLE, &title) ) 24 | return false; 25 | 26 | // Get the IDAView associated to this TForm 27 | TForm *tform = find_tform(title.c_str()); 28 | if ( tform == NULL ) 29 | return false; 30 | TCustomControl *v = get_tform_idaview(tform); 31 | if ( v == NULL ) 32 | return false; 33 | 34 | // Get unique py_idaview_t associated to that tform 35 | py_idaview_t *py_view; 36 | TCustomControl *found_view; 37 | if ( lookup_info.find_by_form(&found_view, (py_customidamemo_t**) &py_view, tform) ) 38 | { 39 | // If we have a py_idaview_t for that form, ensure it has 40 | // the expected view. 41 | QASSERT(30451, found_view == v); 42 | } 43 | else 44 | { 45 | py_view = new py_idaview_t(); 46 | lookup_info_t::entry_t &e = lookup_info.new_entry(py_view); 47 | lookup_info.commit(e, tform, v); 48 | } 49 | 50 | // Finally, bind: 51 | // py_idaview_t <=> IDAViewWrapper 52 | // py_idaview_t => TCustomControl 53 | bool ok = py_view->bind(self, v); 54 | if ( ok ) 55 | { 56 | ok = py_view->collect_pyobject_callbacks(self); 57 | if ( ok ) 58 | py_view->install_custom_viewer_handlers(); 59 | else 60 | delete py_view; 61 | } 62 | return ok; 63 | } 64 | 65 | //------------------------------------------------------------------------- 66 | bool py_idaview_t::Unbind(PyObject *self) 67 | { 68 | py_idaview_t *_this = view_extract_this(self); 69 | if ( _this == NULL ) 70 | return false; 71 | _this->unbind(); 72 | return true; 73 | } 74 | 75 | //------------------------------------------------------------------------- 76 | bool pyidag_bind(PyObject *self) 77 | { 78 | return py_idaview_t::Bind(self); 79 | } 80 | 81 | //------------------------------------------------------------------------- 82 | bool pyidag_unbind(PyObject *self) 83 | { 84 | return py_idaview_t::Unbind(self); 85 | } 86 | 87 | // 88 | 89 | //-------------------------------------------------------------------------- 90 | 91 | // 92 | bool pyidag_bind(PyObject *self); 93 | bool pyidag_unbind(PyObject *self); 94 | // 95 | 96 | #endif // __PY_IDA_VIEW__ 97 | -------------------------------------------------------------------------------- /pywraps/py_idaview.py: -------------------------------------------------------------------------------- 1 | 2 | # 3 | class IDAViewWrapper(CustomIDAMemo): 4 | """This class wraps access to native IDA views. See kernwin.hpp file""" 5 | def __init__(self, title): 6 | """ 7 | Constructs the IDAViewWrapper object around the view 8 | whose title is 'title'. 9 | 10 | @param title: The title of the existing IDA view. E.g., 'IDA View-A' 11 | """ 12 | self._title = title 13 | 14 | def Bind(self): 15 | return _idaapi.pyidag_bind(self) 16 | 17 | def Unbind(self): 18 | return _idaapi.pyidag_unbind(self) 19 | 20 | # 21 | -------------------------------------------------------------------------------- /pywraps/py_kernwin.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # Standalone and testing code 3 | import sys 4 | try: 5 | import pywraps 6 | pywraps_there = True 7 | print "Using pywraps" 8 | except: 9 | pywraps_there = False 10 | print "Not using pywraps" 11 | 12 | try: 13 | import _idaapi 14 | except: 15 | print "Please try me from inside IDA" 16 | sys.exit(0) 17 | 18 | if pywraps_there: 19 | _idaapi.execute_sync = pywraps.py_execute_sync 20 | _idaapi.add_hotkey = pywraps.py_add_hotkey 21 | _idaapi.del_hotkey = pywraps.py_del_hotkey 22 | 23 | # ----------------------------------------------------------------------- 24 | # 25 | DP_LEFT = 0x0001 26 | DP_TOP = 0x0002 27 | DP_RIGHT = 0x0004 28 | DP_BOTTOM = 0x0008 29 | DP_INSIDE = 0x0010 30 | # if not before, then it is after 31 | # (use DP_INSIDE | DP_BEFORE to insert a tab before a given tab) 32 | # this flag alone cannot be used to determine orientation 33 | DP_BEFORE = 0x0020 34 | # used with combination of other flags 35 | DP_TAB = 0x0040 36 | DP_FLOATING = 0x0080 37 | 38 | # ---------------------------------------------------------------------- 39 | def load_custom_icon(file_name=None, data=None, format=None): 40 | """ 41 | Loads a custom icon and returns an identifier that can be used with other APIs 42 | 43 | If file_name is passed then the other two arguments are ignored. 44 | 45 | @param file_name: The icon file name 46 | @param data: The icon data 47 | @param format: The icon data format 48 | 49 | @return: Icon id or 0 on failure. 50 | Use free_custom_icon() to free it 51 | """ 52 | if file_name is not None: 53 | return _idaapi.py_load_custom_icon_fn(file_name) 54 | elif not (data is None and format is None): 55 | return _idaapi.py_load_custom_icon_data(data, format) 56 | else: 57 | return 0 58 | 59 | # ---------------------------------------------------------------------- 60 | def asklong(defval, format): 61 | res, val = _idaapi._asklong(defval, format) 62 | 63 | if res == 1: 64 | return val 65 | else: 66 | return None 67 | 68 | # ---------------------------------------------------------------------- 69 | def askaddr(defval, format): 70 | res, ea = _idaapi._askaddr(defval, format) 71 | 72 | if res == 1: 73 | return ea 74 | else: 75 | return None 76 | 77 | # ---------------------------------------------------------------------- 78 | def askseg(defval, format): 79 | res, sel = _idaapi._askseg(defval, format) 80 | 81 | if res == 1: 82 | return sel 83 | else: 84 | return None 85 | 86 | # ---------------------------------------------------------------------- 87 | class action_handler_t: 88 | def __init__(self): 89 | pass 90 | 91 | def activate(self, ctx): 92 | return 0 93 | 94 | def update(self, ctx): 95 | pass 96 | 97 | # 98 | 99 | # ---------------------------------------------------------------------- 100 | from threading import Thread 101 | import time 102 | 103 | # ---------------------------------------------------------------------- 104 | def myfunction(cnt): 105 | i = 1 106 | while i <= cnt: 107 | print "i=", i 108 | i += 1 109 | time.sleep(1) 110 | 111 | print "done!" 112 | 113 | def test_thread(): 114 | t = Thread(target=myfunction, args=(2,)) 115 | 116 | t.start() 117 | t.join() 118 | 119 | # ---------------------------------------------------------------------- 120 | def hotkey_func1(): 121 | print "Hello from hotkey handler in Python!" 122 | -------------------------------------------------------------------------------- /pywraps/py_lines.py: -------------------------------------------------------------------------------- 1 | # 2 | 3 | # ---------------- Color escape sequence defitions ------------------------- 4 | COLOR_ADDR_SIZE = 16 if _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL else 8 5 | SCOLOR_FG_MAX = '\x28' # Max color number 6 | SCOLOR_OPND1 = chr(cvar.COLOR_ADDR+1) # Instruction operand 1 7 | SCOLOR_OPND2 = chr(cvar.COLOR_ADDR+2) # Instruction operand 2 8 | SCOLOR_OPND3 = chr(cvar.COLOR_ADDR+3) # Instruction operand 3 9 | SCOLOR_OPND4 = chr(cvar.COLOR_ADDR+4) # Instruction operand 4 10 | SCOLOR_OPND5 = chr(cvar.COLOR_ADDR+5) # Instruction operand 5 11 | SCOLOR_OPND6 = chr(cvar.COLOR_ADDR+6) # Instruction operand 6 12 | SCOLOR_UTF8 = chr(cvar.COLOR_ADDR+10) # Following text is UTF-8 encoded 13 | 14 | # ---------------- Line prefix colors -------------------------------------- 15 | PALETTE_SIZE = (cvar.COLOR_FG_MAX+_idaapi.COLOR_BG_MAX) 16 | 17 | def requires_color_esc(c): 18 | """ 19 | Checks if the given character requires escaping 20 | @param c: character (string of one char) 21 | @return: Boolean 22 | """ 23 | t = ord(c[0]) 24 | return c >= COLOR_ON and c <= COLOR_INV 25 | 26 | def COLSTR(str, tag): 27 | """ 28 | Utility function to create a colored line 29 | @param str: The string 30 | @param tag: Color tag constant. One of SCOLOR_XXXX 31 | """ 32 | return SCOLOR_ON + tag + str + SCOLOR_OFF + tag 33 | 34 | # 35 | -------------------------------------------------------------------------------- /pywraps/py_loader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __PY_LOADER___ 2 | #define __PY_LOADER___ 3 | 4 | //------------------------------------------------------------------------ 5 | // 6 | 7 | //------------------------------------------------------------------------ 8 | /* 9 | # 10 | def mem2base(mem, ea, fpos): 11 | """ 12 | Load database from the memory. 13 | @param mem: the buffer 14 | @param ea: start linear addresses 15 | @param fpos: position in the input file the data is taken from. 16 | if == -1, then no file position correspond to the data. 17 | @return: 18 | - Returns zero if the passed buffer was not a string 19 | - Otherwise 1 is returned 20 | """ 21 | pass 22 | # 23 | */ 24 | static int py_mem2base(PyObject *py_mem, ea_t ea, long fpos = -1) 25 | { 26 | Py_ssize_t len; 27 | char *buf; 28 | { 29 | PYW_GIL_CHECK_LOCKED_SCOPE(); 30 | if ( PyString_AsStringAndSize(py_mem, &buf, &len) == -1 ) 31 | return 0; 32 | } 33 | 34 | return mem2base((void *)buf, ea, ea+len, fpos); 35 | } 36 | 37 | //------------------------------------------------------------------------ 38 | /* 39 | # 40 | def load_plugin(name): 41 | """ 42 | Loads a plugin 43 | @return: 44 | - None if plugin could not be loaded 45 | - An opaque object representing the loaded plugin 46 | """ 47 | pass 48 | # 49 | */ 50 | static PyObject *py_load_plugin(const char *name) 51 | { 52 | plugin_t *r = load_plugin(name); 53 | PYW_GIL_CHECK_LOCKED_SCOPE(); 54 | if ( r == NULL ) 55 | Py_RETURN_NONE; 56 | else 57 | return PyCObject_FromVoidPtr(r, NULL); 58 | } 59 | 60 | //------------------------------------------------------------------------ 61 | /* 62 | # 63 | def run_plugin(plg): 64 | """ 65 | Runs a plugin 66 | @param plg: A plugin object (returned by load_plugin()) 67 | @return: Boolean 68 | """ 69 | pass 70 | # 71 | */ 72 | static bool py_run_plugin(PyObject *plg, int arg) 73 | { 74 | PYW_GIL_CHECK_LOCKED_SCOPE(); 75 | if ( !PyCObject_Check(plg) ) 76 | { 77 | return false; 78 | } 79 | else 80 | { 81 | plugin_t *p = (plugin_t *)PyCObject_AsVoidPtr(plg); 82 | bool rc; 83 | Py_BEGIN_ALLOW_THREADS; 84 | rc = run_plugin(p, arg); 85 | Py_END_ALLOW_THREADS; 86 | return rc; 87 | } 88 | } 89 | 90 | // 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /pywraps/py_name.hpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------ 2 | // 3 | //------------------------------------------------------------------------ 4 | PyObject *py_get_debug_names(ea_t ea1, ea_t ea2) 5 | { 6 | // Get debug names 7 | ea_name_vec_t names; 8 | PYW_GIL_CHECK_LOCKED_SCOPE(); 9 | Py_BEGIN_ALLOW_THREADS; 10 | get_debug_names(ea1, ea2, names); 11 | Py_END_ALLOW_THREADS; 12 | PyObject *dict = Py_BuildValue("{}"); 13 | if (dict != NULL) 14 | { 15 | for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it) 16 | { 17 | PyDict_SetItem(dict, 18 | Py_BuildValue(PY_FMT64, it->ea), 19 | PyString_FromString(it->name.c_str())); 20 | } 21 | } 22 | return dict; 23 | } 24 | //------------------------------------------------------------------------ 25 | // 26 | //------------------------------------------------------------------------ 27 | -------------------------------------------------------------------------------- /pywraps/py_name.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | # 4 | 5 | class NearestName: 6 | """ 7 | Utility class to help find the nearest name in a given ea/name dictionary 8 | """ 9 | def __init__(self, ea_names): 10 | self.update(ea_names) 11 | 12 | 13 | def update(self, ea_names): 14 | """Updates the ea/names map""" 15 | self._names = ea_names 16 | self._addrs = ea_names.keys() 17 | self._addrs.sort() 18 | 19 | 20 | def find(self, ea): 21 | """ 22 | Returns a tupple (ea, name, pos) that is the nearest to the passed ea 23 | If no name is matched then None is returned 24 | """ 25 | pos = bisect.bisect_left(self._addrs, ea) 26 | # no match 27 | if pos >= len(self._addrs): 28 | return None 29 | # exact match? 30 | if self._addrs[pos] != ea: 31 | pos -= 1 # go to previous element 32 | if pos < 0: 33 | return None 34 | return self[pos] 35 | 36 | 37 | def _get_item(self, index): 38 | ea = self._addrs[index] 39 | return (ea, self._names[ea], index) 40 | 41 | 42 | def __iter__(self): 43 | return (self._get_item(index) for index in xrange(0, len(self._addrs))) 44 | 45 | 46 | def __getitem__(self, index): 47 | """Returns the tupple (ea, name, index)""" 48 | if index > len(self._addrs): 49 | raise StopIteration 50 | return self._get_item(index) 51 | 52 | # -------------------------------------------------------------------------------- /pywraps/py_notifywhen.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # Standalone and testing code 3 | import sys 4 | try: 5 | import pywraps 6 | pywraps_there = True 7 | print "Using pywraps" 8 | except: 9 | pywraps_there = False 10 | print "Not using pywraps" 11 | 12 | try: 13 | import _idaapi 14 | except: 15 | print "Please try me from inside IDA" 16 | sys.exit(0) 17 | 18 | import struct 19 | 20 | if pywraps_there: 21 | _idaapi.notify_when = pywraps.notify_when 22 | 23 | # ----------------------------------------------------------------------- 24 | # 25 | # The general callback format of notify_when() is: 26 | # def notify_when_callback(nw_code) 27 | # In the case of NW_OPENIDB, the callback is: 28 | # def notify_when_callback(nw_code, is_old_database) 29 | NW_OPENIDB = 0x0001 30 | """Notify when the database is opened. Its callback is of the form: def notify_when_callback(nw_code, is_old_database)""" 31 | NW_CLOSEIDB = 0x0002 32 | """Notify when the database is closed. Its callback is of the form: def notify_when_callback(nw_code)""" 33 | NW_INITIDA = 0x0004 34 | """Notify when the IDA starts. Its callback is of the form: def notify_when_callback(nw_code)""" 35 | NW_TERMIDA = 0x0008 36 | """Notify when the IDA terminates. Its callback is of the form: def notify_when_callback(nw_code)""" 37 | NW_REMOVE = 0x0010 38 | """Use this flag with other flags to uninstall a notifywhen callback""" 39 | 40 | # 41 | # ----------------------------------------------------------------------- 42 | 43 | def nw_openidb(code, old): 44 | print "Open IDB, old=", old 45 | 46 | def nw_closeidb(code): 47 | print "Close IDB" 48 | 49 | def nw_openclose(code, old = None): 50 | if code == NW_CLOSEIDB: 51 | print "openclose: Close IDB" 52 | elif code == NW_OPENIDB: 53 | print "openclose: Open IDB, old=", old 54 | 55 | def nw_closeida(code): 56 | import ctypes 57 | user32 = ctypes.windll.user32 58 | user32.MessageBoxA(0, "Close IDA", "Info", 0) 59 | 60 | print "registering nw_openidb->", _idaapi.notify_when(NW_OPENIDB, nw_openidb) 61 | print "registering nw_closeidb->", _idaapi.notify_when(NW_CLOSEIDB, nw_closeidb) 62 | print "registering nw_openclose->", _idaapi.notify_when(NW_OPENIDB|NW_CLOSEIDB, nw_openclose) 63 | print "registering nw_closeida->", _idaapi.notify_when(NW_TERMIDA, nw_closeida) 64 | -------------------------------------------------------------------------------- /pywraps/py_plgform.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __PY_PLGFORM__ 2 | #define __PY_PLGFORM__ 3 | 4 | // 5 | //--------------------------------------------------------------------------- 6 | class plgform_t 7 | { 8 | private: 9 | ref_t py_obj; 10 | TForm *form; 11 | 12 | static int idaapi s_callback(void *ud, int notification_code, va_list va) 13 | { 14 | // This hook gets called from the kernel. Ensure we hold the GIL. 15 | PYW_GIL_GET; 16 | 17 | plgform_t *_this = (plgform_t *)ud; 18 | if ( notification_code == ui_tform_visible ) 19 | { 20 | TForm *form = va_arg(va, TForm *); 21 | if ( form == _this->form ) 22 | { 23 | // Qt: QWidget* 24 | // G: HWND 25 | // We wrap and pass as a CObject in the hope that a Python UI framework 26 | // can unwrap a CObject and get the hwnd/widget back 27 | newref_t py_result( 28 | PyObject_CallMethod( 29 | _this->py_obj.o, 30 | (char *)S_ON_CREATE, "O", 31 | PyCObject_FromVoidPtr(form, NULL))); 32 | PyW_ShowCbErr(S_ON_CREATE); 33 | } 34 | } 35 | else if ( notification_code == ui_tform_invisible ) 36 | { 37 | TForm *form = va_arg(va, TForm *); 38 | if ( form == _this->form ) 39 | { 40 | { 41 | newref_t py_result( 42 | PyObject_CallMethod( 43 | _this->py_obj.o, 44 | (char *)S_ON_CLOSE, "O", 45 | PyCObject_FromVoidPtr(form, NULL))); 46 | PyW_ShowCbErr(S_ON_CLOSE); 47 | } 48 | _this->unhook(); 49 | } 50 | } 51 | return 0; 52 | } 53 | 54 | void unhook() 55 | { 56 | unhook_from_notification_point(HT_UI, s_callback, this); 57 | form = NULL; 58 | 59 | // Call DECREF at last, since it may trigger __del__ 60 | PYW_GIL_CHECK_LOCKED_SCOPE(); 61 | py_obj = ref_t(); 62 | } 63 | 64 | public: 65 | plgform_t(): form(NULL) 66 | { 67 | } 68 | 69 | bool show( 70 | PyObject *obj, 71 | const char *caption, 72 | int options) 73 | { 74 | // Already displayed? 75 | TForm *f = find_tform(caption); 76 | if ( f != NULL ) 77 | { 78 | // Our form? 79 | if ( f == form ) 80 | { 81 | // Switch to it 82 | switchto_tform(form, true); 83 | return true; 84 | } 85 | // Fail to create 86 | return false; 87 | } 88 | 89 | // Create a form 90 | form = create_tform(caption, NULL); 91 | if ( form == NULL ) 92 | return false; 93 | 94 | if ( !hook_to_notification_point(HT_UI, s_callback, this) ) 95 | { 96 | form = NULL; 97 | return false; 98 | } 99 | 100 | py_obj = borref_t(obj); 101 | 102 | if ( is_idaq() ) 103 | options |= FORM_QWIDGET; 104 | 105 | this->form = form; 106 | open_tform(form, options); 107 | return true; 108 | } 109 | 110 | void close(int options = 0) 111 | { 112 | if ( form != NULL ) 113 | close_tform(form, options); 114 | } 115 | 116 | static PyObject *create() 117 | { 118 | PYW_GIL_CHECK_LOCKED_SCOPE(); 119 | return PyCObject_FromVoidPtr(new plgform_t(), destroy); 120 | } 121 | 122 | static void destroy(void *obj) 123 | { 124 | delete (plgform_t *)obj; 125 | } 126 | }; 127 | // 128 | 129 | // 130 | //--------------------------------------------------------------------------- 131 | #define DECL_PLGFORM PYW_GIL_CHECK_LOCKED_SCOPE(); plgform_t *plgform = (plgform_t *) PyCObject_AsVoidPtr(py_link); 132 | static PyObject *plgform_new() 133 | { 134 | return plgform_t::create(); 135 | } 136 | 137 | static bool plgform_show( 138 | PyObject *py_link, 139 | PyObject *py_obj, 140 | const char *caption, 141 | int options = FORM_TAB|FORM_MENU|FORM_RESTORE) 142 | { 143 | DECL_PLGFORM; 144 | return plgform->show(py_obj, caption, options); 145 | } 146 | 147 | static void plgform_close( 148 | PyObject *py_link, 149 | int options) 150 | { 151 | DECL_PLGFORM; 152 | plgform->close(options); 153 | } 154 | #undef DECL_PLGFORM 155 | // 156 | 157 | #endif // __PY_PLGFORM__ 158 | -------------------------------------------------------------------------------- /pywraps/py_plgform.py: -------------------------------------------------------------------------------- 1 | import _idaapi 2 | 3 | # 4 | class PluginForm(object): 5 | """ 6 | PluginForm class. 7 | 8 | This form can be used to host additional controls. Please check the PyQt example. 9 | """ 10 | 11 | FORM_MDI = 0x01 12 | """start by default as MDI (obsolete)""" 13 | FORM_TAB = 0x02 14 | """attached by default to a tab""" 15 | FORM_RESTORE = 0x04 16 | """restore state from desktop config""" 17 | FORM_ONTOP = 0x08 18 | """form should be "ontop""" 19 | FORM_MENU = 0x10 20 | """form must be listed in the windows menu (automatically set for all plugins)""" 21 | FORM_CENTERED = 0x20 22 | """form will be centered on the screen""" 23 | FORM_PERSIST = 0x40 24 | """form will persist until explicitly closed with Close()""" 25 | 26 | 27 | def __init__(self): 28 | """ 29 | """ 30 | self.__clink__ = _idaapi.plgform_new() 31 | 32 | 33 | 34 | def Show(self, caption, options = 0): 35 | """ 36 | Creates the form if not was not created or brings to front if it was already created 37 | 38 | @param caption: The form caption 39 | @param options: One of PluginForm.FORM_ constants 40 | """ 41 | options |= PluginForm.FORM_TAB|PluginForm.FORM_MENU|PluginForm.FORM_RESTORE 42 | return _idaapi.plgform_show(self.__clink__, self, caption, options) 43 | 44 | 45 | @staticmethod 46 | def FormToPyQtWidget(form, ctx = sys.modules['__main__']): 47 | """ 48 | Use this method to convert a TForm* to a QWidget to be used by PyQt 49 | 50 | @param ctx: Context. Reference to a module that already imported SIP and QtGui modules 51 | """ 52 | return ctx.sip.wrapinstance(ctx.sip.voidptr(form).__int__(), ctx.QtGui.QWidget) 53 | 54 | 55 | @staticmethod 56 | def FormToPySideWidget(form, ctx = sys.modules['__main__']): 57 | """ 58 | Use this method to convert a TForm* to a QWidget to be used by PySide 59 | 60 | @param ctx: Context. Reference to a module that already imported QtGui module 61 | """ 62 | if form is None: 63 | return None 64 | if type(form).__name__ == "SwigPyObject": 65 | # Since 'form' is a SwigPyObject, we first need to convert it to a PyCObject. 66 | # However, there's no easy way of doing it, so we'll use a rather brutal approach: 67 | # converting the SwigPyObject to a 'long' (will go through 'SwigPyObject_long', 68 | # that will return the pointer's value as a long), and then convert that value 69 | # back to a pointer into a PyCObject. 70 | ptr_l = long(form) 71 | from ctypes import pythonapi, c_void_p, py_object 72 | pythonapi.PyCObject_FromVoidPtr.restype = py_object 73 | pythonapi.PyCObject_AsVoidPtr.argtypes = [c_void_p, c_void_p] 74 | form = pythonapi.PyCObject_FromVoidPtr(ptr_l, 0) 75 | return ctx.QtGui.QWidget.FromCObject(form) 76 | 77 | 78 | def OnCreate(self, form): 79 | """ 80 | This event is called when the plugin form is created. 81 | The programmer should populate the form when this event is triggered. 82 | 83 | @return: None 84 | """ 85 | pass 86 | 87 | 88 | def OnClose(self, form): 89 | """ 90 | Called when the plugin form is closed 91 | 92 | @return: None 93 | """ 94 | pass 95 | 96 | 97 | def Close(self, options): 98 | """ 99 | Closes the form. 100 | 101 | @param options: Close options (FORM_SAVE, FORM_NO_CONTEXT, ...) 102 | 103 | @return: None 104 | """ 105 | return _idaapi.plgform_close(self.__clink__, options) 106 | 107 | FORM_SAVE = 0x1 108 | """Save state in desktop config""" 109 | 110 | FORM_NO_CONTEXT = 0x2 111 | """Don't change the current context (useful for toolbars)""" 112 | 113 | FORM_DONT_SAVE_SIZE = 0x4 114 | """Don't save size of the window""" 115 | 116 | FORM_CLOSE_LATER = 0x8 117 | """This flag should be used when Close() is called from an event handler""" 118 | # 119 | 120 | plg = PluginForm() 121 | plg.Show("This is it") 122 | -------------------------------------------------------------------------------- /pywraps/py_registry.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __PY_REGISTRY__ 3 | #define __PY_REGISTRY__ 4 | 5 | // 6 | //------------------------------------------------------------------------- 7 | static PyObject *_py_reg_subkey_children(const char *name, bool subkeys) 8 | { 9 | PYW_GIL_CHECK_LOCKED_SCOPE(); 10 | PyObject *result = NULL; 11 | qstrvec_t children; 12 | Py_BEGIN_ALLOW_THREADS; 13 | if ( reg_subkey_children(&children, name, subkeys) ) 14 | { 15 | result = PyList_New(children.size()); 16 | if ( result != NULL ) 17 | for ( size_t i = 0, n = children.size(); i < n; ++i ) 18 | PyList_SET_ITEM(result, i, PyString_FromString(children[i].c_str())); 19 | } 20 | Py_END_ALLOW_THREADS; 21 | if ( result == NULL ) 22 | Py_RETURN_NONE; 23 | else 24 | return result; 25 | } 26 | // 27 | 28 | 29 | // 30 | //------------------------------------------------------------------------- 31 | PyObject *py_reg_read_string(const char *name, const char *subkey = NULL, const char *def = NULL) 32 | { 33 | PYW_GIL_CHECK_LOCKED_SCOPE(); 34 | char utf8[MAXSTR * 10]; 35 | bool ok; 36 | Py_BEGIN_ALLOW_THREADS; 37 | if ( def == NULL ) 38 | { 39 | ok = reg_read_string(name, utf8, sizeof(utf8), subkey); 40 | } 41 | else 42 | { 43 | reg_read_string(name, sizeof(utf8), utf8, def, subkey); 44 | ok = true; 45 | } 46 | Py_END_ALLOW_THREADS; 47 | return PyString_FromString(ok ? utf8 : ""); 48 | } 49 | 50 | //------------------------------------------------------------------------- 51 | regval_type_t py_reg_data_type(const char *name, const char *subkey = NULL) 52 | { 53 | PYW_GIL_CHECK_LOCKED_SCOPE(); 54 | regval_type_t rt = reg_unknown; 55 | Py_BEGIN_ALLOW_THREADS; 56 | reg_data_type(&rt, name, subkey); 57 | Py_END_ALLOW_THREADS; 58 | return rt; 59 | } 60 | 61 | //------------------------------------------------------------------------- 62 | PyObject *py_reg_read_binary(const char *name, const char *subkey = NULL) 63 | { 64 | PYW_GIL_CHECK_LOCKED_SCOPE(); 65 | bytevec_t bytes; 66 | bool ok; 67 | Py_BEGIN_ALLOW_THREADS; 68 | ok = reg_read_binary(name, &bytes, subkey); 69 | Py_END_ALLOW_THREADS; 70 | if ( ok ) 71 | return PyString_FromStringAndSize((const char *) bytes.begin(), bytes.size()); 72 | else 73 | Py_RETURN_NONE; 74 | } 75 | 76 | //------------------------------------------------------------------------- 77 | void py_reg_write_binary(const char *name, PyObject *py_bytes, const char *subkey = NULL) 78 | { 79 | PYW_GIL_CHECK_LOCKED_SCOPE(); 80 | if ( PyString_Check(py_bytes) ) 81 | { 82 | char *py_bytes_raw = NULL; 83 | Py_ssize_t py_size = 0; 84 | PyString_AsStringAndSize(py_bytes, &py_bytes_raw, &py_size); 85 | bytevec_t bytes; 86 | bytes.append(py_bytes_raw, py_size); 87 | Py_BEGIN_ALLOW_THREADS; 88 | reg_write_binary(name, bytes.begin(), bytes.size(), subkey); 89 | Py_END_ALLOW_THREADS; 90 | } 91 | else 92 | { 93 | PyErr_SetString(PyExc_ValueError, "Bytes string expected!"); 94 | } 95 | } 96 | 97 | //------------------------------------------------------------------------- 98 | PyObject *py_reg_subkey_subkeys(const char *name) 99 | { 100 | return _py_reg_subkey_children(name, true); 101 | } 102 | 103 | //------------------------------------------------------------------------- 104 | PyObject *py_reg_subkey_values(const char *name) 105 | { 106 | return _py_reg_subkey_children(name, false); 107 | } 108 | 109 | // 110 | 111 | 112 | #endif // __PY_REGISTRY__ 113 | -------------------------------------------------------------------------------- /pywraps/py_typeinf.py: -------------------------------------------------------------------------------- 1 | # 2 | 3 | def get_type_size0(ti, tp): 4 | """ 5 | DEPRECATED. Please use calc_type_size instead 6 | Returns the size of a type 7 | @param ti: Type info. 'idaapi.cvar.idati' can be passed. 8 | @param tp: type string 9 | @return: 10 | - None on failure 11 | - The size of the type 12 | """ 13 | return calc_type_size(ti, tp) 14 | 15 | # 16 | -------------------------------------------------------------------------------- /pywraps/py_view_base.py: -------------------------------------------------------------------------------- 1 | 2 | # 3 | class CustomIDAMemo(object): 4 | def Refresh(self): 5 | """ 6 | Refreshes the graph. This causes the OnRefresh() to be called 7 | """ 8 | _idaapi.pygc_refresh(self) 9 | 10 | def GetCurrentRendererType(self): 11 | return _idaapi.pygc_get_current_renderer_type(self) 12 | 13 | def SetCurrentRendererType(self, rtype): 14 | """ 15 | Set the current view's renderer. 16 | 17 | @param rtype: The renderer type. Should be one of the idaapi.TCCRT_* values. 18 | """ 19 | _idaapi.pygc_set_current_renderer_type(self, rtype) 20 | 21 | def SetNodeInfo(self, node_index, node_info, flags): 22 | """ 23 | Set the properties for the given node. 24 | 25 | Example usage (set second nodes's bg color to red): 26 | inst = ... 27 | p = idaapi.node_info_t() 28 | p.bg_color = 0x00ff0000 29 | inst.SetNodeInfo(1, p, idaapi.NIF_BG_COLOR) 30 | 31 | @param node_index: The node index. 32 | @param node_info: An idaapi.node_info_t instance. 33 | @param flags: An OR'ed value of NIF_* values. 34 | """ 35 | _idaapi.pygc_set_node_info(self, node_index, node_info, flags) 36 | 37 | def SetNodesInfos(self, values): 38 | """ 39 | Set the properties for the given nodes. 40 | 41 | Example usage (set first three nodes's bg color to purple): 42 | inst = ... 43 | p = idaapi.node_info_t() 44 | p.bg_color = 0x00ff00ff 45 | inst.SetNodesInfos({0 : p, 1 : p, 2 : p}) 46 | 47 | @param values: A dictionary of 'int -> node_info_t' objects. 48 | """ 49 | _idaapi.pygc_set_nodes_infos(self, values) 50 | 51 | def GetNodeInfo(self, node): 52 | """ 53 | Get the properties for the given node. 54 | 55 | @param node: The index of the node. 56 | @return: A tuple (bg_color, frame_color, ea, text), or None. 57 | """ 58 | return _idaapi.pygc_get_node_info(self, node) 59 | 60 | def DelNodesInfos(self, *nodes): 61 | """ 62 | Delete the properties for the given node(s). 63 | 64 | @param nodes: A list of node IDs 65 | """ 66 | return _idaapi.pygc_del_nodes_infos(self, nodes) 67 | 68 | def CreateGroups(self, groups_infos): 69 | """ 70 | Send a request to modify the graph by creating a 71 | (set of) group(s), and perform an animation. 72 | 73 | Each object in the 'groups_infos' list must be of the format: 74 | { 75 | "nodes" : [, , , ...] # The list of nodes to group 76 | "text" : # The synthetic text for that group 77 | } 78 | 79 | @param groups_infos: A list of objects that describe those groups. 80 | @return: A [, , ...] list of group nodes, or None (failure). 81 | """ 82 | return _idaapi.pygc_create_groups(self, groups_infos) 83 | 84 | def DeleteGroups(self, groups, new_current = -1): 85 | """ 86 | Send a request to delete the specified groups in the graph, 87 | and perform an animation. 88 | 89 | @param groups: A list of group node numbers. 90 | @param new_current: A node to focus on after the groups have been deleted 91 | @return: True on success, False otherwise. 92 | """ 93 | return _idaapi.pygc_delete_groups(self, groups, new_current) 94 | 95 | def SetGroupsVisibility(self, groups, expand, new_current = -1): 96 | """ 97 | Send a request to expand/collapse the specified groups in the graph, 98 | and perform an animation. 99 | 100 | @param groups: A list of group node numbers. 101 | @param expand: True to expand the group, False otherwise. 102 | @param new_current: A node to focus on after the groups have been expanded/collapsed. 103 | @return: True on success, False otherwise. 104 | """ 105 | return _idaapi.pygc_set_groups_visibility(self, groups, expand, new_current) 106 | 107 | def GetTForm(self): 108 | """ 109 | Return the TForm hosting this view. 110 | 111 | @return: The TForm that hosts this view, or None. 112 | """ 113 | return _idaapi.pycim_get_tform(self) 114 | 115 | def GetTCustomControl(self): 116 | """ 117 | Return the TCustomControl underlying this view. 118 | 119 | @return: The TCustomControl underlying this view, or None. 120 | """ 121 | return _idaapi.pycim_get_tcustom_control(self) 122 | 123 | 124 | # 125 | -------------------------------------------------------------------------------- /pywraps/pywraps.hpp: -------------------------------------------------------------------------------- 1 | // Just a proxy header 2 | #include "../pywraps.hpp" -------------------------------------------------------------------------------- /pywraps/pywraps.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pywraps", "pywraps.vcxproj", "{F43D6BB8-B7D6-486A-82E5-BABBA9848525}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Rel64|Win32 = Rel64|Win32 10 | Release|Win32 = Release|Win32 11 | Release64|Win32 = Release64|Win32 12 | SemiDebug|Win32 = SemiDebug|Win32 13 | SemiDebugx64|Win32 = SemiDebugx64|Win32 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug|Win32.Build.0 = Debug|Win32 18 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Rel64|Win32.ActiveCfg = Rel64|Win32 19 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Rel64|Win32.Build.0 = Rel64|Win32 20 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release|Win32.ActiveCfg = Release|Win32 21 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release|Win32.Build.0 = Release|Win32 22 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release64|Win32.ActiveCfg = Release64|Win32 23 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release64|Win32.Build.0 = Release64|Win32 24 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebug|Win32.ActiveCfg = SemiDebug|Win32 25 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebug|Win32.Build.0 = SemiDebug|Win32 26 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebugx64|Win32.ActiveCfg = SemiDebugx64|Win32 27 | {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebugx64|Win32.Build.0 = SemiDebugx64|Win32 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /pywraps/readme.txt: -------------------------------------------------------------------------------- 1 | ============================ 2 | deploy.py - usage 3 | ============================ 4 | 5 | The deploy script is used to deploy python and c++ code into SWIG interface files appropriately. 6 | The reason it was created was because working with .i files to put a mixture of C++ and Python code is not practical for testing and development process. 7 | 8 | In SWIG, there are three sections: 9 | 10 | Inline 11 | --------- 12 | 13 | C++ code will be wrapped by SWIG. 14 | 15 | In SWIG .i files the inline code is marked with: 16 | %inline %{ 17 | C++ code 18 | %} 19 | 20 | In deploy.py supporting files the code to be pasted into .i files is marked with: 21 | // 22 | C++ code 23 | // 24 | 25 | 26 | Code 27 | ------- 28 | C++ code will be pasted and compiled into the wrapped module but will not be wrapped by SWIG. 29 | 30 | In SWIG .i files the code is marked with: 31 | %{ 32 | C++ code 33 | %} 34 | 35 | Similarly, for deploy.py supporting files should be marked with: 36 | // 37 | C++ code 38 | // 39 | 40 | Pythoncode 41 | -------------- 42 | 43 | Python code allows you to insert Python code into the final Python module. 44 | 45 | In SWIG .i files, the extra python code is marked with: 46 | %pythoncode %{ 47 | Py code 48 | %} 49 | 50 | In deploy.py supporting python files, it is marked with: 51 | # 52 | Py code 53 | # 54 | 55 | Using deploy.py 56 | ------------------ 57 | Make sure that all of the 3 code markers exist in the interface files and deploy.py support files (C++ or Python). 58 | 59 | As an example, let us interpret the meaning of: 60 | deploy.py py_idaapi py_idaapi.hpp,py_idaapi.py ..\swig\idaapi.i 61 | It means: 62 | NAME = py_idaapi 63 | ...take code snips from py_idaapi.hpp and py_idaapi.py 64 | ...and paste the code there into idaapi.i SWIG interface file 65 | 66 | Now remember that both the input files have the special markers (discussed above) and so does idaapi.i file 67 | 68 | 69 | ============================ 70 | linkgen.py - usage 71 | ============================ 72 | TODO 73 | 74 | 75 | ============================ 76 | swigdocs.py - usage 77 | ============================ 78 | 79 | The swigdocs script will extract python comments from SWIG interface files (*.i). 80 | 81 | There are two places where Python code documentation can be found: 82 | 1. In the "%pythoncode %{" section, we extract all the python code because it could contain docstrings. 83 | Inside the pythoncode section, one can find embedded commented that are commented out. 84 | Because they are commented out, the documentation generator will miss them. The swigdocs script will remove the comment character: 85 | # 86 | # def OnClose(self): 87 | # """ 88 | # Called when the window is being closed. 89 | # This callback is mandatory. 90 | # @return: nothing 91 | # """ 92 | # pass 93 | # 94 | After swigdocs finishes, the output will contain all the python code and all the commented code (now uncommented). 95 | 96 | 2. In the "%inline %{" section (in C++ code), one can find functions comments like this: 97 | /* 98 | # 99 | def dbg_read_memory(ea, sz): 100 | """ 101 | Reads from the debugee's memory at the specified ea 102 | @return: 103 | - The read buffer (as a string) 104 | - Or None on failure 105 | """ 106 | pass 107 | # 108 | */ 109 | static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz) 110 | { 111 | ...... 112 | } 113 | In this case, the code inside tag will be extracted as well. 114 | 115 | 116 | After swigdocs finishes, the output is a Python file containing all code and comments extracted from the *.i file(s). -------------------------------------------------------------------------------- /pywraps/swig_stub.cpp: -------------------------------------------------------------------------------- 1 | #include "swig_stub.h" 2 | 3 | PyObject *SWIG_NewPointerObj(void *ptr, void *type, int flags) 4 | { 5 | return PyCObject_FromVoidPtr(ptr, NULL); 6 | } 7 | -------------------------------------------------------------------------------- /pywraps/swig_stub.h: -------------------------------------------------------------------------------- 1 | #ifndef __SWIG_STUB__ 2 | #define __SWIG_STUB__ 3 | 4 | #include 5 | 6 | #define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) 7 | 8 | PyObject *SWIG_NewPointerObj(void *ptr, void *type, int flags); 9 | 10 | namespace Swig 11 | { 12 | class DirectorException 13 | { 14 | public: 15 | const char *getMessage() const 16 | { 17 | return "NULL"; 18 | } 19 | }; 20 | } 21 | 22 | #define SWIG_RUNTIME_VERSION "4" 23 | 24 | // Some fake SWIG types 25 | #define SWIGTYPE_p_member_t NULL 26 | 27 | #endif -------------------------------------------------------------------------------- /swig/allins.i: -------------------------------------------------------------------------------- 1 | // Ignore the unnedded externals 2 | %ignore Instructions; 3 | 4 | %include "allins.hpp" 5 | -------------------------------------------------------------------------------- /swig/area.i: -------------------------------------------------------------------------------- 1 | %ignore ANODE; 2 | %ignore ANODE2; 3 | %ignore AREA_LONG_COMMENT_TAG; 4 | %ignore area_visitor_t; 5 | %ignore areacb_t_link_dont_load; 6 | %ignore add_area_from_cache; 7 | %ignore areacb_t_valid_push_back; 8 | 9 | // Ignore the private members in areacb_t 10 | %ignore areacb_t::areasCode; 11 | %ignore areacb_t::infosize; 12 | %ignore areacb_t::lastreq; 13 | %ignore areacb_t::reserved; 14 | %ignore areacb_t::areas; 15 | %ignore areacb_t::move_area_comment; 16 | %ignore areacb_t::pack_and_write_area; 17 | %ignore areacb_t::move_away; 18 | 19 | %ignore areacb_t::read_cb; 20 | %ignore areacb_t::write_cb; 21 | %ignore areacb_t::delcache_cb; 22 | %ignore areacb_t::edit_cb; 23 | %ignore areacb_t::kill_cb; 24 | %ignore areacb_t::new_cb; 25 | 26 | %ignore areacb_t::choose_area; 27 | %ignore areacb_t::choose_area2; 28 | %ignore areacb_t::find_prev_gap; 29 | %ignore areacb_t::find_next_gap; 30 | 31 | %ignore areacb_t::move_areas; 32 | %ignore areacb_t::for_all_areas; 33 | 34 | %ignore areaset_t::count; 35 | %ignore areaset_t::lower_bound; 36 | %ignore areaset_t::upper_bound; 37 | %ignore areaset_t::move_chunk; 38 | %ignore areaset_t::check_move_args; 39 | 40 | %include "area.hpp" 41 | -------------------------------------------------------------------------------- /swig/auto.i: -------------------------------------------------------------------------------- 1 | %ignore queue_weak_code; 2 | %ignore auto_process_all; 3 | %ignore autoPlanned; 4 | %ignore nextPlanned; 5 | %ignore is_planned_ea; 6 | %ignore get_next_planned_ea; 7 | %ignore autoDelCode; 8 | %ignore autoPeek; 9 | %ignore autoProcess; 10 | %ignore auto_init; 11 | %ignore auto_save; 12 | %ignore auto_term; 13 | %ignore ea_without_xrefs; 14 | %ignore postpone_lastinsn_analysis; 15 | 16 | %include "auto.hpp" 17 | 18 | -------------------------------------------------------------------------------- /swig/entry.i: -------------------------------------------------------------------------------- 1 | %ignore init_entries; 2 | %ignore term_entries; 3 | %ignore move_entries; 4 | %ignore set_entry_name; 5 | 6 | %include "entry.hpp" 7 | 8 | -------------------------------------------------------------------------------- /swig/enum.i: -------------------------------------------------------------------------------- 1 | // Kernel only & unexported symbols 2 | %ignore enums; 3 | %ignore init_enums; 4 | %ignore save_enums; 5 | %ignore term_enums; 6 | %ignore set_enum_flag; 7 | %ignore sync_from_enum;; 8 | %ignore del_all_enum_members; 9 | %ignore get_selected_enum; 10 | %ignore add_selected_enum; 11 | %ignore unmark_selected_enums; 12 | %ignore is_good_bmask; 13 | %ignore get_bmask_enum; 14 | %ignore ENUM_REVERSE; 15 | %ignore ENUM_SELMEMS; 16 | %ignore ENUM_QTY_IDX; 17 | %ignore ENUM_FLG_IDX; 18 | %ignore ENUM_FLAGS; 19 | %ignore ENUM_FLAGS_IS_BF; 20 | %ignore ENUM_FLAGS_HIDDEN; 21 | %ignore ENUM_MASKS; 22 | %ignore ENUM_MEMBERS; 23 | %ignore CONST_ENUM; 24 | %ignore CONST_VALUE; 25 | %ignore CONST_BMASK; 26 | %ignore CONST_SERIAL; 27 | %ignore CONST_SERIALS; 28 | 29 | %include "enum.hpp" 30 | -------------------------------------------------------------------------------- /swig/fixup.i: -------------------------------------------------------------------------------- 1 | %ignore apply_fixup; 2 | %ignore convert_fixups; 3 | %ignore move_fixups; 4 | %ignore custom_fixup_handler_t; 5 | %ignore custom_fixup_handlers_t; 6 | %ignore register_custom_fixup; 7 | %ignore unregister_custom_fixup; 8 | %ignore set_custom_fixup; 9 | 10 | %include "fixup.hpp" 11 | 12 | -------------------------------------------------------------------------------- /swig/frame.i: -------------------------------------------------------------------------------- 1 | %ignore add_frame_spec_member; 2 | %ignore del_stkvars; 3 | %ignore calc_frame_offset; 4 | %ignore read_regvars; 5 | %ignore write_regvars; 6 | %ignore del_regvars; 7 | %ignore free_regvar; 8 | %ignore gen_regvar_defs; 9 | %ignore set_llabel; 10 | %ignore get_llabel_ea; 11 | %ignore get_llabel; 12 | %ignore read_llabels; 13 | %ignore write_llabels; 14 | %ignore del_llabels; 15 | %ignore free_llabel; 16 | %ignore read_stkpnts; 17 | %ignore write_stkpnts; 18 | %ignore del_stkpnts; 19 | %ignore rename_frame; 20 | %ignore _set_frame_size; 21 | %ignore add_empty_frame; 22 | 23 | %ignore get_stkvar; 24 | %rename (get_stkvar) py_get_stkvar; 25 | 26 | %ignore add_stkvar3; 27 | %rename (add_stkvar3) py_add_stkvar3; 28 | 29 | %ignore calc_frame_offset; 30 | %ignore add_stkvar; 31 | 32 | %template(xreflist_t) qvector; 33 | 34 | %include "frame.hpp" 35 | -------------------------------------------------------------------------------- /swig/funcs.i: -------------------------------------------------------------------------------- 1 | %cstring_bounded_output_none(char *buf, MAXSTR); 2 | %cstring_bounded_output_none(char *optlibs, MAXSTR); 3 | 4 | // FIXME: Are these really useful? 5 | %ignore iterate_func_chunks; 6 | %ignore get_idasgn_header_by_short_name; 7 | 8 | // Kernel-only & unexported symbols 9 | %ignore del_regargs; 10 | %ignore write_regargs; 11 | %ignore find_regarg; 12 | %ignore free_regarg; 13 | %ignore determine_rtl; 14 | %ignore init_signatures; 15 | %ignore save_signatures; 16 | %ignore term_signatures; 17 | %ignore init_funcs; 18 | %ignore save_funcs; 19 | %ignore term_funcs; 20 | %ignore move_funcs; 21 | %ignore copy_noret_info; 22 | %ignore recalc_func_noret_flag; 23 | %ignore plan_for_noret_analysis; 24 | %ignore invalidate_sp_analysis; 25 | 26 | %ignore create_func_eas_array; 27 | %ignore auto_add_func_tails; 28 | %ignore read_tails; 29 | 30 | %ignore get_idasgn_desc; 31 | %rename (get_idasgn_desc) py_get_idasgn_desc; 32 | 33 | %ignore get_func_cmt; 34 | %rename (get_func_cmt) py_get_func_cmt; 35 | 36 | %include "funcs.hpp" 37 | 38 | %inline %{ 39 | #ifndef FUNC_STATICDEF 40 | #define FUNC_STATICDEF 0x00000008 41 | #endif 42 | %} 43 | 44 | %clear(char *buf); 45 | %clear(char *optlibs); 46 | 47 | %inline %{ 48 | //----------------------------------------------------------------------- 49 | /* 50 | # 51 | def get_fchunk_referer(ea, idx): 52 | pass 53 | # 54 | */ 55 | static ea_t get_fchunk_referer(ea_t ea, size_t idx) 56 | { 57 | func_t *pfn = get_fchunk(ea); 58 | func_parent_iterator_t dummy(pfn); // read referer info 59 | if (idx >= pfn->refqty || pfn->referers == NULL) 60 | return BADADDR; 61 | else 62 | return pfn->referers[idx]; 63 | } 64 | 65 | //----------------------------------------------------------------------- 66 | /* 67 | # 68 | def get_idasgn_desc(n): 69 | """ 70 | Get information about a signature in the list. 71 | It returns both: the name of the signature, and names of the 72 | optional libraries 73 | 74 | @param n: number of signature in the list (0..get_idasgn_qty()-1) 75 | @return: None on failure or tuple(signame, optlibs) 76 | """ 77 | pass 78 | # 79 | */ 80 | static PyObject *py_get_idasgn_desc(int n) 81 | { 82 | char signame[MAXSTR]; 83 | char optlibs[MAXSTR]; 84 | 85 | if ( get_idasgn_desc(n, signame, sizeof(signame), optlibs, sizeof(optlibs)) == -1 ) 86 | Py_RETURN_NONE; 87 | else 88 | return Py_BuildValue("(ss)", signame, optlibs); 89 | } 90 | 91 | //----------------------------------------------------------------------- 92 | /* 93 | # 94 | def get_func_cmt(fn, repeatable): 95 | """ 96 | Retrieve function comment 97 | @param fn: function instance 98 | @param repeatable: retrieve repeatable or non-repeatable comments 99 | @return: None on failure or the comment 100 | """ 101 | pass 102 | # 103 | */ 104 | static PyObject *py_get_func_cmt(func_t *fn, bool repeatable) 105 | { 106 | char *s = get_func_cmt(fn, repeatable); 107 | if ( s == NULL ) 108 | { 109 | Py_RETURN_NONE; 110 | } 111 | else 112 | { 113 | PyObject *py_s = PyString_FromString(s); 114 | qfree(s); 115 | return py_s; 116 | } 117 | } 118 | %} 119 | -------------------------------------------------------------------------------- /swig/gdl.i: -------------------------------------------------------------------------------- 1 | %ignore cancellable_graph_t; 2 | %ignore gdl_graph_t; 3 | 4 | %ignore intmap_t; 5 | %ignore intset_t; 6 | %ignore intseq_t; 7 | %ignore node_set_t; 8 | %ignore qflow_chart_t::blocks; 9 | %ignore flow_chart_t; 10 | %ignore default_graph_format; 11 | %ignore setup_graph_subsystem; 12 | %ignore qbasic_block_t::succ; 13 | %ignore qbasic_block_t::pred; 14 | 15 | %include "gdl.hpp" 16 | 17 | %extend qflow_chart_t 18 | { 19 | qbasic_block_t *__getitem__(int n) 20 | { 21 | return &(self->blocks[n]); 22 | } 23 | } 24 | 25 | %pythoncode %{ 26 | # 27 | # ----------------------------------------------------------------------- 28 | class BasicBlock(object): 29 | """Basic block class. It is returned by the Flowchart class""" 30 | def __init__(self, id, bb, fc): 31 | self._fc = fc 32 | 33 | self.id = id 34 | """Basic block ID""" 35 | 36 | self.startEA = bb.startEA 37 | """startEA of basic block""" 38 | 39 | self.endEA = bb.endEA 40 | """endEA of basic block""" 41 | 42 | self.type = self._fc._q.calc_block_type(self.id) 43 | """Block type (check fc_block_type_t enum)""" 44 | 45 | 46 | def preds(self): 47 | """ 48 | Iterates the predecessors list 49 | """ 50 | q = self._fc._q 51 | for i in xrange(0, self._fc._q.npred(self.id)): 52 | yield self._fc[q.pred(self.id, i)] 53 | 54 | 55 | def succs(self): 56 | """ 57 | Iterates the successors list 58 | """ 59 | q = self._fc._q 60 | for i in xrange(0, q.nsucc(self.id)): 61 | yield self._fc[q.succ(self.id, i)] 62 | 63 | # ----------------------------------------------------------------------- 64 | class FlowChart(object): 65 | """ 66 | Flowchart class used to determine basic blocks. 67 | Check ex_gdl_qflow_chart.py for sample usage. 68 | """ 69 | def __init__(self, f=None, bounds=None, flags=0): 70 | """ 71 | Constructor 72 | @param f: A func_t type, use get_func(ea) to get a reference 73 | @param bounds: A tuple of the form (start, end). Used if "f" is None 74 | @param flags: one of the FC_xxxx flags. One interesting flag is FC_PREDS 75 | """ 76 | if (f is None) and (bounds is None or type(bounds) != types.TupleType): 77 | raise Exception("Please specifiy either a function or start/end pair") 78 | 79 | if bounds is None: 80 | bounds = (BADADDR, BADADDR) 81 | 82 | # Create the flowchart 83 | self._q = qflow_chart_t("", f, bounds[0], bounds[1], flags) 84 | 85 | size = property(lambda self: self._q.size()) 86 | """Number of blocks in the flow chart""" 87 | 88 | 89 | def refresh(): 90 | """Refreshes the flow chart""" 91 | self._q.refresh() 92 | 93 | 94 | def _getitem(self, index): 95 | return BasicBlock(index, self._q[index], self) 96 | 97 | 98 | def __iter__(self): 99 | return (self._getitem(index) for index in xrange(0, self.size)) 100 | 101 | 102 | def __getitem__(self, index): 103 | """ 104 | Returns a basic block 105 | 106 | @return: BasicBlock 107 | """ 108 | if index >= self.size: 109 | raise KeyError 110 | else: 111 | return self._getitem(index) 112 | 113 | # 114 | %} 115 | -------------------------------------------------------------------------------- /swig/ida.i: -------------------------------------------------------------------------------- 1 | // Ignore kernel-only symbols 2 | %ignore dual_text_options_t; 3 | %ignore idainfo::init; 4 | %ignore idainfo::init_netnode; 5 | %ignore idainfo::precheck_idb_version; 6 | %ignore idainfo::retrieve; 7 | %ignore idainfo::read; 8 | %ignore idainfo::write; 9 | %ignore idainfo::convert_va_format; 10 | %ignore idainfo::upgrade_approved; 11 | %ignore idainfo::will_upgrade; 12 | %ignore idainfo::approve_upgrade; 13 | %ignore idainfo::show_progress; 14 | %ignore idainfo::align_short_demnames; 15 | %ignore idainfo::align_strtype; 16 | %ignore idainfo::align_long_demnames; 17 | 18 | %ignore setflag(uchar &where,uchar bit,int value); 19 | %ignore setflag(ushort &where,ushort bit,int value); 20 | %ignore setflag(uint32 &where,uint32 bit,int value); 21 | 22 | // Make idainfo::get_proc_name() work 23 | %cstring_bounded_output(char *buf, 8); 24 | 25 | %ignore BADADDR; 26 | %ignore BADSEL; 27 | 28 | %include "ida.hpp" 29 | 30 | %clear(char *buf); 31 | -------------------------------------------------------------------------------- /swig/ints.i: -------------------------------------------------------------------------------- 1 | // Kernel-only symbols 2 | %ignore init_predefs; 3 | %ignore term_predefs; 4 | 5 | %include "ints.i" 6 | 7 | -------------------------------------------------------------------------------- /swig/moves.i: -------------------------------------------------------------------------------- 1 | 2 | // Ignore kernel only symbols 3 | %ignore init_marks; 4 | %ignore term_marks; 5 | %ignore change_jumps_stack_format; 6 | %ignore move_marks; 7 | %ignore curloc_after_segments_moved; 8 | %ignore curloc::rebase_stack; 9 | %ignore loc_gtag; 10 | %ignore DEFINE_CURLOC_HELPERS; 11 | %ignore DEFINE_LOCATION_HELPERS; 12 | 13 | %include "moves.hpp" -------------------------------------------------------------------------------- /swig/name.i: -------------------------------------------------------------------------------- 1 | %cstring_output_maxstr_none(char *buf, int bufsize); 2 | 3 | %cstring_bounded_output(char *dstname, MAXSTR); 4 | %cstring_bounded_output(char *buf, MAXSTR); 5 | 6 | // This is for get_name_value's output value 7 | %apply unsigned long *OUTPUT { uval_t *value }; 8 | 9 | // FIXME: These should be fixed 10 | %ignore append_struct_fields; 11 | %ignore get_struct_operand; 12 | %ignore set_debug_names; 13 | %ignore get_debug_name; 14 | %ignore nameVa; 15 | 16 | // Unexported & kernel-only 17 | %ignore get_short_name; 18 | %ignore get_long_name; 19 | %ignore get_colored_short_name; 20 | %ignore get_colored_long_name; 21 | %ignore addDummyName; 22 | %ignore convert_debug_names_to_normal; 23 | %ignore convert_name_formats; 24 | %ignore showhide_name; 25 | %ignore clear_lname_bit; 26 | %ignore fix_new_name; 27 | %ignore rename; 28 | %ignore move_names; 29 | %ignore is_noret_name; 30 | %ignore is_exit_name; 31 | %ignore dummy_name_ea; 32 | 33 | %ignore get_debug_names; 34 | %rename (get_debug_names) py_get_debug_names; 35 | %inline %{ 36 | // 37 | //------------------------------------------------------------------------ 38 | PyObject *py_get_debug_names(ea_t ea1, ea_t ea2) 39 | { 40 | // Get debug names 41 | ea_name_vec_t names; 42 | PYW_GIL_CHECK_LOCKED_SCOPE(); 43 | Py_BEGIN_ALLOW_THREADS; 44 | get_debug_names(ea1, ea2, names); 45 | Py_END_ALLOW_THREADS; 46 | PyObject *dict = Py_BuildValue("{}"); 47 | if (dict != NULL) 48 | { 49 | for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it) 50 | { 51 | PyDict_SetItem(dict, 52 | Py_BuildValue(PY_FMT64, it->ea), 53 | PyString_FromString(it->name.c_str())); 54 | } 55 | } 56 | return dict; 57 | } 58 | //------------------------------------------------------------------------ 59 | // 60 | %} 61 | 62 | %pythoncode %{ 63 | # 64 | 65 | class NearestName: 66 | """ 67 | Utility class to help find the nearest name in a given ea/name dictionary 68 | """ 69 | def __init__(self, ea_names): 70 | self.update(ea_names) 71 | 72 | 73 | def update(self, ea_names): 74 | """Updates the ea/names map""" 75 | self._names = ea_names 76 | self._addrs = ea_names.keys() 77 | self._addrs.sort() 78 | 79 | 80 | def find(self, ea): 81 | """ 82 | Returns a tupple (ea, name, pos) that is the nearest to the passed ea 83 | If no name is matched then None is returned 84 | """ 85 | pos = bisect.bisect_left(self._addrs, ea) 86 | # no match 87 | if pos >= len(self._addrs): 88 | return None 89 | # exact match? 90 | if self._addrs[pos] != ea: 91 | pos -= 1 # go to previous element 92 | if pos < 0: 93 | return None 94 | return self[pos] 95 | 96 | 97 | def _get_item(self, index): 98 | ea = self._addrs[index] 99 | return (ea, self._names[ea], index) 100 | 101 | 102 | def __iter__(self): 103 | return (self._get_item(index) for index in xrange(0, len(self._addrs))) 104 | 105 | 106 | def __getitem__(self, index): 107 | """Returns the tupple (ea, name, index)""" 108 | if index > len(self._addrs): 109 | raise StopIteration 110 | return self._get_item(index) 111 | 112 | # 113 | %} 114 | %include "name.hpp" 115 | -------------------------------------------------------------------------------- /swig/netnode.i: -------------------------------------------------------------------------------- 1 | // Ignore kernel only & unexported symbols 2 | %ignore netlink; 3 | 4 | %ignore RootNode; 5 | %ignore for_all_supvals; 6 | %ignore netErrorHandler; 7 | %ignore netNoDiskSpaceHandler; 8 | %ignore netnode_key_count; 9 | 10 | %ignore netnode_check; 11 | %ignore netnode_kill; 12 | %ignore netnode_start; 13 | %ignore netnode_end; 14 | %ignore netnode_next; 15 | %ignore netnode_prev; 16 | %ignore netnode_name; 17 | %ignore netnode_rename; 18 | %ignore netnode_valobj; 19 | %ignore netnode_valstr; 20 | %ignore netnode_set; 21 | %ignore netnode_delvalue; 22 | %ignore netnode_altval; 23 | %ignore netnode_charval; 24 | %ignore netnode_altval_idx8; 25 | %ignore netnode_charval_idx8; 26 | %ignore netnode_supval; 27 | %ignore netnode_supstr; 28 | %ignore netnode_supset; 29 | %ignore netnode_supdel; 30 | %ignore netnode_sup1st; 31 | %ignore netnode_supnxt; 32 | %ignore netnode_suplast; 33 | %ignore netnode_supprev; 34 | %ignore netnode_supval_idx8; 35 | %ignore netnode_supstr_idx8; 36 | %ignore netnode_supset_idx8; 37 | %ignore netnode_supdel_idx8; 38 | %ignore netnode_sup1st_idx8; 39 | %ignore netnode_supnxt_idx8; 40 | %ignore netnode_suplast_idx8; 41 | %ignore netnode_supprev_idx8; 42 | %ignore netnode_supdel_all; 43 | %ignore netnode_supdel_range; 44 | %ignore netnode_supdel_range_idx8; 45 | %ignore netnode_hashval; 46 | %ignore netnode_hashstr; 47 | %ignore netnode_hashval_long; 48 | %ignore netnode_hashset; 49 | %ignore netnode_hashdel; 50 | %ignore netnode_hash1st; 51 | %ignore netnode_hashnxt; 52 | %ignore netnode_hashlast; 53 | %ignore netnode_hashprev; 54 | %ignore netnode_blobsize; 55 | %ignore netnode_getblob; 56 | %ignore netnode_setblob; 57 | %ignore netnode_delblob; 58 | %ignore netnode_inited; 59 | %ignore netnode_copy; 60 | %ignore netnode_altshift; 61 | %ignore netnode_charshift; 62 | %ignore netnode_supshift; 63 | %ignore netnode_altadjust; 64 | %ignore netnode_exist; 65 | 66 | %ignore netnode::truncate_zero_pages; 67 | %ignore netnode::append_zero_pages; 68 | %ignore netnode::createbase; 69 | %ignore netnode::checkbase; 70 | %ignore netnode::set_close_flag; 71 | %ignore netnode::reserve_nodes; 72 | %ignore netnode::validate; 73 | %ignore netnode::upgrade16; 74 | %ignore netnode::upgrade; 75 | %ignore netnode::compress; 76 | %ignore netnode::inited; 77 | %ignore netnode::init; 78 | %ignore netnode::can_write; 79 | %ignore netnode::flush; 80 | %ignore netnode::get_linput; 81 | %ignore netnode::term; 82 | %ignore netnode::killbase; 83 | %ignore netnode::getdrive; 84 | %ignore netnode::getgraph; 85 | %ignore netnode::registerbase; 86 | %ignore netnode::setbase; 87 | 88 | %ignore netnode::altadjust; 89 | %ignore netnode::getblob(void *buf, size_t *bufsize, nodeidx_t start, char tag); 90 | %ignore netnode::operator nodeidx_t; 91 | %ignore netnode::validate_names; 92 | 93 | // Renaming one version of hashset() otherwise SWIG will not be able to activate the other one 94 | %rename (hashset_idx) netnode::hashset(const char *idx, nodeidx_t value, char tag=htag); 95 | 96 | %include "netnode.hpp" 97 | 98 | %extend netnode 99 | { 100 | nodeidx_t index() 101 | { 102 | return self->operator nodeidx_t(); 103 | } 104 | 105 | PyObject *getblob(nodeidx_t start, const char *tag) 106 | { 107 | // Get the blob and let IDA allocate the memory 108 | size_t bufsize; 109 | void *buf = self->getblob(NULL, &bufsize, start, *tag); 110 | if ( buf == NULL ) 111 | Py_RETURN_NONE; 112 | // Create a Python string 113 | PyObject *py_str = PyString_FromStringAndSize((const char *)buf, bufsize); 114 | // Free memory 115 | qfree(buf); 116 | 117 | return py_str; 118 | } 119 | 120 | PyObject *hashstr_buf(const char *idx, char tag=htag) 121 | { 122 | char buf[MAXSPECSIZE]; 123 | ssize_t sz = self->hashstr(idx, buf, sizeof(buf), tag); 124 | if ( sz < 0 ) 125 | Py_RETURN_NONE; 126 | else 127 | return PyString_FromStringAndSize(buf, sz); 128 | } 129 | 130 | bool hashset_buf(const char *idx, PyObject *py_str, char tag=htag) 131 | { 132 | char *buf; 133 | Py_ssize_t sz; 134 | 135 | if ( PyString_AsStringAndSize(py_str, &buf, &sz) == -1 ) 136 | return false; 137 | else 138 | return self->hashset(idx, buf, sz, tag); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /swig/offset.i: -------------------------------------------------------------------------------- 1 | %ignore calc_probable_base; 2 | 3 | %include "offset.hpp" 4 | -------------------------------------------------------------------------------- /swig/queue.i: -------------------------------------------------------------------------------- 1 | // TODO: This could be wrapped. 2 | %ignore QueueGet; 3 | 4 | // Kernel-only & unexported symbols 5 | %ignore QueueDel(ea_t); 6 | %ignore init_queue; 7 | %ignore save_queue; 8 | %ignore term_queue; 9 | %ignore move_problems; 10 | %ignore queue_del; 11 | 12 | %ignore mark_rollback; 13 | %ignore get_rollback_type; 14 | %ignore mark_ida_decision; 15 | %ignore unmark_ida_decision; 16 | 17 | %include "queue.hpp" -------------------------------------------------------------------------------- /swig/registry.i: -------------------------------------------------------------------------------- 1 | 2 | %ignore reg_bin_op; 3 | %ignore reg_str_op; 4 | %ignore reg_int_op; 5 | %ignore _RVN_; 6 | %ignore REG_VAL_NAME; 7 | %ignore REG_BOOL_FUNC; 8 | %ignore REG_INT_FUNC; 9 | %ignore MAX_HISTORY_FILES_DEF; 10 | %ignore regkey_history; 11 | %ignore max_history_files; 12 | %ignore regget_history; 13 | %ignore reg_update_history; 14 | %ignore reg_history_size_truncate; 15 | 16 | %ignore reg_read_string; 17 | %rename (reg_read_string) py_reg_read_string; 18 | 19 | %ignore reg_data_type; 20 | %rename (reg_data_type) py_reg_data_type; 21 | 22 | %ignore reg_read_binary; 23 | %rename (reg_read_binary) py_reg_read_binary; 24 | %ignore reg_write_binary; 25 | %rename (reg_write_binary) py_reg_write_binary; 26 | 27 | %ignore reg_read_binary_part; 28 | 29 | /* inline bool reg_subkey_subkeys(qstrvec_t *out, const char *name) */ 30 | %ignore reg_subkey_subkeys; 31 | %rename (reg_subkey_subkeys) py_reg_subkey_subkeys; 32 | %ignore reg_subkey_values; 33 | %rename (reg_subkey_values) py_reg_subkey_values; 34 | %ignore reg_subkey_children; 35 | 36 | %{ 37 | // 38 | //------------------------------------------------------------------------- 39 | static PyObject *_py_reg_subkey_children(const char *name, bool subkeys) 40 | { 41 | PYW_GIL_CHECK_LOCKED_SCOPE(); 42 | PyObject *result = NULL; 43 | qstrvec_t children; 44 | Py_BEGIN_ALLOW_THREADS; 45 | if ( reg_subkey_children(&children, name, subkeys) ) 46 | { 47 | result = PyList_New(children.size()); 48 | if ( result != NULL ) 49 | for ( size_t i = 0, n = children.size(); i < n; ++i ) 50 | PyList_SET_ITEM(result, i, PyString_FromString(children[i].c_str())); 51 | } 52 | Py_END_ALLOW_THREADS; 53 | if ( result == NULL ) 54 | Py_RETURN_NONE; 55 | else 56 | return result; 57 | } 58 | // 59 | %} 60 | 61 | %inline %{ 62 | // 63 | //------------------------------------------------------------------------- 64 | PyObject *py_reg_read_string(const char *name, const char *subkey = NULL, const char *def = NULL) 65 | { 66 | PYW_GIL_CHECK_LOCKED_SCOPE(); 67 | char utf8[MAXSTR * 10]; 68 | bool ok; 69 | Py_BEGIN_ALLOW_THREADS; 70 | if ( def == NULL ) 71 | { 72 | ok = reg_read_string(name, utf8, sizeof(utf8), subkey); 73 | } 74 | else 75 | { 76 | reg_read_string(name, sizeof(utf8), utf8, def, subkey); 77 | ok = true; 78 | } 79 | Py_END_ALLOW_THREADS; 80 | return PyString_FromString(ok ? utf8 : ""); 81 | } 82 | 83 | //------------------------------------------------------------------------- 84 | regval_type_t py_reg_data_type(const char *name, const char *subkey = NULL) 85 | { 86 | PYW_GIL_CHECK_LOCKED_SCOPE(); 87 | regval_type_t rt = reg_unknown; 88 | Py_BEGIN_ALLOW_THREADS; 89 | reg_data_type(&rt, name, subkey); 90 | Py_END_ALLOW_THREADS; 91 | return rt; 92 | } 93 | 94 | //------------------------------------------------------------------------- 95 | PyObject *py_reg_read_binary(const char *name, const char *subkey = NULL) 96 | { 97 | PYW_GIL_CHECK_LOCKED_SCOPE(); 98 | bytevec_t bytes; 99 | bool ok; 100 | Py_BEGIN_ALLOW_THREADS; 101 | ok = reg_read_binary(name, &bytes, subkey); 102 | Py_END_ALLOW_THREADS; 103 | if ( ok ) 104 | return PyString_FromStringAndSize((const char *) bytes.begin(), bytes.size()); 105 | else 106 | Py_RETURN_NONE; 107 | } 108 | 109 | //------------------------------------------------------------------------- 110 | void py_reg_write_binary(const char *name, PyObject *py_bytes, const char *subkey = NULL) 111 | { 112 | PYW_GIL_CHECK_LOCKED_SCOPE(); 113 | if ( PyString_Check(py_bytes) ) 114 | { 115 | char *py_bytes_raw = NULL; 116 | Py_ssize_t py_size = 0; 117 | PyString_AsStringAndSize(py_bytes, &py_bytes_raw, &py_size); 118 | bytevec_t bytes; 119 | bytes.append(py_bytes_raw, py_size); 120 | Py_BEGIN_ALLOW_THREADS; 121 | reg_write_binary(name, bytes.begin(), bytes.size(), subkey); 122 | Py_END_ALLOW_THREADS; 123 | } 124 | else 125 | { 126 | PyErr_SetString(PyExc_ValueError, "Bytes string expected!"); 127 | } 128 | } 129 | 130 | //------------------------------------------------------------------------- 131 | PyObject *py_reg_subkey_subkeys(const char *name) 132 | { 133 | return _py_reg_subkey_children(name, true); 134 | } 135 | 136 | //------------------------------------------------------------------------- 137 | PyObject *py_reg_subkey_values(const char *name) 138 | { 139 | return _py_reg_subkey_children(name, false); 140 | } 141 | 142 | // 143 | %} 144 | 145 | %include "registry.hpp" 146 | -------------------------------------------------------------------------------- /swig/search.i: -------------------------------------------------------------------------------- 1 | %apply int * OUTPUT { int *opnum }; 2 | 3 | %ignore search; 4 | %ignore user2bin; 5 | 6 | %include "search.hpp" 7 | %clear int *opnum; 8 | -------------------------------------------------------------------------------- /swig/segment.i: -------------------------------------------------------------------------------- 1 | // Ignore functions with callbacks 2 | %ignore enumerate_selectors; 3 | %ignore enumerate_segments_with_selector; 4 | 5 | // Kernel-only 6 | %ignore init_groups; 7 | %ignore save_groups; 8 | %ignore term_groups; 9 | %ignore vset_segm_name; 10 | %ignore get_segm_expr; 11 | %ignore get_based_segm_expr; 12 | %ignore createSegmentation; 13 | %ignore initSegment; 14 | %ignore save_segments; 15 | %ignore termSegment; 16 | %ignore DeleteAllSegments; 17 | %ignore delete_debug_segments; 18 | %ignore is_debugger_segm; 19 | %ignore is_ephemeral_segm; 20 | %ignore correct_address; 21 | 22 | %{ 23 | void segment_t_startEA_set(segment_t *segm, ea_t newea) 24 | { 25 | if ( getseg(segm->startEA) == segm ) 26 | { 27 | PyErr_SetString(PyExc_AttributeError, "Can't modify startEA, please use set_segm_start() instead"); 28 | } 29 | else 30 | { 31 | segm->startEA = newea; 32 | } 33 | } 34 | 35 | ea_t segment_t_startEA_get(segment_t *segm) 36 | { 37 | return segm->startEA; 38 | } 39 | 40 | void segment_t_endEA_set(segment_t *segm, ea_t newea) 41 | { 42 | if ( getseg(segm->startEA) == segm ) 43 | { 44 | PyErr_SetString(PyExc_AttributeError, "Can't modify endEA, please use set_segm_end() instead"); 45 | } 46 | else 47 | { 48 | segm->endEA = newea; 49 | } 50 | } 51 | 52 | ea_t segment_t_endEA_get(segment_t *segm) 53 | { 54 | return segm->endEA; 55 | } 56 | %} 57 | %extend segment_t 58 | { 59 | ea_t startEA; 60 | ea_t endEA; 61 | } 62 | 63 | %include "segment.hpp" 64 | 65 | %inline %{ 66 | sel_t get_defsr(segment_t *s, int reg) 67 | { 68 | return s->defsr[reg]; 69 | } 70 | void set_defsr(segment_t *s, int reg, sel_t value) 71 | { 72 | s->defsr[reg] = value; 73 | } 74 | %} 75 | -------------------------------------------------------------------------------- /swig/srarea.i: -------------------------------------------------------------------------------- 1 | // Ignore kernel-only symbols 2 | %ignore repairSRarea; 3 | 4 | %ignore init_srarea; 5 | %ignore term_srarea; 6 | %ignore reset_srarea; 7 | %ignore add_srarea_from_cache; 8 | %ignore srareas_got_loaded; 9 | %ignore save_srarea; 10 | %ignore create_segment_registers_area; 11 | %ignore set_segment_register_start; 12 | %ignore set_segment_register_end; 13 | %ignore kill_srareras; 14 | %ignore create_srarea; 15 | %ignore del_srareas; 16 | %ignore move_srareas; 17 | %ignore delete_v660_segreg_t; 18 | %ignore v660_segreg_t; 19 | 20 | %ignore SRareas_get_area; 21 | %ignore SRareas_get_area_qty; 22 | %ignore SRareas_getn_area; 23 | %ignore SRareas_update; 24 | %ignore SRareas_get_area_num; 25 | %ignore SRareas_get_next_area; 26 | %ignore SRareas_get_prev_area; 27 | %ignore SRareas_next_area_ptr; 28 | %ignore SRareas_prev_area_ptr; 29 | %ignore SRareas_first_area_ptr; 30 | %ignore SRareas_choose_area2; 31 | %ignore SRareas_may_start_at; 32 | %ignore SRareas_may_end_at; 33 | %ignore SRareas_set_start; 34 | %ignore SRareas_set_end; 35 | %ignore SRareas_prepare_to_create; 36 | %ignore SRareas_create_area; 37 | %ignore SRareas_for_all_areas2; 38 | %ignore SRareas_del_area; 39 | 40 | %ignore segreg_t::tag(int n); 41 | %ignore segreg_t::reg(int n); 42 | 43 | #define R_es 29 44 | #define R_cs 30 45 | #define R_ss 31 46 | #define R_ds 32 47 | #define R_fs 33 48 | #define R_gs 34 49 | 50 | %include "srarea.hpp" 51 | -------------------------------------------------------------------------------- /swig/strlist.i: -------------------------------------------------------------------------------- 1 | // Ignore kernel-only symbol 2 | 3 | %ignore strwinsetup_t::setup_strings_window; 4 | %ignore strwinsetup_t::save_config; 5 | %ignore strwinsetup_t::restore_config; 6 | 7 | %ignore move_strings; 8 | 9 | 10 | 11 | %include "strlist.hpp" 12 | -------------------------------------------------------------------------------- /swig/struct.i: -------------------------------------------------------------------------------- 1 | // Kernel-only symbols 2 | %ignore init_structs; 3 | %ignore save_structs; 4 | %ignore term_structs; 5 | 6 | %ignore sync_from_struc; 7 | 8 | %include "struct.hpp" 9 | // Add a get_member() member function to struc_t. 10 | // This helps to access the members array in the class. 11 | %extend struc_t { 12 | member_t *get_member(int index) { return &(self->members[index]); } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /swig/xref.i: -------------------------------------------------------------------------------- 1 | // Ignore kernel-only functions and variables 2 | %ignore create_xrefs_from; 3 | %ignore create_xrefs_from_data; 4 | %ignore delete_all_xrefs_from; 5 | %ignore delete_data_xrefs_from; 6 | %ignore delete_code_xrefs_from; 7 | %ignore destroy_if_align; 8 | %ignore lastXR; 9 | %ignore has_jump_or_flow_xref; 10 | %ignore has_call_xref; 11 | %ignore destroy_switch_info; 12 | %ignore create_switch_xrefs; 13 | %ignore create_switch_table; 14 | %rename (calc_switch_cases) py_calc_switch_cases; 15 | 16 | // These functions should not be called directly (according to docs) 17 | %ignore xrefblk_t_first_from; 18 | %ignore xrefblk_t_next_from; 19 | %ignore xrefblk_t_first_to; 20 | %ignore xrefblk_t_next_to; 21 | 22 | // 'from' is a reserved Python keyword 23 | %rename (frm) from; 24 | 25 | %include "xref.hpp" 26 | -------------------------------------------------------------------------------- /tools/gendocs.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # gendoc.py: Generate an API cross-reference for IDAPython 3 | #------------------------------------------------------------ 4 | __author__ = "Gergely Erdelyi " 5 | 6 | import epydoc.cli 7 | 8 | # This is a small hack to prevent epydoc from exiting the whole 9 | # IDA process in case something goes wrong. 10 | def exit(eval): 11 | print "not exiting" 12 | epydoc.cli.sys.exit = exit 13 | 14 | # Fill in the command-line arguments 15 | epydoc.cli.optparse.sys.argv = [ 'epydoc', 16 | '--no-sourcecode', 17 | '-u', 'http://www.d-dome.net/idapython/', 18 | '--navlink', 'IDAPython Reference', 19 | '--no-private', 20 | '--simple-term', 21 | '-o', 'idapython-reference-%d.%d.%d' % (IDAPYTHON_VERSION[:3]), 22 | '--html', 23 | 'idc', 'idautils', 'idaapi' ] 24 | # Generate the documentation 25 | epydoc.cli.cli() 26 | -------------------------------------------------------------------------------- /tools/swigdocs.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This script is used to extract embedded documentation strings 3 | # from SWIG interface files. 4 | # (c) Hex-Rays 5 | # 6 | import glob 7 | import sys 8 | import os 9 | 10 | # --------------------------------------------------------------------------- 11 | def extract_docs(lines, out): 12 | S_SWIG_CLOSE = '%}' 13 | S_PYDOC_START = '#' 14 | S_PYDOC_END = '#' 15 | S_COMMENT = '#' 16 | S_INLINE = '%inline %{' 17 | S_PYCODE_START = '%pythoncode %{' 18 | 19 | in_inline = False 20 | in_pythoncode = False 21 | in_pydoc = False 22 | 23 | for line in lines: 24 | line = line.rstrip() 25 | # skip empty lines 26 | if not line: 27 | continue 28 | 29 | # Inside pythoncode tag? 30 | if in_pythoncode: 31 | if line == S_PYDOC_START: 32 | in_pydoc = True 33 | continue 34 | elif line == S_PYDOC_END: 35 | in_pydoc = False 36 | continue 37 | elif line == S_SWIG_CLOSE: 38 | in_pythoncode = False 39 | continue 40 | # Skip unneeded tags 41 | elif line[:8] == '#