mirror of
https://github.com/cemu-project/idapython.git
synced 2025-04-20 09:51:27 +02:00
Compare commits
338 Commits
build-0.9.
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0028bac297 | ||
![]() |
a2c4f50f31 | ||
![]() |
f9f3ccb63b | ||
![]() |
2fa1f9a64b | ||
![]() |
081b988a03 | ||
![]() |
3e9ea5f503 | ||
![]() |
bbf628d3a3 | ||
![]() |
49dcdc5ed3 | ||
![]() |
960a670de9 | ||
![]() |
fbb5bfabd6 | ||
![]() |
1c6752de40 | ||
![]() |
866e631dc7 | ||
![]() |
78c79f85b9 | ||
![]() |
c88a77e809 | ||
![]() |
7eb6d04c6e | ||
![]() |
db58b31711 | ||
![]() |
ce06fdd7d2 | ||
![]() |
4e295155bb | ||
![]() |
21cd5a95eb | ||
![]() |
223e4a5268 | ||
![]() |
69d5c83d28 | ||
![]() |
4d21b10dc4 | ||
![]() |
0282e67982 | ||
![]() |
06f0ff19d5 | ||
![]() |
930d7cbcd4 | ||
![]() |
1258fab948 | ||
![]() |
96cd02db6c | ||
![]() |
7bd77d534c | ||
![]() |
8413f9f791 | ||
![]() |
f5ec434bf7 | ||
![]() |
88aa875c55 | ||
![]() |
c29e1ef2da | ||
![]() |
2327aada40 | ||
![]() |
7e63ea0747 | ||
![]() |
a12974b66c | ||
![]() |
c94f5c10bb | ||
![]() |
a52b90c771 | ||
![]() |
7179b2c654 | ||
![]() |
50b66d0264 | ||
![]() |
47f7f2e48b | ||
![]() |
8375368d6d | ||
![]() |
58a002ce5b | ||
![]() |
109158fabb | ||
![]() |
63b22d00d5 | ||
![]() |
1bd58bda60 | ||
![]() |
197a94f5d7 | ||
![]() |
ac5d88a83b | ||
![]() |
1d2f1d1f07 | ||
![]() |
faf5063818 | ||
![]() |
80896bc1d9 | ||
![]() |
36c814331a | ||
![]() |
0f64f33981 | ||
![]() |
930b333d3b | ||
![]() |
2d763844ed | ||
![]() |
40d46c34a9 | ||
![]() |
67c94b2f02 | ||
![]() |
2c33ce00c5 | ||
![]() |
4867b405a9 | ||
![]() |
f216eb9a6d | ||
![]() |
9858aae998 | ||
![]() |
c1d87c0c7c | ||
![]() |
15a72289f7 | ||
![]() |
686e018bdc | ||
![]() |
97a9805336 | ||
![]() |
d76ccd7b1e | ||
![]() |
6b0dfd84c0 | ||
![]() |
8495e5205b | ||
![]() |
4b1c3cd4c4 | ||
![]() |
5b59791156 | ||
![]() |
3a5063330c | ||
![]() |
5f2262fad9 | ||
![]() |
8ecfe8b218 | ||
![]() |
7da6dd916c | ||
![]() |
5cede13626 | ||
![]() |
f4b1a7d87c | ||
![]() |
69e35391a5 | ||
![]() |
ff7ab3f1dc | ||
![]() |
f09375cf70 | ||
![]() |
0c6b9b31b9 | ||
![]() |
6112217cab | ||
![]() |
1157ea1487 | ||
![]() |
1757dec387 | ||
![]() |
dc20f63143 | ||
![]() |
0dfdad1f42 | ||
![]() |
0acf7aa44a | ||
![]() |
3e0343daf5 | ||
![]() |
ecb4232040 | ||
![]() |
53d99a141a | ||
![]() |
4bd83af5a3 | ||
![]() |
0c11d8f170 | ||
![]() |
ab81000187 | ||
![]() |
729084a1ff | ||
![]() |
f57af01a21 | ||
![]() |
ee8fab6c4c | ||
![]() |
8e78513e91 | ||
![]() |
57d37a638a | ||
![]() |
b935e24aba | ||
![]() |
33c93df0cf | ||
![]() |
7d32ff30f0 | ||
![]() |
42a2f7f630 | ||
![]() |
8b7625f145 | ||
![]() |
06e8cad773 | ||
![]() |
e056f5670f | ||
![]() |
bbabb3d6fa | ||
![]() |
dd5273fee9 | ||
![]() |
e1298031ac | ||
![]() |
5ec97ef3aa | ||
![]() |
ea4cd26a6a | ||
![]() |
a39ada9fb6 | ||
![]() |
d7c6f94f08 | ||
![]() |
277facf240 | ||
![]() |
ab7a03431e | ||
![]() |
0e9f53eaad | ||
![]() |
01601d7eea | ||
![]() |
7970f9696d | ||
![]() |
b9465ab7f6 | ||
![]() |
06e3f4f80f | ||
![]() |
62b9382ee8 | ||
![]() |
608c8f0eb8 | ||
![]() |
dac4a0629e | ||
![]() |
a4627a6d36 | ||
![]() |
3862f05f3f | ||
![]() |
99c60a82de | ||
![]() |
c21a932cec | ||
![]() |
cb57938dcc | ||
![]() |
9d3fb35f87 | ||
![]() |
bbf6b2e547 | ||
![]() |
2edeeae88b | ||
![]() |
8e66e14588 | ||
![]() |
9c80378afe | ||
![]() |
2f31ce656b | ||
![]() |
b09eea4de8 | ||
![]() |
9917459559 | ||
![]() |
4191b186d9 | ||
![]() |
5fe579530a | ||
![]() |
e2a0ee8204 | ||
![]() |
7ea3709021 | ||
![]() |
d278419064 | ||
![]() |
56f6dc02be | ||
![]() |
9f4df6991f | ||
![]() |
45099f4ad4 | ||
![]() |
5e0deab556 | ||
![]() |
8bf3e2054d | ||
![]() |
4e02442b9a | ||
![]() |
910f88f6b7 | ||
![]() |
3ea31d70c7 | ||
![]() |
38b7c484f3 | ||
![]() |
e27524cca5 | ||
![]() |
e51eb69e3a | ||
![]() |
5e93f49c97 | ||
![]() |
08ea62d8fa | ||
![]() |
39d692c258 | ||
![]() |
e48d6a99ff | ||
![]() |
fb507d9f85 | ||
![]() |
5b0260c301 | ||
![]() |
02c6a5519e | ||
![]() |
88f7e089aa | ||
![]() |
ab34ed6573 | ||
![]() |
013546b569 | ||
![]() |
a01b3fbde0 | ||
![]() |
1a4a43a389 | ||
![]() |
860c96daf3 | ||
![]() |
2395fd6b1d | ||
![]() |
573ffccc4e | ||
![]() |
b9f442ee1d | ||
![]() |
b22d629990 | ||
![]() |
b184767ba0 | ||
![]() |
3eb4d4710a | ||
![]() |
9530fbacfa | ||
![]() |
9876c4ffa7 | ||
![]() |
b0d8723ccb | ||
![]() |
09ead310b7 | ||
![]() |
c25f1a0121 | ||
![]() |
e64fdf16b3 | ||
![]() |
5cb6044277 | ||
![]() |
700dcef6cd | ||
![]() |
b5f3edf5fc | ||
![]() |
dadf628feb | ||
![]() |
2cc8e934f6 | ||
![]() |
e0de735f3d | ||
![]() |
7d468f3b94 | ||
![]() |
f2e422d208 | ||
![]() |
d197df5653 | ||
![]() |
3fbe778385 | ||
![]() |
dec108c25b | ||
![]() |
5a66395061 | ||
![]() |
05e10a0f25 | ||
![]() |
ef9921587b | ||
![]() |
260c813f05 | ||
![]() |
097a6ae4b0 | ||
![]() |
791fde6af7 | ||
![]() |
9b6a6eda86 | ||
![]() |
b4d2b3f813 | ||
![]() |
6d6f4f70fc | ||
![]() |
78ca9145bf | ||
![]() |
b21e3b5230 | ||
![]() |
d26536abd4 | ||
![]() |
769e9d70f4 | ||
![]() |
864165a44c | ||
![]() |
5e1871f485 | ||
![]() |
1c4a240cfb | ||
![]() |
5876f4324f | ||
![]() |
252fcf8052 | ||
![]() |
f9f30154d2 | ||
![]() |
8f69725171 | ||
![]() |
a91da72224 | ||
![]() |
56476d656a | ||
![]() |
265db07b35 | ||
![]() |
a447822586 | ||
![]() |
f4f5aa0441 | ||
![]() |
927ccec772 | ||
![]() |
f352f77edf | ||
![]() |
b961ced412 | ||
![]() |
32654c9ee8 | ||
![]() |
e4aaf2b166 | ||
![]() |
419a08135a | ||
![]() |
f703a5fb3c | ||
![]() |
48301d9703 | ||
![]() |
b97846eeae | ||
![]() |
0b812262a7 | ||
![]() |
9a8f92ac52 | ||
![]() |
e9f1e04519 | ||
![]() |
d3ac331e36 | ||
![]() |
00224b8e40 | ||
![]() |
c1e87cc17b | ||
![]() |
98240e2ee9 | ||
![]() |
599d1c3c29 | ||
![]() |
0bc9d6477c | ||
![]() |
04492e420c | ||
![]() |
43af79132f | ||
![]() |
1a45b5952a | ||
![]() |
507ea15b7a | ||
![]() |
473bd07bdb | ||
![]() |
f8c34bd805 | ||
![]() |
bb99a7076e | ||
![]() |
b687523dd9 | ||
![]() |
f59fbb02fe | ||
![]() |
1da716734e | ||
![]() |
9fe2d0048b | ||
![]() |
867940ae80 | ||
![]() |
c03dd84eef | ||
![]() |
d05ef16b13 | ||
![]() |
e0e7d9d56c | ||
![]() |
e8df46dc30 | ||
![]() |
ef61a9bac7 | ||
![]() |
caecd08a77 | ||
![]() |
97213fabb4 | ||
![]() |
ca5ed24ff0 | ||
![]() |
7d0f743143 | ||
![]() |
23dcd0a165 | ||
![]() |
0b8d39d230 | ||
![]() |
b499990614 | ||
![]() |
919b3d9987 | ||
![]() |
c8f6c02147 | ||
![]() |
490fa999c4 | ||
![]() |
ec4d2f7a06 | ||
![]() |
1844d89d34 | ||
![]() |
91df782723 | ||
![]() |
ee137adaa6 | ||
![]() |
8d9869b527 | ||
![]() |
b4552cb676 | ||
![]() |
6449172afe | ||
![]() |
2d4662a3c3 | ||
![]() |
2c09e0e429 | ||
![]() |
b6a6513dec | ||
![]() |
e994bd9d11 | ||
![]() |
70e5a9a55c | ||
![]() |
a7726cbbd6 | ||
![]() |
b6864df344 | ||
![]() |
17a5eca7a6 | ||
![]() |
e0186f450a | ||
![]() |
358d85ac46 | ||
![]() |
e3a0a26f16 | ||
![]() |
ab13c8b983 | ||
![]() |
d39feebe72 | ||
![]() |
b4e25f451a | ||
![]() |
565a80c62e | ||
![]() |
187f75d329 | ||
![]() |
8bac109f3b | ||
![]() |
76aa24fecd | ||
![]() |
3656585dd8 | ||
![]() |
9498c80547 | ||
![]() |
d06fa3e155 | ||
![]() |
29187c6f53 | ||
![]() |
e4d97c7261 | ||
![]() |
a73663582e | ||
![]() |
61796a5623 | ||
![]() |
9450a528fd | ||
![]() |
79493bdb4f | ||
![]() |
ea7daef522 | ||
![]() |
353b4f9f92 | ||
![]() |
a0beaefd26 | ||
![]() |
2a77375c0e | ||
![]() |
08f81d8b96 | ||
![]() |
86d9408b93 | ||
![]() |
1a7b765989 | ||
![]() |
af27d1a6dd | ||
![]() |
a8f6676623 | ||
![]() |
9b2a2fd02d | ||
![]() |
9c4907d76c | ||
![]() |
a33eeef018 | ||
![]() |
04af0d20f5 | ||
![]() |
40846fe7c9 | ||
![]() |
ee564d8a03 | ||
![]() |
c947c3f759 | ||
![]() |
c026c32dc7 | ||
![]() |
e2f6ba10dc | ||
![]() |
0315608029 | ||
![]() |
375606cefd | ||
![]() |
754622e1c4 | ||
![]() |
c6444d4ff5 | ||
![]() |
0065fdce94 | ||
![]() |
398ffdae3a | ||
![]() |
921d57098a | ||
![]() |
a979882e50 | ||
![]() |
ae694a52ba | ||
![]() |
9216f83c87 | ||
![]() |
f103d84c83 | ||
![]() |
e94a201897 | ||
![]() |
c4830f3e81 | ||
![]() |
d0e3a964d8 | ||
![]() |
52f26ecf67 | ||
![]() |
52d048cf5b | ||
![]() |
471191088b | ||
![]() |
b500b41661 | ||
![]() |
f9e166c69c | ||
![]() |
6ac2bb185d | ||
![]() |
4762f325d9 | ||
![]() |
c08d06ab82 | ||
![]() |
6b739548fc | ||
![]() |
18b7a6b0ad | ||
![]() |
a24d2753ec | ||
![]() |
d99b2eb64b | ||
![]() |
bab52674ca | ||
![]() |
45b614fff0 | ||
![]() |
4059c6ec72 | ||
![]() |
ef44c5f123 | ||
![]() |
fc25932632 |
27
AUTHORS.txt
Normal file
27
AUTHORS.txt
Normal file
@ -0,0 +1,27 @@
|
||||
The IDAPython Team:
|
||||
|
||||
* Gergely Erdelyi - http://d-dome.net/idapython/
|
||||
|
||||
Original IDAPython author - The IDAPython Guy -
|
||||
|
||||
|
||||
* Hex-Rays - http://www.hex-rays.com/ - <support@hex-rays.com>
|
||||
|
||||
Hex-Rays joined the IDAPython project in September 2009 and started contributing.
|
||||
It is primarily maintained, updated and improved by Arnaud Diederen of Hex-Rays.
|
||||
|
||||
* Elias Bachaalany - elias.bachaalany@gmail.com
|
||||
Maintains IDAPython online source code repository and coordinates patches/updates/contributions from Hex-Rays and 3rd party contributors
|
||||
|
||||
|
||||
* Ero Carrera - http://dkbza.org/
|
||||
|
||||
Project contributor
|
||||
|
||||
|
||||
* Special thanks to the following people for their contribution, suggestions and bug fixes:
|
||||
|
||||
Igor Skochinsky
|
||||
Sebastian Muniz
|
||||
cbwhiz
|
||||
Arnaud Diederen
|
141
BUILDING.txt
141
BUILDING.txt
@ -1,63 +1,78 @@
|
||||
----------------------------------------------------------
|
||||
IDAPython - Python plugin for Interactive Disassembler Pro
|
||||
----------------------------------------------------------
|
||||
Building From Source
|
||||
--------------------
|
||||
|
||||
REQUIREMENTS
|
||||
|
||||
[Tested versions are in brackets]
|
||||
|
||||
- IDA and IDA SDK [5.1]
|
||||
http://www.datarescue.com/idabase/
|
||||
|
||||
- Python [2.4.4, 2.5.1]
|
||||
http://www.python.org/
|
||||
|
||||
- Simplified Wrapper Interface Generator (SWIG) [1.3.31]
|
||||
http://www.swig.org/
|
||||
|
||||
- Unix utilities (GNU patch on Windows):
|
||||
http://www.research.att.com/sw/tools/uwin/ or
|
||||
http://unxutils.sourceforge.net/ or
|
||||
http://www.cygwin.com/
|
||||
|
||||
- GCC on Linux and Mac OS X [4.1.3]
|
||||
Comes with your distribution
|
||||
|
||||
- Microsoft Visual C on Windows [Microsoft Visual C++ 2005 Express Edition]
|
||||
http://msdn.microsoft.com/vstudio/express/visualc/
|
||||
|
||||
|
||||
BUILDING
|
||||
|
||||
Make sure all the needed tools (compiler, swig) are on the PATH.
|
||||
|
||||
1, Unpack the IDAPython source and IDA Pro SDK into the following
|
||||
directory structure:
|
||||
|
||||
swigsdk-versions/5.1/ - version 5.1 of the IDA Pro SDK
|
||||
idapython/ - IDAPython source code
|
||||
|
||||
2, Patch the SDK using GNU Patch with one of patches from patches/ directory.
|
||||
You will have to use the -P option depending on which directory you
|
||||
patch from.
|
||||
|
||||
3, On Mac OS X copy libida.dylib from the IDA install directory to
|
||||
swigsdk-versions/5.1/libgcc32.mac/
|
||||
|
||||
4, Build the plugin
|
||||
|
||||
python build.py
|
||||
|
||||
It is possible to build the plugin for different Python versions by
|
||||
running build.py with the corresponding Python binary.
|
||||
|
||||
5, Install the components as described in README.txt
|
||||
|
||||
See build.py for build details and possible tweaks.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (c) 2004-2007 Gergely Erdelyi <dyce@d-dome.net>. All rights reserved.
|
||||
-------------------------------------------------------------------------------
|
||||
------------------------------------------------------
|
||||
IDAPython - Python plugin for Interactive Disassembler
|
||||
------------------------------------------------------
|
||||
Building From Source
|
||||
--------------------
|
||||
|
||||
REQUIREMENTS
|
||||
------------
|
||||
|
||||
[Tested versions are in brackets]
|
||||
|
||||
|
||||
- IDA and IDA SDK [> 5.6]
|
||||
http://www.hex-rays.com/idapro/
|
||||
|
||||
- Python [2.5.1, 2.6.1, 2.7]
|
||||
http://www.python.org/
|
||||
|
||||
- Simplified Wrapper Interface Generator (SWIG) [2.0.12]
|
||||
http://www.swig.org/
|
||||
Hex-Rays cannot guarantee support for IDAPython
|
||||
versions built with other versions of SWIG.
|
||||
|
||||
- Unix utilities (GNU patch on Windows):
|
||||
http://www.research.att.com/sw/tools/uwin/ or
|
||||
http://unxutils.sourceforge.net/ or
|
||||
http://www.cygwin.com/
|
||||
|
||||
- GCC on Linux and Mac OS X [4.0.1, 4.1.3]
|
||||
Comes with your distribution
|
||||
|
||||
- Microsoft Visual C on Windows [Microsoft Visual C++ 2008 Express Edition]
|
||||
http://msdn.microsoft.com/vstudio/express/visualc/
|
||||
|
||||
|
||||
BUILDING
|
||||
--------
|
||||
|
||||
Make sure all the needed tools (compiler, swig) are on the PATH.
|
||||
|
||||
1. Unpack the IDAPython source and IDA SDK into the following
|
||||
directory structure:
|
||||
|
||||
swigsdk-versions/x.y/ - A supported version of the IDA SDK
|
||||
idapython/ - IDAPython source code
|
||||
|
||||
Note: To build with Hex-Rays decompiler support, please copy hexrays.hpp from
|
||||
the decompiler SDK folder into IDA's include folder (in the SDK).
|
||||
|
||||
2. On Mac OS X copy libida.dylib from the IDA install directory to
|
||||
swigsdk-versions/x.y/lib/x86_mac_gcc_32/
|
||||
and libida64.dylib to
|
||||
swigsdk-versions/x.y/lib/x86_mac_gcc_64/
|
||||
|
||||
3. Build the plugin
|
||||
|
||||
python build.py
|
||||
|
||||
It is possible to build the plugin for different Python versions by
|
||||
running build.py with the corresponding Python binary.
|
||||
|
||||
Run 'build.py --help' for more information.
|
||||
|
||||
4. Install the components as described in README.txt
|
||||
|
||||
See build.py for build details and possible tweaks.
|
||||
|
||||
On 64 bits distributions, you may need to compile Python to generate a 32bit
|
||||
version of the interpreter:
|
||||
|
||||
1. tar xvf Python-2.6.6.tar.bz2
|
||||
2. cd Python-2.6.6
|
||||
3. CC="gcc -m32" CXX="c++ -m32" ./configure --prefix=/path/to/py32 --enable-shared
|
||||
4. make
|
||||
5. make install
|
||||
6. cd /path/to/py32/lib
|
||||
7. ln -s libpython2.6.so.1.0 libpython2.6.so.1
|
||||
8. PYTHONHOME=/path/to/py32 LD_LIBRARY_PATH=/path/to/py32/lib idaq
|
||||
|
301
CHANGES.txt
301
CHANGES.txt
@ -1,72 +1,229 @@
|
||||
Changes from version 0.9.0 to 0.9.53
|
||||
------------------------------------
|
||||
|
||||
- Upgraded IDA Pro base version to 5.1
|
||||
- Experimental Mac OS X support
|
||||
- Improved IDC coverage
|
||||
- Cleanups and fixes
|
||||
|
||||
|
||||
Changes from version 0.8.0 to 0.9.0
|
||||
-----------------------------------
|
||||
|
||||
- Upgraded base version to IDA Pro 5.0
|
||||
- Works with IDA Pro 5.1
|
||||
- Python 2.4 and 2.5 supported
|
||||
- Close to complete IDC compatbility layer (in sync with 4.9)
|
||||
- Significatnly improved IDA SDK API covergage (see STATUS.txt for details)
|
||||
- IDA SDK patch size reduced to less than half
|
||||
- Simplified installation (plugins.cfg modification not needed)
|
||||
- Evaluation window content is saved over IDA restarts (in the database)
|
||||
- Windows version is built with Microsoft Visual C++ Express Edition
|
||||
- Build makefile replaced with a Python script
|
||||
- Cleanups and small fixes
|
||||
|
||||
|
||||
Changes from version 0.7.0 to 0.8.0
|
||||
-----------------------------------
|
||||
|
||||
- Added support for IDA Pro 4.9
|
||||
- Dropped support for IDA Pro 4.7
|
||||
- NOTE: Windows version is linked against Python 2.4.
|
||||
- New wrappers: search.hpp, dbg.hpp, loader.hpp, diskio.hpp, nalt.hpp
|
||||
- idc.py synced up to IDA 4.8
|
||||
- Added 38 IDC functions
|
||||
- Fixed asklong(), askseg() and askaddr()
|
||||
- Automatically generated cross reference documentation (epydoc)
|
||||
- User-specific init file support (see README,txt)
|
||||
- Deprecated some functions that have direct Python equivalents (see idc.py)
|
||||
- Fixed exception in ScriptBox when invoked empty.
|
||||
- Lots of cleanups and small fixes
|
||||
|
||||
|
||||
Changes from version 0.6.0 to 0.7.0
|
||||
-----------------------------------
|
||||
- Batch execution support (use the option -OIDAPython:yourscript.py)
|
||||
- Added ScriptBox - lists previously run scripts (Hotkey:Alt-7)
|
||||
- Added support for IDA Pro 4.8 (both Linux and Windows)
|
||||
- Dropped support for IDA Pro 4.6 and 4.6SP1 versions
|
||||
- Wrapped the list chooser (see examples/choose.py)
|
||||
- A dozen or so IDC functions added
|
||||
- Lots of char * API calls wrapped
|
||||
- Added Python error handling in the plugin C layer
|
||||
- Bunch of misc small cleanups and fixes
|
||||
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
|
||||
|
||||
- API CHANGE: {Next|Prev}Function() return BADADDR instead of -1
|
||||
|
||||
|
||||
Changes from version 0.5.0 to 0.6.0
|
||||
-----------------------------------
|
||||
- Added support for IDA Pro 4.7 (both Linux and Windows)
|
||||
- Dropped support for IDA Pro 4.6SP1 beta on Linux
|
||||
- Lots of IDC wrapper additions and fixes:
|
||||
- Added 30+ new wrappers to idc.py
|
||||
- Most Find*, Ask* and Seg* are now wrapped
|
||||
- Fixed broken NextAddr(), PrevAddr(), MakeFunction() and MakeName()
|
||||
- Fixes to the makefile
|
||||
- Cleanups for the idaapi wrapper
|
||||
- Bunch of misc small cleanups and fixes
|
||||
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
|
||||
|
||||
|
||||
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
|
||||
|
||||
Changes from version 1.5.6 to 1.5.7
|
||||
------------------------------------
|
||||
- Added '--with-hexrays' switch to the build script so it wrap Hex-Rays Decompiler API
|
||||
- Experimental: integrated Hex-Rays Decompiler bindings that were contributed by EiNSTeiN:
|
||||
https://github.com/EiNSTeiN-/hexrays-python
|
||||
- Added one Hex-Rays decompiler sample: vds1.py
|
||||
- Fixed small mismatch between SWIG define and CL defines (/DNO_OBSOLETE_FUNCS)
|
||||
- Use print_type2() instead of the deprecated function print_type()
|
||||
|
||||
Changes from version 1.5.5 to 1.5.6
|
||||
------------------------------------
|
||||
- IDA Pro 6.4 support
|
||||
|
||||
Changes from version 1.5.4 to 1.5.5
|
||||
------------------------------------
|
||||
- IDA Pro 6.3 support
|
||||
- The Functions() generator function now accepts function tail start parameter
|
||||
- Added into idc.py: DbgRead/DbgWrite/SetTargetAssembler and stack pointer related functions
|
||||
- Wrapped more type info related functions
|
||||
|
||||
Changes from version 1.5.3 to 1.5.4
|
||||
------------------------------------
|
||||
- fix for Python autorun script vulnerability reported by Greg MacManus
|
||||
- remove current directory from sys.path during initialization
|
||||
- added PyWraps sources. This will facilitate deployment, development and
|
||||
debugging of IDAPython additions
|
||||
- bugfix: op_t.is_reg() was buggy
|
||||
- bugfix: build.py was putting duplicate files into the .zip
|
||||
- bugfix: added back wrapped version of get_ascii_contents()
|
||||
|
||||
Changes from version 1.5.2 to 1.5.3
|
||||
------------------------------------
|
||||
- IDA Pro 6.2 support
|
||||
- added set_idc_func_ex(): it is now possible to add new IDC functions using Python
|
||||
- added visit_patched_bytes() (see ex_patch.py)
|
||||
- added support for the multiline text input control in the Form class
|
||||
- added support for the editable/readonly dropdown list control in the Form class
|
||||
- added execute_sync() to register a function call into the UI message queue
|
||||
- added execute_ui_requests() / check ex_uirequests.py
|
||||
- added add_hotkey() / del_hotkey() to bind Python methods to hotkeys
|
||||
- added register_timer()/unregister_timer(). Check ex_timer.py
|
||||
- added the IDC (Arrays) netnode manipulation layer into idc.py
|
||||
- added idautils.Structs() and StructMembers() generator functions
|
||||
- removed the "Run Python Statement" menu item. IDA now has a unified dialog.
|
||||
Use RunPlugin("python", 0) to invoke it manually.
|
||||
- better error messages for script plugins, loaders and processor modules
|
||||
- bugfix: Dbg_Hooks.dbg_run_to() was receiving wrong input
|
||||
- bugfix: A few Enum related functions were not properly working in idc.py
|
||||
- bugfix: GetIdaDirectory() and GetProcessName() were broken in idc.py
|
||||
- bugfix: idaapi.get_item_head() / idc.ItemHead() were not working
|
||||
|
||||
Changes from version 1.5.1 to 1.5.2
|
||||
------------------------------------
|
||||
- added ui_term/ui_save/ui_saved/ui_get_ea_hint UI notifications
|
||||
- added ph_get_operand_info() to retrieve operand information while debugging
|
||||
- added PteDump.py script
|
||||
- bugfix: read/write_dbg_memory() and dbg_get_thread_sreg_base() were not working with all debugger modules
|
||||
- bugfix: idaapi.netnode.getblob() was limited to MAXSPECSIZE
|
||||
- bugfix: idc.GetString()/idaapi.get_ascii_contents()/idautils.Strings() were limited to MAXSTR string length
|
||||
- bugfix: idaapi.del_menu_item() was failing to delete some menu items
|
||||
- bugfix: dbg_bpt was called instead of dbg_trace for a DBG_Hooks class implementation (old bug from 0.9.x)
|
||||
- bugfix: Form.GetControlValue() was not working with numeric controls
|
||||
- bugfix: SetBptCnd() was broken
|
||||
- bugfix: idaapi.get_func_cmt() was memory leaking
|
||||
|
||||
Changes from version 1.5.0 to 1.5.1
|
||||
------------------------------------
|
||||
- Introduced the CLI '?' pseudo-command to retrieve doc strings
|
||||
- Introduced the CLI '!' pseudo-command to shell execute a command
|
||||
- bugfix: High 64 bit addresses were not parsed correctly in IDA64
|
||||
- Added IDP/assemble notification event
|
||||
- bugfix: AskUsingForm() C function was not wrapped by SWIG
|
||||
- NextHead()/PrevHead() have optional 2nd parameter now
|
||||
|
||||
Changes from version 1.4.3 to 1.5.0
|
||||
------------------------------------
|
||||
- IDA Pro 6.1 support
|
||||
- Added AskUsingForm() with embedded forms support (check ex_askusingform.py example and formchooser.py in the SDK)
|
||||
- Added idautils.DecodePreviousInstruction() / DecodePrecedingInstruction()
|
||||
- Added idc.BeginTypeUpdating() / EndTypeUpdating() for fast batch type update operations
|
||||
- Added more IDP callbacks
|
||||
- Added UI_Hooks with a few notification events
|
||||
- Added idaapi.process_ui_action() / idc.ProcessUiAction()
|
||||
- Added netnode.index() to get netnode number
|
||||
- Better handling of ea_t values with bitwise negation
|
||||
- Execute statement hotkey (Ctrl-F3), script timeout, and other options are now configurable with Python.cfg
|
||||
- bugfix: idaapi.msg() / error() and warning() so they don't accept vararg
|
||||
- bugfix: processor_t.id constants were incorrect
|
||||
- bugfix: get_debug_names() was broken with IDA64
|
||||
- Various bugfixes
|
||||
- Added Scripts folder containing various IDAPython scripts
|
||||
|
||||
Changes from version 1.4.2 to 1.4.3
|
||||
------------------------------------
|
||||
- IDA Pro 6.0 support
|
||||
- Python CLI now prints expression evaluation result (no need to use print())
|
||||
- Changed Alt-8 to Ctrl-F3 (because it conflicts with window switching key Alt+n)
|
||||
- Added get_highlighted_identifier()
|
||||
- Added PluginForm class to allow UI development with either PyQt4 or PySide
|
||||
- Added idautils.Entries() to enum entrypoints
|
||||
|
||||
|
||||
Changes from version 1.4.1 to 1.4.2
|
||||
------------------------------------
|
||||
- Added command completion
|
||||
- Added necessary changes so it compiles with Python 2.7
|
||||
- Wrapped set_user_defined_prefix()
|
||||
|
||||
|
||||
Changes from version 1.4.0 to 1.4.1
|
||||
------------------------------------
|
||||
- Added cli_t
|
||||
- Added idaapi.ph to access current process fields
|
||||
- Changed the copyright string to IDAPython Team
|
||||
- Some platform dependant classes are present but useable only where applicable
|
||||
|
||||
|
||||
Changes from version 1.3.0 to 1.4.0
|
||||
------------------------------------
|
||||
- IDA Pro 5.7 support
|
||||
- idaapi.cvar.cmd is now accessible via idapi.cmd instead
|
||||
- Python statement (Alt-8) is now 16kb long
|
||||
- Dropped script box and File/Python file. IDA has this functionality now.
|
||||
- Refactored the code
|
||||
- It is possible to turn off script timeout
|
||||
- All scripts are executed via 'IDAPython_ExecScript' (check idaapi.i)
|
||||
- Added '--doc' switch to "build.py" script
|
||||
- Documented all manually wrapped functions (check 'pywraps' module in the docs)
|
||||
- Lots of cleanups and fixes
|
||||
|
||||
|
||||
Changes from version 1.2.0 to 1.3.0
|
||||
------------------------------------
|
||||
- IDA Pro 5.6 support
|
||||
- Added Appcall mechanism
|
||||
- Added procregs to idautils.py (r254)
|
||||
- Lots of cleanups and fixes
|
||||
|
||||
Changes from version 1.1.0 to 1.2.0
|
||||
------------------------------------
|
||||
- 64-bit support (largely untested)
|
||||
- IDA Pro 5.5 support
|
||||
- Long running (or inifinitely looping) scripts can now be stopped
|
||||
- Host of IDC updates and fixes
|
||||
- netnode.hpp is now mostly wrapped
|
||||
- idautils use generators instead of lists
|
||||
- Functions() and GetFchunkAttr() now work properly
|
||||
- Lots of cleanups and fixes
|
||||
|
||||
|
||||
Changes from version 0.9.0 to 1.0.0
|
||||
-----------------------------------
|
||||
- Upgraded IDA Pro base version to 5.1
|
||||
- Dropped Python 2.4 support
|
||||
- Mac OS X support
|
||||
- IDC compatibility layer is now complete and up to date for IDA 5.1
|
||||
- INCOMPATIBLE CHANGE: the idaapi module needs to be imported manually
|
||||
- Support for IDB and debug notification hooks
|
||||
- Support for GUI hotkeys (see examples/hotkey.py)
|
||||
- Simple two-way calling mechanism between IDC and IDAPython
|
||||
- Significantly better IDA API coverage
|
||||
- Support for IDB and debug event hooks
|
||||
- get_current_instruction() deprecated, use the idaapi.cvar.cmd variable
|
||||
- Tons of IDC fixes
|
||||
- Tons of other misc fixes
|
||||
|
||||
|
||||
Changes from version 0.8.0 to 0.9.0
|
||||
-----------------------------------
|
||||
- Upgraded base version to IDA Pro 5.0
|
||||
- Works with IDA Pro 5.1
|
||||
- Python 2.4 and 2.5 supported
|
||||
- Close to complete IDC compatbility layer (in sync with 4.9)
|
||||
- Significatnly improved IDA SDK API covergage (see STATUS.txt for details)
|
||||
- IDA SDK patch size reduced to less than half
|
||||
- Simplified installation (plugins.cfg modification not needed)
|
||||
- Evaluation window content is saved over IDA restarts (in the database)
|
||||
- Windows version is built with Microsoft Visual C++ Express Edition
|
||||
- Build makefile replaced with a Python script
|
||||
- Cleanups and small fixes
|
||||
|
||||
|
||||
Changes from version 0.7.0 to 0.8.0
|
||||
-----------------------------------
|
||||
- Added support for IDA Pro 4.9
|
||||
- Dropped support for IDA Pro 4.7
|
||||
- NOTE: Windows version is linked against Python 2.4.
|
||||
- New wrappers: search.hpp, dbg.hpp, loader.hpp, diskio.hpp, nalt.hpp
|
||||
- idc.py synced up to IDA 4.8
|
||||
- Added 38 IDC functions
|
||||
- Fixed asklong(), askseg() and askaddr()
|
||||
- Automatically generated cross reference documentation (epydoc)
|
||||
- User-specific init file support (see README,txt)
|
||||
- Deprecated some functions that have direct Python equivalents (see idc.py)
|
||||
- Fixed exception in ScriptBox when invoked empty.
|
||||
- Lots of cleanups and small fixes
|
||||
|
||||
|
||||
Changes from version 0.6.0 to 0.7.0
|
||||
-----------------------------------
|
||||
- Batch execution support (use the option -OIDAPython:yourscript.py)
|
||||
- Added ScriptBox - lists previously run scripts (Hotkey:Alt-7)
|
||||
- Added support for IDA Pro 4.8 (both Linux and Windows)
|
||||
- Dropped support for IDA Pro 4.6 and 4.6SP1 versions
|
||||
- Wrapped the list chooser (see examples/choose.py)
|
||||
- A dozen or so IDC functions added
|
||||
- Lots of char * API calls wrapped
|
||||
- Added Python error handling in the plugin C layer
|
||||
- Bunch of misc small cleanups and fixes
|
||||
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
|
||||
|
||||
- API CHANGE: {Next|Prev}Function() return BADADDR instead of -1
|
||||
|
||||
|
||||
Changes from version 0.5.0 to 0.6.0
|
||||
-----------------------------------
|
||||
- Added support for IDA Pro 4.7 (both Linux and Windows)
|
||||
- Dropped support for IDA Pro 4.6SP1 beta on Linux
|
||||
- Lots of IDC wrapper additions and fixes:
|
||||
- Added 30+ new wrappers to idc.py
|
||||
- Most Find*, Ask* and Seg* are now wrapped
|
||||
- Fixed broken NextAddr(), PrevAddr(), MakeFunction() and MakeName()
|
||||
- Fixes to the makefile
|
||||
- Cleanups for the idaapi wrapper
|
||||
- Bunch of misc small cleanups and fixes
|
||||
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
|
||||
|
||||
|
54
COPYING.txt
54
COPYING.txt
@ -1,27 +1,27 @@
|
||||
Copyright (c) 2004-2007 Gergely Erdelyi <dyce@d-dome.net>. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
|
||||
|
||||
Copyright (c) 2004-2010 Gergely Erdelyi <gergely.erdelyi@d-dome.net>. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
184
README.txt
184
README.txt
@ -1,70 +1,114 @@
|
||||
----------------------------------------------------------
|
||||
IDAPython - Python plugin for Interactive Disassembler Pro
|
||||
----------------------------------------------------------
|
||||
|
||||
WHAT IS IDAPTYHON?
|
||||
|
||||
IDAPython is an IDA plugin which makes it possible to write scripts
|
||||
for IDA in the Python programming language. IDAPython provides full
|
||||
access to both the IDA API and any installed Python module.
|
||||
|
||||
Check the scripts in the examples directory to get an quick glimpse.
|
||||
|
||||
|
||||
AVAILABILITY
|
||||
|
||||
Latest versions of IDAPython are available from
|
||||
|
||||
http://www.d-dome.net/idapython/
|
||||
|
||||
|
||||
INSTALLATION FROM BINARIES
|
||||
|
||||
1, Install Python 2.4 or 2.5 from http://www.python.org/
|
||||
2, Copy the directory python\ to the IDA install directory
|
||||
3. Copy the plugin to the %IDADIR%\plugins\
|
||||
|
||||
|
||||
USAGE
|
||||
|
||||
The plugin has three hotkeys:
|
||||
|
||||
- Run script (Alt-9)
|
||||
- Execute Python statement(s) (Alt-8)
|
||||
- Run previously executed script again (Alt-7)
|
||||
|
||||
Batch mode execution:
|
||||
|
||||
Start IDA with the following command line options:
|
||||
|
||||
-A -OIDAPython:yourscript.py file_to_work_on
|
||||
|
||||
If you want fully unattended execution mode, make sure your script
|
||||
exits with a qexit() call.
|
||||
|
||||
|
||||
User init file:
|
||||
|
||||
You can place your custom settings to a file called 'idapythonrc.py'
|
||||
that should be placed to
|
||||
|
||||
${HOME}/.idapro/
|
||||
|
||||
or
|
||||
|
||||
C:\Documents and Settings\%USER%\Application Data\Datarescue\IDA Pro
|
||||
|
||||
The user init file is read and executed at the end of the init process.
|
||||
|
||||
|
||||
THANKS
|
||||
|
||||
This project is sponsored by F-Secure Corporation by allowing me to
|
||||
use some company time and resources for development. Please note that
|
||||
F-Secure is only sponsoring the project, the company does not provide
|
||||
any formal support for this software. Questions, comments, bug reports
|
||||
should be directed to the author.
|
||||
|
||||
F-Secure Corporation's website is located at
|
||||
|
||||
http://www.F-Secure.com/
|
||||
------------------------------------------------------
|
||||
IDAPython - Python plugin for Interactive Disassembler
|
||||
------------------------------------------------------
|
||||
|
||||
What is IDAPython?
|
||||
------------------
|
||||
|
||||
IDAPython is an IDA plugin which makes it possible to write scripts
|
||||
for IDA in the Python programming language. IDAPython provides full
|
||||
access to both the IDA API and any installed Python module.
|
||||
|
||||
Check the scripts in the examples directory to get an quick glimpse.
|
||||
|
||||
|
||||
Availability
|
||||
------------
|
||||
|
||||
Latest stable versions of IDAPython are available from
|
||||
http://code.google.com/p/idapython/downloads/list
|
||||
|
||||
Development builds are available from
|
||||
http://code.google.com/p/idapython/
|
||||
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
The full function cross-reference is readable online at
|
||||
http://www.hex-rays.com/idapro/idapython_docs/
|
||||
|
||||
Bugs and enhancement requests should be submitted to
|
||||
http://code.google.com/p/idapython/issues/list
|
||||
|
||||
Mailing list for the project is hosted by Google Groups at
|
||||
http://groups.google.com/group/idapython
|
||||
|
||||
|
||||
Installation from binaries
|
||||
--------------------------
|
||||
|
||||
1. Install 2.6 or 2.7 from http://www.python.org/
|
||||
2. Copy the whole "python" directory to %IDADIR%
|
||||
3. Copy the contents of the "plugins" directory to the %IDADIR%\plugins\
|
||||
4. Copy "python.cfg" to %IDADIR%\cfg
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
- Run script: File / Script file (Alt-F7)
|
||||
- Execute Python statement(s) (Ctrl-F3)
|
||||
- Run previously executed script again: View / Recent Scripts (Alt+F9)
|
||||
|
||||
|
||||
* Batch mode execution:
|
||||
|
||||
Start IDA with the following command line options:
|
||||
|
||||
-A -OIDAPython:yourscript.py file_to_work_on
|
||||
or
|
||||
-Syourscript.py
|
||||
or
|
||||
-S"yourscript.py arg1 arg2 arg3"
|
||||
|
||||
(Please see http://www.hexblog.com/?p=128)
|
||||
|
||||
If you want fully unattended execution mode, make sure your script
|
||||
exits with a qexit() call.
|
||||
|
||||
By default scripts run after the database is opened. Extended option
|
||||
format is:
|
||||
|
||||
-OIDAPython:[N;]script.py
|
||||
|
||||
Where N can be:
|
||||
0: run script after opening database (default)
|
||||
1: run script when UI is ready
|
||||
2: run script immediately on plugin load (shortly after IDA starts and before processor modules and loaders)
|
||||
|
||||
* User init file
|
||||
|
||||
You can place your custom settings to a file called 'idapythonrc.py'
|
||||
that should be placed to
|
||||
|
||||
${HOME}/.idapro/
|
||||
|
||||
or
|
||||
|
||||
%AppData%\Hex-Rays\IDA Pro
|
||||
|
||||
The user init file is read and executed at the end of the init process.
|
||||
|
||||
Please note that IDAPython can be configured with "python.cfg" file.
|
||||
|
||||
* Invoking Python from IDC
|
||||
|
||||
The IDAPython plugin exposes a new IDC function "RunPythonStatement(string idc_code)" that allows execution
|
||||
of Python code from IDC
|
||||
|
||||
* Invoking IDC from Python
|
||||
|
||||
It is possible to use the idc.Eval() to evaluate IDC expressions from Python
|
||||
|
||||
* Making Python the default language
|
||||
|
||||
By default, IDA will use IDC to evaluate expressions. It is possible to change the default language to use
|
||||
Python instead of IDC.
|
||||
|
||||
In order to do that, please use the following IDC code:
|
||||
|
||||
RunPlugin("python", 3)
|
||||
|
||||
To disable Python language and revert back to IDC:
|
||||
RunPlugin("python", 4)
|
||||
|
||||
|
BIN
RELEASES/idapython-0.9.54_ida5.1_py2.4_win32.zip
Normal file
BIN
RELEASES/idapython-0.9.54_ida5.1_py2.4_win32.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.54_ida5.1_py2.4_win32.zip.asc
Normal file
7
RELEASES/idapython-0.9.54_ida5.1_py2.4_win32.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBHE7IKZaxJ/axd7pgRAk5YAJ9y6CTRsu4ZG0sHD+TyqyGyGAS0CwCgl1+2
|
||||
vcxrUd1VhMXr2XVxoKWrGsE=
|
||||
=oFqa
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.54_ida5.1_py2.5_win32.zip
Normal file
BIN
RELEASES/idapython-0.9.54_ida5.1_py2.5_win32.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.54_ida5.1_py2.5_win32.zip.asc
Normal file
7
RELEASES/idapython-0.9.54_ida5.1_py2.5_win32.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBHE7ITZaxJ/axd7pgRAtZ9AJ41pJYymOYkP7redeJJpcqYTmSAKgCeMFIw
|
||||
v0tfXhFTmr39EJCwUjOdrec=
|
||||
=3cbr
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.55-src.zip
Normal file
BIN
RELEASES/idapython-0.9.55-src.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.55-src.zip.asc
Normal file
7
RELEASES/idapython-0.9.55-src.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBHV/eIZaxJ/axd7pgRAiFZAKCiLDVs0vzFNuS5ZgZh3CL5n56qMACfeos+
|
||||
3c2kfbIV+Q4qCpbz8Cw8Cyg=
|
||||
=dvct
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.55_ida5.1_py2.4_win32.zip
Normal file
BIN
RELEASES/idapython-0.9.55_ida5.1_py2.4_win32.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.55_ida5.1_py2.4_win32.zip.asc
Normal file
7
RELEASES/idapython-0.9.55_ida5.1_py2.4_win32.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBHV/eTZaxJ/axd7pgRAlKiAJ0a9mjI9eGfsqPb/WdObb4XAFBDugCgjByQ
|
||||
YcbaQN3tk2VxdmpD+Tqltbw=
|
||||
=6fP6
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.55_ida5.1_py2.5_win32.zip
Normal file
BIN
RELEASES/idapython-0.9.55_ida5.1_py2.5_win32.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.55_ida5.1_py2.5_win32.zip.asc
Normal file
7
RELEASES/idapython-0.9.55_ida5.1_py2.5_win32.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBHV/ebZaxJ/axd7pgRAjTFAJ9f3SRhFNp2SvFz68SbjmxeEWToSwCfX/Y7
|
||||
8cHoxcACw6/gEM/mzKrjuv8=
|
||||
=zX9g
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.56.zip
Normal file
BIN
RELEASES/idapython-0.9.56.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.56.zip.asc
Normal file
7
RELEASES/idapython-0.9.56.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBIAI/1ZaxJ/axd7pgRAhDEAJ4rYUPd3x7hkRKwJcMHQXgVQBy74gCeM7jj
|
||||
zdYiv5B/0xj1AN4IhJqd4LQ=
|
||||
=yfc/
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.57.zip
Normal file
BIN
RELEASES/idapython-0.9.57.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.57.zip.asc
Normal file
7
RELEASES/idapython-0.9.57.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBIIYK0ZaxJ/axd7pgRApsYAJwORF9/az2CXhmK5PXKrsq+UxJW7gCeKH+J
|
||||
5Ius8QbqouoDuro9/zHrzm4=
|
||||
=5GuH
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.57_ida5.1_py2.4_win32.zip
Normal file
BIN
RELEASES/idapython-0.9.57_ida5.1_py2.4_win32.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.57_ida5.1_py2.4_win32.zip.asc
Normal file
7
RELEASES/idapython-0.9.57_ida5.1_py2.4_win32.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBIIYLKZaxJ/axd7pgRAlieAJoDVm1O67aD7sEPUtKkknMudhh18wCePZGZ
|
||||
9MGQK7mKI1IEQO0OzMx4E+s=
|
||||
=T+6A
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.57_ida5.1_py2.5_win32.zip
Normal file
BIN
RELEASES/idapython-0.9.57_ida5.1_py2.5_win32.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.57_ida5.1_py2.5_win32.zip.asc
Normal file
7
RELEASES/idapython-0.9.57_ida5.1_py2.5_win32.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBIIYLjZaxJ/axd7pgRAu/+AKCaii6AeImJVnsHzvCoWSwjcNNhrwCcDW0p
|
||||
Pp2/23GBZO9+ibd7OgzZ6n0=
|
||||
=XMWh
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.58.zip
Normal file
BIN
RELEASES/idapython-0.9.58.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-0.9.58.zip.asc
Normal file
7
RELEASES/idapython-0.9.58.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBIVVv9ZaxJ/axd7pgRAvYfAKCK3Vmm702tiF/h1K8g7ZXWyU5CHwCfYnqY
|
||||
h9ZBFhpl8RtK74kIOr4I9TU=
|
||||
=S0SV
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-0.9.58_ida5.1_py2.4_win32.zip
Normal file
BIN
RELEASES/idapython-0.9.58_ida5.1_py2.4_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.1.92.zip
Normal file
BIN
RELEASES/idapython-1.1.92.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-1.1.92.zip.asc
Normal file
7
RELEASES/idapython-1.1.92.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBKGC63ZaxJ/axd7pgRAjrwAJ9KKGQN1sPVCSJmSAoNSn5CzCruUQCfeEhm
|
||||
DMqahOYRKgV8w9V1AOFjxBg=
|
||||
=g8BL
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-1.1.92_ida5.4_py2.5_macosx.zip
Normal file
BIN
RELEASES/idapython-1.1.92_ida5.4_py2.5_macosx.zip
Normal file
Binary file not shown.
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBKGC7KZaxJ/axd7pgRAr5tAJwMo4EkBm6eB0X9sGoEofBRl9tgnACfTft/
|
||||
fpd3BdtPWOdGWKuJPvS4vd8=
|
||||
=0ZxF
|
||||
-----END PGP SIGNATURE-----
|
7
RELEASES/idapython-1.1.92_ida5.4_py2.5_macosx.zip.asc
Normal file
7
RELEASES/idapython-1.1.92_ida5.4_py2.5_macosx.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBKGC7KZaxJ/axd7pgRAr5tAJwMo4EkBm6eB0X9sGoEofBRl9tgnACfTft/
|
||||
fpd3BdtPWOdGWKuJPvS4vd8=
|
||||
=0ZxF
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-1.1.92_ida5.4_py2.5_win32.zip
Normal file
BIN
RELEASES/idapython-1.1.92_ida5.4_py2.5_win32.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-1.1.92_ida5.4_py2.5_win32.zip.asc
Normal file
7
RELEASES/idapython-1.1.92_ida5.4_py2.5_win32.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBKGC7SZaxJ/axd7pgRApyBAKCcHSb4RH7uj+W6wjOy9tXI9r21mwCeNqnx
|
||||
4vsxNx32RwrvDXtZQLO6T0I=
|
||||
=VZ2O
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-1.2.0.zip
Normal file
BIN
RELEASES/idapython-1.2.0.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-1.2.0.zip.asc
Normal file
7
RELEASES/idapython-1.2.0.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBKWgHmZaxJ/axd7pgRAuwHAJ47RV5xqKSsxlrAgSC/2EreBvJbLgCfUaLg
|
||||
9f720rZUvhKfNDHUkLD9IHw=
|
||||
=vd7I
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-1.2.0_ida5.4_py2.5_macosx.zip
Normal file
BIN
RELEASES/idapython-1.2.0_ida5.4_py2.5_macosx.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-1.2.0_ida5.4_py2.5_macosx.zip.asc
Normal file
7
RELEASES/idapython-1.2.0_ida5.4_py2.5_macosx.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBKWgHvZaxJ/axd7pgRAgw7AJ9suUEB71dLbr+baldwnNfHVLU2ZQCeMLf8
|
||||
d5zK7g95mypV9ZAaLPXcAsw=
|
||||
=666W
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-1.2.0_ida5.4_py2.5_win32.zip
Normal file
BIN
RELEASES/idapython-1.2.0_ida5.4_py2.5_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.3.2_ida5.6_py2.5_win32.zip
Normal file
BIN
RELEASES/idapython-1.3.2_ida5.6_py2.5_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.4.3_ida6.0_py2.7_win32.zip
Normal file
BIN
RELEASES/idapython-1.4.3_ida6.0_py2.7_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.1_ida6.1_py2.6_linux.zip
Normal file
BIN
RELEASES/idapython-1.5.1_ida6.1_py2.6_linux.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.1_ida6.1_py2.6_macosx.zip
Normal file
BIN
RELEASES/idapython-1.5.1_ida6.1_py2.6_macosx.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.1r357_ida6.1_py2.6_win32.zip
Normal file
BIN
RELEASES/idapython-1.5.1r357_ida6.1_py2.6_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.2.3_ida6.1_py2.6_linux.zip
Normal file
BIN
RELEASES/idapython-1.5.2.3_ida6.1_py2.6_linux.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.2.3_ida6.1_py2.6_macosx.zip
Normal file
BIN
RELEASES/idapython-1.5.2.3_ida6.1_py2.6_macosx.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.2.3_ida6.1_py2.6_win32.zip
Normal file
BIN
RELEASES/idapython-1.5.2.3_ida6.1_py2.6_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.6_linux.zip
Normal file
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.6_linux.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.6_macosx.zip
Normal file
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.6_macosx.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.6_win32.zip
Normal file
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.6_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.7_linux.zip
Normal file
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.7_linux.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.7_win32.zip
Normal file
BIN
RELEASES/idapython-1.5.2_ida6.1_py2.7_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.3.zip
Normal file
BIN
RELEASES/idapython-1.5.3.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.6_linux.zip
Normal file
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.6_linux.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.6_macosx.zip
Normal file
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.6_macosx.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.6_win32.zip
Normal file
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.6_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.7_linux.zip
Normal file
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.7_linux.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.7_win32.zip
Normal file
BIN
RELEASES/idapython-1.5.3_ida6.2_py2.7_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.5.5_ida6.3_py2.7_win32.zip
Normal file
BIN
RELEASES/idapython-1.5.5_ida6.3_py2.7_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.6.0_ida6.5_py2.7_win32.zip
Normal file
BIN
RELEASES/idapython-1.6.0_ida6.5_py2.7_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.7.0_ida6.6_py2.7_win32.zip
Normal file
BIN
RELEASES/idapython-1.7.0_ida6.6_py2.7_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-1.7.1_ida6.7_py2.7_win32.zip
Normal file
BIN
RELEASES/idapython-1.7.1_ida6.7_py2.7_win32.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-reference-1.0.0.zip
Normal file
BIN
RELEASES/idapython-reference-1.0.0.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-reference-1.0.0.zip.asc
Normal file
7
RELEASES/idapython-reference-1.0.0.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBI4QXlZaxJ/axd7pgRAl0EAKCXX5dPLjozMgOgma7adf9iHWuQ7QCgmgA9
|
||||
Cyy6dkras6IWTlMA4rDVfc4=
|
||||
=50Nz
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-reference-1.2.0.zip
Normal file
BIN
RELEASES/idapython-reference-1.2.0.zip
Normal file
Binary file not shown.
7
RELEASES/idapython-reference-1.2.0.zip.asc
Normal file
7
RELEASES/idapython-reference-1.2.0.zip.asc
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (Darwin)
|
||||
|
||||
iD8DBQBKWgYSZaxJ/axd7pgRAlJOAKCMMltS5iwpiM6UYF0BbRUWPZKrXQCgo3gs
|
||||
E3b+tP+ZyDN3a/U1szIJ0pA=
|
||||
=EV5g
|
||||
-----END PGP SIGNATURE-----
|
BIN
RELEASES/idapython-reference-1.4.1.zip
Normal file
BIN
RELEASES/idapython-reference-1.4.1.zip
Normal file
Binary file not shown.
BIN
RELEASES/idapython-reference-1.5.1-doc.zip
Normal file
BIN
RELEASES/idapython-reference-1.5.1-doc.zip
Normal file
Binary file not shown.
138
STATUS.txt
138
STATUS.txt
@ -1,72 +1,66 @@
|
||||
Status of the IDC wrapper
|
||||
-------------------------
|
||||
|
||||
6 function unimplemented out of 434 (98% coverage):
|
||||
|
||||
rotate_left
|
||||
XRefType
|
||||
SetMemberType
|
||||
GetType
|
||||
GuessType
|
||||
SetType
|
||||
|
||||
|
||||
Status of IDA API wrappers
|
||||
--------------------------
|
||||
|
||||
COMPLETE: all possible functions wrapped, no SWIG ifdefs
|
||||
INCOMPLETE: some wrapping or SWIG ifdefs still left
|
||||
EXCLUDED: will not be wrapped
|
||||
|
||||
allins.hpp - COMPLETE
|
||||
area.hpp - INCOMPLETE (SWIGdefs left)
|
||||
auto.hpp - COMPLETE
|
||||
bytes.hpp - INCOMPLETE (no SWIGs, some unwrapped)
|
||||
compress.hpp - EXCLUDED
|
||||
dbg.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
|
||||
demangle.hpp - EXCLUDED
|
||||
diskio.hpp - INCOMPLETE (no SWIGs, some unwrapped)
|
||||
entry.hpp - COMPLETE
|
||||
enum.hpp - INCOMPLETE (no SWIGs, one FIXME)
|
||||
err.h - EXCLUDED
|
||||
exehdr.h - EXCLUDED
|
||||
expr.hpp - INCOMPLETE (wrapped, needs testing)
|
||||
fixup.hpp - COMPLETE
|
||||
fpro.h - EXCLUDED
|
||||
frame.hpp - COMPLETE
|
||||
funcs.hpp - INCOMPLETE (some SWIGs, few FIXMEs)
|
||||
gdl.hpp - EXCLUDED
|
||||
graph.hpp - EXCLUDED
|
||||
help.h - EXCLUDED
|
||||
ida.hpp - INCOMPLETE (SWIGs)
|
||||
idd.hpp - INCOMPLETE (SWIGs)
|
||||
idp.hpp - INCOMPLETE (SWIGs)
|
||||
ieee.h - EXCLUDED
|
||||
intel.hpp - EXCLUDED
|
||||
ints.hpp - INCOMPLETE (SWIGs)
|
||||
kernwin.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
|
||||
lex.hpp - EXCLUDED
|
||||
lines.hpp - INCOMPLETE (few FIXMEs)
|
||||
llong.hpp - EXCLUDED
|
||||
loader.hpp - INCOMPLETE (few FIXMEs)
|
||||
md5.h - EXCLUDED
|
||||
moves.hpp - COMPLETE (some needed SWIGs)
|
||||
nalt.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
|
||||
name.hpp - INCOMPLETE (few FIXMEs)
|
||||
netnode.hpp - INCOMPLETE (not wrapped at all)
|
||||
offset.hpp - COMPLETE
|
||||
prodir.h - EXCLUDED
|
||||
pro.h - COMPLETE (some needed SWIGs)
|
||||
queue.hpp - INCOMPLETE (one FIXME)
|
||||
regex.h - EXCLUDED
|
||||
search.hpp - INCOMPLETE (one FIXME)
|
||||
segment.hpp - INCOMPLETE (no SWIGs, few FIXMEs)
|
||||
sistack.hpp - EXCLUDED
|
||||
srarea.hpp - INCOMPLETE (not wrapped at all)
|
||||
strlist.hpp - COMPLETE
|
||||
struct.hpp - COMPLETE
|
||||
typeinf.hpp - INCOMPLETE (no SWIGs, lot of fixing to do)
|
||||
ua.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
|
||||
va.hpp - EXCLUDED
|
||||
vm.hpp - EXCLUDED
|
||||
xref.hpp - COMPLETE
|
||||
Status of the IDC layer
|
||||
-----------------------
|
||||
|
||||
The IDC emulation layer is complete and at par with IDA 5.1,
|
||||
although it would benefit from more testing.
|
||||
|
||||
|
||||
Status of IDA API wrappers
|
||||
--------------------------
|
||||
|
||||
COMPLETE: all possible functions wrapped, no SWIG ifdefs
|
||||
INCOMPLETE: some wrapping or SWIG ifdefs still left
|
||||
EXCLUDED: will not be wrapped
|
||||
|
||||
allins.hpp - COMPLETE
|
||||
area.hpp - COMPLETE (necessary SWIGdefs)
|
||||
auto.hpp - COMPLETE
|
||||
bytes.hpp - COMPLETE (some minor unwrapped)
|
||||
compress.hpp - EXCLUDED
|
||||
dbg.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
|
||||
demangle.hpp - EXCLUDED
|
||||
diskio.hpp - INCOMPLETE (no SWIGs, some unwrapped)
|
||||
entry.hpp - COMPLETE
|
||||
enum.hpp - COMPLETE
|
||||
err.h - EXCLUDED
|
||||
exehdr.h - EXCLUDED
|
||||
expr.hpp - COMPLETE (necessary SWIGs)
|
||||
fixup.hpp - COMPLETE
|
||||
fpro.h - EXCLUDED
|
||||
frame.hpp - COMPLETE
|
||||
funcs.hpp - COMPLETE (necessary SWIGs, minor FIXME)
|
||||
gdl.hpp - EXCLUDED
|
||||
graph.hpp - INCOMPLETE
|
||||
help.h - EXCLUDED
|
||||
ida.hpp - COMPLETE
|
||||
idd.hpp - COMPLETE (necessary SWIGs)
|
||||
idp.hpp - COMPLETE
|
||||
ieee.h - EXCLUDED
|
||||
intel.hpp - EXCLUDED
|
||||
ints.hpp - COMPLETE
|
||||
kernwin.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
|
||||
lex.hpp - EXCLUDED
|
||||
lines.hpp - INCOMPLETE (few FIXMEs)
|
||||
llong.hpp - EXCLUDED
|
||||
loader.hpp - INCOMPLETE (few FIXMEs)
|
||||
md5.h - EXCLUDED
|
||||
moves.hpp - COMPLETE (some needed SWIGs)
|
||||
nalt.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
|
||||
name.hpp - INCOMPLETE (few FIXMEs)
|
||||
netnode.hpp - COMPLETE
|
||||
offset.hpp - COMPLETE
|
||||
prodir.h - EXCLUDED
|
||||
pro.h - COMPLETE (some needed SWIGs)
|
||||
queue.hpp - INCOMPLETE (one FIXME)
|
||||
regex.h - EXCLUDED
|
||||
search.hpp - COMPLETE
|
||||
segment.hpp - COMPLETE
|
||||
sistack.hpp - EXCLUDED
|
||||
srarea.hpp - INCOMPLETE (not wrapped at all)
|
||||
strlist.hpp - COMPLETE
|
||||
struct.hpp - COMPLETE
|
||||
typeinf.hpp - INCOMPLETE (no SWIGs, lot of fixing to do)
|
||||
ua.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
|
||||
va.hpp - EXCLUDED
|
||||
vm.hpp - EXCLUDED
|
||||
xref.hpp - COMPLETE
|
||||
|
156
Scripts/3rd/BboeVt.py
Normal file
156
Scripts/3rd/BboeVt.py
Normal file
@ -0,0 +1,156 @@
|
||||
"""
|
||||
Original code by Bryce Boe: http://www.bryceboe.com/2010/09/01/submitting-binaries-to-virustotal/
|
||||
|
||||
Modified by Elias Bachaalany <elias at hex-rays.com>
|
||||
|
||||
"""
|
||||
|
||||
import hashlib, httplib, mimetypes, os, pprint, simplejson, sys, urlparse
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
DEFAULT_TYPE = 'application/octet-stream'
|
||||
FILE_REPORT_URL = 'https://www.virustotal.com/api/get_file_report.json'
|
||||
SCAN_URL = 'https://www.virustotal.com/api/scan_file.json'
|
||||
API_KEY = "" # Put API key here. Register an account in VT Community
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# The following function is modified from the snippet at:
|
||||
# http://code.activestate.com/recipes/146306/
|
||||
def _encode_multipart_formdata(fields, files=()):
|
||||
"""
|
||||
fields is a dictionary of name to value for regular form fields.
|
||||
files is a sequence of (name, filename, value) elements for data to be
|
||||
uploaded as files.
|
||||
Return (content_type, body) ready for httplib.HTTP instance
|
||||
"""
|
||||
BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
|
||||
CRLF = '\r\n'
|
||||
L = []
|
||||
for key, value in fields.items():
|
||||
L.append('--' + BOUNDARY)
|
||||
L.append('Content-Disposition: form-data; name="%s"' % key)
|
||||
L.append('')
|
||||
L.append(value)
|
||||
for (key, filename, value) in files:
|
||||
L.append('--' + BOUNDARY)
|
||||
L.append('Content-Disposition: form-data; name="%s"; filename="%s"' %
|
||||
(key, filename))
|
||||
content_type = mimetypes.guess_type(filename)[0] or DEFAULT_TYPE
|
||||
L.append('Content-Type: %s' % content_type)
|
||||
L.append('')
|
||||
L.append(value)
|
||||
L.append('--' + BOUNDARY + '--')
|
||||
L.append('')
|
||||
body = CRLF.join(L)
|
||||
content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
|
||||
return content_type, body
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def _post_multipart(url, fields, files=()):
|
||||
"""
|
||||
url is the full to send the post request to.
|
||||
fields is a dictionary of name to value for regular form fields.
|
||||
files is a sequence of (name, filename, value) elements for data to be
|
||||
uploaded as files.
|
||||
Return body of http response.
|
||||
"""
|
||||
content_type, data = _encode_multipart_formdata(fields, files)
|
||||
url_parts = urlparse.urlparse(url)
|
||||
if url_parts.scheme == 'http':
|
||||
h = httplib.HTTPConnection(url_parts.netloc)
|
||||
elif url_parts.scheme == 'https':
|
||||
h = httplib.HTTPSConnection(url_parts.netloc)
|
||||
else:
|
||||
raise Exception('Unsupported URL scheme')
|
||||
path = urlparse.urlunparse(('', '') + url_parts[2:])
|
||||
h.request('POST', path, data, {'content-type':content_type})
|
||||
return h.getresponse().read()
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def set_apikey(key, dbg = False):
|
||||
"""
|
||||
Set the VT API key
|
||||
"""
|
||||
global API_KEY
|
||||
API_KEY = key
|
||||
if dbg:
|
||||
httplib.HTTPConnection.debuglevel = 1
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def scan_file(filename):
|
||||
"""
|
||||
Uploads a file for scanning.
|
||||
|
||||
@param filename: The filename to upload
|
||||
|
||||
@return: - None if upload failed
|
||||
- scan_id value if upload succeeds
|
||||
- raises an exception on IO failures
|
||||
"""
|
||||
files = [('file', filename, open(filename, 'rb').read())]
|
||||
json = _post_multipart(SCAN_URL, {'key':API_KEY}, files)
|
||||
data = simplejson.loads(json)
|
||||
return str(data['scan_id']) if data['result'] == 1 else None
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def get_file_md5_hash(filename):
|
||||
f = open(filename, 'rb')
|
||||
r = hashlib.md5(f.read()).hexdigest()
|
||||
f.close()
|
||||
return r
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def get_file_report(filename=None, md5sum=None):
|
||||
"""
|
||||
Returns an report for a file or md5su.
|
||||
|
||||
@param filename: File name to get report. The file is used just
|
||||
to compute its MD5Sum
|
||||
@param md5sum: MD5sum string (in case filename was not passed)
|
||||
|
||||
@return: - None: if file was not previously analyzed
|
||||
- A dictionary if report exists: key=scanner, value=reported name
|
||||
"""
|
||||
if filename is None and md5sum is None:
|
||||
raise Exception('Either filename or md5sum should be passed!')
|
||||
|
||||
# Filename passed? Compute its MD5
|
||||
if filename:
|
||||
global LAST_FILE_HASH
|
||||
LAST_FILE_HASH = md5sum = get_file_md5_hash(filename)
|
||||
|
||||
# Form the request
|
||||
json = _post_multipart(FILE_REPORT_URL, {'resource':md5sum, 'key':API_KEY})
|
||||
data = simplejson.loads(json)
|
||||
if data['result'] != 1:
|
||||
# No results
|
||||
return None
|
||||
else:
|
||||
# date, result_dict = data['report']
|
||||
return data['report'][1]
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def pretty_print(obj):
|
||||
pprint.pprint(obj)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 2:
|
||||
print('Usage: %s filename' % sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
||||
filename = sys.argv[1]
|
||||
if not os.path.isfile(filename):
|
||||
print('%s is not a valid file' % filename)
|
||||
sys.exit(1)
|
||||
|
||||
get_file_report(filename=filename)
|
216
Scripts/AsmViewer.py
Normal file
216
Scripts/AsmViewer.py
Normal file
@ -0,0 +1,216 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to use customview in Python
|
||||
# The sample will allow you to open an assembly file and display it in color
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
import idaapi
|
||||
import idautils
|
||||
import idc
|
||||
import os
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
class asm_colorizer_t(object):
|
||||
def is_id(self, ch):
|
||||
return ch == '_' or ch.isalpha() or '0' <= ch <= '9'
|
||||
|
||||
def get_identifier(self, line, x, e):
|
||||
i = x
|
||||
is_digit = line[i].isdigit()
|
||||
while i < e:
|
||||
ch = line[i]
|
||||
if not self.is_id(ch):
|
||||
if ch != '.' or not is_digit:
|
||||
break
|
||||
i += 1
|
||||
return (i, line[x:i])
|
||||
|
||||
def get_quoted_string(self, line, x, e):
|
||||
quote = line[x]
|
||||
i = x + 1
|
||||
while i < e:
|
||||
ch = line[i]
|
||||
if ch == '\\' and line[i+1] == quote:
|
||||
i += 1
|
||||
elif ch == quote:
|
||||
i += 1 # also take the quote
|
||||
break
|
||||
i += 1
|
||||
return (i, line[x:i])
|
||||
|
||||
def colorize(self, lines):
|
||||
for line in lines:
|
||||
line = line.rstrip()
|
||||
if not line:
|
||||
self.add_line()
|
||||
continue
|
||||
x = 0
|
||||
e = len(line)
|
||||
s = ""
|
||||
while x < e:
|
||||
ch = line[x]
|
||||
# String?
|
||||
if ch == '"' or ch == "'":
|
||||
x, w = self.get_quoted_string(line, x, e)
|
||||
s += self.as_string(w)
|
||||
# Tab?
|
||||
elif ch == '\t':
|
||||
s += ' ' * 4
|
||||
x += 1
|
||||
# Comment?
|
||||
elif ch == ';':
|
||||
s += self.as_comment(line[x:])
|
||||
# Done with this line
|
||||
break
|
||||
elif ch == '.' and x + 1 < e:
|
||||
x, w = self.get_identifier(line, x + 1, e)
|
||||
s += self.as_directive(ch + w)
|
||||
# Identifiers?
|
||||
elif self.is_id(ch):
|
||||
x, w = self.get_identifier(line, x, e)
|
||||
# Number?
|
||||
if ch.isdigit():
|
||||
s += self.as_num(w)
|
||||
# Other identifier
|
||||
else:
|
||||
s += self.as_id(w)
|
||||
# Output as is
|
||||
else:
|
||||
s += ch
|
||||
x += 1
|
||||
self.add_line(s)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
|
||||
def Create(self, fn):
|
||||
# Create the customview
|
||||
if not idaapi.simplecustviewer_t.Create(self, "Viewing file - %s" % os.path.basename(fn)):
|
||||
return False
|
||||
|
||||
self.instruction_list = idautils.GetInstructionList()
|
||||
self.instruction_list.extend(["ret"])
|
||||
self.register_list = idautils.GetRegisterList()
|
||||
self.register_list.extend(["eax", "ebx", "ecx", "edx", "edi", "esi", "ebp", "esp"])
|
||||
|
||||
self.fn = fn
|
||||
if not self.reload_file():
|
||||
return False
|
||||
|
||||
self.id_refresh = self.AddPopupMenu("Refresh")
|
||||
self.id_close = self.AddPopupMenu("Close")
|
||||
|
||||
return True
|
||||
|
||||
def reload_file(self):
|
||||
if not self.colorize_file(self.fn):
|
||||
self.Close()
|
||||
return False
|
||||
return True
|
||||
|
||||
def colorize_file(self, fn):
|
||||
try:
|
||||
f = open(fn, "r")
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
self.ClearLines()
|
||||
self.colorize(lines)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def add_line(self, s=None):
|
||||
if not s:
|
||||
s = ""
|
||||
self.AddLine(s)
|
||||
|
||||
def as_comment(self, s):
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_RPTCMT)
|
||||
|
||||
def as_id(self, s):
|
||||
t = s.lower()
|
||||
if t in self.register_list:
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_REG)
|
||||
elif t in self.instruction_list:
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_INSN)
|
||||
else:
|
||||
return s
|
||||
|
||||
def as_string(self, s):
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_STRING)
|
||||
|
||||
def as_num(self, s):
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_NUMBER)
|
||||
|
||||
def as_directive(self, s):
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_KEYWORD)
|
||||
|
||||
def OnPopupMenu(self, menu_id):
|
||||
"""
|
||||
A context (or popup) menu item was executed.
|
||||
@param menu_id: ID previously registered with AddPopupMenu()
|
||||
@return: Boolean
|
||||
"""
|
||||
if self.id_refresh == menu_id:
|
||||
return self.reload_file()
|
||||
elif self.id_close == menu_id:
|
||||
self.Close()
|
||||
return True
|
||||
return False
|
||||
|
||||
def OnKeydown(self, vkey, shift):
|
||||
"""
|
||||
User pressed a key
|
||||
@param vkey: Virtual key code
|
||||
@param shift: Shift flag
|
||||
@return Boolean. True if you handled the event
|
||||
"""
|
||||
# ESCAPE
|
||||
if vkey == 27:
|
||||
self.Close()
|
||||
elif vkey == ord('H'):
|
||||
lineno = self.GetLineNo()
|
||||
if lineno is not None:
|
||||
line, fg, bg = self.GetLine(lineno)
|
||||
if line and line[0] != idaapi.SCOLOR_INV:
|
||||
s = idaapi.SCOLOR_INV + line + idaapi.SCOLOR_INV
|
||||
self.EditLine(lineno, s, fg, bg)
|
||||
self.Refresh()
|
||||
elif vkey == ord('C'):
|
||||
self.ClearLines()
|
||||
self.Refresh()
|
||||
elif vkey == ord('S'):
|
||||
print "Selection (x1, y1, x2, y2) = ", self.GetSelection()
|
||||
elif vkey == ord('I'):
|
||||
print "Position (line, x, y) = ", self.GetPos(mouse = 0)
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class asmviewplg(idaapi.plugin_t):
|
||||
flags = idaapi.PLUGIN_KEEP
|
||||
comment = "ASM viewer"
|
||||
help = "This is help"
|
||||
wanted_name = "ASM file viewer"
|
||||
wanted_hotkey = "Alt-F8"
|
||||
def __init__(self):
|
||||
self.view = None
|
||||
|
||||
def init(self):
|
||||
return idaapi.PLUGIN_KEEP
|
||||
def run(self, arg):
|
||||
if self.view:
|
||||
self.Close()
|
||||
fn = idc.AskFile(0, "*.asm", "Select ASM file to view")
|
||||
if not fn:
|
||||
return
|
||||
self.view = asmview_t()
|
||||
if not self.view.Create(fn):
|
||||
return
|
||||
self.view.Show()
|
||||
|
||||
def term(self):
|
||||
if self.view:
|
||||
self.view.Close()
|
||||
|
||||
def PLUGIN_ENTRY():
|
||||
return asmviewplg()
|
175
Scripts/CallStackWalk.py
Normal file
175
Scripts/CallStackWalk.py
Normal file
@ -0,0 +1,175 @@
|
||||
"""
|
||||
|
||||
A script that tries to determine the call stack
|
||||
|
||||
Run the application with the debugger, suspend the debugger, select a thread and finally run the script.
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
|
||||
v1.0 - initial version
|
||||
v1.0.1 - added stack segment bitness detection, thus works with 64bit processes too
|
||||
"""
|
||||
import idaapi
|
||||
import idc
|
||||
import idautils
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# class to take a copy of a segment_t
|
||||
class Seg():
|
||||
def __init__(self, s):
|
||||
self.startEA = s.startEA
|
||||
self.endEA = s.endEA
|
||||
self.perm = s.perm
|
||||
self.bitness = s.bitness
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.startEA, other.startEA)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# each item described as:
|
||||
# [ delta, [ opcode(s) ] ]
|
||||
#FF10 call d,[eax]
|
||||
#FF5000 call d,[eax][0]
|
||||
#FF9044332211 call d,[eax][011223344]
|
||||
#FF1500000100 call d,[000010000]
|
||||
#FF9300000000 call d,[ebx][0]
|
||||
#FF10 call d,[eax]
|
||||
CallPattern = \
|
||||
[
|
||||
[-2, [0xFF] ],
|
||||
[-3, [0xFF] ],
|
||||
[-5, [0xE8] ],
|
||||
[-6, [0xFF] ],
|
||||
]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def IsPrevInsnCall(ea):
|
||||
"""
|
||||
Given a return address, this function tries to check if previous instruction
|
||||
is a CALL instruction
|
||||
"""
|
||||
global CallPattern
|
||||
if ea == idaapi.BADADDR or ea < 10:
|
||||
return None
|
||||
|
||||
for delta, opcodes in CallPattern:
|
||||
# assume caller's ea
|
||||
caller = ea + delta
|
||||
# get the bytes
|
||||
bytes = [x for x in GetDataList(caller, len(opcodes), 1)]
|
||||
# do we have a match? is it a call instruction?
|
||||
if bytes == opcodes and idaapi.is_call_insn(caller):
|
||||
return caller
|
||||
return None
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def CallStackWalk(nn):
|
||||
class Result:
|
||||
"""
|
||||
Class holding the result of one call stack item
|
||||
Each call stack item instance has the following attributes:
|
||||
caller = ea of caller
|
||||
displ = display string
|
||||
sp = stack pointer
|
||||
"""
|
||||
def __init__(self, caller, sp):
|
||||
self.caller = caller
|
||||
self.sp = sp
|
||||
f = idaapi.get_func(caller)
|
||||
self.displ = "%08x: " % caller
|
||||
if f:
|
||||
self.displ += idc.GetFunctionName(caller)
|
||||
t = caller - f.startEA
|
||||
if t > 0: self.displ += "+" + hex(t)
|
||||
else:
|
||||
self.displ += hex(caller)
|
||||
self.displ += " [" + hex(sp) + "]"
|
||||
|
||||
def __str__(self):
|
||||
return self.displ
|
||||
|
||||
# get stack pointer
|
||||
sp = cpu.Esp
|
||||
seg = idaapi.getseg(sp)
|
||||
if not seg:
|
||||
return (False, "Could not locate stack segment!")
|
||||
|
||||
stack_seg = Seg(seg)
|
||||
word_size = 2 ** (seg.bitness + 1)
|
||||
callers = []
|
||||
sp = cpu.Esp - word_size
|
||||
while sp < stack_seg.endEA:
|
||||
sp += word_size
|
||||
ptr = idautils.GetDataList(sp, 1, word_size).next()
|
||||
seg = idaapi.getseg(ptr)
|
||||
# only accept executable segments
|
||||
if (not seg) or ((seg.perm & idaapi.SEGPERM_EXEC) == 0):
|
||||
continue
|
||||
# try to find caller
|
||||
caller = IsPrevInsnCall(ptr)
|
||||
# we have no recognized caller, skip!
|
||||
if caller is None:
|
||||
continue
|
||||
|
||||
# do we have a debug name that is near?
|
||||
if nn:
|
||||
ret = nn.find(caller)
|
||||
if ret:
|
||||
ea = ret[0]
|
||||
# function exists?
|
||||
f = idaapi.get_func(ea)
|
||||
if not f:
|
||||
# create function
|
||||
idc.MakeFunction(ea, idaapi.BADADDR)
|
||||
|
||||
# get the flags
|
||||
f = idc.GetFlags(caller)
|
||||
# no code there?
|
||||
if not isCode(f):
|
||||
MakeCode(caller)
|
||||
|
||||
callers.append(Result(caller, sp))
|
||||
#
|
||||
return (True, callers)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Chooser class
|
||||
class CallStackWalkChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
idc.Jump(o.caller)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def main():
|
||||
if not idaapi.is_debugger_on():
|
||||
idc.Warning("Please run the process first!")
|
||||
return
|
||||
if idaapi.get_process_state() != -1:
|
||||
idc.Warning("Please suspend the debugger first!")
|
||||
return
|
||||
|
||||
# only avail from IdaPython r232
|
||||
if hasattr(idaapi, "NearestName"):
|
||||
# get all debug names
|
||||
dn = idaapi.get_debug_names(idaapi.cvar.inf.minEA, idaapi.cvar.inf.maxEA)
|
||||
# initiate a nearest name search (using debug names)
|
||||
nn = idaapi.NearestName(dn)
|
||||
else:
|
||||
nn = None
|
||||
|
||||
ret, callstack = CallStackWalk(nn)
|
||||
if ret:
|
||||
title = "Call stack walker (thread %X)" % (GetCurrentThreadId())
|
||||
idaapi.close_chooser(title)
|
||||
c = CallStackWalkChoose(callstack, title)
|
||||
c.choose()
|
||||
else:
|
||||
idc.Warning("Failed to walk the stack:" + callstack)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
main()
|
101
Scripts/DbgCmd.py
Normal file
101
Scripts/DbgCmd.py
Normal file
@ -0,0 +1,101 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# Debugger command prompt with CustomViewers
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
import idaapi
|
||||
import idc
|
||||
from idaapi import simplecustviewer_t
|
||||
|
||||
def SendDbgCommand(cmd):
|
||||
"""Sends a command to the debugger and returns the output string.
|
||||
An exception will be raised if the debugger is not running or the current debugger does not export
|
||||
the 'SendDbgCommand' IDC command.
|
||||
"""
|
||||
s = Eval('SendDbgCommand("%s");' % cmd)
|
||||
if s.startswith("IDC_FAILURE"):
|
||||
raise Exception, "Debugger command is available only when the debugger is active!"
|
||||
return s
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class dbgcmd_t(simplecustviewer_t):
|
||||
def Create(self):
|
||||
# Form the title
|
||||
title = "Debugger command window"
|
||||
# Create the customview
|
||||
if not simplecustviewer_t.Create(self, title):
|
||||
return False
|
||||
self.last_cmd = ""
|
||||
self.menu_clear = self.AddPopupMenu("Clear")
|
||||
self.menu_cmd = self.AddPopupMenu("New command")
|
||||
|
||||
self.ResetOutput()
|
||||
return True
|
||||
|
||||
def IssueCommand(self):
|
||||
s = idaapi.askstr(0, self.last_cmd, "Please enter a debugger command")
|
||||
if not s:
|
||||
return
|
||||
|
||||
# Save last command
|
||||
self.last_cmd = s
|
||||
|
||||
# Add it using a different color
|
||||
self.AddLine("debugger>" + idaapi.COLSTR(s, idaapi.SCOLOR_VOIDOP))
|
||||
|
||||
try:
|
||||
r = SendDbgCommand(s).split("\n")
|
||||
for s in r:
|
||||
self.AddLine(idaapi.COLSTR(s, idaapi.SCOLOR_LIBNAME))
|
||||
except:
|
||||
self.AddLine(idaapi.COLSTR("Debugger is not active or does not export SendDbgCommand()", idaapi.SCOLOR_ERROR))
|
||||
self.Refresh()
|
||||
|
||||
def ResetOutput(self):
|
||||
self.ClearLines()
|
||||
self.AddLine(idaapi.COLSTR("Please press INS to enter command; X to clear output", idaapi.SCOLOR_AUTOCMT))
|
||||
self.Refresh()
|
||||
|
||||
def OnKeydown(self, vkey, shift):
|
||||
# ESCAPE?
|
||||
if vkey == 27:
|
||||
self.Close()
|
||||
# VK_INSERT
|
||||
elif vkey == 45:
|
||||
self.IssueCommand()
|
||||
elif vkey == ord('X'):
|
||||
self.ResetOutput()
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
def OnPopupMenu(self, menu_id):
|
||||
if menu_id == self.menu_clear:
|
||||
self.ResetOutput()
|
||||
elif menu_id == self.menu_cmd:
|
||||
self.IssueCommand()
|
||||
else:
|
||||
# Unhandled
|
||||
return False
|
||||
return True
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def show_win():
|
||||
x = dbgcmd_t()
|
||||
if not x.Create():
|
||||
print "Failed to create debugger command line!"
|
||||
return None
|
||||
x.Show()
|
||||
return x
|
||||
|
||||
try:
|
||||
# created already?
|
||||
dbgcmd
|
||||
dbgcmd.Close()
|
||||
del dbgcmd
|
||||
except:
|
||||
pass
|
||||
|
||||
dbgcmd = show_win()
|
||||
if not dbgcmd:
|
||||
del dbgcmd
|
||||
|
105
Scripts/DrvsDispatch.py
Normal file
105
Scripts/DrvsDispatch.py
Normal file
@ -0,0 +1,105 @@
|
||||
"""
|
||||
|
||||
A script to demonstrate how to send commands to the debugger and then parse and use the output in IDA
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
"""
|
||||
|
||||
import re
|
||||
from idaapi import Choose
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def CmdDriverList():
|
||||
s = Eval('WinDbgCommand("lm o");')
|
||||
if "IDC_FAILURE" in s: return False
|
||||
return s
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def CmdDrvObj(drvname, flag=2):
|
||||
return Eval('WinDbgCommand("!drvobj %s %d");' % (drvname, flag))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def CmdReloadForce():
|
||||
s = Eval('WinDbgCommand(".reload /f");')
|
||||
if "IDC_FAILURE" in s: return False
|
||||
return True
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# class to hold dispatch entry information
|
||||
class DispatchEntry:
|
||||
def __init__(self, addr, name):
|
||||
self.addr = addr
|
||||
self.name = name
|
||||
def __repr__(self):
|
||||
return "%08X: %s" % (self.addr, self.name)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def GetDriverDispatch():
|
||||
|
||||
# return a list of arrays of the form: [addr, name]
|
||||
ret_list = []
|
||||
|
||||
# build the RE for parsing output from the "lm o" command
|
||||
re_drv = re.compile('^[a-f0-9]+\s+[a-f0-9]+\s+(\S+)', re.I)
|
||||
|
||||
# build the RE for parsing output from the "!drvobj DRV_NAME 2" command
|
||||
re_tbl = re.compile('^\[\d{2}\]\s+IRP_MJ_(\S+)\s+([0-9a-f]+)', re.I)
|
||||
|
||||
# force reloading of module symbols
|
||||
if not CmdReloadForce():
|
||||
print "Could not communicate with WinDbg, make sure the debugger is running!"
|
||||
return None
|
||||
|
||||
# get driver list
|
||||
lm_out = CmdDriverList()
|
||||
if not lm_out:
|
||||
return "Failed to get driver list!"
|
||||
|
||||
# for each line
|
||||
for line in lm_out.split("\n"):
|
||||
# parse
|
||||
r = re_drv.match(line)
|
||||
if not r: continue
|
||||
|
||||
# extract driver name
|
||||
drvname = r.group(1).strip()
|
||||
|
||||
# execute "drvobj" command
|
||||
tbl_out = CmdDrvObj(drvname)
|
||||
|
||||
if not tbl_out:
|
||||
print "Failed to get driver object for", drvname
|
||||
continue
|
||||
|
||||
# for each line
|
||||
for line in tbl_out.split("\n"):
|
||||
# parse
|
||||
r = re_tbl.match(line)
|
||||
if not r: continue
|
||||
disp_addr = int(r.group(2), 16) # convert hex string to number
|
||||
disp_name = "Dispatch" + r.group(1)
|
||||
ret_list.append(DispatchEntry(disp_addr, drvname + "_" + disp_name))
|
||||
|
||||
return ret_list
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Chooser class
|
||||
class DispatchChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
idc.Jump(o.addr)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# main
|
||||
r = GetDriverDispatch()
|
||||
if r:
|
||||
c = DispatchChoose(r, "Dispatch table browser")
|
||||
c.choose()
|
||||
else:
|
||||
print "Failed to retrieve dispatchers list!"
|
52
Scripts/ExchainDump.py
Normal file
52
Scripts/ExchainDump.py
Normal file
@ -0,0 +1,52 @@
|
||||
"""
|
||||
|
||||
This script shows how to send debugger commands and use the result in IDA
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
"""
|
||||
|
||||
import idc
|
||||
import re
|
||||
|
||||
# class to store parsed results
|
||||
class exchain:
|
||||
def __init__(self, m):
|
||||
self.name = m.group(1)
|
||||
self.addr = int(m.group(2), 16)
|
||||
|
||||
def __str__(self):
|
||||
return "%x: %s" % (self.addr, self.name)
|
||||
|
||||
# Chooser class
|
||||
class MyChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
idc.Jump(o.addr)
|
||||
|
||||
# main
|
||||
def main():
|
||||
s = idc.Eval('SendDbgCommand("!exchain")')
|
||||
if "IDC_FAILURE" in s:
|
||||
return (False, "Cannot execute the command")
|
||||
|
||||
matches = re.finditer(r'[^:]+: ([^\(]+) \(([^\)]+)\)\n', s)
|
||||
L = []
|
||||
for x in matches:
|
||||
L.append(exchain(x))
|
||||
if not L:
|
||||
return (False, "Nothing to display: Could parse the result!")
|
||||
|
||||
# Get a Choose instance
|
||||
chooser = MyChoose(L, "Exchain choose")
|
||||
# Run the chooser
|
||||
chooser.choose()
|
||||
return (True, "Success!")
|
||||
ok, r = main()
|
||||
if not ok:
|
||||
print r
|
139
Scripts/FindInstructions.py
Normal file
139
Scripts/FindInstructions.py
Normal file
@ -0,0 +1,139 @@
|
||||
"""
|
||||
FindInstructions.py: A script to help you find desired opcodes/instructions in a database
|
||||
|
||||
The script accepts opcodes and assembly statements (which will be assembled) separated by semicolon
|
||||
|
||||
The general syntax is:
|
||||
find(asm or opcodes, x=Bool, asm_where=ea)
|
||||
|
||||
* Example:
|
||||
find("asm_statement1;asm_statement2;de ea dc 0d e0;asm_statement3;xx yy zz;...")
|
||||
* To filter-out non-executable segments pass x=True
|
||||
find("jmp dword ptr [esp]", x=True)
|
||||
* To specify in which context the instructions should be assembled, pass asm_where=ea:
|
||||
find("jmp dword ptr [esp]", asm_where=here())
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
v1.0 - initial version
|
||||
"""
|
||||
import idaapi
|
||||
import idautils
|
||||
import idc
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def FindInstructions(instr, asm_where=None):
|
||||
"""
|
||||
Finds instructions/opcodes
|
||||
@return: Returns a tuple(True, [ ea, ... ]) or a tuple(False, "error message")
|
||||
"""
|
||||
if not asm_where:
|
||||
# get first segment
|
||||
asm_where = FirstSeg()
|
||||
if asm_where == idaapi.BADADDR:
|
||||
return (False, "No segments defined")
|
||||
|
||||
# regular expression to distinguish between opcodes and instructions
|
||||
re_opcode = re.compile('^[0-9a-f]{2} *', re.I)
|
||||
|
||||
# split lines
|
||||
lines = instr.split(";")
|
||||
|
||||
# all the assembled buffers (for each instruction)
|
||||
bufs = []
|
||||
for line in lines:
|
||||
if re_opcode.match(line):
|
||||
# convert from hex string to a character list then join the list to form one string
|
||||
buf = ''.join([chr(int(x, 16)) for x in line.split()])
|
||||
else:
|
||||
# assemble the instruction
|
||||
ret, buf = Assemble(asm_where, line)
|
||||
if not ret:
|
||||
return (False, "Failed to assemble:"+line)
|
||||
# add the assembled buffer
|
||||
bufs.append(buf)
|
||||
|
||||
# join the buffer into one string
|
||||
buf = ''.join(bufs)
|
||||
|
||||
# take total assembled instructions length
|
||||
tlen = len(buf)
|
||||
|
||||
# convert from binary string to space separated hex string
|
||||
bin_str = ' '.join(["%02X" % ord(x) for x in buf])
|
||||
|
||||
# find all binary strings
|
||||
print "Searching for: [%s]" % bin_str
|
||||
ea = MinEA()
|
||||
ret = []
|
||||
while True:
|
||||
ea = FindBinary(ea, SEARCH_DOWN, bin_str)
|
||||
if ea == idaapi.BADADDR:
|
||||
break
|
||||
ret.append(ea)
|
||||
Message(".")
|
||||
ea += tlen
|
||||
if not ret:
|
||||
return (False, "Could not match [%s]" % bin_str)
|
||||
Message("\n")
|
||||
return (True, ret)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Chooser class
|
||||
class SearchResultChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
Jump(o.ea)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# class to represent the results
|
||||
class SearchResult:
|
||||
def __init__(self, ea):
|
||||
self.ea = ea
|
||||
if not isCode(GetFlags(ea)):
|
||||
MakeCode(ea)
|
||||
t = idaapi.generate_disasm_line(ea)
|
||||
if t:
|
||||
line = idaapi.tag_remove(t)
|
||||
else:
|
||||
line = ""
|
||||
func = GetFunctionName(ea)
|
||||
self.display = hex(ea) + ": "
|
||||
if func:
|
||||
self.display += func + ": "
|
||||
else:
|
||||
n = SegName(ea)
|
||||
if n: self.display += n + ": "
|
||||
self.display += line
|
||||
|
||||
def __str__(self):
|
||||
return self.display
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def find(s=None, x=False, asm_where=None):
|
||||
b, ret = FindInstructions(s, asm_where)
|
||||
if b:
|
||||
# executable segs only?
|
||||
if x:
|
||||
results = []
|
||||
for ea in ret:
|
||||
seg = idaapi.getseg(ea)
|
||||
if (not seg) or (seg.perm & idaapi.SEGPERM_EXEC) == 0:
|
||||
continue
|
||||
results.append(SearchResult(ea))
|
||||
else:
|
||||
results = [SearchResult(ea) for ea in ret]
|
||||
title = "Search result for: [%s]" % s
|
||||
idaapi.close_chooser(title)
|
||||
c = SearchResultChoose(results, title)
|
||||
c.choose()
|
||||
else:
|
||||
print ret
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
print "Please use find('asm_stmt1;xx yy;...', x=Bool,asm_where=ea) to search for instructions or opcodes. Specify x=true to filter out non-executable segments"
|
69
Scripts/ImpRef.py
Normal file
69
Scripts/ImpRef.py
Normal file
@ -0,0 +1,69 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to enumerate all addresses
|
||||
# that refer to all imported functions in a given module
|
||||
#
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
|
||||
import idaapi
|
||||
import idc
|
||||
import idautils
|
||||
import re
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def find_imported_funcs(dllname):
|
||||
def imp_cb(ea, name, ord):
|
||||
if not name:
|
||||
name = ''
|
||||
imports.append([ea, name, ord])
|
||||
return True
|
||||
|
||||
imports = []
|
||||
nimps = idaapi.get_import_module_qty()
|
||||
for i in xrange(0, nimps):
|
||||
name = idaapi.get_import_module_name(i)
|
||||
if re.match(dllname, name, re.IGNORECASE) is None:
|
||||
continue
|
||||
idaapi.enum_import_names(i, imp_cb)
|
||||
|
||||
return imports
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def find_import_ref(dllname):
|
||||
imports = find_imported_funcs(dllname)
|
||||
R = dict()
|
||||
for i, (ea, name,_) in enumerate(imports):
|
||||
#print "%x -> %s" % (ea, name)
|
||||
for xref in idautils.XrefsTo(ea):
|
||||
# check if referrer is a thunk
|
||||
ea = xref.frm
|
||||
f = idaapi.get_func(ea)
|
||||
if f and (f.flags & idaapi.FUNC_THUNK) != 0:
|
||||
imports.append([f.startEA, idaapi.get_func_name(f.startEA), 0])
|
||||
#print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.startEA)
|
||||
continue
|
||||
|
||||
# save results
|
||||
if not R.has_key(i):
|
||||
R[i] = []
|
||||
|
||||
R[i].append(ea)
|
||||
|
||||
return (imports, R)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def main():
|
||||
dllname = idc.AskStr('kernel32', "Enter module name")
|
||||
if not dllname:
|
||||
print("Cancelled")
|
||||
return
|
||||
|
||||
imports, R = find_import_ref(dllname)
|
||||
for k, v in R.items():
|
||||
print(imports[k][1])
|
||||
for ea in v:
|
||||
print("\t%x" % ea)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
main()
|
124
Scripts/ImportExportViewer.py
Normal file
124
Scripts/ImportExportViewer.py
Normal file
@ -0,0 +1,124 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to:
|
||||
# - enumerate imports
|
||||
# - enumerate entrypoints
|
||||
# - Use PluginForm class
|
||||
# - Use PySide with PluginForm to create a Python UI
|
||||
#
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
import idaapi
|
||||
import idautils
|
||||
from idaapi import PluginForm
|
||||
from PySide import QtGui, QtCore
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
class ImpExpForm_t(PluginForm):
|
||||
|
||||
def imports_names_cb(self, ea, name, ord):
|
||||
self.items.append((ea, '' if not name else name, ord))
|
||||
# True -> Continue enumeration
|
||||
return True
|
||||
|
||||
|
||||
def BuildImports(self):
|
||||
tree = {}
|
||||
nimps = idaapi.get_import_module_qty()
|
||||
|
||||
for i in xrange(0, nimps):
|
||||
name = idaapi.get_import_module_name(i)
|
||||
if not name:
|
||||
continue
|
||||
# Create a list for imported names
|
||||
self.items = []
|
||||
|
||||
# Enum imported entries in this module
|
||||
idaapi.enum_import_names(i, self.imports_names_cb)
|
||||
|
||||
if name not in tree:
|
||||
tree[name] = []
|
||||
tree[name].extend(self.items)
|
||||
|
||||
return tree
|
||||
|
||||
|
||||
def BuildExports(self):
|
||||
return list(idautils.Entries())
|
||||
|
||||
|
||||
def PopulateTree(self):
|
||||
# Clear previous items
|
||||
self.tree.clear()
|
||||
|
||||
# Build imports
|
||||
root = QtGui.QTreeWidgetItem(self.tree)
|
||||
root.setText(0, "Imports")
|
||||
|
||||
for dll_name, imp_entries in self.BuildImports().items():
|
||||
imp_dll = QtGui.QTreeWidgetItem(root)
|
||||
imp_dll.setText(0, dll_name)
|
||||
|
||||
for imp_ea, imp_name, imp_ord in imp_entries:
|
||||
item = QtGui.QTreeWidgetItem(imp_dll)
|
||||
item.setText(0, "%s [0x%08x]" %(imp_name, imp_ea))
|
||||
|
||||
|
||||
# Build exports
|
||||
root = QtGui.QTreeWidgetItem(self.tree)
|
||||
root.setText(0, "Exports")
|
||||
|
||||
for exp_i, exp_ord, exp_ea, exp_name in self.BuildExports():
|
||||
item = QtGui.QTreeWidgetItem(root)
|
||||
item.setText(0, "%s [#%d] [0x%08x]" % (exp_name, exp_ord, exp_ea))
|
||||
|
||||
|
||||
def OnCreate(self, form):
|
||||
"""
|
||||
Called when the plugin form is created
|
||||
"""
|
||||
|
||||
# Get parent widget
|
||||
self.parent = self.FormToPySideWidget(form)
|
||||
|
||||
# Create tree control
|
||||
self.tree = QtGui.QTreeWidget()
|
||||
self.tree.setHeaderLabels(("Names",))
|
||||
self.tree.setColumnWidth(0, 100)
|
||||
|
||||
# Create layout
|
||||
layout = QtGui.QVBoxLayout()
|
||||
layout.addWidget(self.tree)
|
||||
|
||||
self.PopulateTree()
|
||||
# Populate PluginForm
|
||||
self.parent.setLayout(layout)
|
||||
|
||||
|
||||
def OnClose(self, form):
|
||||
"""
|
||||
Called when the plugin form is closed
|
||||
"""
|
||||
global ImpExpForm
|
||||
del ImpExpForm
|
||||
print "Closed"
|
||||
|
||||
|
||||
def Show(self):
|
||||
"""Creates the form is not created or focuses it if it was"""
|
||||
return PluginForm.Show(self,
|
||||
"Imports / Exports viewer",
|
||||
options = PluginForm.FORM_PERSIST)
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def main():
|
||||
global ImpExpForm
|
||||
|
||||
try:
|
||||
ImpExpForm
|
||||
except:
|
||||
ImpExpForm = ImpExpForm_t()
|
||||
|
||||
ImpExpForm.Show()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
main()
|
85
Scripts/PteDump.py
Normal file
85
Scripts/PteDump.py
Normal file
@ -0,0 +1,85 @@
|
||||
import idaapi
|
||||
import idc
|
||||
from idaapi import Choose2
|
||||
|
||||
def parse_pte(str):
|
||||
try:
|
||||
parse_pte.re
|
||||
except:
|
||||
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)
|
||||
parse_pte.items = ('pde', 'pte', 'pdec', 'ptec', 'pdepfn', 'pdepfns', 'ptepfn', 'ptepfns')
|
||||
|
||||
m = parse_pte.re.search(s)
|
||||
r = {}
|
||||
for i in range(0, len(parse_pte.items)):
|
||||
r[parse_pte.items[i]] = m.group(i+1)
|
||||
return r
|
||||
|
||||
class MyChoose2(Choose2):
|
||||
|
||||
def __init__(self, title, ea1, ea2):
|
||||
Choose2.__init__(self, title, [ ["VA", 10], ["PTE attr", 30] ])
|
||||
self.ea1 = ea1
|
||||
self.ea2 = ea2
|
||||
self.n = 0
|
||||
self.icon = 5
|
||||
self.items = []
|
||||
self.Refresh()
|
||||
self.selcount = 0
|
||||
|
||||
def OnGetLine(self, n):
|
||||
print("getline %d" % n)
|
||||
return self.items[n]
|
||||
|
||||
def OnGetSize(self):
|
||||
n = len(self.items)
|
||||
self.Refresh()
|
||||
return n
|
||||
|
||||
def OnRefresh(self, n):
|
||||
print("refresh %d" % n)
|
||||
return n
|
||||
|
||||
def Refresh(self):
|
||||
items = []
|
||||
PG = 0x1000
|
||||
ea1 = self.ea1
|
||||
npages = (self.ea2 - ea1) / PG
|
||||
for i in range(npages):
|
||||
r = idc.SendDbgCommand("!pte %x" % ea1)
|
||||
if not r:
|
||||
return False
|
||||
r = parse_pte(r)
|
||||
items.append([hex(ea1), r['ptepfns']])
|
||||
ea1 += PG
|
||||
|
||||
self.items = items
|
||||
print(self.items)
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def Execute(ea1, ea2):
|
||||
c = MyChoose2("PTE Viewer [%x..%x]" % (ea1, ea2), ea1, ea2)
|
||||
return (c, c.Show())
|
||||
|
||||
|
||||
def DumpPTE(ea1, ea2):
|
||||
items = []
|
||||
PG = 0x1000
|
||||
npages = (ea2 - ea1) / PG
|
||||
for i in range(npages):
|
||||
r = idc.SendDbgCommand("!pte %x" % ea1)
|
||||
if not r:
|
||||
return False
|
||||
print r
|
||||
r = parse_pte(r)
|
||||
print("VA: %08X PTE: %s PDE: %s" % (ea1, r['ptepfns'], r['pdepfns']))
|
||||
ea1 += PG
|
||||
|
||||
def DumpSegPTE(ea):
|
||||
DumpPTE(idc.SegStart(ea), idc.SegEnd(ea))
|
||||
|
||||
DumpSegPTE(here())
|
||||
|
||||
#MyChoose2.Execute(0xF718F000, 0xF718F000+0x1000)
|
||||
|
149
Scripts/SEHGraph.py
Normal file
149
Scripts/SEHGraph.py
Normal file
@ -0,0 +1,149 @@
|
||||
"""
|
||||
|
||||
A script that graphs all the exception handlers in a given process
|
||||
|
||||
It will be easy to see what thread uses what handler and what handlers are commonly used between threads
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
|
||||
v1.0 - initial version
|
||||
|
||||
"""
|
||||
|
||||
import idaapi
|
||||
import idautils
|
||||
import idc
|
||||
|
||||
from idaapi import GraphViewer
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Since Windbg debug module does not support get_thread_sreg_base()
|
||||
# we will call the debugger engine "dg" command and parse its output
|
||||
def WindbgGetRegBase(tid):
|
||||
s = idc.Eval('WinDbgCommand("dg %x")' % cpu.fs)
|
||||
if "IDC_FAILURE" in s:
|
||||
return 0
|
||||
m = re.compile("[0-9a-f]{4} ([0-9a-f]{8})")
|
||||
t = m.match(s.split('\n')[-2])
|
||||
if not t:
|
||||
return 0
|
||||
return int(t.group(1), 16)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def GetFsBase(tid):
|
||||
idc.SelectThread(tid)
|
||||
base = idaapi.dbg_get_thread_sreg_base(tid, cpu.fs)
|
||||
if base != 0:
|
||||
return base
|
||||
return WindbgGetRegBase(tid)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Walks the SEH chain and returns a list of handlers
|
||||
def GetExceptionChain(tid):
|
||||
fs_base = GetFsBase(tid)
|
||||
exc_rr = Dword(fs_base)
|
||||
result = []
|
||||
while exc_rr != 0xffffffff:
|
||||
prev = Dword(exc_rr)
|
||||
handler = Dword(exc_rr + 4)
|
||||
exc_rr = prev
|
||||
result.append(handler)
|
||||
return result
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class SEHGraph(GraphViewer):
|
||||
def __init__(self, title, result):
|
||||
GraphViewer.__init__(self, title)
|
||||
self.result = result
|
||||
self.names = {} # ea -> name
|
||||
|
||||
def OnRefresh(self):
|
||||
self.Clear()
|
||||
addr_id = {}
|
||||
|
||||
for (tid, chain) in self.result.items():
|
||||
# Each node data will contain a tuple of the form: (Boolean->Is_thread, Int->Value, String->Label)
|
||||
# For threads the is_thread will be true and the value will hold the thread id
|
||||
# For exception handlers, is_thread=False and Value=Handler address
|
||||
|
||||
# Add the thread node
|
||||
id_parent = self.AddNode( (True, tid, "Thread %X" % tid) )
|
||||
|
||||
# Add each handler
|
||||
for handler in chain:
|
||||
# Check if a function is created at the handler's address
|
||||
f = idaapi.get_func(handler)
|
||||
if not f:
|
||||
# create function
|
||||
idc.MakeFunction(handler, idaapi.BADADDR)
|
||||
|
||||
# Node label is function name or address
|
||||
s = GetFunctionName(handler)
|
||||
if not s:
|
||||
s = "%x" % handler
|
||||
|
||||
# cache name
|
||||
self.names[handler] = s
|
||||
|
||||
# Get the node id given the handler address
|
||||
# We use an addr -> id dictionary so that similar addresses get similar node id
|
||||
if not addr_id.has_key(handler):
|
||||
id = self.AddNode( (False, handler, s) )
|
||||
addr_id[handler] = id # add this ID
|
||||
else:
|
||||
id = addr_id[handler]
|
||||
|
||||
# Link handlers to each other
|
||||
self.AddEdge(id_parent, id)
|
||||
id_parent = id
|
||||
|
||||
return True
|
||||
|
||||
def OnGetText(self, node_id):
|
||||
is_thread, value, label = self[node_id]
|
||||
if is_thread:
|
||||
return (label, 0xff00f0)
|
||||
return label
|
||||
|
||||
def OnDblClick(self, node_id):
|
||||
is_thread, value, label = self[node_id]
|
||||
if is_thread:
|
||||
idc.SelectThread(value)
|
||||
self.Show()
|
||||
s = "SEH chain for " + hex(value)
|
||||
t = "-" * len(s)
|
||||
print t
|
||||
print s
|
||||
print t
|
||||
for handler in self.result[value]:
|
||||
print "%x: %s" % (handler, self.names[handler])
|
||||
print t
|
||||
else:
|
||||
idc.Jump(value)
|
||||
return True
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def main():
|
||||
if not idaapi.dbg_can_query():
|
||||
print "The debugger must be active and suspended before using this script!"
|
||||
return
|
||||
|
||||
# Save current thread id
|
||||
tid = GetCurrentThreadId()
|
||||
|
||||
# Iterate through all function instructions and take only call instructions
|
||||
result = {}
|
||||
for tid in idautils.Threads():
|
||||
result[tid] = GetExceptionChain(tid)
|
||||
|
||||
# Restore previously selected thread
|
||||
idc.SelectThread(tid)
|
||||
|
||||
# Build the graph
|
||||
g = SEHGraph("SEH graph", result)
|
||||
g.Show()
|
||||
|
||||
main()
|
70
Scripts/VaDump.py
Normal file
70
Scripts/VaDump.py
Normal file
@ -0,0 +1,70 @@
|
||||
"""
|
||||
|
||||
This script shows how to send debugger commands and use the result in IDA
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
"""
|
||||
|
||||
import idc
|
||||
from idaapi import Choose
|
||||
|
||||
import re
|
||||
|
||||
# class to store parsed results
|
||||
class memva:
|
||||
def __init__(self, m):
|
||||
self.base = int(m.group(1), 16)
|
||||
self.regionsize = int(m.group(2), 16)
|
||||
self.state = int(m.group(3), 16)
|
||||
self.statestr = m.group(4).strip()
|
||||
self.protect = int(m.group(5), 16)
|
||||
self.protectstr = m.group(6).strip()
|
||||
if m.group(7):
|
||||
self.type = int(m.group(8), 16)
|
||||
self.typestr = m.group(9).strip()
|
||||
else:
|
||||
self.type = 0
|
||||
self.typestr = ""
|
||||
def __str__(self):
|
||||
return "(Base %08X; RegionSize: %08X; State: %08X/%10s; protect: %08X/%10s; type: %08X/%10s)" % (
|
||||
self.base, self.regionsize, self.state,
|
||||
self.statestr, self.protect,
|
||||
self.protectstr, self.type, self.typestr)
|
||||
|
||||
# Chooser class
|
||||
class MemChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
idc.Jump(o.base)
|
||||
|
||||
# main
|
||||
def main():
|
||||
s = idc.Eval('SendDbgCommand("!vadump")')
|
||||
if "IDC_FAILURE" in s:
|
||||
return (False, "Cannot execute the command")
|
||||
|
||||
matches = re.finditer(r'BaseAddress:\s*?(\w+?)\n' \
|
||||
+'RegionSize:\s*?(\w*?)\n' \
|
||||
+'State:\s*?(\w*?)\s*?(\w*?)\n' \
|
||||
+'Protect:\s*?(\w*?)\s*?(\w*?)\n' \
|
||||
+'(Type:\s*?(\w*?)\s*?(\w*?)\n)*', s)
|
||||
L = []
|
||||
for x in matches:
|
||||
L.append(memva(x))
|
||||
if not L:
|
||||
return (False, "Nothing to display: Could not parse the result!")
|
||||
|
||||
# Get a Choose instance
|
||||
chooser = MemChoose(L, "Memory choose")
|
||||
# Run the chooser
|
||||
chooser.choose()
|
||||
return (True, "Success!")
|
||||
r = main()
|
||||
if not r[0]:
|
||||
print r[1]
|
367
Scripts/VirusTotal.py
Normal file
367
Scripts/VirusTotal.py
Normal file
@ -0,0 +1,367 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# VirusTotal IDA Plugin
|
||||
# By Elias Bachaalany <elias at hex-rays.com>
|
||||
# (c) Hex-Rays 2011
|
||||
#
|
||||
# Special thanks:
|
||||
# - VirusTotal team
|
||||
# - Bryce Boe for his VirusTotal Python code
|
||||
#
|
||||
import idaapi
|
||||
import idc
|
||||
from idaapi import Choose2, plugin_t
|
||||
import BboeVt as vt
|
||||
import webbrowser
|
||||
import urllib
|
||||
import os
|
||||
|
||||
|
||||
PLUGIN_TEST = 0
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Configuration file
|
||||
VT_CFGFILE = os.path.join(idaapi.get_user_idadir(), "virustotal.cfg")
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# VirusTotal Icon in PNG format
|
||||
VT_ICON = (
|
||||
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52"
|
||||
"\x00\x00\x00\x10\x00\x00\x00\x10\x04\x03\x00\x00\x00\xED\xDD\xE2"
|
||||
"\x52\x00\x00\x00\x30\x50\x4C\x54\x45\x03\x8B\xD3\x5C\xB4\xE3\x9C"
|
||||
"\xD1\xED\xF7\xFB\xFD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD3\xF2\x42\x61\x00\x00\x00"
|
||||
"\x4B\x49\x44\x41\x54\x78\x9C\x2D\xCA\xC1\x0D\x80\x30\x0C\x43\x51"
|
||||
"\x27\x2C\x50\x89\x05\x40\x2C\x40\xEB\xFD\x77\xC3\x76\xC9\xE9\xEB"
|
||||
"\xC5\x20\x5F\xE8\x1A\x0F\x97\xA3\xD0\xE4\x1D\xF9\x49\xD1\x59\x29"
|
||||
"\x4C\x43\x9B\xD0\x15\x01\xB5\x4A\x9C\xE4\x70\x14\x39\xB3\x31\xF8"
|
||||
"\x15\x70\x04\xF4\xDA\x20\x39\x02\x8A\x0D\xA8\x0F\x94\xA7\x09\x0E"
|
||||
"\xC5\x16\x2D\x54\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class VirusTotalConfig(object):
|
||||
def __init__(self):
|
||||
self.Default()
|
||||
|
||||
|
||||
def Default(self):
|
||||
self.md5sum = GetInputMD5()
|
||||
self.infile = idaapi.dbg_get_input_path()
|
||||
if not self.infile:
|
||||
self.infile = ""
|
||||
|
||||
# Persistent options
|
||||
self.apikey = ""
|
||||
self.options = 1 | 2
|
||||
|
||||
|
||||
def Read(self):
|
||||
"""
|
||||
Read configuration from file
|
||||
"""
|
||||
if not os.path.exists(VT_CFGFILE):
|
||||
return
|
||||
f = open(VT_CFGFILE, 'r')
|
||||
lines = f.readlines()
|
||||
for i, line in enumerate(lines):
|
||||
line = line.strip()
|
||||
if i == 0:
|
||||
self.apikey = line
|
||||
elif i == 1:
|
||||
self.options = int(line)
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
def Write(self):
|
||||
"""
|
||||
Write configuration to file
|
||||
"""
|
||||
lines = (self.apikey.strip(), str(self.options))
|
||||
try:
|
||||
f = open(VT_CFGFILE, 'w')
|
||||
f.write("\n".join(lines))
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def VtReport(apikey, filename=None, md5sum=None):
|
||||
if filename is None and md5sum is None:
|
||||
return (False, "No parameters passed!")
|
||||
|
||||
# Check filename existance
|
||||
if filename is not None and not os.path.exists(filename):
|
||||
return (False, "Input file '%s' does not exist!" % filename)
|
||||
|
||||
#print("fn=%s md5=%s" % (filename, md5sum))
|
||||
# Get file report from VirusTotal
|
||||
try:
|
||||
vt.set_apikey(apikey)
|
||||
result = vt.get_file_report(filename=filename, md5sum=md5sum)
|
||||
except Exception as e:
|
||||
return (False, "Exception:\n%s" % str(e))
|
||||
|
||||
# Already analyzed?
|
||||
if result is not None:
|
||||
# Transform the results
|
||||
items = []
|
||||
for av, mwname in result.items():
|
||||
mwname = str(mwname) if mwname else "n/a"
|
||||
av = str(av)
|
||||
items.append([av, mwname])
|
||||
result = items
|
||||
|
||||
return (True, result)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class VirusTotalChooser(Choose2):
|
||||
"""
|
||||
Chooser class to display results from VT
|
||||
"""
|
||||
def __init__(self, title, items, icon, embedded=False):
|
||||
Choose2.__init__(self,
|
||||
title,
|
||||
[ ["Antivirus", 20], ["Result", 40] ],
|
||||
embedded=embedded)
|
||||
self.items = items
|
||||
self.icon = icon
|
||||
|
||||
|
||||
def GetItems(self):
|
||||
return self.items
|
||||
|
||||
|
||||
def SetItems(self, items):
|
||||
self.items = [] if items is None else items
|
||||
|
||||
|
||||
def OnClose(self):
|
||||
pass
|
||||
|
||||
|
||||
def OnGetLine(self, n):
|
||||
return self.items[n]
|
||||
|
||||
|
||||
def OnGetSize(self):
|
||||
return len(self.items)
|
||||
|
||||
|
||||
def OnSelectLine(self, n):
|
||||
# Google search for the malware name and the antivirus name
|
||||
s = urllib.urlencode({"q" : " ".join(self.items[n])})
|
||||
webbrowser.open_new_tab("http://www.google.com/search?%s" % s)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
class VirusTotalForm(Form):
|
||||
def __init__(self, icon):
|
||||
self.EChooser = VirusTotalChooser("E1", [], icon, embedded=True)
|
||||
Form.__init__(self, r"""STARTITEM {id:txtInput}
|
||||
VirusTotal - IDAPython plugin v1.0 (c) Hex-Rays
|
||||
|
||||
{FormChangeCb}
|
||||
<#API key#~A~pi key:{txtApiKey}>
|
||||
|
||||
Options:
|
||||
<#Open results in a chooser when form closes#~P~opout results on close:{rOptRemember}>
|
||||
<#Use MD5 checksum#~M~D5Sum:{rOptMD5}>
|
||||
<#Use file on disk#~F~ile:{rOptFile}>{grpOptions}>
|
||||
|
||||
<#Type input (file or MD5 string)#~I~nput:{txtInput}>
|
||||
<Results:{cEChooser}>
|
||||
<#Get reports from VT#~R~eport:{btnReport}>
|
||||
""", {
|
||||
'FormChangeCb': Form.FormChangeCb(self.OnFormChange),
|
||||
'txtApiKey' : Form.StringInput(swidth=80),
|
||||
'grpOptions' : Form.ChkGroupControl(("rOptRemember", "rOptMD5", "rOptFile")),
|
||||
'txtInput' : Form.FileInput(open=True),
|
||||
'btnReport' : Form.ButtonInput(self.OnReportClick),
|
||||
'cEChooser' : Form.EmbeddedChooserControl(self.EChooser)
|
||||
})
|
||||
|
||||
|
||||
|
||||
def OnReportClick(self, code=0):
|
||||
pass
|
||||
|
||||
|
||||
def OnFormChange(self, fid):
|
||||
if fid == self.rOptMD5.id or fid == self.rOptFile.id:
|
||||
input = (self.cfg.md5sum, self.cfg.infile)
|
||||
if fid == self.rOptMD5.id:
|
||||
c1 = self.rOptMD5
|
||||
c2 = self.rOptFile
|
||||
idx = 0
|
||||
else:
|
||||
c1 = self.rOptFile
|
||||
c2 = self.rOptMD5
|
||||
idx = 1
|
||||
|
||||
v = not self.GetControlValue(c1)
|
||||
if v: idx = not idx
|
||||
|
||||
# Uncheck the opposite input type
|
||||
self.SetControlValue(c2, v)
|
||||
|
||||
# Set input field depending on input type
|
||||
self.SetControlValue(self.txtInput, input[idx])
|
||||
#
|
||||
# Report button
|
||||
#
|
||||
elif fid == self.btnReport.id:
|
||||
input = self.GetControlValue(self.txtInput)
|
||||
as_file = self.GetControlValue(self.rOptFile)
|
||||
apikey = self.GetControlValue(self.txtApiKey)
|
||||
|
||||
ok, r = VtReport(self.cfg.apikey,
|
||||
filename=input if as_file else None,
|
||||
md5sum=None if as_file else input)
|
||||
|
||||
# Error?
|
||||
if not ok:
|
||||
idc.Warning(r)
|
||||
return 1
|
||||
|
||||
# Pass the result
|
||||
self.EChooser.SetItems(r)
|
||||
|
||||
# We have results and it was a file? Print its MD5
|
||||
if r and as_file:
|
||||
print("%s: %s" % (vt.LAST_FILE_HASH, input))
|
||||
|
||||
# Refresh the embedded chooser control
|
||||
# (Could also clear previous results if not were retrieved during this run)
|
||||
self.RefreshField(self.cEChooser)
|
||||
|
||||
# Store the input for the caller
|
||||
self.cfg.input = input
|
||||
|
||||
# No results and file as input was supplied?
|
||||
if r is None:
|
||||
if as_file:
|
||||
# Propose to upload
|
||||
if idc.AskYN(0, "HIDECANCEL\nNo previous results. Do you want to submit the file:\n\n'%s'\n\nto VirusTotal?" % input) == 0:
|
||||
return 1
|
||||
|
||||
try:
|
||||
r = vt.scan_file(input)
|
||||
except Exception as e:
|
||||
idc.Warning("Exceptio during upload: %s" % str(e))
|
||||
else:
|
||||
if r is None:
|
||||
idc.Warning("Failed to upload the file!")
|
||||
else:
|
||||
idc.Warning("File uploaded. Check again later to get the analysis report. Scan id: %s" % r)
|
||||
else:
|
||||
idc.Warning("No results found for hash: %s" % input)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
def Show(self, cfg):
|
||||
# Compile the form once
|
||||
if not self.Compiled():
|
||||
_, args = self.Compile()
|
||||
#print args[0]
|
||||
|
||||
# Populate the form
|
||||
self.txtApiKey.value = cfg.apikey
|
||||
self.grpOptions.value = cfg.options
|
||||
self.txtInput.value = cfg.infile if self.rOptFile.checked else cfg.md5sum
|
||||
|
||||
# Remember the config
|
||||
self.cfg = cfg
|
||||
|
||||
# Execute the form
|
||||
ok = self.Execute()
|
||||
|
||||
# Forget the cfg
|
||||
del self.cfg
|
||||
|
||||
# Success?
|
||||
if ok != 0:
|
||||
# Update config
|
||||
cfg.options = self.grpOptions.value
|
||||
cfg.apikey = self.txtApiKey.value
|
||||
|
||||
# Popup results?
|
||||
if self.rOptRemember.checked:
|
||||
ok = 2
|
||||
|
||||
return ok
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class VirusTotalPlugin_t(plugin_t):
|
||||
flags = idaapi.PLUGIN_UNL
|
||||
comment = "VirusTotal plugin for IDA"
|
||||
help = ""
|
||||
wanted_name = "VirusTotal report"
|
||||
wanted_hotkey = "Alt-F8"
|
||||
|
||||
|
||||
def init(self):
|
||||
# Some initialization
|
||||
self.icon_id = 0
|
||||
return idaapi.PLUGIN_OK
|
||||
|
||||
|
||||
def run(self, arg=0):
|
||||
# Load icon from the memory and save its id
|
||||
self.icon_id = idaapi.load_custom_icon(data=VT_ICON, format="png")
|
||||
if self.icon_id == 0:
|
||||
raise RuntimeError("Failed to load icon data!")
|
||||
|
||||
# Create config object
|
||||
cfg = VirusTotalConfig()
|
||||
|
||||
# Read previous config
|
||||
cfg.Read()
|
||||
|
||||
# Create form
|
||||
f = VirusTotalForm(self.icon_id)
|
||||
|
||||
# Show the form
|
||||
ok = f.Show(cfg)
|
||||
if ok == 0:
|
||||
f.Free()
|
||||
return
|
||||
|
||||
# Save configuration
|
||||
cfg.Write()
|
||||
|
||||
# Spawn a non-modal chooser w/ the results if any
|
||||
if ok == 2 and f.EChooser.GetItems():
|
||||
VirusTotalChooser(
|
||||
"VirusTotal results [%s]" % cfg.input,
|
||||
f.EChooser.GetItems(),
|
||||
self.icon_id).Show()
|
||||
|
||||
f.Free()
|
||||
return
|
||||
|
||||
|
||||
def term(self):
|
||||
# Free the custom icon
|
||||
if self.icon_id != 0:
|
||||
idaapi.free_custom_icon(self.icon_id)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def PLUGIN_ENTRY():
|
||||
return VirusTotalPlugin_t()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
if PLUGIN_TEST:
|
||||
# Create form
|
||||
f = PLUGIN_ENTRY()
|
||||
f.init()
|
||||
f.run()
|
||||
f.term()
|
||||
|
||||
|
91
Scripts/callstack_test.py
Normal file
91
Scripts/callstack_test.py
Normal file
@ -0,0 +1,91 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
def __sys(cmd, fmt=None, echo=True):
|
||||
"""Executes a string of OS commands and returns the a list of tuples (return code,command executed)"""
|
||||
if not fmt:
|
||||
fmt = {}
|
||||
r = []
|
||||
for cmd in [x for x in (cmd % fmt).split("\n") if len(x)]:
|
||||
if echo:
|
||||
print ">>>", cmd
|
||||
r.append((os.system(cmd), cmd))
|
||||
return r
|
||||
|
||||
body = r"""/// Autogenerated file
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <ctype.h>
|
||||
#include <windows.h>
|
||||
|
||||
void want_break(int n)
|
||||
{
|
||||
printf("do you want to DebugBreak in func%d()?", n);
|
||||
char ch = _toupper(_getch());
|
||||
printf("\n");
|
||||
if (ch == 'Y')
|
||||
DebugBreak();
|
||||
else if (ch == 'X')
|
||||
ExitProcess(n);
|
||||
}
|
||||
%FUNCS%
|
||||
int main(int /*argc*/, char * /*argv[]*/)
|
||||
{
|
||||
func1();
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
|
||||
funcs_body = []
|
||||
|
||||
func_body = r"""
|
||||
void func%(n)d()
|
||||
{
|
||||
printf("%(ident)senter %(n)d\n");%(pause)s
|
||||
func%(n1)d();
|
||||
printf("%(ident)sleave %(n)d\n");
|
||||
}
|
||||
"""
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print "usage: gen nb_calls pause_frequency"
|
||||
sys.exit(0)
|
||||
|
||||
n = int(sys.argv[1])
|
||||
if n < 1:
|
||||
print "at least one call should be passed!"
|
||||
sys.exit(1)
|
||||
|
||||
m = int(sys.argv[2])
|
||||
|
||||
func_params = {'n': 0, 'n1': 0, 'ident': '', 'pause' : ''}
|
||||
|
||||
for i in xrange(1, n + 1):
|
||||
func_params['n'] = i
|
||||
func_params['n1'] = i+1
|
||||
func_params['ident'] = " " * i
|
||||
func_params['pause'] = ("\n want_break(%d);" % i) if (i % m) == 0 else ''
|
||||
|
||||
funcs_body.append(func_body % func_params)
|
||||
funcs_body.append(r"""
|
||||
void func%(n)d()
|
||||
{
|
||||
printf("that's it #%(n)d!\n");
|
||||
}
|
||||
""" % {'n':i+1})
|
||||
funcs_body.reverse()
|
||||
|
||||
# write the file
|
||||
body = body.replace('%FUNCS%', ''.join(funcs_body))
|
||||
f = file('src.cpp', 'w')
|
||||
f.write(body)
|
||||
f.close()
|
||||
|
||||
|
||||
__sys("""
|
||||
if exist src.exe del src.exe
|
||||
bcc32 src
|
||||
if exist src.exe move src.exe src_bcc.exe
|
||||
if exist src.obj del src.obj
|
||||
cl32 src.cpp /Zi /Od
|
||||
""")
|
68
Scripts/msdnapihelp.py
Normal file
68
Scripts/msdnapihelp.py
Normal file
@ -0,0 +1,68 @@
|
||||
"""
|
||||
User contributed script: MSDN API HELP plugin
|
||||
|
||||
This script fetches the API reference (from MSDN) of a given highlighted identifier
|
||||
and returns the results in a new web browser page.
|
||||
|
||||
This script depends on the feedparser package: http://code.google.com/p/feedparser/
|
||||
|
||||
10/05/2010
|
||||
- initial version
|
||||
|
||||
|
||||
"""
|
||||
|
||||
import idaapi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class msdnapihelp_plugin_t(idaapi.plugin_t):
|
||||
flags = idaapi.PLUGIN_UNL
|
||||
comment = "Online MSDN API Help"
|
||||
help = "Help me"
|
||||
wanted_name = "MSDN API Help"
|
||||
wanted_hotkey = "F3"
|
||||
|
||||
def init(self):
|
||||
return idaapi.PLUGIN_OK
|
||||
|
||||
|
||||
@staticmethod
|
||||
def sanitize_name(name):
|
||||
t = idaapi.FUNC_IMPORT_PREFIX
|
||||
if name.startswith(t):
|
||||
return name[len(t):]
|
||||
return name
|
||||
|
||||
|
||||
def run(self, arg):
|
||||
# Get the highlighted identifier
|
||||
id = idaapi.get_highlighted_identifier()
|
||||
if not id:
|
||||
print "No identifier was highlighted"
|
||||
return
|
||||
|
||||
import webbrowser
|
||||
|
||||
try:
|
||||
import feedparser
|
||||
except:
|
||||
idaapi.warning('Feedparser package not installed')
|
||||
return
|
||||
|
||||
id = self.sanitize_name(id)
|
||||
print "Looking up '%s' in MSDN online" % id
|
||||
d = feedparser.parse("http://social.msdn.microsoft.com/Search/Feed.aspx?locale=en-us&format=RSS&Query=%s" % id)
|
||||
if len(d['entries']) > 0:
|
||||
url = d['entries'][0].link
|
||||
webbrowser.open_new_tab(url)
|
||||
else:
|
||||
print "API documentation not found for: %s" % id
|
||||
|
||||
|
||||
def term(self):
|
||||
pass
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def PLUGIN_ENTRY():
|
||||
return msdnapihelp_plugin_t()
|
@ -1,4 +1,4 @@
|
||||
#ifndef _BASETSD_H
|
||||
#define _BASETSD_H
|
||||
/* Microsoft free compilers seem to lack this file and Python needs it */
|
||||
#endif
|
||||
#ifndef _BASETSD_H
|
||||
#define _BASETSD_H
|
||||
/* Microsoft free compilers seem to lack this file and Python needs it */
|
||||
#endif
|
||||
|
475
build.py
475
build.py
@ -1,30 +1,46 @@
|
||||
#!/usr/bin/env python
|
||||
#------------------------------------------------------------
|
||||
# IDAPython - Python plugin for Interactive Disassembler Pro
|
||||
#---------------------------------------------------------------------
|
||||
# IDAPython - Python plugin for Interactive Disassembler
|
||||
#
|
||||
# Copyright (c) 2004-2007 Gergely Erdelyi <dyce@d-dome.net>
|
||||
# (c) The IDAPython Team <idapython@googlegroups.com>
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# For detailed copyright information see the file COPYING in
|
||||
# the root of the distribution archive.
|
||||
#------------------------------------------------------------
|
||||
#---------------------------------------------------------------------
|
||||
# build.py - Custom build script
|
||||
#------------------------------------------------------------
|
||||
import os, sys, platform, types, shutil
|
||||
#---------------------------------------------------------------------
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import sys
|
||||
import types
|
||||
import zipfile
|
||||
import glob
|
||||
from distutils import sysconfig
|
||||
|
||||
# Start of user configurable options
|
||||
VERBOSE = True
|
||||
IDA_MAJOR_VERSION = 5
|
||||
IDA_MINOR_VERSION = 1
|
||||
IDA_SDK = ".." + os.sep + "swigsdk-versions" + os.sep + "%d.%d" % (IDA_MAJOR_VERSION, IDA_MINOR_VERSION)
|
||||
|
||||
IDA_MAJOR_VERSION = 6
|
||||
IDA_MINOR_VERSION = 8
|
||||
|
||||
if 'IDA' in os.environ:
|
||||
IDA_SDK = os.environ['IDA']
|
||||
else:
|
||||
IDA_SDK = os.path.join("..", "..", "include")
|
||||
if not os.path.exists(IDA_SDK):
|
||||
IDA_SDK = os.path.join("..", "swigsdk-versions", ("%d.%d" % (IDA_MAJOR_VERSION, IDA_MINOR_VERSION)))
|
||||
assert os.path.exists(IDA_SDK), "Could not find IDA SDK include path"
|
||||
|
||||
|
||||
# End of user configurable options
|
||||
|
||||
# IDAPython version
|
||||
VERSION_MAJOR = 0
|
||||
VERSION_MINOR = 9
|
||||
VERSION_PATCH = 55
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 7
|
||||
VERSION_PATCH = 0
|
||||
|
||||
# Determine Python version
|
||||
PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
|
||||
@ -33,8 +49,13 @@ PYTHON_MINOR_VERSION = int(platform.python_version()[2])
|
||||
# Find Python headers
|
||||
PYTHON_INCLUDE_DIRECTORY = sysconfig.get_config_var('INCLUDEPY')
|
||||
|
||||
S_EA64 = 'ea64'
|
||||
S_WITH_HEXRAYS = 'with-hexrays'
|
||||
S_NO_OPT = 'no-opt'
|
||||
S_DEBUG = 'debug'
|
||||
|
||||
# Swig command-line parameters
|
||||
SWIG_OPTIONS = '-modern -python -c++ -w451 -shadow -D__GNUC__'
|
||||
SWIG_OPTIONS = '-modern -python -threads -c++ -w451 -shadow -D__GNUC__'
|
||||
|
||||
# Common macros for all compilations
|
||||
COMMON_MACROS = [
|
||||
@ -49,28 +70,60 @@ COMMON_MACROS = [
|
||||
# Common includes for all compilations
|
||||
COMMON_INCLUDES = [ ".", "swig" ]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# List files for the binary distribution
|
||||
BINDIST_MANIFEST = [
|
||||
"README.txt",
|
||||
"COPYING.txt",
|
||||
"CHANGES.txt",
|
||||
"AUTHORS.txt",
|
||||
"STATUS.txt",
|
||||
"python/init.py",
|
||||
"python/idc.py",
|
||||
"python/idautils.py",
|
||||
("idaapi.py", "python"),
|
||||
"python.cfg",
|
||||
"docs/notes.txt",
|
||||
"examples/chooser.py",
|
||||
"examples/colours.py",
|
||||
"examples/ex_idphook_asm.py",
|
||||
"examples/ex_uirequests.py",
|
||||
"examples/debughook.py",
|
||||
"examples/ex_cli.py",
|
||||
"examples/ex1.idc",
|
||||
"examples/ex_custdata.py",
|
||||
"examples/ex1_idaapi.py",
|
||||
"examples/ex1_idautils.py" ]
|
||||
"examples/ex1_idautils.py",
|
||||
"examples/hotkey.py",
|
||||
"examples/structure.py",
|
||||
"examples/ex_gdl_qflow_chart.py",
|
||||
"examples/ex_strings.py",
|
||||
"examples/ex_actions.py",
|
||||
"examples/ex_func_chooser.py",
|
||||
"examples/ex_choose2.py",
|
||||
"examples/ex_debug_names.py",
|
||||
"examples/ex_graph.py",
|
||||
"examples/ex_hotkey.py",
|
||||
"examples/ex_patch.py",
|
||||
"examples/ex_expr.py",
|
||||
"examples/ex_timer.py",
|
||||
"examples/ex_dbg.py",
|
||||
"examples/ex_custview.py",
|
||||
"examples/ex_prefix_plugin.py",
|
||||
"examples/ex_pyside.py",
|
||||
"examples/ex_pyqt.py",
|
||||
"examples/ex_askusingform.py",
|
||||
"examples/ex_uihook.py",
|
||||
"examples/ex_idphook_asm.py",
|
||||
"examples/ex_imports.py"
|
||||
]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# List files for the source distribution (appended to binary list)
|
||||
SRCDIST_MANIFEST = [
|
||||
"BUILDING.txt",
|
||||
"python.cpp",
|
||||
"basetsd.h",
|
||||
"build.py",
|
||||
"python.cfg",
|
||||
"swig/allins.i",
|
||||
"swig/area.i",
|
||||
"swig/auto.i",
|
||||
"swig/bytes.i",
|
||||
"swig/dbg.i",
|
||||
@ -81,8 +134,10 @@ SRCDIST_MANIFEST = [
|
||||
"swig/fixup.i",
|
||||
"swig/frame.i",
|
||||
"swig/funcs.i",
|
||||
"swig/gdl.i",
|
||||
"swig/ida.i",
|
||||
"swig/idaapi.i",
|
||||
"swig/idd.i",
|
||||
"swig/idp.i",
|
||||
"swig/ints.i",
|
||||
"swig/kernwin.i",
|
||||
@ -91,6 +146,7 @@ SRCDIST_MANIFEST = [
|
||||
"swig/moves.i",
|
||||
"swig/nalt.i",
|
||||
"swig/name.i",
|
||||
"swig/netnode.i",
|
||||
"swig/offset.i",
|
||||
"swig/pro.i",
|
||||
"swig/queue.i",
|
||||
@ -103,27 +159,34 @@ SRCDIST_MANIFEST = [
|
||||
"swig/typeinf.i",
|
||||
"swig/ua.i",
|
||||
"swig/xref.i",
|
||||
"patches/ida51.patch"
|
||||
"swig/graph.i",
|
||||
"swig/fpro.i",
|
||||
"swig/hexrays.i",
|
||||
]
|
||||
|
||||
# Temporaty build files to remove
|
||||
BUILD_TEMPFILES = [
|
||||
"idaapi.cpp",
|
||||
"idaapi.obj",
|
||||
"idaapi.o",
|
||||
"idaapi.py",
|
||||
"idapython.sln",
|
||||
"idapython.ncb",
|
||||
"python.exp",
|
||||
"python.lib",
|
||||
"python.obj"
|
||||
]
|
||||
# -----------------------------------------------------------------------
|
||||
def parse_options(args):
|
||||
"""Parse arguments and returned a dictionary of options"""
|
||||
|
||||
no_opt = '--' + S_NO_OPT in sys.argv
|
||||
ea64 = '--' + S_EA64 in sys.argv
|
||||
with_hexrays = '--' + S_WITH_HEXRAYS in sys.argv
|
||||
debug = '--' + S_DEBUG in sys.argv
|
||||
|
||||
return {
|
||||
S_EA64: ea64,
|
||||
S_WITH_HEXRAYS: with_hexrays,
|
||||
S_NO_OPT: no_opt,
|
||||
S_DEBUG: debug
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class BuilderBase:
|
||||
""" Base class for builders """
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def compile(self, source, objectname=None, includes=[], macros=[]):
|
||||
"""
|
||||
Compile the source file
|
||||
@ -149,7 +212,8 @@ class BuilderBase:
|
||||
includestring,
|
||||
macrostring)
|
||||
|
||||
if VERBOSE: print cmdstring
|
||||
if VERBOSE:
|
||||
print cmdstring
|
||||
return os.system(cmdstring)
|
||||
|
||||
|
||||
@ -160,21 +224,17 @@ class BuilderBase:
|
||||
self.linker_out_string(outfile))
|
||||
|
||||
for objectfile in objects:
|
||||
cmdstring = "%s %s" % (cmdstring, objectfile + self.object_extension)
|
||||
|
||||
cmdstring = "%s %s" % (cmdstring, objectfile + self.object_extension)
|
||||
for libpath in libpaths:
|
||||
cmdstring = "%s %s%s" % (cmdstring, self.libpath_delimiter, libpath)
|
||||
|
||||
for library in libraries:
|
||||
cmdstring = "%s %s" % (cmdstring, library)
|
||||
|
||||
if extra_parameters:
|
||||
cmdstring = "%s %s" % (cmdstring, extra_parameters)
|
||||
|
||||
if VERBOSE: print cmdstring
|
||||
return os.system(cmdstring)
|
||||
|
||||
|
||||
def _build_command_string(self, macros, argument_delimiter):
|
||||
macrostring = ""
|
||||
|
||||
@ -185,19 +245,20 @@ class BuilderBase:
|
||||
macrostring += '%s%s ' % (argument_delimiter, item)
|
||||
|
||||
return macrostring
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class GCCBuilder(BuilderBase):
|
||||
""" Generic GCC compiler class """
|
||||
def __init__(self):
|
||||
self.include_delimiter = "-I"
|
||||
self.macro_delimiter = "-D"
|
||||
self.libpath_delimiter = "-L"
|
||||
self.compiler_parameters = "-fpermissive"
|
||||
self.compiler_parameters = "-fpermissive -Wno-write-strings"
|
||||
self.linker_parameters = "-shared"
|
||||
self.basemacros = [ ]
|
||||
self.compiler = "g++"
|
||||
self.linker = "g++"
|
||||
self.compiler = "g++ -m32"
|
||||
self.linker = "g++ -m32"
|
||||
self.source_extension = ".cpp"
|
||||
self.object_extension = ".o"
|
||||
|
||||
@ -211,8 +272,9 @@ class GCCBuilder(BuilderBase):
|
||||
return "-o %s" % filename
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class MSVCBuilder(BuilderBase):
|
||||
""" Generic GCC compiler class """
|
||||
""" Generic Visual C compiler class """
|
||||
def __init__(self):
|
||||
self.include_delimiter = "/I"
|
||||
self.macro_delimiter = "/D"
|
||||
@ -226,113 +288,156 @@ class MSVCBuilder(BuilderBase):
|
||||
self.linker = "link"
|
||||
self.source_extension = ".cpp"
|
||||
self.object_extension = ".obj"
|
||||
|
||||
|
||||
def compiler_in_string(self, filename):
|
||||
return "/c %s" % filename
|
||||
|
||||
|
||||
def compiler_out_string(self, filename):
|
||||
return "/Fo%s" % filename
|
||||
|
||||
def linker_out_string(self, filename):
|
||||
return "/out:%s" % filename
|
||||
|
||||
|
||||
def build_distribution(manifest, distrootdir):
|
||||
""" Create dist tree and copy files to it """
|
||||
|
||||
# Remove the previous distibution if exits
|
||||
# -----------------------------------------------------------------------
|
||||
def build_distribution(manifest, distrootdir, ea64, nukeold):
|
||||
""" Create a distibution to a directory and a ZIP file """
|
||||
# (Re)create the output directory
|
||||
if os.path.exists(distrootdir):
|
||||
shutil.rmtree(distrootdir)
|
||||
|
||||
# Create output directory
|
||||
os.makedirs(distrootdir)
|
||||
|
||||
if nukeold:
|
||||
shutil.rmtree(distrootdir)
|
||||
os.makedirs(distrootdir)
|
||||
else:
|
||||
os.makedirs(distrootdir)
|
||||
|
||||
# Also make a ZIP archive of the build
|
||||
zippath = distrootdir + ".zip"
|
||||
zip = zipfile.ZipFile(zippath, nukeold and "w" or "a", zipfile.ZIP_DEFLATED)
|
||||
|
||||
# Copy files, one by one
|
||||
for f in manifest:
|
||||
if type(f) == types.TupleType:
|
||||
srcfilepath = f[0]
|
||||
srcfilename = os.path.basename(srcfilepath)
|
||||
dstdir = distrootdir + os.sep + f[1]
|
||||
dstfilepath = dstdir + os.sep + srcfilename
|
||||
dstdir = os.path.join(distrootdir, f[1])
|
||||
dstfilepath = os.path.join(dstdir, srcfilename)
|
||||
else:
|
||||
srcfilepath = f
|
||||
srcfilename = os.path.basename(f)
|
||||
srcdir = os.path.dirname(f)
|
||||
|
||||
if srcdir == "":
|
||||
dstdir = distrootdir
|
||||
else:
|
||||
dstdir = distrootdir + os.sep + srcdir
|
||||
|
||||
dstdir = os.path.join(distrootdir, srcdir)
|
||||
|
||||
if not os.path.exists(dstdir):
|
||||
os.makedirs(dstdir)
|
||||
|
||||
dstfilepath = dstdir + os.sep + srcfilename
|
||||
|
||||
dstfilepath = os.path.join(dstdir, srcfilename)
|
||||
shutil.copyfile(srcfilepath, dstfilepath)
|
||||
zip.write(dstfilepath)
|
||||
|
||||
zip.close()
|
||||
|
||||
|
||||
def build_plugin(system, idasdkdir):
|
||||
# -----------------------------------------------------------------------
|
||||
def build_plugin(
|
||||
platform,
|
||||
idasdkdir,
|
||||
plugin_name,
|
||||
options):
|
||||
""" Build the plugin from the SWIG wrapper and plugin main source """
|
||||
|
||||
# Find IDA SDK headers
|
||||
ida_include_directory = idasdkdir + os.sep + "include"
|
||||
global SWIG_OPTIONS
|
||||
|
||||
# Get the arguments
|
||||
ea64 = options[S_EA64]
|
||||
with_hexrays = options[S_WITH_HEXRAYS]
|
||||
|
||||
# Path to the IDA SDK headers
|
||||
ida_include_directory = os.path.join(idasdkdir, "include")
|
||||
|
||||
builder = None
|
||||
# Platform-specific settings for the Linux build
|
||||
if system == "Linux":
|
||||
if platform == "linux":
|
||||
builder = GCCBuilder()
|
||||
plugin_name = "python.plx"
|
||||
platform_macros = [ "__LINUX__" ]
|
||||
python_libpath = sysconfig.EXEC_PREFIX + os.sep + "lib"
|
||||
python_library = "-lpython%d.%d" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
|
||||
ida_libpath = idasdkdir + os.sep + "libgcc32.lnx"
|
||||
python_libpath = os.path.join(sysconfig.EXEC_PREFIX, "lib")
|
||||
python_library = "-Bdynamic -lpython%d.%d" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_linux_gcc_64" or "x86_linux_gcc_32")
|
||||
ida_lib = ""
|
||||
extra_link_parameters = "/usr/lib/python%s.%s/lib-dynload/*.so" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
|
||||
|
||||
extra_link_parameters = " -s"
|
||||
builder.compiler_parameters += " -O2"
|
||||
# Platform-specific settings for the Windows build
|
||||
if system == "Windows":
|
||||
elif platform == "win32":
|
||||
builder = MSVCBuilder()
|
||||
plugin_name = "python.plw"
|
||||
platform_macros = [ "__NT__" ]
|
||||
python_libpath = sysconfig.EXEC_PREFIX + os.sep + "libs"
|
||||
python_libpath = os.path.join(sysconfig.EXEC_PREFIX, "libs")
|
||||
python_library = "python%d%d.lib" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
|
||||
ida_libpath = idasdkdir + os.sep + "libvc.w32"
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_win_vc_64" or "x86_win_vc_32")
|
||||
ida_lib = "ida.lib"
|
||||
extra_link_parameters = None
|
||||
|
||||
# Platform-specific settings for the Linux build
|
||||
if system == "Darwin":
|
||||
SWIG_OPTIONS += " -D__NT__ "
|
||||
extra_link_parameters = ""
|
||||
if options[S_DEBUG]:
|
||||
builder.compiler_parameters += " /Zi"
|
||||
builder.linker_parameters += " /DEBUG"
|
||||
if not options[S_NO_OPT] and not options[S_DEBUG]:
|
||||
builder.compiler_parameters += " -Ox"
|
||||
# Platform-specific settings for the Mac OS X build
|
||||
elif platform == "macosx":
|
||||
builder = GCCBuilder()
|
||||
builder.linker_parameters = "-dynamiclib"
|
||||
plugin_name = "python.pmc"
|
||||
platform_macros = [ "__MAC__" ]
|
||||
python_libpath = "."
|
||||
python_library = "-framework Python"
|
||||
ida_libpath = idasdkdir + os.sep + "libgcc32.mac"
|
||||
ida_lib = "-lida"
|
||||
extra_link_parameters = ""
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_mac_gcc_64" or "x86_mac_gcc_32")
|
||||
ida_lib = ea64 and "-lida64" or "-lida"
|
||||
extra_link_parameters = " -s"
|
||||
builder.compiler_parameters += " -O3"
|
||||
|
||||
assert builder, "Unknown platform! No idea how to build here..."
|
||||
|
||||
# Enable EA64 for the compiler if necessary
|
||||
if ea64:
|
||||
platform_macros.append("__EA64__")
|
||||
|
||||
# Build with Hex-Rays decompiler
|
||||
if with_hexrays:
|
||||
platform_macros.append("WITH_HEXRAYS")
|
||||
SWIG_OPTIONS += ' -DWITH_HEXRAYS '
|
||||
|
||||
platform_macros.append("NDEBUG")
|
||||
|
||||
if not '--no-early-load' in sys.argv:
|
||||
platform_macros.append("PLUGINFIX")
|
||||
|
||||
# Turn off obsolete functions
|
||||
#platform_macros.append("NO_OBSOLETE_FUNCS")
|
||||
|
||||
# Build the wrapper from the interface files
|
||||
swigcmd = "swig %s -Iswig -o idaapi.cpp -I%s idaapi.i" % (SWIG_OPTIONS, ida_include_directory)
|
||||
ea64flag = ea64 and "-D__EA64__" or ""
|
||||
swigcmd = "swig %s -Iswig -o idaapi.cpp %s -I%s idaapi.i" % (SWIG_OPTIONS, ea64flag, ida_include_directory)
|
||||
if VERBOSE: print swigcmd
|
||||
res = os.system(swigcmd)
|
||||
assert res == 0, "Failed to build the wrapper with SWIG"
|
||||
|
||||
if res != 0: return False
|
||||
# If we are running on windows, we have to patch some directors'
|
||||
# virtual methods, so they have the right calling convention.
|
||||
# Without that, compilation just won't succeed.
|
||||
if platform == "win32":
|
||||
res = os.system("python patch_directors_cc.py -f idaapi.h")
|
||||
assert res == 0, "Failed to patch directors' calling conventions"
|
||||
|
||||
# Compile the wrapper
|
||||
res = builder.compile("idaapi",
|
||||
includes=[ PYTHON_INCLUDE_DIRECTORY, ida_include_directory ],
|
||||
macros=platform_macros)
|
||||
|
||||
if res != 0: return False
|
||||
assert res == 0, "Failed to build the wrapper module"
|
||||
|
||||
# Compile the main plugin source
|
||||
res = builder.compile("python",
|
||||
includes=[ PYTHON_INCLUDE_DIRECTORY, ida_include_directory ],
|
||||
macros=platform_macros)
|
||||
|
||||
if res != 0: return False
|
||||
assert res == 0, "Failed to build the main plugin object"
|
||||
|
||||
# Link the final binary
|
||||
res = builder.link( ["idaapi", "python"],
|
||||
@ -340,69 +445,163 @@ def build_plugin(system, idasdkdir):
|
||||
[ python_libpath, ida_libpath ],
|
||||
[ python_library, ida_lib ],
|
||||
extra_link_parameters)
|
||||
assert res == 0, "Failed to link the plugin binary"
|
||||
|
||||
if res != 0: return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def clean(manifest):
|
||||
""" Clean the temporary files """
|
||||
|
||||
for i in manifest:
|
||||
try:
|
||||
os.unlink(i)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# -----------------------------------------------------------------------
|
||||
def detect_platform(ea64):
|
||||
# Detect the platform
|
||||
system = platform.system()
|
||||
|
||||
if system == "Windows" or system == "Microsoft":
|
||||
system = "Windows"
|
||||
platform_string = "win32"
|
||||
plugin_name = "python.plw"
|
||||
|
||||
if system == "Linux":
|
||||
platform_string = "linux"
|
||||
plugin_name = "python.plx"
|
||||
plugin_name = ea64 and "python.p64" or "python.plw"
|
||||
|
||||
if system == "Darwin":
|
||||
elif system == "Linux":
|
||||
platform_string = "linux"
|
||||
plugin_name = ea64 and "python.plx64" or "python.plx"
|
||||
|
||||
elif system == "Darwin":
|
||||
platform_string = "macosx"
|
||||
plugin_name = "python.pmc"
|
||||
|
||||
BINDISTDIR = "idapython-%d.%d.%d_ida%d.%d_py%d.%d_%s" % ( VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
VERSION_PATCH,
|
||||
IDA_MAJOR_VERSION,
|
||||
IDA_MINOR_VERSION,
|
||||
PYTHON_MAJOR_VERSION,
|
||||
PYTHON_MINOR_VERSION,
|
||||
platform_string)
|
||||
SRCDISTDIR = "idapython-%d.%d.%d" % ( VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
VERSION_PATCH )
|
||||
|
||||
plugin_name = ea64 and "python.pmc64" or "python.pmc"
|
||||
else:
|
||||
print "Unknown platform!"
|
||||
sys.exit(-1)
|
||||
|
||||
return (system, platform_string, plugin_name)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def build_binary_package(options, nukeold):
|
||||
ea64 = options[S_EA64]
|
||||
system, platform_string, plugin_name = detect_platform(ea64)
|
||||
BINDISTDIR = "idapython-%d.%d.%d_ida%d.%d_py%d.%d_%s" % (VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
VERSION_PATCH,
|
||||
IDA_MAJOR_VERSION,
|
||||
IDA_MINOR_VERSION,
|
||||
PYTHON_MAJOR_VERSION,
|
||||
PYTHON_MINOR_VERSION,
|
||||
platform_string)
|
||||
# Build the plugin
|
||||
res = build_plugin(system, IDA_SDK)
|
||||
if not res: sys.exit(1)
|
||||
|
||||
build_plugin(platform_string, IDA_SDK, plugin_name, options)
|
||||
|
||||
# Build the binary distribution
|
||||
binmanifest = []
|
||||
binmanifest.extend(BINDIST_MANIFEST)
|
||||
binmanifest.append((plugin_name, "plugins"))
|
||||
build_distribution(binmanifest, BINDISTDIR)
|
||||
if nukeold:
|
||||
binmanifest.extend(BINDIST_MANIFEST)
|
||||
|
||||
# Build the binary distribution
|
||||
if not ea64 or nukeold:
|
||||
binmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py", "idaapi.py"])
|
||||
|
||||
binmanifest.append((plugin_name, "plugins"))
|
||||
|
||||
build_distribution(binmanifest, BINDISTDIR, ea64, nukeold)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def build_source_package():
|
||||
""" Build a directory and a ZIP file with all the sources """
|
||||
SRCDISTDIR = "idapython-%d.%d.%d" % (VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
VERSION_PATCH)
|
||||
# Build the source distribution
|
||||
srcmanifest = []
|
||||
srcmanifest.extend(BINDIST_MANIFEST)
|
||||
srcmanifest.extend(SRCDIST_MANIFEST)
|
||||
build_distribution(srcmanifest, SRCDISTDIR)
|
||||
srcmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py"])
|
||||
build_distribution(srcmanifest, SRCDISTDIR, ea64=False, nukeold=True)
|
||||
|
||||
# Clean the temp files
|
||||
cleanlist = []
|
||||
cleanlist.extend(BUILD_TEMPFILES)
|
||||
cleanlist.append(plugin_name)
|
||||
# clean(cleanlist)
|
||||
# -----------------------------------------------------------------------
|
||||
def gen_docs(z = False):
|
||||
print "Generating documentation....."
|
||||
old_dir = os.getcwd()
|
||||
try:
|
||||
curdir = os.getcwd() + os.sep
|
||||
docdir = 'idapython-reference-%d.%d.%d' % (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH)
|
||||
sys.path.append(curdir + 'python')
|
||||
sys.path.append(curdir + 'tools')
|
||||
sys.path.append(curdir + 'docs')
|
||||
import epydoc.cli
|
||||
import swigdocs
|
||||
os.chdir('docs')
|
||||
PYWRAPS_FN = 'pywraps'
|
||||
swigdocs.gen_docs(outfn = PYWRAPS_FN + '.py')
|
||||
epydoc.cli.optparse.sys.argv = [ 'epydoc',
|
||||
'--no-sourcecode',
|
||||
'-u', 'http://code.google.com/p/idapython/',
|
||||
'--navlink', '<a href="http://www.hex-rays.com/idapro/idapython_docs/">IDAPython Reference</a>',
|
||||
'--no-private',
|
||||
'--simple-term',
|
||||
'-o', docdir,
|
||||
'--html',
|
||||
'idc', 'idautils', PYWRAPS_FN, 'idaapi']
|
||||
# Generate the documentation
|
||||
epydoc.cli.cli()
|
||||
|
||||
print "Documentation generated!"
|
||||
|
||||
# Clean temp files
|
||||
for f in [PYWRAPS_FN + '.py', PYWRAPS_FN + '.pyc']:
|
||||
if os.path.exists(f):
|
||||
os.unlink(f)
|
||||
|
||||
if z:
|
||||
z = docdir + '-doc.zip'
|
||||
zip = zipfile.ZipFile(z, "w", zipfile.ZIP_DEFLATED)
|
||||
for fn in glob.glob(docdir + os.sep + '*'):
|
||||
zip.write(fn)
|
||||
zip.close()
|
||||
print "Documentation compressed to", z
|
||||
except Exception, e:
|
||||
print 'Failed to generate documentation:', e
|
||||
finally:
|
||||
os.chdir(old_dir)
|
||||
return
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def usage():
|
||||
print """IDAPython build script.
|
||||
|
||||
Available switches:
|
||||
--doc:
|
||||
Generate documentation into the 'docs' directory
|
||||
--zip:
|
||||
Used with '--doc' switch. It will compress the generated documentation
|
||||
--ea64:
|
||||
Builds also the 64bit version of the plugin
|
||||
--with-hexrays:
|
||||
Build with the Hex-Rays Decompiler wrappings
|
||||
--no-early-load:
|
||||
The plugin will be compiled as normal plugin
|
||||
This switch disables processor, plugin and loader scripts
|
||||
"""
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def main():
|
||||
if '--help' in sys.argv:
|
||||
return usage()
|
||||
elif '--doc' in sys.argv:
|
||||
return gen_docs(z = '--zip' in sys.argv)
|
||||
|
||||
if '--debug' in sys.argv:
|
||||
debug = True
|
||||
|
||||
# Parse options
|
||||
options = parse_options(sys.argv)
|
||||
ea64 = options[S_EA64]
|
||||
|
||||
# Always build the non __EA64__ version
|
||||
options[S_EA64] = False
|
||||
build_binary_package(options, nukeold=True)
|
||||
|
||||
# Rebuild package with __EA64__ if needed
|
||||
if ea64:
|
||||
options[S_EA64] = True
|
||||
build_binary_package(options, nukeold=False)
|
||||
|
||||
# Always build the source package
|
||||
build_source_package()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
106
docs/notes.txt
106
docs/notes.txt
@ -1,53 +1,53 @@
|
||||
Assorted notes
|
||||
--------------
|
||||
|
||||
Wrapped functions and constants:
|
||||
|
||||
All the symbols from the idaapi module are listed in symbollist.txt.
|
||||
Documentation for the plugin API functions functions is in the IDA
|
||||
SDK header files. All function and symbol names directly translate
|
||||
to the C++ counterparts. If you try to use a function that is not
|
||||
wrapped yet you will get an exception like this:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "<string>", line 1, in ?
|
||||
NameError: name 'foobar' is not defined
|
||||
|
||||
If this happens you can check the function in symbollist.txt. If it
|
||||
is not included and it should be please report it to the author.
|
||||
|
||||
|
||||
Data types:
|
||||
|
||||
All the C++ data types are mapped to corresponding Python data types.
|
||||
For example ea_t maps to a Python integer. Complex data types (like
|
||||
structures and classes) are mapped to Python classes that have the
|
||||
same attributes as the original type.
|
||||
|
||||
|
||||
Arguments and return values:
|
||||
|
||||
Generally all function arguments should be the same type as specified
|
||||
by the original headers. Pointers to complex types (structures, classes)
|
||||
are checked and must match the original declarations.
|
||||
|
||||
For example comment = get_func_comment("aa", 0) will raise an exception:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "<string>", line 1, in ?
|
||||
TypeError: Type error. Got aa, expected _p_func_t
|
||||
|
||||
When calling functions that return a string in a buffer (usually with
|
||||
maximum size) the buffer and size parameter is omitted. These functions
|
||||
return either the result in a string or None if the call fails and returns
|
||||
NULL. The output buffers are maximized at MAXSTR.
|
||||
|
||||
Example:
|
||||
|
||||
C++: get_func_name(0x1234, buf, sizeof(buf));
|
||||
Python: name = get_func_name(0x1234)
|
||||
|
||||
Any function that should return a char * is going to return either a
|
||||
Python string (up to MAXSTR) or None.
|
||||
|
||||
|
||||
Assorted notes
|
||||
--------------
|
||||
|
||||
Wrapped functions and constants:
|
||||
|
||||
All the symbols from the idaapi module are listed in symbollist.txt.
|
||||
Documentation for the plugin API functions functions is in the IDA
|
||||
SDK header files. All function and symbol names directly translate
|
||||
to the C++ counterparts. If you try to use a function that is not
|
||||
wrapped yet you will get an exception like this:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "<string>", line 1, in ?
|
||||
NameError: name 'foobar' is not defined
|
||||
|
||||
If this happens you can check the function in symbollist.txt. If it
|
||||
is not included and it should be please report it to the author.
|
||||
|
||||
|
||||
Data types:
|
||||
|
||||
All the C++ data types are mapped to corresponding Python data types.
|
||||
For example ea_t maps to a Python integer. Complex data types (like
|
||||
structures and classes) are mapped to Python classes that have the
|
||||
same attributes as the original type.
|
||||
|
||||
|
||||
Arguments and return values:
|
||||
|
||||
Generally all function arguments should be the same type as specified
|
||||
by the original headers. Pointers to complex types (structures, classes)
|
||||
are checked and must match the original declarations.
|
||||
|
||||
For example comment = get_func_comment("aa", 0) will raise an exception:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "<string>", line 1, in ?
|
||||
TypeError: Type error. Got aa, expected _p_func_t
|
||||
|
||||
When calling functions that return a string in a buffer (usually with
|
||||
maximum size) the buffer and size parameter is omitted. These functions
|
||||
return either the result in a string or None if the call fails and returns
|
||||
NULL. The output buffers are maximized at MAXSTR.
|
||||
|
||||
Example:
|
||||
|
||||
C++: get_func_name(0x1234, buf, sizeof(buf));
|
||||
Python: name = get_func_name(0x1234)
|
||||
|
||||
Any function that should return a char * is going to return either a
|
||||
Python string (up to MAXSTR) or None.
|
||||
|
||||
|
||||
|
@ -1,46 +1,50 @@
|
||||
#
|
||||
# Demonstration of the new chooser usage
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# Modal chooser
|
||||
#
|
||||
|
||||
# Get a modal Choose instance
|
||||
chooser = Choose([], "MyChooser", 1)
|
||||
# List to choose from
|
||||
chooser.list = [ "First", "Second", "Third" ]
|
||||
# Set the width
|
||||
chooser.width = 50
|
||||
# Run the chooser
|
||||
ch = chooser.choose()
|
||||
# Print the results
|
||||
if ch > 0:
|
||||
print "You chose %d which is %s" % (ch, chooser.list[ch-1])
|
||||
else:
|
||||
print "Escape from chooser"
|
||||
|
||||
|
||||
#
|
||||
# Normal chooser
|
||||
#
|
||||
class MyChoose(Choose):
|
||||
"""
|
||||
You have to subclass Chooser to override the enter() method
|
||||
"""
|
||||
def __init__(self, list=[], name="Choose"):
|
||||
Choose.__init__(self, list, name)
|
||||
# Set the width
|
||||
self.width = 50
|
||||
|
||||
def enter(self, n):
|
||||
print "Enter called. Do some stuff here."
|
||||
print "The chosen item is %d = %s" % (n, self.list[n-1])
|
||||
print "Now press ESC to leave."
|
||||
|
||||
# Get a Choose instance
|
||||
chooser = MyChoose([ "First", "Second", "Third" ], "MyChoose")
|
||||
# Run the chooser
|
||||
ch = chooser.choose()
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Chooser test
|
||||
#
|
||||
# This script demonstrates the usage of the class-based chooser.
|
||||
#
|
||||
# Author: Gergely Erdelyi <gergely.erdelyi@d-dome.net>
|
||||
#---------------------------------------------------------------------
|
||||
from idaapi import Choose
|
||||
|
||||
#
|
||||
# Modal chooser
|
||||
#
|
||||
|
||||
# Get a modal Choose instance
|
||||
chooser = Choose([], "MyChooser", 1)
|
||||
# List to choose from
|
||||
chooser.list = [ "First", "Second", "Third" ]
|
||||
# Set the width
|
||||
chooser.width = 50
|
||||
# Run the chooser
|
||||
ch = chooser.choose()
|
||||
# Print the results
|
||||
if ch > 0:
|
||||
print "You chose %d which is %s" % (ch, chooser.list[ch-1])
|
||||
else:
|
||||
print "Escape from chooser"
|
||||
|
||||
#
|
||||
# Normal chooser
|
||||
#
|
||||
class MyChoose(Choose):
|
||||
"""
|
||||
You have to subclass Chooser to override the enter() method
|
||||
"""
|
||||
def __init__(self, list=[], name="Choose"):
|
||||
Choose.__init__(self, list, name)
|
||||
# Set the width
|
||||
self.width = 50
|
||||
self.deflt = 1
|
||||
|
||||
def enter(self, n):
|
||||
print "Enter called. Do some stuff here."
|
||||
print "The chosen item is %d = %s" % (n, self.list[n-1])
|
||||
print "Now press ESC to leave."
|
||||
|
||||
# Get a Choose instance
|
||||
chooser = MyChoose([ "First", "Second", "Third" ], "MyChoose")
|
||||
|
||||
# Run the chooser
|
||||
ch = chooser.choose()
|
||||
|
19
examples/colours.py
Normal file
19
examples/colours.py
Normal file
@ -0,0 +1,19 @@
|
||||
#---------------------------------------------------------------------
|
||||
# Colour test
|
||||
#
|
||||
# This script demonstrates the usage of background colours.
|
||||
#
|
||||
# Author: Gergely Erdelyi <gergely.erdelyi@d-dome.net>
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
# Set the colour of the current segment to BLUE
|
||||
SetColor(here(), CIC_SEGM, 0xc02020)
|
||||
# Set the colour of the current function to GREEN
|
||||
SetColor(here(), CIC_FUNC, 0x208020)
|
||||
# Set the colour of the current item to RED
|
||||
SetColor(here(), CIC_ITEM, 0x2020c0)
|
||||
|
||||
# Print the colours just set
|
||||
print "%x" % GetColor(here(), CIC_SEGM)
|
||||
print "%x" % GetColor(here(), CIC_FUNC)
|
||||
print "%x" % GetColor(here(), CIC_ITEM)
|
107
examples/debughook.py
Normal file
107
examples/debughook.py
Normal file
@ -0,0 +1,107 @@
|
||||
#---------------------------------------------------------------------
|
||||
# Debug notification hook test
|
||||
#
|
||||
# This script start the executable and steps through the first five
|
||||
# instructions. Each instruction is disassembled after execution.
|
||||
#
|
||||
# Original Author: Gergely Erdelyi <gergely.erdelyi@d-dome.net>
|
||||
#
|
||||
# Maintained By: IDAPython Team
|
||||
#
|
||||
#---------------------------------------------------------------------
|
||||
from idaapi import *
|
||||
|
||||
class MyDbgHook(DBG_Hooks):
|
||||
""" Own debug hook class that implementd the callback functions """
|
||||
|
||||
def dbg_process_start(self, pid, tid, ea, name, base, size):
|
||||
print("Process started, pid=%d tid=%d name=%s" % (pid, tid, name))
|
||||
|
||||
def dbg_process_exit(self, pid, tid, ea, code):
|
||||
print("Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code))
|
||||
|
||||
def dbg_library_unload(self, pid, tid, ea, info):
|
||||
print("Library unloaded: pid=%d tid=%d ea=0x%x info=%s" % (pid, tid, ea, info))
|
||||
return 0
|
||||
|
||||
def dbg_process_attach(self, pid, tid, ea, name, base, size):
|
||||
print("Process attach pid=%d tid=%d ea=0x%x name=%s base=%x size=%x" % (pid, tid, ea, name, base, size))
|
||||
|
||||
def dbg_process_detach(self, pid, tid, ea):
|
||||
print("Process detached, pid=%d tid=%d ea=0x%x" % (pid, tid, ea))
|
||||
return 0
|
||||
|
||||
def dbg_library_load(self, pid, tid, ea, name, base, size):
|
||||
print "Library loaded: pid=%d tid=%d name=%s base=%x" % (pid, tid, name, base)
|
||||
|
||||
def dbg_bpt(self, tid, ea):
|
||||
print "Break point at 0x%x pid=%d" % (ea, tid)
|
||||
# return values:
|
||||
# -1 - to display a breakpoint warning dialog
|
||||
# if the process is suspended.
|
||||
# 0 - to never display a breakpoint warning dialog.
|
||||
# 1 - to always display a breakpoint warning dialog.
|
||||
return 0
|
||||
|
||||
def dbg_suspend_process(self):
|
||||
print "Process suspended"
|
||||
|
||||
def dbg_exception(self, pid, tid, ea, exc_code, exc_can_cont, exc_ea, exc_info):
|
||||
print("Exception: pid=%d tid=%d ea=0x%x exc_code=0x%x can_continue=%d exc_ea=0x%x exc_info=%s" % (
|
||||
pid, tid, ea, exc_code & idaapi.BADADDR, exc_can_cont, exc_ea, exc_info))
|
||||
# return values:
|
||||
# -1 - to display an exception warning dialog
|
||||
# if the process is suspended.
|
||||
# 0 - to never display an exception warning dialog.
|
||||
# 1 - to always display an exception warning dialog.
|
||||
return 0
|
||||
|
||||
def dbg_trace(self, tid, ea):
|
||||
print("Trace tid=%d ea=0x%x" % (tid, ea))
|
||||
# return values:
|
||||
# 1 - do not log this trace event;
|
||||
# 0 - log it
|
||||
return 0
|
||||
|
||||
def dbg_step_into(self):
|
||||
print("Step into")
|
||||
self.dbg_step_over()
|
||||
|
||||
def dbg_run_to(self, pid, tid=0, ea=0):
|
||||
print "Runto: tid=%d" % tid
|
||||
idaapi.continue_process()
|
||||
|
||||
|
||||
def dbg_step_over(self):
|
||||
eip = GetRegValue("EIP")
|
||||
print("0x%x %s" % (eip, GetDisasm(eip)))
|
||||
|
||||
self.steps += 1
|
||||
if self.steps >= 5:
|
||||
request_exit_process()
|
||||
else:
|
||||
request_step_over()
|
||||
|
||||
|
||||
# Remove an existing debug hook
|
||||
try:
|
||||
if debughook:
|
||||
print("Removing previous hook ...")
|
||||
debughook.unhook()
|
||||
except:
|
||||
pass
|
||||
|
||||
# Install the debug hook
|
||||
debughook = MyDbgHook()
|
||||
debughook.hook()
|
||||
debughook.steps = 0
|
||||
|
||||
# Stop at the entry point
|
||||
ep = GetLongPrm(INF_START_IP)
|
||||
request_run_to(ep)
|
||||
|
||||
# Step one instruction
|
||||
request_step_over()
|
||||
|
||||
# Start debugging
|
||||
run_requests()
|
@ -1,35 +1,35 @@
|
||||
//
|
||||
// Reference Lister
|
||||
//
|
||||
// List all functions and all references to them in the current section.
|
||||
//
|
||||
// Implemented in IDC
|
||||
//
|
||||
#include <idc.idc>
|
||||
|
||||
static main()
|
||||
{
|
||||
auto ea, func, ref;
|
||||
|
||||
// Get current ea
|
||||
ea = ScreenEA();
|
||||
|
||||
// Loop from start to end in the current segment
|
||||
for (func=SegStart(ea);
|
||||
func != BADADDR && func < SegEnd(ea);
|
||||
func=NextFunction(func))
|
||||
{
|
||||
// If the current address is function process it
|
||||
if (GetFunctionFlags(func) != -1)
|
||||
{
|
||||
Message("Function %s at 0x%x\n", GetFunctionName(func), func);
|
||||
|
||||
// Find all code references to func
|
||||
for (ref=RfirstB(func); ref != BADADDR; ref=RnextB(func, ref))
|
||||
{
|
||||
Message(" called from %s(0x%x)\n", GetFunctionName(ref), ref);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Reference Lister
|
||||
//
|
||||
// List all functions and all references to them in the current section.
|
||||
//
|
||||
// Implemented in IDC
|
||||
//
|
||||
#include <idc.idc>
|
||||
|
||||
static main()
|
||||
{
|
||||
auto ea, func, ref;
|
||||
|
||||
// Get current ea
|
||||
ea = ScreenEA();
|
||||
|
||||
// Loop from start to end in the current segment
|
||||
for (func=SegStart(ea);
|
||||
func != BADADDR && func < SegEnd(ea);
|
||||
func=NextFunction(func))
|
||||
{
|
||||
// If the current address is function process it
|
||||
if (GetFunctionFlags(func) != -1)
|
||||
{
|
||||
Message("Function %s at 0x%x\n", GetFunctionName(func), func);
|
||||
|
||||
// Find all code references to func
|
||||
for (ref=RfirstB(func); ref != BADADDR; ref=RnextB(func, ref))
|
||||
{
|
||||
Message(" called from %s(0x%x)\n", GetFunctionName(ref), ref);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,23 +7,27 @@
|
||||
#
|
||||
from idaapi import *
|
||||
|
||||
# Get current ea
|
||||
ea = get_screen_ea()
|
||||
def main():
|
||||
# Get current ea
|
||||
ea = get_screen_ea()
|
||||
|
||||
# Get segment class
|
||||
seg = getseg(ea)
|
||||
# Get segment class
|
||||
seg = getseg(ea)
|
||||
|
||||
# Loop from segment start to end
|
||||
func = get_func(seg.startEA)
|
||||
# Loop from segment start to end
|
||||
func = get_next_func(seg.startEA)
|
||||
seg_end = seg.endEA
|
||||
while func is not None and func.startEA < seg_end:
|
||||
funcea = func.startEA
|
||||
print "Function %s at 0x%x" % (GetFunctionName(funcea), funcea)
|
||||
|
||||
while func != None and func.startEA < seg.endEA:
|
||||
funcea = func.startEA
|
||||
print "Function %s at 0x%x" % (GetFunctionName(funcea), funcea)
|
||||
ref = get_first_cref_to(funcea)
|
||||
|
||||
ref = get_first_cref_to(funcea)
|
||||
while ref != BADADDR:
|
||||
print " called from %s(0x%x)" % (get_func_name(ref), ref)
|
||||
ref = get_next_cref_to(funcea, ref)
|
||||
|
||||
while ref != BADADDR:
|
||||
print " called from %s(0x%x)" % (get_func_name(ref), ref)
|
||||
ref = get_next_cref_to(funcea, ref)
|
||||
func = get_next_func(funcea)
|
||||
|
||||
func = get_next_func(funcea)
|
||||
|
||||
main()
|
@ -7,14 +7,21 @@
|
||||
#
|
||||
from idautils import *
|
||||
|
||||
# Get current ea
|
||||
ea = ScreenEA()
|
||||
def main():
|
||||
# Get current ea
|
||||
ea = ScreenEA()
|
||||
if ea == idaapi.BADADDR:
|
||||
print("Could not get get_screen_ea()")
|
||||
return
|
||||
|
||||
# Loop from start to end in the current segment
|
||||
for funcea in Functions(SegStart(ea), SegEnd(ea)):
|
||||
print "Function %s at 0x%x" % (GetFunctionName(funcea), funcea)
|
||||
# Loop from start to end in the current segment
|
||||
for funcea in Functions(SegStart(ea), SegEnd(ea)):
|
||||
print("Function %s at 0x%x" % (GetFunctionName(funcea), funcea))
|
||||
|
||||
# Find all code references to funcea
|
||||
for ref in CodeRefsTo(funcea, 1):
|
||||
print " called from %s(0x%x)" % (GetFunctionName(ref), ref)
|
||||
# Find all code references to funcea
|
||||
for ref in CodeRefsTo(funcea, 1):
|
||||
print(" called from %s(0x%x)" % (GetFunctionName(ref), ref))
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
119
examples/ex_actions.py
Normal file
119
examples/ex_actions.py
Normal file
@ -0,0 +1,119 @@
|
||||
import idaapi
|
||||
|
||||
class SayHi(idaapi.action_handler_t):
|
||||
def __init__(self, message):
|
||||
idaapi.action_handler_t.__init__(self)
|
||||
self.message = message
|
||||
|
||||
def activate(self, ctx):
|
||||
print "Hi, %s" % (self.message)
|
||||
return 1
|
||||
|
||||
# You can implement update(), to inform IDA when:
|
||||
# * your action is enabled
|
||||
# * update() should queried again
|
||||
# E.g., returning 'idaapi.AST_ENABLE_FOR_FORM' will
|
||||
# tell IDA that this action is available while the
|
||||
# user is in the current widget, and that update()
|
||||
# must be queried again once the user gives focus
|
||||
# to another widget.
|
||||
#
|
||||
# For example, the following update() implementation
|
||||
# will let IDA know that the action is available in
|
||||
# "IDA View-*" views, and that it's not even worth
|
||||
# querying update() anymore until the user has moved
|
||||
# to another view..
|
||||
def update(self, ctx):
|
||||
return idaapi.AST_ENABLE_FOR_FORM if ctx.form_type == idaapi.BWN_DISASM else idaapi.AST_DISABLE_FOR_FORM
|
||||
|
||||
|
||||
print "Creating a custom icon from raw data!"
|
||||
# Stunned panda face icon data.
|
||||
icon_data = "".join([
|
||||
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1F\xF3\xFF\x61\x00\x00\x02\xCA\x49\x44\x41\x54\x78\x5E\x65",
|
||||
"\x53\x6D\x48\x53\x6F\x14\x3F\xBA\xB5\xB7\xA0\x8D\x20\x41\xF2\xBA\x5D\xB6\x0F\x56\xF4\x41\xA2\xC0\x9C\xE9\xB4\x29\x4A\x7D\xB0\x22\x7A\x11\x02\x23\x48\x2A\xD4\x74\x53\x33\x3F\xD4",
|
||||
"\x3E\x4A\x50\x19\xE4\xB0\xD0\x22\xCD\x44\x45\x4A\x31\x8C\x92\xA2\x3E\x65\x0A\x4D\xCB\x96\x7E\xE8\xD5\x97\xCC\xFE\xFE\x37\xA7\x77\xDB\xBD\xA7\xE7\x3C\xBE\x05\x9E\xED\xB7\xB3\xF3",
|
||||
"\x7B\x39\xF7\xEE\x19\x17\xA8\xAC\x56\xDB\x54\x82\x60\x41\xB3\x59\xBC\xFF\xAC\xF9\xCA\xB5\xAE\x86\xCA\xF9\x4E\xAF\x1B\x3B\xEA\x5D\x48\x9D\x66\xE2\x49\x27\x9F\xD5\x66\x9B\xA2\x1C",
|
||||
"\x22\x02\xD0\x40\xE4\x81\x6C\x3B\x76\x37\x56\xE3\x37\x5F\x2F\x62\xE8\x0B\xD3\x66\x19\x7E\x53\xA7\x99\x78\xAE\x1F\x64\x3E\x21\x71\x69\x09\x5F\x20\x98\x2D\x58\x70\x24\x07\x07\x7B",
|
||||
"\x6F\xB0\x79\x82\x61\x81\x21\xCC\xDE\x21\x54\x16\x02\xD4\x69\x26\x9E\x74\xEE\xCB\xCF\x4D\xC7\x44\xB3\x88\x7C\x81\xC5\x22\xFE\x6C\xB9\xE9\x46\x67\x46\x1A\x8A\x16\x2B\x0A\x5B\x05",
|
||||
"\x74\x66\x65\xE1\x98\x6F\x00\x31\x32\x87\x9F\x59\x77\x66\x66\x61\x42\xBC\xC0\xF5\x6C\x47\x1A\x36\xD7\xB9\x51\x14\xC5\x1E\xBE\xA0\xC3\x5B\xD9\x98\x99\xE1\xC0\xCE\xBE\x57\x48\xD7",
|
||||
"\x9A\x63\x68\xEA\x7C\x8A\xF6\x14\x3B\x9F\xF6\xA6\xA4\x60\xEB\xE3\x3E\x9C\x5F\xD6\x5A\x7A\xFA\x71\xBF\xC3\x81\x3D\x4D\x35\x0D\x7C\xC1\xF3\x87\x57\x43\xF9\x87\x8F\x21\x95\x5E\xAB",
|
||||
"\x41\x83\x4E\x83\x54\xDB\x92\x76\x20\xCA\xBF\xD0\x99\x9D\xBB\x4E\xDB\xBD\xC7\x8E\x2F\x5A\x3D\x74\x3D\x50\x03\x80\x7E\x7A\x7A\x06\x46\x47\xFD\xA0\x33\x6C\x84\x18\x46\x0C\xBD\x1F",
|
||||
"\x86\x2D\x71\x71\x00\x52\x10\x16\x17\xE6\xC1\xE7\x1B\x61\x9A\x81\x69\x31\x30\xFC\x61\x14\xB4\x3A\x3D\x20\x82\x1E\x58\xA9\x15\x05\x41\x14\x05\xB8\x58\xEE\x82\x7D\xE9\x99\x20\xCB",
|
||||
"\x32\x94\x95\x95\xC3\xA5\xD2\x53\x00\x51\x09\xAA\x4B\x0B\xA1\xB8\xA4\x0C\x52\x53\x33\x40\xA5\x52\x81\xDB\x5D\x01\xA2\x45\x00\x45\x51\x80\x2A\x36\x12\x8D\x42\x49\x51\x01\x44\xE5",
|
||||
"\x18\x90\x22\x0A\x98\x8C\x46\xF0\x54\x14\x42\x6D\x7D\x3B\xE4\x1C\x75\x41\xAD\xB7\x1D\x3C\x55\x85\x60\x32\x19\x41\x8A\x2A\xDC\x57\x5C\x74\x12\x28\x47\xA5\x8E\x44\xE4\xF0\x76\x5B",
|
||||
"\x82\xA6\xCD\x5B\x0D\xB2\x12\xE6\xE4\x06\xB5\x1A\x66\xA7\x26\x41\x92\xC2\xA0\xD5\x6A\x60\x67\x92\x19\xAE\x7B\xCE\x70\x4D\x15\xAB\x01\xAD\xC1\x08\x3F\x46\x64\x6E\x8E\x9D\xF9\x13",
|
||||
"\xE8\x1A\xFF\xE4\x63\x8A\x0E\xE6\x02\x41\xF8\x3F\x18\x82\x40\x28\x04\xFD\xDD\x75\xF0\xB6\xFF\x2E\x75\x9A\x89\x27\x9D\xFB\xC8\x4F\x39\xBE\xE0\xB4\xAB\xCE\x35\xFE\x71\x00\x16\x17",
|
||||
"\x25\x76\x50\x26\x76\x6B\x61\x86\x08\xE4\x1D\xAF\x81\xBC\x13\x97\xA9\xD3\x4C\x3C\xE9\xDC\x47\x7E\xCA\xF1\x05\x0C\x5F\x7D\xFE\xEF\x35\x03\xAF\x9F\x00\xB0\x73\x30\x9A\xE2\x81\x0E",
|
||||
"\xF6\xC1\xED\x52\xB8\x77\xAB\x98\x3A\xCD\xC4\x73\x9D\x7C\x6F\xDE\xF9\xCF\x53\x0E\xFE\xA9\xCD\xAE\xB3\x87\xCE\x75\x35\x54\xE1\xD0\xCB\x47\x38\x39\x36\x88\xFF\x4D\xF8\x57\x41\x33",
|
||||
"\xF1\xA4\x93\x0F\x00\x36\xAD\x3E\x4C\x6B\xC5\xC9\x5D\x77\x6A\x2F\xB4\x31\xA3\xC4\x40\x4F\x21\x0F\xD1\x4C\x3C\xE9\x2B\xE1\xF5\x0B\xD6\x90\xC8\x90\x4C\xE6\x35\xD0\xCC\x79\x5E\xFF",
|
||||
"\x2E\xF8\x0B\x2F\x3D\xE5\xC3\x97\x06\xCF\xCF\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"])
|
||||
act_icon = idaapi.load_custom_icon(data=icon_data, format="png")
|
||||
|
||||
hooks = None
|
||||
act_name = "example:add_action"
|
||||
|
||||
if idaapi.register_action(idaapi.action_desc_t(
|
||||
act_name, # Name. Acts as an ID. Must be unique.
|
||||
"Say hi!", # Label. That's what users see.
|
||||
SayHi("developer"), # Handler. Called when activated, and for updating
|
||||
"Ctrl+F12", # Shortcut (optional)
|
||||
"Greets the user", # Tooltip (optional)
|
||||
act_icon)): # Icon ID (optional)
|
||||
print "Action registered. Attaching to menu."
|
||||
|
||||
# Insert the action in the menu
|
||||
if idaapi.attach_action_to_menu("Edit/Export data", act_name, idaapi.SETMENU_APP):
|
||||
print "Attached to menu."
|
||||
else:
|
||||
print "Failed attaching to menu."
|
||||
|
||||
# Insert the action in a toolbar
|
||||
if idaapi.attach_action_to_toolbar("AnalysisToolBar", act_name):
|
||||
print "Attached to toolbar."
|
||||
else:
|
||||
print "Failed attaching to toolbar."
|
||||
|
||||
# We will also want our action to be available in the context menu
|
||||
# for the "IDA View-A" widget.
|
||||
#
|
||||
# To do that, we could in theory retrieve a reference to "IDA View-A", and
|
||||
# then request to "permanently" attach the action to it, using something
|
||||
# like this:
|
||||
# idaapi.attach_action_to_popup(ida_view_a, None, act_name, None)
|
||||
#
|
||||
# but alas, that won't do: widgets in IDA are very "volatile", and
|
||||
# can be deleted & re-created on some occasions (e.g., starting a
|
||||
# debugging session), and our efforts to permanently register our
|
||||
# action on "IDA View-A" would be annihilated as soon as "IDA View-A"
|
||||
# is deleted.
|
||||
#
|
||||
# Instead, we can opt for a different method: attach our action on-the-fly,
|
||||
# when the popup for "IDA View-A" is being populated, right before
|
||||
# it is displayed.
|
||||
class Hooks(idaapi.UI_Hooks):
|
||||
def finish_populating_tform_popup(self, form, popup):
|
||||
# We'll add our action to all "IDA View-*"s.
|
||||
# If we wanted to add it only to "IDA View-A", we could
|
||||
# also discriminate on the widget's title:
|
||||
#
|
||||
# if idaapi.get_tform_title(form) == "IDA View-A":
|
||||
# ...
|
||||
#
|
||||
if idaapi.get_tform_type(form) == idaapi.BWN_DISASM:
|
||||
idaapi.attach_action_to_popup(form, popup, act_name, None)
|
||||
|
||||
hooks = Hooks()
|
||||
hooks.hook()
|
||||
else:
|
||||
print "Action found; unregistering."
|
||||
# No need to call detach_action_from_menu(); it'll be
|
||||
# done automatically on destruction of the action.
|
||||
if idaapi.unregister_action(act_name):
|
||||
print "Unregistered."
|
||||
else:
|
||||
print "Failed to unregister action."
|
||||
|
||||
if hooks is not None:
|
||||
hooks.unhook()
|
||||
hooks = None
|
18
examples/ex_add_menu_item.py
Normal file
18
examples/ex_add_menu_item.py
Normal file
@ -0,0 +1,18 @@
|
||||
import idaapi
|
||||
|
||||
def cb(*args):
|
||||
print("Callback called!")
|
||||
return 1
|
||||
|
||||
try:
|
||||
ex_addmenu_item_ctx
|
||||
idaapi.del_menu_item(ex_addmenu_item_ctx)
|
||||
print("Menu removed")
|
||||
del ex_addmenu_item_ctx
|
||||
except:
|
||||
ex_addmenu_item_ctx = idaapi.add_menu_item("Search/", "X", "", 0, cb, tuple("hello world"))
|
||||
if ex_addmenu_item_ctx is None:
|
||||
print("Failed to add menu!")
|
||||
del ex_addmenu_item_ctx
|
||||
else:
|
||||
print("Menu added successfully. Run the script again to delete the menu")
|
379
examples/ex_askusingform.py
Normal file
379
examples/ex_askusingform.py
Normal file
@ -0,0 +1,379 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to use the Form class
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
from idaapi import Form
|
||||
|
||||
#<pycode(ex_askusingform)>
|
||||
# --------------------------------------------------------------------------
|
||||
class TestEmbeddedChooserClass(Choose2):
|
||||
"""
|
||||
A simple chooser to be used as an embedded chooser
|
||||
"""
|
||||
def __init__(self, title, nb = 5, flags=0):
|
||||
Choose2.__init__(self,
|
||||
title,
|
||||
[ ["Address", 10], ["Name", 30] ],
|
||||
embedded=True, width=30, height=20, flags=flags)
|
||||
self.n = 0
|
||||
self.items = [ self.make_item() for x in xrange(0, nb+1) ]
|
||||
self.icon = 5
|
||||
self.selcount = 0
|
||||
|
||||
def make_item(self):
|
||||
r = [str(self.n), "func_%04d" % self.n]
|
||||
self.n += 1
|
||||
return r
|
||||
|
||||
def OnClose(self):
|
||||
pass
|
||||
|
||||
def OnGetLine(self, n):
|
||||
print("getline %d" % n)
|
||||
return self.items[n]
|
||||
|
||||
def OnGetSize(self):
|
||||
n = len(self.items)
|
||||
print("getsize -> %d" % n)
|
||||
return n
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
class MyForm(Form):
|
||||
def __init__(self):
|
||||
self.invert = False
|
||||
self.EChooser = TestEmbeddedChooserClass("E1", flags=Choose2.CH_MULTI)
|
||||
Form.__init__(self, r"""STARTITEM {id:rNormal}
|
||||
BUTTON YES* Yeah
|
||||
BUTTON NO Nope
|
||||
BUTTON CANCEL Nevermind
|
||||
Form Test
|
||||
|
||||
{FormChangeCb}
|
||||
This is a string: +{cStr1}+
|
||||
This is an address: +{cAddr1}+
|
||||
|
||||
Escape\{control}
|
||||
This is a string: '{cStr2}'
|
||||
This is a number: {cVal1}
|
||||
|
||||
<#Hint1#Enter name:{iStr1}>
|
||||
<#Hint2#Select color:{iColor1}>
|
||||
Browse test
|
||||
<#Select a file to open#Browse to open:{iFileOpen}>
|
||||
<#Select a file to save#Browse to save:{iFileSave}>
|
||||
<#Select dir#Browse for dir:{iDir}>
|
||||
Type
|
||||
<#Select type#Write a type:{iType}>
|
||||
Numbers
|
||||
<##Enter a selector value:{iSegment}>
|
||||
<##Enter a raw hex:{iRawHex}>
|
||||
<##Enter a character:{iChar}>
|
||||
<##Enter an address:{iAddr}>
|
||||
Button test
|
||||
<##Button1:{iButton1}> <##Button2:{iButton2}>
|
||||
|
||||
Check boxes:
|
||||
<Error output:{rError}>
|
||||
<Normal output:{rNormal}>
|
||||
<Warnings:{rWarnings}>{cGroup1}>
|
||||
|
||||
Radio boxes:
|
||||
<Green:{rGreen}>
|
||||
<Red:{rRed}>
|
||||
<Blue:{rBlue}>{cGroup2}>
|
||||
<Embedded chooser:{cEChooser}>
|
||||
The end!
|
||||
""", {
|
||||
'cStr1': Form.StringLabel("Hello"),
|
||||
'cStr2': Form.StringLabel("StringTest"),
|
||||
'cAddr1': Form.NumericLabel(0x401000, Form.FT_ADDR),
|
||||
'cVal1' : Form.NumericLabel(99, Form.FT_HEX),
|
||||
'iStr1': Form.StringInput(),
|
||||
'iColor1': Form.ColorInput(),
|
||||
'iFileOpen': Form.FileInput(open=True),
|
||||
'iFileSave': Form.FileInput(save=True),
|
||||
'iDir': Form.DirInput(),
|
||||
'iType': Form.StringInput(tp=Form.FT_TYPE),
|
||||
'iSegment': Form.NumericInput(tp=Form.FT_SEG),
|
||||
'iRawHex': Form.NumericInput(tp=Form.FT_RAWHEX),
|
||||
'iAddr': Form.NumericInput(tp=Form.FT_ADDR),
|
||||
'iChar': Form.NumericInput(tp=Form.FT_CHAR),
|
||||
'iButton1': Form.ButtonInput(self.OnButton1),
|
||||
'iButton2': Form.ButtonInput(self.OnButton2),
|
||||
'cGroup1': Form.ChkGroupControl(("rNormal", "rError", "rWarnings")),
|
||||
'cGroup2': Form.RadGroupControl(("rRed", "rGreen", "rBlue")),
|
||||
'FormChangeCb': Form.FormChangeCb(self.OnFormChange),
|
||||
'cEChooser' : Form.EmbeddedChooserControl(self.EChooser)
|
||||
})
|
||||
|
||||
|
||||
def OnButton1(self, code=0):
|
||||
print("Button1 pressed")
|
||||
|
||||
|
||||
def OnButton2(self, code=0):
|
||||
print("Button2 pressed")
|
||||
|
||||
|
||||
def OnFormChange(self, fid):
|
||||
if fid == self.iButton1.id:
|
||||
print("Button1 fchg;inv=%s" % self.invert)
|
||||
self.SetFocusedField(self.rNormal)
|
||||
self.EnableField(self.rError, self.invert)
|
||||
self.invert = not self.invert
|
||||
elif fid == self.iButton2.id:
|
||||
g1 = self.GetControlValue(self.cGroup1)
|
||||
g2 = self.GetControlValue(self.cGroup2)
|
||||
d = self.GetControlValue(self.iDir)
|
||||
f = self.GetControlValue(self.iFileOpen)
|
||||
print("cGroup2:%x;Dir=%s;fopen=%s;cGroup1:%x" % (g1, d, f, g2))
|
||||
elif fid == self.cEChooser.id:
|
||||
l = self.GetControlValue(self.cEChooser)
|
||||
print("Chooser: %s" % l)
|
||||
else:
|
||||
print(">>fid:%d" % fid)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def stdalone_main():
|
||||
f = MyForm()
|
||||
f, args = f.Compile()
|
||||
print args[0]
|
||||
print args[1:]
|
||||
f.rNormal.checked = True
|
||||
f.rWarnings.checked = True
|
||||
print hex(f.cGroup1.value)
|
||||
|
||||
f.rGreen.selected = True
|
||||
print f.cGroup2.value
|
||||
print "Title: '%s'" % f.title
|
||||
|
||||
f.Free()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def ida_main():
|
||||
# Create form
|
||||
global f
|
||||
f = MyForm()
|
||||
|
||||
# Compile (in order to populate the controls)
|
||||
f.Compile()
|
||||
|
||||
f.iColor1.value = 0x5bffff
|
||||
f.iDir.value = os.getcwd()
|
||||
f.rNormal.checked = True
|
||||
f.rWarnings.checked = True
|
||||
f.rGreen.selected = True
|
||||
f.iStr1.value = "Hello"
|
||||
f.iFileSave.value = "*.*"
|
||||
f.iFileOpen.value = "*.*"
|
||||
# Execute the form
|
||||
ok = f.Execute()
|
||||
print("r=%d" % ok)
|
||||
if ok == 1:
|
||||
print("f.str1=%s" % f.iStr1.value)
|
||||
print("f.color1=%x" % f.iColor1.value)
|
||||
print("f.openfile=%s" % f.iFileOpen.value)
|
||||
print("f.savefile=%s" % f.iFileSave.value)
|
||||
print("f.dir=%s" % f.iDir.value)
|
||||
print("f.type=%s" % f.iType.value)
|
||||
print("f.seg=%s" % f.iSegment.value)
|
||||
print("f.rawhex=%x" % f.iRawHex.value)
|
||||
print("f.char=%x" % f.iChar.value)
|
||||
print("f.addr=%x" % f.iAddr.value)
|
||||
print("f.cGroup1=%x" % f.cGroup1.value)
|
||||
print("f.cGroup2=%x" % f.cGroup2.value)
|
||||
|
||||
sel = f.EChooser.GetEmbSelection()
|
||||
if sel is None:
|
||||
print("No selection")
|
||||
else:
|
||||
print("Selection: %s" % sel)
|
||||
|
||||
# Dispose the form
|
||||
f.Free()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def ida_main_legacy():
|
||||
# Here we simply show how to use the old style form format using Python
|
||||
|
||||
# Sample form from kernwin.hpp
|
||||
s = """Sample dialog box
|
||||
|
||||
|
||||
This is sample dialog box for %A
|
||||
using address %$
|
||||
|
||||
<~E~nter value:N:32:16::>
|
||||
"""
|
||||
|
||||
# Use either StringArgument or NumericArgument to pass values to the function
|
||||
num = Form.NumericArgument('N', value=123)
|
||||
ok = idaapi.AskUsingForm(s,
|
||||
Form.StringArgument("PyAskUsingForm").arg,
|
||||
Form.NumericArgument('$', 0x401000).arg,
|
||||
num.arg)
|
||||
if ok == 1:
|
||||
print("You entered: %x" % num.value)
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def test_multilinetext_legacy():
|
||||
# Here we text the multi line text control in legacy mode
|
||||
|
||||
# Sample form from kernwin.hpp
|
||||
s = """Sample dialog box
|
||||
|
||||
This is sample dialog box
|
||||
<Enter multi line text:t40:80:50::>
|
||||
"""
|
||||
# Use either StringArgument or NumericArgument to pass values to the function
|
||||
ti = textctrl_info_t("Some initial value")
|
||||
ok = idaapi.AskUsingForm(s, pointer(c_void_p.from_address(ti.clink_ptr)))
|
||||
if ok == 1:
|
||||
print("You entered: %s" % ti.text)
|
||||
|
||||
del ti
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
class MyForm2(Form):
|
||||
"""Simple Form to test multilinetext and combo box controls"""
|
||||
def __init__(self):
|
||||
Form.__init__(self, r"""STARTITEM 0
|
||||
BUTTON YES* Yeah
|
||||
BUTTON NO Nope
|
||||
BUTTON CANCEL NONE
|
||||
Form Test
|
||||
|
||||
{FormChangeCb}
|
||||
<Multilinetext:{txtMultiLineText}>
|
||||
""", {
|
||||
'txtMultiLineText': Form.MultiLineTextControl(text="Hello"),
|
||||
'FormChangeCb': Form.FormChangeCb(self.OnFormChange),
|
||||
})
|
||||
|
||||
|
||||
def OnFormChange(self, fid):
|
||||
if fid == self.txtMultiLineText.id:
|
||||
pass
|
||||
elif fid == -2:
|
||||
ti = self.GetControlValue(self.txtMultiLineText)
|
||||
print "ti.text = %s" % ti.text
|
||||
else:
|
||||
print(">>fid:%d" % fid)
|
||||
return 1
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def test_multilinetext(execute=True):
|
||||
"""Test the multilinetext and combobox controls"""
|
||||
f = MyForm2()
|
||||
f, args = f.Compile()
|
||||
if execute:
|
||||
ok = f.Execute()
|
||||
else:
|
||||
print args[0]
|
||||
print args[1:]
|
||||
ok = 0
|
||||
|
||||
if ok == 1:
|
||||
assert f.txtMultiLineText.text == f.txtMultiLineText.value
|
||||
print f.txtMultiLineText.text
|
||||
|
||||
f.Free()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
class MyForm3(Form):
|
||||
"""Simple Form to test multilinetext and combo box controls"""
|
||||
def __init__(self):
|
||||
self.__n = 0
|
||||
Form.__init__(self,
|
||||
r"""BUTTON YES* Yeah
|
||||
BUTTON NO Nope
|
||||
BUTTON CANCEL NONE
|
||||
Dropdown list test
|
||||
|
||||
{FormChangeCb}
|
||||
<Dropdown list (readonly):{cbReadonly}> <Add element:{iButtonAddelement}> <Set index:{iButtonSetIndex}>
|
||||
<Dropdown list (editable):{cbEditable}> <Set string:{iButtonSetString}>
|
||||
""", {
|
||||
'FormChangeCb': Form.FormChangeCb(self.OnFormChange),
|
||||
'cbReadonly': Form.DropdownListControl(
|
||||
items=["red", "green", "blue"],
|
||||
readonly=True,
|
||||
selval=1),
|
||||
'cbEditable': Form.DropdownListControl(
|
||||
items=["1MB", "2MB", "3MB", "4MB"],
|
||||
readonly=False,
|
||||
selval="4MB"),
|
||||
'iButtonAddelement': Form.ButtonInput(self.OnButtonNop),
|
||||
'iButtonSetIndex': Form.ButtonInput(self.OnButtonNop),
|
||||
'iButtonSetString': Form.ButtonInput(self.OnButtonNop),
|
||||
})
|
||||
|
||||
|
||||
def OnButtonNop(self, code=0):
|
||||
"""Do nothing, we will handle events in the form callback"""
|
||||
pass
|
||||
|
||||
def OnFormChange(self, fid):
|
||||
if fid == self.iButtonSetString.id:
|
||||
s = idc.AskStr("none", "Enter value")
|
||||
if s:
|
||||
self.SetControlValue(self.cbEditable, s)
|
||||
elif fid == self.iButtonSetIndex.id:
|
||||
s = idc.AskStr("1", "Enter index value:")
|
||||
if s:
|
||||
try:
|
||||
i = int(s)
|
||||
except:
|
||||
i = 0
|
||||
self.SetControlValue(self.cbReadonly, i)
|
||||
elif fid == self.iButtonAddelement.id:
|
||||
# add a value to the string list
|
||||
self.__n += 1
|
||||
self.cbReadonly.add("some text #%d" % self.__n)
|
||||
# Refresh the control
|
||||
self.RefreshField(self.cbReadonly)
|
||||
elif fid == -2:
|
||||
s = self.GetControlValue(self.cbEditable)
|
||||
print "user entered: %s" % s
|
||||
sel_idx = self.GetControlValue(self.cbReadonly)
|
||||
|
||||
return 1
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def test_dropdown(execute=True):
|
||||
"""Test the combobox controls, in a modal dialog"""
|
||||
f = MyForm3()
|
||||
f, args = f.Compile()
|
||||
if execute:
|
||||
ok = f.Execute()
|
||||
else:
|
||||
print args[0]
|
||||
print args[1:]
|
||||
ok = 0
|
||||
|
||||
if ok == 1:
|
||||
print "Editable: %s" % f.cbEditable.value
|
||||
print "Readonly: %s" % f.cbReadonly.value
|
||||
|
||||
f.Free()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
tdn_form = None
|
||||
def test_dropdown_nomodal():
|
||||
"""Test the combobox controls, in a non-modal form"""
|
||||
global tdn_form
|
||||
if tdn_form is None:
|
||||
tdn_form = MyForm3()
|
||||
tdn_form.modal = False
|
||||
tdn_form.openform_flags = idaapi.PluginForm.FORM_TAB
|
||||
tdn_form, _ = tdn_form.Compile()
|
||||
tdn_form.Open()
|
||||
|
||||
#</pycode(ex_askusingform)>
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
ida_main()
|
133
examples/ex_choose2.py
Normal file
133
examples/ex_choose2.py
Normal file
@ -0,0 +1,133 @@
|
||||
import idaapi
|
||||
from idaapi import Choose2
|
||||
|
||||
#<pycode(py_choose2ex1)>
|
||||
|
||||
|
||||
class chooser_handler_t(idaapi.action_handler_t):
|
||||
def __init__(self, thing):
|
||||
idaapi.action_handler_t.__init__(self)
|
||||
self.thing = thing
|
||||
|
||||
def activate(self, ctx):
|
||||
sel = []
|
||||
for i in xrange(len(ctx.chooser_selection)):
|
||||
sel.append(str(ctx.chooser_selection.at(i)))
|
||||
print "command %s selected @ %s" % (self.thing, ", ".join(sel))
|
||||
|
||||
def update(self, ctx):
|
||||
return idaapi.AST_ENABLE_FOR_FORM if idaapi.is_chooser_tform(ctx.form_type) else idaapi.AST_DISABLE_FOR_FORM
|
||||
|
||||
|
||||
class MyChoose2(Choose2):
|
||||
|
||||
def __init__(self, title, nb = 5, flags=0, width=None, height=None, embedded=False, modal=False):
|
||||
Choose2.__init__(
|
||||
self,
|
||||
title,
|
||||
[ ["Address", 10], ["Name", 30] ],
|
||||
flags = flags,
|
||||
width = width,
|
||||
height = height,
|
||||
embedded = embedded)
|
||||
self.n = 0
|
||||
self.items = [ self.make_item() for x in xrange(0, nb+1) ]
|
||||
self.icon = 5
|
||||
self.selcount = 0
|
||||
self.modal = modal
|
||||
self.popup_names = ["Inzert", "Del leet", "Ehdeet", "Ree frech"]
|
||||
|
||||
print("created %s" % str(self))
|
||||
|
||||
def OnClose(self):
|
||||
print "closed", str(self)
|
||||
|
||||
def OnEditLine(self, n):
|
||||
self.items[n][1] = self.items[n][1] + "*"
|
||||
print("editing %d" % n)
|
||||
|
||||
def OnInsertLine(self):
|
||||
self.items.append(self.make_item())
|
||||
print("insert line")
|
||||
|
||||
def OnSelectLine(self, n):
|
||||
self.selcount += 1
|
||||
Warning("[%02d] selectline '%s'" % (self.selcount, n))
|
||||
|
||||
def OnGetLine(self, n):
|
||||
print("getline %d" % n)
|
||||
return self.items[n]
|
||||
|
||||
def OnGetSize(self):
|
||||
n = len(self.items)
|
||||
print("getsize -> %d" % n)
|
||||
return n
|
||||
|
||||
def OnDeleteLine(self, n):
|
||||
print("del %d " % n)
|
||||
del self.items[n]
|
||||
return n
|
||||
|
||||
def OnRefresh(self, n):
|
||||
print("refresh %d" % n)
|
||||
return n
|
||||
|
||||
def OnGetIcon(self, n):
|
||||
r = self.items[n]
|
||||
t = self.icon + r[1].count("*")
|
||||
print "geticon", n, t
|
||||
return t
|
||||
|
||||
def show(self):
|
||||
return self.Show(self.modal) >= 0
|
||||
|
||||
def make_item(self):
|
||||
r = [str(self.n), "func_%04d" % self.n]
|
||||
self.n += 1
|
||||
return r
|
||||
|
||||
def OnGetLineAttr(self, n):
|
||||
print("getlineattr %d" % n)
|
||||
if n == 1:
|
||||
return [0xFF0000, 0]
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def test_choose2(modal=False):
|
||||
global c
|
||||
c = MyChoose2("Choose2 - sample 1", nb=10, modal=modal)
|
||||
r = c.show()
|
||||
form = idaapi.get_current_tform()
|
||||
for thing in ["A", "B"]:
|
||||
idaapi.attach_action_to_popup(form, None, "choose2:act%s" % thing)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def test_choose2_embedded():
|
||||
global c
|
||||
c = MyChoose2("Choose2 - embedded", nb=12, embedded = True, width=123, height=222)
|
||||
r = c.Embedded()
|
||||
if r == 1:
|
||||
try:
|
||||
if test_embedded:
|
||||
o, sel = _idaapi.choose2_get_embedded(c)
|
||||
print("o=%s, type(o)=%s" % (str(o), type(o)))
|
||||
test_embedded(o)
|
||||
finally:
|
||||
c.Close()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
|
||||
# Register actions
|
||||
for thing in ["A", "B"]:
|
||||
actname = "choose2:act%s" % thing
|
||||
idaapi.register_action(
|
||||
idaapi.action_desc_t(
|
||||
actname,
|
||||
"command %s" % thing,
|
||||
chooser_handler_t(thing)))
|
||||
|
||||
#test_choose2_embedded()
|
||||
test_choose2(False)
|
||||
|
||||
#</pycode(py_choose2ex1)>
|
100
examples/ex_cli.py
Normal file
100
examples/ex_cli.py
Normal file
@ -0,0 +1,100 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to implement a CLI
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
from idaapi import NW_OPENIDB, NW_CLOSEIDB, NW_TERMIDA, NW_REMOVE, COLSTR, cli_t
|
||||
|
||||
#<pycode(ex_cli_ex1)>
|
||||
class mycli_t(cli_t):
|
||||
flags = 0
|
||||
sname = "pycli"
|
||||
lname = "Python CLI"
|
||||
hint = "pycli hint"
|
||||
|
||||
def OnExecuteLine(self, line):
|
||||
"""
|
||||
The user pressed Enter. The CLI is free to execute the line immediately or ask for more lines.
|
||||
|
||||
This callback is mandatory.
|
||||
|
||||
@param line: typed line(s)
|
||||
@return Boolean: True-executed line, False-ask for more lines
|
||||
"""
|
||||
print "OnExecute:", line
|
||||
return True
|
||||
|
||||
def OnKeydown(self, line, x, sellen, vkey, shift):
|
||||
"""
|
||||
A keyboard key has been pressed
|
||||
This is a generic callback and the CLI is free to do whatever it wants.
|
||||
|
||||
This callback is optional.
|
||||
|
||||
@param line: current input line
|
||||
@param x: current x coordinate of the cursor
|
||||
@param sellen: current selection length (usually 0)
|
||||
@param vkey: virtual key code. if the key has been handled, it should be returned as zero
|
||||
@param shift: shift state
|
||||
|
||||
@return:
|
||||
None - Nothing was changed
|
||||
tuple(line, x, sellen, vkey): if either of the input line or the x coordinate or the selection length has been modified.
|
||||
It is possible to return a tuple with None elements to preserve old values. Example: tuple(new_line, None, None, None) or tuple(new_line)
|
||||
"""
|
||||
print "Onkeydown: line=%s x=%d sellen=%d vkey=%d shift=%d" % (line, x, sellen, vkey, shift)
|
||||
return None
|
||||
|
||||
def OnCompleteLine(self, prefix, n, line, prefix_start):
|
||||
"""
|
||||
The user pressed Tab. Find a completion number N for prefix PREFIX
|
||||
|
||||
This callback is optional.
|
||||
|
||||
@param prefix: Line prefix at prefix_start (string)
|
||||
@param n: completion number (int)
|
||||
@param line: the current line (string)
|
||||
@param prefix_start: the index where PREFIX starts in LINE (int)
|
||||
|
||||
@return: None if no completion could be generated otherwise a String with the completion suggestion
|
||||
"""
|
||||
print "OnCompleteLine: prefix=%s n=%d line=%s prefix_start=%d" % (prefix, n, line, prefix_start)
|
||||
return None
|
||||
#</pycode(ex_cli_ex1)>
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def nw_handler(code, old=0):
|
||||
if code == NW_OPENIDB:
|
||||
print "nw_handler(): installing CLI"
|
||||
mycli.register()
|
||||
elif code == NW_CLOSEIDB:
|
||||
print "nw_handler(): removing CLI"
|
||||
mycli.unregister()
|
||||
elif code == NW_TERMIDA:
|
||||
print "nw_handler(): uninstalled nw handler"
|
||||
idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB | NW_REMOVE, nw_handler)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# Already installed?
|
||||
try:
|
||||
mycli
|
||||
# remove previous CLI
|
||||
mycli.unregister()
|
||||
del mycli
|
||||
# remove previous handler
|
||||
nw_handler(NW_TERMIDA)
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
mycli = mycli_t()
|
||||
|
||||
# register CLI
|
||||
if mycli.register():
|
||||
print "CLI installed"
|
||||
# install new handler
|
||||
idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB, nw_handler)
|
||||
else:
|
||||
del mycli
|
||||
print "Failed to install CLI"
|
||||
|
216
examples/ex_custdata.py
Normal file
216
examples/ex_custdata.py
Normal file
@ -0,0 +1,216 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to use custom data types in Python
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
from idaapi import data_type_t, data_format_t, NW_OPENIDB, NW_CLOSEIDB, NW_TERMIDA, NW_REMOVE, COLSTR
|
||||
import struct
|
||||
import ctypes
|
||||
import platform
|
||||
|
||||
#<pycode(ex_custdata)>
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class pascal_data_type(data_type_t):
|
||||
def __init__(self):
|
||||
data_type_t.__init__(self, name="py_pascal_string",
|
||||
value_size = 2, menu_name = "Pascal string",
|
||||
asm_keyword = "pstr")
|
||||
|
||||
def calc_item_size(self, ea, maxsize):
|
||||
# Custom data types may be used in structure definitions. If this case
|
||||
# ea is a member id. Check for this situation and return 1
|
||||
if _idaapi.is_member_id(ea):
|
||||
return 1
|
||||
|
||||
# get the length byte
|
||||
n = _idaapi.get_byte(ea)
|
||||
|
||||
# string too big?
|
||||
if n > maxsize:
|
||||
return 0
|
||||
# ok, accept the string
|
||||
return n + 1
|
||||
|
||||
class pascal_data_format(data_format_t):
|
||||
FORMAT_NAME = "py_pascal_string_pstr"
|
||||
def __init__(self):
|
||||
data_format_t.__init__(self, name=pascal_data_format.FORMAT_NAME)
|
||||
|
||||
def printf(self, value, current_ea, operand_num, dtid):
|
||||
# Take the length byte
|
||||
n = ord(value[0])
|
||||
o = ['"']
|
||||
for ch in value[1:]:
|
||||
b = ord(ch)
|
||||
if b < 0x20 or b > 128:
|
||||
o.append(r'\x%02x' % ord(ch))
|
||||
else:
|
||||
o.append(ch)
|
||||
o.append('"')
|
||||
return "".join(o)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class simplevm_data_type(data_type_t):
|
||||
ASM_KEYWORD = "svm_emit"
|
||||
def __init__(self):
|
||||
data_type_t.__init__(self,
|
||||
name="py_simple_vm",
|
||||
value_size = 1,
|
||||
menu_name = "SimpleVM",
|
||||
asm_keyword = simplevm_data_type.ASM_KEYWORD)
|
||||
|
||||
def calc_item_size(self, ea, maxsize):
|
||||
if _idaapi.is_member_id(ea):
|
||||
return 1
|
||||
# get the opcode and see if it has an imm
|
||||
n = 5 if (_idaapi.get_byte(ea) & 3) == 0 else 1
|
||||
# string too big?
|
||||
if n > maxsize:
|
||||
return 0
|
||||
# ok, accept
|
||||
return n
|
||||
|
||||
class simplevm_data_format(data_format_t):
|
||||
def __init__(self):
|
||||
data_format_t.__init__(self,
|
||||
name="py_simple_vm_format",
|
||||
menu_name = "SimpleVM")
|
||||
|
||||
# Some tables for the disassembler
|
||||
INST = {1: 'add', 2: 'mul', 3: 'sub', 4: 'xor', 5: 'mov'}
|
||||
REGS = {1: 'r1', 2: 'r2', 3: 'r3'}
|
||||
def disasm(self, inst):
|
||||
"""A simple local disassembler. In reality one can use a full-blown disassembler to render the text"""
|
||||
opbyte = ord(inst[0])
|
||||
op = opbyte >> 4
|
||||
if not (1<=op<=5):
|
||||
return None
|
||||
r1 = (opbyte & 0xf) >> 2
|
||||
r2 = opbyte & 3
|
||||
sz = 0
|
||||
if r2 == 0:
|
||||
if len(inst) != 5:
|
||||
return None
|
||||
imm = struct.unpack_from('L', inst, 1)[0]
|
||||
sz = 5
|
||||
else:
|
||||
imm = None
|
||||
sz = 1
|
||||
text = "%s %s, %s" % (
|
||||
COLSTR(simplevm_data_format.INST[op], idaapi.SCOLOR_INSN),
|
||||
COLSTR(simplevm_data_format.REGS[r1], idaapi.SCOLOR_REG),
|
||||
COLSTR("0x%08X" % imm, idaapi.SCOLOR_NUMBER) if imm is not None else COLSTR(simplevm_data_format.REGS[r2], idaapi.SCOLOR_REG))
|
||||
return (sz, text)
|
||||
|
||||
def printf(self, value, current_ea, operand_num, dtid):
|
||||
r = self.disasm(value)
|
||||
if not r:
|
||||
return None
|
||||
if dtid == 0:
|
||||
return "%s(%s)" % (simplevm_data_type.ASM_KEYWORD, r[1])
|
||||
return r[1]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# This format will display DWORD values as MAKE_DWORD(0xHI, 0xLO)
|
||||
class makedword_data_format(data_format_t):
|
||||
def __init__(self):
|
||||
data_format_t.__init__(self,
|
||||
name="py_makedword",
|
||||
value_size = 4,
|
||||
menu_name = "Make DWORD")
|
||||
|
||||
def printf(self, value, current_ea, operand_num, dtid):
|
||||
if len(value) != 4: return None
|
||||
w1 = struct.unpack_from("H", value, 0)[0]
|
||||
w2 = struct.unpack_from("H", value, 2)[0]
|
||||
return "MAKE_DWORD(0x%04X, 0x%04X)" % (w2, w1)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# This format will try to load a resource string given a number
|
||||
# So instead of displaying:
|
||||
# push 66h
|
||||
# call message_box_from_rsrc_string
|
||||
# It can be rendered as;
|
||||
# push RSRC("The message")
|
||||
# call message_box_from_rsrc_string
|
||||
#
|
||||
# The get_rsrc_string() is not optimal since it loads/unloads the
|
||||
# DLL each time for a new string. It can be improved in many ways.
|
||||
class rsrc_string_format(data_format_t):
|
||||
def __init__(self):
|
||||
data_format_t.__init__(self,
|
||||
name="py_w32rsrcstring",
|
||||
value_size = 1,
|
||||
menu_name = "Resource string")
|
||||
self.cache_node = idaapi.netnode("$ py_w32rsrcstring", 0, 1)
|
||||
|
||||
def get_rsrc_string(self, fn, id):
|
||||
"""
|
||||
Simple method that loads the input file as a DLL with LOAD_LIBRARY_AS_DATAFILE flag.
|
||||
It then tries to LoadString()
|
||||
"""
|
||||
k32 = ctypes.windll.kernel32
|
||||
u32 = ctypes.windll.user32
|
||||
|
||||
hinst = k32.LoadLibraryExA(fn, 0, 0x2)
|
||||
if hinst == 0:
|
||||
return ""
|
||||
buf = ctypes.create_string_buffer(1024)
|
||||
r = u32.LoadStringA(hinst, id, buf, 1024-1)
|
||||
k32.FreeLibrary(hinst)
|
||||
return buf.value if r else ""
|
||||
|
||||
def printf(self, value, current_ea, operand_num, dtid):
|
||||
# Is it already cached?
|
||||
val = self.cache_node.supval(current_ea)
|
||||
|
||||
# Not cached?
|
||||
if val == None:
|
||||
# Retrieve it
|
||||
num = idaapi.struct_unpack(value)
|
||||
val = self.get_rsrc_string(idaapi.get_input_file_path(), num)
|
||||
# Cache it
|
||||
self.cache_node.supset(current_ea, val)
|
||||
|
||||
# Failed to retrieve?
|
||||
if val == "" or val == "\x00":
|
||||
return None
|
||||
# Return the format
|
||||
return "RSRC_STR(\"%s\")" % COLSTR(val, idaapi.SCOLOR_IMPNAME)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Table of formats and types to be registered/unregistered
|
||||
# If a tuple has one element then it is the format to be registered with dtid=0
|
||||
# If the tuple has more than one element, the tuple[0] is the data type and tuple[1:] are the data formats
|
||||
new_formats = [
|
||||
(pascal_data_type(), pascal_data_format()),
|
||||
(simplevm_data_type(), simplevm_data_format()),
|
||||
(makedword_data_format(),),
|
||||
(simplevm_data_format(),)
|
||||
]
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
new_formats.append((rsrc_string_format(),))
|
||||
|
||||
#</pycode(ex_custdata)>
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def nw_handler(code, old=0):
|
||||
# delete notifications
|
||||
if code == NW_OPENIDB:
|
||||
idaapi.register_data_types_and_formats(new_formats)
|
||||
elif code == NW_CLOSEIDB:
|
||||
idaapi.unregister_data_types_and_formats(new_formats)
|
||||
elif code == NW_TERMIDA:
|
||||
idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB | NW_REMOVE, nw_handler)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Check if already installed
|
||||
if idaapi.find_custom_data_type(pascal_data_format.FORMAT_NAME) == -1:
|
||||
if not idaapi.register_data_types_and_formats(new_formats):
|
||||
print "Failed to register types!"
|
||||
else:
|
||||
idaapi.notify_when(NW_TERMIDA | NW_OPENIDB | NW_CLOSEIDB, nw_handler)
|
||||
print "Formats installed!"
|
||||
else:
|
||||
print "Formats already installed!"
|
183
examples/ex_custview.py
Normal file
183
examples/ex_custview.py
Normal file
@ -0,0 +1,183 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to use customview in Python
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
import idaapi
|
||||
import idc
|
||||
from idaapi import simplecustviewer_t
|
||||
#<pycode(py_custviewerex1)>
|
||||
|
||||
class say_something_handler_t(idaapi.action_handler_t):
|
||||
def __init__(self, thing):
|
||||
idaapi.action_handler_t.__init__(self)
|
||||
self.thing = thing
|
||||
|
||||
def activate(self, ctx):
|
||||
print self.thing
|
||||
|
||||
def update(self, ctx):
|
||||
return idaapi.AST_ENABLE_ALWAYS
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class mycv_t(simplecustviewer_t):
|
||||
def Create(self, sn=None):
|
||||
# Form the title
|
||||
title = "Simple custom view test"
|
||||
if sn:
|
||||
title += " %d" % sn
|
||||
|
||||
# Create the customviewer
|
||||
if not simplecustviewer_t.Create(self, title):
|
||||
return False
|
||||
|
||||
for i in xrange(0, 100):
|
||||
self.AddLine("Line %d" % i)
|
||||
|
||||
# self.Jump(0)
|
||||
|
||||
return True
|
||||
|
||||
def OnClick(self, shift):
|
||||
"""
|
||||
User clicked in the view
|
||||
@param shift: Shift flag
|
||||
@return: Boolean. True if you handled the event
|
||||
"""
|
||||
print "OnClick, shift=%d" % shift
|
||||
return True
|
||||
|
||||
def OnDblClick(self, shift):
|
||||
"""
|
||||
User dbl-clicked in the view
|
||||
@param shift: Shift flag
|
||||
@return: Boolean. True if you handled the event
|
||||
"""
|
||||
word = self.GetCurrentWord()
|
||||
if not word: word = "<None>"
|
||||
print "OnDblClick, shift=%d, current word=%s" % (shift, word)
|
||||
return True
|
||||
|
||||
def OnCursorPosChanged(self):
|
||||
"""
|
||||
Cursor position changed.
|
||||
@return: Nothing
|
||||
"""
|
||||
print "OnCurposChanged"
|
||||
|
||||
def OnClose(self):
|
||||
"""
|
||||
The view is closing. Use this event to cleanup.
|
||||
@return: Nothing
|
||||
"""
|
||||
print "OnClose " + self.title
|
||||
|
||||
def OnKeydown(self, vkey, shift):
|
||||
"""
|
||||
User pressed a key
|
||||
@param vkey: Virtual key code
|
||||
@param shift: Shift flag
|
||||
@return: Boolean. True if you handled the event
|
||||
"""
|
||||
print "OnKeydown, vk=%d shift=%d" % (vkey, shift)
|
||||
# ESCAPE?
|
||||
if vkey == 27:
|
||||
self.Close()
|
||||
# VK_DELETE
|
||||
elif vkey == 46:
|
||||
n = self.GetLineNo()
|
||||
if n is not None:
|
||||
self.DelLine(n)
|
||||
self.Refresh()
|
||||
print "Deleted line %d" % n
|
||||
# Goto?
|
||||
elif vkey == ord('G'):
|
||||
n = self.GetLineNo()
|
||||
if n is not None:
|
||||
v = idc.AskLong(self.GetLineNo(), "Where to go?")
|
||||
if v:
|
||||
self.Jump(v, 0, 5)
|
||||
elif vkey == ord('R'):
|
||||
print "refreshing...."
|
||||
self.Refresh()
|
||||
elif vkey == ord('C'):
|
||||
print "refreshing current line..."
|
||||
self.RefreshCurrent()
|
||||
elif vkey == ord('A'):
|
||||
s = idc.AskStr("NewLine%d" % self.Count(), "Append new line")
|
||||
self.AddLine(s)
|
||||
self.Refresh()
|
||||
elif vkey == ord('X'):
|
||||
print "Clearing all lines"
|
||||
self.ClearLines()
|
||||
self.Refresh()
|
||||
elif vkey == ord('I'):
|
||||
n = self.GetLineNo()
|
||||
s = idc.AskStr("InsertedLine%d" % n, "Insert new line")
|
||||
self.InsertLine(n, s)
|
||||
self.Refresh()
|
||||
elif vkey == ord('E'):
|
||||
l = self.GetCurrentLine(notags=1)
|
||||
if not l:
|
||||
return False
|
||||
n = self.GetLineNo()
|
||||
print "curline=<%s>" % l
|
||||
l = l + idaapi.COLSTR("*", idaapi.SCOLOR_VOIDOP)
|
||||
self.EditLine(n, l)
|
||||
self.RefreshCurrent()
|
||||
print "Edited line %d" % n
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
def OnHint(self, lineno):
|
||||
"""
|
||||
Hint requested for the given line number.
|
||||
@param lineno: The line number (zero based)
|
||||
@return:
|
||||
- tuple(number of important lines, hint string)
|
||||
- None: if no hint available
|
||||
"""
|
||||
return (1, "OnHint, line=%d" % lineno)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
try:
|
||||
# created already?
|
||||
mycv
|
||||
print "Already created, will close it..."
|
||||
mycv.Close()
|
||||
del mycv
|
||||
except:
|
||||
pass
|
||||
|
||||
def show_win():
|
||||
x = mycv_t()
|
||||
if not x.Create():
|
||||
print "Failed to create!"
|
||||
return None
|
||||
x.Show()
|
||||
tcc = x.GetTCustomControl()
|
||||
|
||||
# Register actions
|
||||
for thing in ["Hello", "World"]:
|
||||
actname = "custview:say_%s" % thing
|
||||
idaapi.register_action(
|
||||
idaapi.action_desc_t(actname, "Say %s" % thing, say_something_handler_t(thing)))
|
||||
idaapi.attach_action_to_popup(tcc, None, actname)
|
||||
return x
|
||||
|
||||
mycv = show_win()
|
||||
if not mycv:
|
||||
del mycv
|
||||
|
||||
def make_many(n):
|
||||
L = []
|
||||
for i in xrange(1, n+1):
|
||||
v = mycv_t()
|
||||
if not v.Create(i):
|
||||
break
|
||||
v.Show()
|
||||
L.append(v)
|
||||
return L
|
||||
|
||||
#</pycode(py_custviewerex1)>
|
34
examples/ex_dbg.py
Normal file
34
examples/ex_dbg.py
Normal file
@ -0,0 +1,34 @@
|
||||
from tempo import *;
|
||||
|
||||
def test_getmeminfo():
|
||||
L = tempo.getmeminfo()
|
||||
out = []
|
||||
|
||||
# startEA endEA name sclass sbase bitness perm
|
||||
for (startEA, endEA, name, sclass, sbase, bitness, perm) in L:
|
||||
out.append("%x: %x name=<%s> sclass=<%s> sbase=%x bitness=%2x perm=%2x" % (startEA, endEA, name, sclass, sbase, bitness, perm))
|
||||
|
||||
f = file(r"d:\temp\out.log", "w")
|
||||
f.write("\n".join(out))
|
||||
f.close()
|
||||
|
||||
print "dumped meminfo!"
|
||||
|
||||
|
||||
def test_getregs():
|
||||
# name flags class dtyp bit_strings bit_strings_default_mask
|
||||
L = tempo.getregs()
|
||||
out = []
|
||||
for (name, flags, cls, dtype, bit_strings, bit_strings_default_mask) in L:
|
||||
out.append("name=<%s> flags=%x class=%x dtype=%x bit_strings_mask=%x" % (name, flags, cls, dtype, bit_strings_default_mask))
|
||||
if bit_strings:
|
||||
for s in bit_strings:
|
||||
out.append(" %s" % s)
|
||||
|
||||
f = file(r"d:\temp\out.log", "w")
|
||||
f.write("\n".join(out))
|
||||
f.close()
|
||||
|
||||
print "dumped regs!"
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user