Skip to main content

Plugin Manager for IDA Pro

Project description

IDA Pro Plugin Manager

Installation

There are two steps:

  1. to fetch the plugin manager
  2. to register the plugin manager with IDA Pro

1. Fetch the package from PyPI

The plugin manager is distributed via PyPI, so install it via pip:

$ pip install idapro-plugin-manager

Make sure to use the pip from your IDAPython installation, which I recommend to be a virtual environment.

You can find the location of the pip executable by running the following within your IDAPython console in IDA Pro:

Python>import subprocess
Python>subprocess.run(["which", "pip"], capture_output=True).stdout.decode("utf-8").strip()
'/Users/user/.idapro/venv/bin/pip'

(TODO: check this works on Windows, too.)

2. Register the plugin manager in IDA Pro

Copy plugins/load_idapro_plugin_manager.py to ~/.idapro/plugins/.

You only have to do this once, even if you upgrade IDA.

Packaging Plugins

Plugins are distributed via PyPI, which is usually (but not always) used for Python packages. We use Python-style metadata, such as a pyproject.toml file, to describe the plugin.

By adding an "entry point" for the idapro.plugins group, we can register a plugin with the IDA Pro Plugin Manager.

For example, consider a simple IDA plugin with a single file: hello.py. (Recall that IDAPython plugins should have a function named PLUGIN_ENTRY that's used to initialize the plugin.)

The package structure would look like:

basic-ida-plugin/
├── hello.py
└── pyproject.toml

with the pyproject.toml contents:

[project]
name = "basic-ida-plugin"
...

[project.entry-points.'idapro.plugins']
idapython = 'hello'

and hello.py contents:

import idaapi

class hello_plugmod_t(idaapi.plugmod_t):
    def run(self, arg):
        print("Hello world! (py)")
        return 0

class hello_plugin_t(idaapi.plugin_t):
    flags = idaapi.PLUGIN_UNL | idaapi.PLUGIN_MULTI
    comment = "This is a comment"
    help = "This is help"
    wanted_name = "Hello Python plugin"
    wanted_hotkey = "Alt-F8"

    def init(self):
        print("hello from init")
        return hello_plugmod_t()

def PLUGIN_ENTRY():
    return hello_plugin_t()

Entry Points

Each package contains a single plugin. The keys within the entry points section describe the sort of plugin thats available:

  • idapython for IDAPython-based plugins
  • target triple for compiled plugins, like aarch64-apple-darwin

Examples

For a single Python file named hello.py (like above):

[project.entry-points.'idapro.plugins']
idapython = 'hello'  # note: there's no file extension

For a plugin within a larger Python package, such as for the default plugin provided by capa in capa.ida.plugin:

[project.entry-points.'idapro.plugins']
idapython = 'capa.ida.plugin'

In this scenario, the entry point section would be in capa's pyproject.toml, so you'd install capa within your IDAPython virtualenv and the plugin would now be available within IDA.

Since the name capa doesn't match the idapro-plugin-* prefix for IDA plugins available on PyPI, it would have to be registered with the extras list.

Native plugins

For a compiled plugin, create a Python package with the compiled artifacts stored within the "Python" package:

 eza --tree --level=2 --long --git
native-ida-plugin
├── bin
│   └── native_ida_plugin
│       ├── __init__.py
│       ├── mysample.so
│       ├── mysample.dll
│       ├── mysample_aarch64.dylib
│       └── mysample_x86_64.dylib
├── pyproject.toml
└── README.md

And use target triple names as the entry point keys to specify filenames for the compiled artifacts:

[project.entry-points.'idapro.plugins']
aarch64-apple-darwin = "native_ida_plugin:mysample_aarch64"  # note: extensions are automatically appended
x86_64-apple-darwin  = "native_ida_plugin:mysample_x86_64"
x86_64-unknown-linux = "native_ida_plugin:mysample"
x86_64-pc-windows    = "native_ida_plugin:mysample"

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
package-dir = {"" = "bin"}  # Python package data is found in "bin/" directory.
                            # "src/" is the default, but we'll use "bin/" for all this binary data.

[tool.setuptools.package-data]
"native_ida_plugin" = [
    # filenames relative to: bin/native_ida_plugin/
    "mysample.*",
    "mysample_aarch64.*",
    "mysample_x86_64.*",
]

Unfortunately the entry point value (native_ida_plugin:mysample_aarch64) cannot contain / or ., so the compiled artifacts are best placed in that package root directory. Its also possible to use a layout like native_ida_plugin.aarch64:mysample.

Technically, the entry point value is supposed to point to a Python object. We abuse this a bit, because we assign a specific meaning to entry point keys like aarch64-apple-darwin. To make this safe, add package level variables to bin/native_ida_plugin/__init__.py:

mysample_aarch64 = None
mysample_x86_64 = None
mysample = None

But this is not strictly necessary today.

Native Dependencies

(this is experimental/not implemented yet/just an idea)

Extend the search path for libraries like this:

[tool.idapro.plugins.lib]
'aarch64-apple-darwin' = 'lib/darwin-aarch64/'
'x86_64-apple-darwin'  = 'lib/darwin-x86_64/'

Which is useful if your plugin depends on additional native libraries; for example, OpenSSL.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

idapro_plugin_manager-0.1.0.tar.gz (9.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

idapro_plugin_manager-0.1.0-py3-none-any.whl (5.9 kB view details)

Uploaded Python 3

File details

Details for the file idapro_plugin_manager-0.1.0.tar.gz.

File metadata

  • Download URL: idapro_plugin_manager-0.1.0.tar.gz
  • Upload date:
  • Size: 9.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for idapro_plugin_manager-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dedf1e5158288ab850c12758840f6440e1f904fac7487dacefe46cad481458a0
MD5 72197b00ad629ffe5f3116f0dd45109c
BLAKE2b-256 354b9d15cbf6cb8e5f11bab63ecbedd5c109817bb4faa62e29ed8f573e4b3abe

See more details on using hashes here.

Provenance

The following attestation bundles were made for idapro_plugin_manager-0.1.0.tar.gz:

Publisher: publish-idapro-plugin-manager.yml on williballenthin/idawilli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file idapro_plugin_manager-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for idapro_plugin_manager-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9a0182f360ba5bce39108890f8e9871313ed75c483c5155330a08eb1576c81b4
MD5 a5ae9513bbe2bd0519a7efb403d27097
BLAKE2b-256 f35539d7fa1ee9e1a5d27be05fe8cb2cffbc1a871e7e8b90123b4331c0a3d244

See more details on using hashes here.

Provenance

The following attestation bundles were made for idapro_plugin_manager-0.1.0-py3-none-any.whl:

Publisher: publish-idapro-plugin-manager.yml on williballenthin/idawilli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page