Skip to content

Commit

Permalink
Merge pull request #10 from james91b/release-0.3
Browse files Browse the repository at this point in the history
Release 0.3
  • Loading branch information
james91b committed Oct 21, 2015
2 parents 44b9acb + 6f68923 commit 018e920
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 39 deletions.
52 changes: 36 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,27 @@ cmake_policy(SET CMP0015 NEW)
set(CMAKE_BUILD_TYPE Release)

if (WIN32)
add_definitions(-D__NT__=1
add_definitions(-D__NT__
-DUNICODE
-DWIN32
-D__IDP__)

find_library(IDA_LIB
find_library(IDA32_LIB
NAMES "ida"
PATHS "${IDA_SDK}/lib/x86_win_vc_32")

find_library(PYTHON_LIB
NAMES "python27"
PATHS "${PYTHON_DIR}/libs")
find_library(IDA64_LIB
NAMES "ida"
PATHS "${IDA_SDK}/lib/x86_win_vc_64")

find_library(MINHOOK_LIB
NAMES "libMinHook-x86-v90-md"
PATHS "lib/MinHook_13_lib/lib")

find_library(PYTHON_LIB
NAMES "python27"
PATHS "${PYTHON_DIR}/libs")

elseif (APPLE)
add_definitions(-D__MAC__=1)
find_library (IDA_LIB
Expand All @@ -36,33 +41,48 @@ endif ( )
set (SOURCES
src/ida_ipython.cpp
src/ipythonEmbed.cpp
src/ipythonEmbed.h)
src/ipythonEmbed.h
src/persist.h
src/persist.cpp)

include_directories(${IDA_SDK}/include
${PYTHON_DIR}/include
lib/MinHook_13_lib/include)

add_library(ida_ipython MODULE ${SOURCES})
add_library(ida32_ipython MODULE ${SOURCES})
add_library(ida64_ipython MODULE ${SOURCES})

if (WIN32)
set (IDA_SUFFIX ".plw")
set (IDA32_SUFFIX ".plw")
set (IDA64_SUFFIX ".p64")
elseif (APPLE)
set (IDA_SUFFIX ".pmc")
# set (IDA_SUFFIX ".pmc")
elseif (UNIX)
set (IDA_SUFFIX ".plx")
# set (IDA_SUFFIX ".plx")
endif ()

set_target_properties (ida_ipython
set_target_properties (ida32_ipython
PROPERTIES
SUFFIX ${IDA32_SUFFIX}
OUTPUT_NAME ida_ipython)

set_target_properties (ida64_ipython
PROPERTIES
SUFFIX ${IDA_SUFFIX}
SUFFIX ${IDA64_SUFFIX}
COMPILE_DEFINITIONS __EA64__
OUTPUT_NAME ida_ipython)

target_link_libraries (ida_ipython
${IDA_LIB}
target_link_libraries (ida32_ipython
${IDA32_LIB}
${MINHOOK_LIB}
${PYTHON_LIB})

target_link_libraries (ida64_ipython
${IDA64_LIB}
${MINHOOK_LIB}
${PYTHON_LIB})

install(TARGETS ida_ipython
DESTINATION ${IDA_DIR}/plugins)
install(TARGETS ida32_ipython DESTINATION ${IDA_DIR}/plugins)
install(TARGETS ida64_ipython DESTINATION ${IDA_DIR}/plugins)
install(FILES python/ipythonEmbed.py DESTINATION ${IDA_DIR}/python)
install(FILES idc/nothing.idc DESTINATION ${IDA_DIR}/idc)
34 changes: 24 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Another useful case is using IPython notebooks.

- [Function Entropy](http://nbviewer.ipython.org/github/james91b/ida_ipython/blob/master/notebook/examples/Function%20Entropy.ipynb) - Here is an example where we compute the entropy (using scipy stats module) of each function in notepad.exe and graph the result.
- [Cython and IDA](http://nbviewer.ipython.org/github/james91b/ida_ipython/blob/master/notebook/examples/Cython%20and%20IDA.ipynb) - Here is an example where we use the cython cell magic to call IDA Api's that are not exposed via IDAPython.
- [Sark Snapshots](http://nbviewer.ipython.org/github/james91b/ida_ipython/blob/master/notebook/examples/Sark%20Snapshots.ipynb) - Example of screen snapshots using Sark.

More examples..soon...

Expand All @@ -36,30 +37,43 @@ I suggest using the [Anaconda](http://continuum.io/downloads) distribution of Py
This plugin should work on all 6.X x86 QT versions of IDA on Windows.

##Basic Installation and QTConsole
1. Download and extract the [release](https://github.com/tmr232/ida_ipython/releases/tag/0.2)
1. Download and extract the [release](https://github.com/tmr232/ida_ipython/releases/tag/0.3)
2. Copy the contents of the `plugins` and `python` directories under IDA's installation directory.
4. Launch IDA.
5. At the command line (Windows), start an IPython qtconsole with the kernel instance (outputted in the IDA console) e.g `ipython qtconsole --existing kernel-4264.json`

##Using the Notebook
1. Copy `idc` directory to your IDA directory. (the nothing.idc scipt is used to pass command line parameters to the plugin)
2. Change the paths to the `idaq.exe` and `idaq64.exe` executables in the `kernel.json` under the `notebook/kernels/ida32`
and `notebook/kernels/ida64` directories respectively
3. Copy the `notebook/kernels` directory to one of Jupyter's data directories, usually `%APPDATA%\jupyter` (list all with
`jupyter --paths`)
1. Copy `idc` directory to your IDA directory. (the `nothing.idc` script is used to pass command line parameters to the plugin)
2. Change the paths to the `idaq.exe` and `idaq64.exe` executables in the `kernel.json` under the `notebook\kernels\ida32`
and `notebook\kernels\ida64` directories respectively
3. Install the kernels using `jupyter-kernelspec install` (e.g. `jupyter-kernelspec install --user notebook\kernels\ida64`)
4. When starting a notebook, choose the `IDA32` or `IDA64` kernels, depending on your desired IDA version.

#How to Build
1. Install cmake
2. At the command line cd to the root directory and run the following
3. `cd build`
4. `cmake -G "Visual Studio 11" -D PYTHON_DIR="<YOUR_PYTHON_DIR>" -D IDA_SDK="<YOUR_IDASDK_LOCATION>" -D IDA_DIR="<YOUR_IDA_DIRECTORY>" ..`
3. `mkdir build`
4. `cd build`
5. `cmake -G "Visual Studio 11" -DPYTHON_DIR="<YOUR_PYTHON_DIR>" -DIDA_SDK="<YOUR_IDASDK_LOCATION>" -DIDA_DIR="<YOUR_IDA_DIRECTORY>" ..`
e.g.
`cmake -G "Visual Studio 11" -D PYTHON_DIR="C:\Anaconda" -D IDA_SDK="C:\dev\IDA\idasdks\idasdk64" -D IDA_DIR="C:/Program Files (x86)/IDA 6.4" ..`
5. `cmake --build . --config Release`
`cmake -G "Visual Studio 11" -DPYTHON_DIR="C:\Anaconda" -DIDA_SDK="C:\dev\IDA\idasdks\idasdk64" -DIDA_DIR="C:/Program Files (x86)/IDA 6.4" ..`
6. `cmake --build . --config Release`

So far only tested with "Visual Studio 11" compiler.

#Changelog
0.3
- 2015-10-04: Running the plugin from the plugins menu or view menu will now launch an IPython QTConsole. Consoles are terminated on exit.
- 2015-10-04: Only capture standard output and error when executing the kernel
- 2015-10-21: Improve error reporting

0.2
- 2015-09-30: Added support for Jupyter (replaces original support for IPython).
- 2015-10-01: Added support for ida64.

0.1
- First release

#To do/Future Ideas
- More examples
- Create a library for cell/line magic functions specific to IDA
93 changes: 93 additions & 0 deletions notebook/examples/Sark Snapshots.ipynb

Large diffs are not rendered by default.

104 changes: 97 additions & 7 deletions python/ipythonEmbed.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import traceback

try:
import os
import sys
import platform
import subprocess
import idaapi
import atexit
import contextlib

#This is a hack to get zmq to work with the Anaconda distribution and IDA.
# This is a hack to get zmq to work with the Anaconda distribution and IDA.
try:
platform.python_implementation()
except ValueError:
Expand All @@ -12,7 +19,10 @@
from ipykernel.kernelapp import IPKernelApp
from IPython.utils.frame import extract_module_locals

sys.__stdout__ = sys.__stderr__ = sys.stdout
kernel_app = None
menu_items = []
qtconsole_processes = []


def embed_kernel(module=None, local_ns=None, **kwargs):
"""Embed and start an IPython kernel in a given scope.
Expand Down Expand Up @@ -57,15 +67,95 @@ def embed_kernel(module=None, local_ns=None, **kwargs):

if app.poller is not None:
app.poller.start()

app.kernel.start()
return app


@contextlib.contextmanager
def capture_output_streams():
_capture_output_streams()
try:
yield
finally:
_release_output_streams()


def _capture_output_streams():
sys.__stdout__, sys.__stderr__, sys.stdout, sys.stderr = sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__


def _release_output_streams():
sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__ = sys.__stdout__, sys.__stderr__, sys.stdout, sys.stderr


def find_python_dir():
# We need to get the python directory like this, because
# sys.executable will return idaq.exe. This just goes two
# directories up from os.py location
return os.path.dirname(os.path.dirname(os.__file__))


def start_qtconsole():
try:
if kernel_app:
python_directory = find_python_dir()
cmd_line = [
"{}/pythonw".format(python_directory),
"-m", "qtconsole",
"--existing", kernel_app.connection_file
]
process = subprocess.Popen(cmd_line,
stdin=None,
stdout=None,
stderr=None,
close_fds=True)
qtconsole_processes.append(process)
else:
print "Error: No kernel defined!"
except Exception, e:
traceback.print_exc()


@atexit.register
def term():
kill_qtconsoles()
remove_menus()

def kill_qtconsoles():
for process in qtconsole_processes:
process.kill()


def remove_menus():
for menu_item in menu_items:
idaapi.del_menu_item(menu_item)


def add_idaipython_menu():
menu_item = idaapi.add_menu_item('View/', 'IDAIPython QtConsole', '', 0, start_qtconsole, tuple())
menu_items.append(menu_item)


def start(argv=None):
if argv:
sys.argv = argv
kapp = embed_kernel(module=__main__, local_ns={})
return kapp.kernel.do_one_iteration
try:
with capture_output_streams():
global kernel_app
if argv:
sys.argv = argv

kernel_app = embed_kernel(module=__main__, local_ns={})

def kernel_iteration():
with capture_output_streams():
kernel_app.kernel.do_one_iteration()

add_idaipython_menu()

return kernel_iteration
except Exception, e:
traceback.print_exc()
raise

except Exception, e:
import traceback
traceback.print_exc()
25 changes: 21 additions & 4 deletions src/ida_ipython.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "pro.h"
#include "ida.hpp"

#include "persist.h"

//Return the arguments in passed via IDC script arguments as a
//python list
PyObject* idc_script_args()
Expand Down Expand Up @@ -38,6 +40,7 @@ PyObject* idc_script_args()
int idaapi init(void)
{
PyObject* idc_args = idc_script_args();
int success = -1;

IPYTHONEMBED_STATUS status = ipython_embed_start(idc_args);
if (status != IPYTHONEMBED_OK) {
Expand All @@ -56,30 +59,44 @@ int idaapi init(void)
}
return PLUGIN_SKIP;
}


/* Try and make the module persist in memory until termination. Failing to do so can cause IDA to crash
when it terminates the plugin. */
success = persist();
if (0 != success) {
warning("Failed to lock the module in memory");
return PLUGIN_SKIP;
}

return PLUGIN_KEEP;
}

void idaapi term(void)
{
ipython_embed_term();
ipython_embed_term();
}

void idaapi run(int options)
{
ipython_start_qtconsole();
}
//--------------------------------------------------------------------------
//
// PLUGIN DESCRIPTION BLOCK
//
//--------------------------------------------------------------------------
static char wanted_name[] = "IDA IPython Kernel";
static char wanted_name[] = "IDA IPython QTConsole";
static char comment[] = "Runs an IPython Kernel within IDA";
static char help[] = "This plugin allows the user to run an IPython kernel within IDA\n";

plugin_t PLUGIN =
{
IDP_INTERFACE_VERSION,
PLUGIN_FIX | PLUGIN_HIDE, // plugin flags
PLUGIN_FIX, // plugin flags
init, // initialize
term, // terminate. this pointer may be NULL.
NULL, // invoke plugin
run, // invoke plugin
comment, // long comment about the plugin
// it could appear in the status line
// or as a hint
Expand Down
Loading

0 comments on commit 018e920

Please sign in to comment.