├── pywraps
├── deploy.bat
├── pywraps.hpp
├── py_dbg.py
├── swig_stub.cpp
├── py_diskio.py
├── py_typeinf.py
├── swig_stub.h
├── driver_nalt.cpp
├── py_idaview.py
├── driver_bytes.cpp
├── py_name.hpp
├── driver_notifywhen.cpp
├── driver_cli.cpp
├── py_lines.py
├── py_name.py
├── driver_graph.cpp
├── driver_diskio.cpp
├── pywraps.sln
├── driver_expr.cpp
├── py_choose.hpp
├── py_diskio.hpp
├── py_notifywhen.py
├── py_loader.hpp
├── py_idaview.hpp
├── driver_dbg.cpp
├── py_gdl.py
├── driver_kernwin.cpp
├── driver_custdata.cpp
├── deploy.py
├── py_registry.hpp
├── py_kernwin.py
├── readme.txt
├── driver_chooser.cpp
├── py_plgform.hpp
├── py_plgform.py
├── py_expr.hpp
└── py_view_base.py
├── swig
├── offset.i
├── allins.i
├── ints.i
├── entry.i
├── search.i
├── strlist.i
├── fixup.i
├── moves.i
├── struct.i
├── queue.i
├── auto.i
├── enum.i
├── xref.i
├── frame.i
├── ida.i
├── area.i
├── srarea.i
├── segment.i
├── funcs.i
├── name.i
├── gdl.i
├── netnode.i
└── registry.i
├── basetsd.h
├── idaapi.i
├── examples
├── ex_strings.py
├── ex_debug_names.py
├── ex_expr.py
├── ex_add_menu_item.py
├── vds1.py
├── idapythonrc.py
├── colours.py
├── ex_hotkey.py
├── hotkey.py
├── ex1_idautils.py
├── ex_imports.py
├── ex1.idc
├── ex1_idaapi.py
├── ex_pyside.py
├── ex_pyqt.py
├── ex_func_chooser.py
├── ex_prefix_plugin.py
├── ex_patch.py
├── ex_timer.py
├── chooser.py
├── ex_gdl_qflow_chart.py
├── ex_idphook_asm.py
├── vds7.py
├── ex_dbg.py
├── structure.py
├── ex_uihook.py
├── ex_graph.py
├── ex_uirequests.py
├── ex_cli.py
├── debughook.py
├── ex_idagraph.py
├── vds4.py
└── ex_choose2.py
├── python.cfg
├── AUTHORS.txt
├── tools
├── gendocs.py
└── swigdocs.py
├── idapython.sln
├── Scripts
├── ExchainDump.py
├── msdnapihelp.py
├── callstack_test.py
├── ImpRef.py
├── VaDump.py
├── PteDump.py
├── DbgCmd.py
├── DrvsDispatch.py
└── ImportExportViewer.py
├── COPYING.txt
├── docs
└── notes.txt
├── patch_directors_cc.py
├── STATUS.txt
├── BUILDING.txt
├── README.txt
├── hrdoc.py
└── python
└── init.py
/pywraps/deploy.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | deploy_all.py
3 |
--------------------------------------------------------------------------------
/pywraps/pywraps.hpp:
--------------------------------------------------------------------------------
1 | // Just a proxy header
2 | #include "../pywraps.hpp"
--------------------------------------------------------------------------------
/swig/offset.i:
--------------------------------------------------------------------------------
1 | %ignore calc_probable_base;
2 |
3 | %include "offset.hpp"
4 |
--------------------------------------------------------------------------------
/swig/allins.i:
--------------------------------------------------------------------------------
1 | // Ignore the unnedded externals
2 | %ignore Instructions;
3 |
4 | %include "allins.hpp"
5 |
--------------------------------------------------------------------------------
/swig/ints.i:
--------------------------------------------------------------------------------
1 | // Kernel-only symbols
2 | %ignore init_predefs;
3 | %ignore term_predefs;
4 |
5 | %include "ints.i"
6 |
7 |
--------------------------------------------------------------------------------
/pywraps/py_dbg.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | NO_PROCESS = 0xFFFFFFFF
4 | NO_THREAD = 0
5 | #
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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"
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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_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")
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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);
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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()
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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()
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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()
--------------------------------------------------------------------------------
/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);
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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_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_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()
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 | #
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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_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);
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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"
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | """)
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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!"
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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_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_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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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_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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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%(tag)s\(%(m)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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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] == '#' + 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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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).
--------------------------------------------------------------------------------
/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()
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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_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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------