SuperAPI AI Directory

re-plugin-dev

General & other

View repository

Updated 10-16 05:07

About this skill

Ghidra / IDA Plugin Development

When to Use / When Not to Use

  • Use: Repetitive analysis steps need to be solidified into reusable tools (batch annotation, decryption loops, custom format parsing, special protocol field annotation)
  • Use: Need interactive UI (menus/shortcuts/panels) or resident functionality that "automatically executes on project load"
  • Use: Team-internal distribution / unified analysis environment across multiple machines (upgrade [[re-ghidra]] / [[re-ida]] scripts to engineered plugins)
  • Don't use: One-off analysis tasks (scripts are use-and-discard; the lightweight scripts in [[re-ghidra]] step 4 / [[re-ida]] step 4 are sufficient)
  • Don't use: Just rewriting existing logic in another language (confirm the scenario first, see step 1)

Tool Preparation

Static analysis tool development can skip the sandbox; plugins run inside the analysis tool process and do not execute sample code (skip the sandbox, [[re-analyze/platform-tips]] static-first).

Ghidra —— Java Extension / Python Script

  • Ghidra installation (JDK 21+, required by Ghidra 11.3+) see [[re-ghidra]] Tool Preparation
  • GhidraDev Eclipse plugin (official, GitHub NationalSecurityAgency/ghidra GhidraDev directory in the repo): requires Eclipse (Linux apt install eclipse / Fedora dnf install eclipse-platform / Arch pacman -S eclipse-java;macOS brew install --cask eclipse-java; Windows official website zip extract); not required——pure Gradle can also build extensions; GhidraDev version and Eclipse version have a compatibility table, if installation fails first check the combination in official release notes
  • Gradle (optional, for building Java extensions): Debian/Ubuntu apt install gradle / Fedora dnf install gradle / Arch pacman -S gradle;macOS brew install gradle;Windows choco install gradle; verify gradle --version; the Gradle in distribution repositories may be too old (fails to build Ghidra extensions)——prefer the gradle wrapper bundled with the GhidraDev project (./gradlew)
  • Verify: Ghidra GUI Script Manager can list scripts;File > Install Extensions can see installed extensions

IDA —— idapython Plugin

  • IDA installation see [[re-ida]] Tool Preparation (idapython is built-in, no separate installation needed)
  • Plugin directory: Windows %APPDATA%\Hex-Rays\IDA Pro\plugins\(or IDA installation directory plugins\);Linux/macOS ~/.idapro/plugins/
  • Verify: after placing the plugin file into the directory, the IDA startup log shows Loading plugin ...;File > Script command execute print(idaapi.IDA_SDK_VERSION) output SDK version

Operation Steps

Execute in order; archive sha256 + path for each plugin artifact (source code/build artifact/test samples and output), for reporting and reuse ([[re-ioc]] evidence chain requirement).

  1. Scenario identification (batch script vs interactive plugin):

    • One-off/simple repetition → script ([[re-ghidra]]'s GhidraScript / [[re-ida]]'s idapython script)
    • Resident/needs UI/execute on load/multi-machine distribution → plugin (Ghidra Java Extension / IDA idapython plugin)
    • Four criteria, hitting any one means a plugin is warranted: ① needs interactive UI (menus/shortcuts/dialogs) ② automatically executes after project load ③ team multi-machine distribution (unified version) ④ needs integration with external services/APIs
    • Record decision: scenario + toolchain + maintenance owner (lay out the maintenance cost from pitfall 4 upfront)
  2. Ghidra plugin skeleton (Java extension / program script):

    • Python script (lightest): @category header comment + save to GhidraScripts directory, run via Script Manager (note built-in Jython 2.7, see pitfall 2 and [[re-ghidra]] pitfalls)
    • Java extension (engineered): GhidraDev New > Ghidra Module Project Select Extension → Implement Plugin class (override init/dispose, register the menu action in init ) → Gradle gradle buildExtension produces .zip → target machine File > Install Extensions install
    • Skeleton key points: for action registration use ToolAction/AbstractAction to attach to the menu; in a headless environment use -postScript for testing ([[re-ghidra]] step 4); for the boundary between scripts and extensions see [[re-ghidra]] pitfall (script vs extension selection)
    • Extension structure: the build artifact .zip contains extension.properties (declaring the applicable Ghidra version range) — installing it on a version outside the range will be rejected at load time, so note the version when distributing and lock the range
    • Verification: after installation trigger the action from the menu; headless analyzeHeadless ... -postScript MyPluginTest.java runs through and produces output;gradle buildExtension after producing the zip, first check the extension.properties version range before distributing
  3. IDA plugin skeleton (idapython):

    # myplugin.py —— 放到 plugins 目录,IDA 启动自动加载
    import idaapi
    class MyPlugin(idaapi.plugin_t):
        flags = idaapi.PLUGIN_KEEP
        comment = "demo plugin"
        help = ""
        wanted_name = "MyPlugin"
        wanted_hotkey = "Ctrl-Shift-M"
        def init(self):
            idaapi.register_action(idaapi.action_desc_t(
                "my:action", "My Action", MyAct(), "Ctrl-Shift-M"))
            return idaapi.PLUGIN_KEEP
        def run(self, arg):
            print("hello from MyPlugin")
    def PLUGIN_ENTRY():
        return MyPlugin()
    
    • Menu registration: idaapi.register_action + idaapi.attach_action_to_menu("Edit/...", "my:action"); dialog: ida_kernwin.ask_str / ask_buttons(note that in IDA 9.x some APIs have moved to ida_kernwin, see pitfall 1)
    • Headless testing: for the headless executable name and -A -S usage see [[re-ida]] (in-script ida_auto etc. also follow the writing style there)
    • Verification: startup log has Loading plugin ... MyPlugin; hotkey-triggered action output is normal
  4. Reuse with existing scripts (scripts from [[re-ghidra]] / [[re-ida]]):

    • Starting materials: the batch rename/decrypt loop script from [[re-ghidra]] step 4, the batch patch/annotate script from [[re-ida]] step 4 — wrap "running it manually once" into "menu-triggered"
    • Scenario examples: automatic constant table scanning (the FindCrypt idea from [[re-crypto-id]]), junk instruction removal batch processing (the D-810 idea from [[re-deobfuscate]]), custom PE/ELF format parsing ([[re-format-pe]] / [[re-format-elf]])
    • Reuse discipline: externalize volatile logic in scripts (pattern strings/tables/thresholds) as config files or plugin options, don't hardcode them into the code (reduces the maintenance cost of pitfall 4)
    • Run the old script once first to verify the baseline output, then wrap it into a plugin — the output before and after the plugin goes live must be identical (regression testing)
  5. Testing and distribution:

    • Test matrix: multiple tool versions (IDA/Ghidra, see pitfall 1), multiple architecture samples (x86/x64/ARM), signed/unsigned samples; run modifying scripts first on a copy .i64/.idb or a separate project ([[re-ida]] pitfall)
    • Read-only verification first: first run a read-only statistics script to confirm expectations, then apply modifying logic ([[re-ida]] pitfall: running a modifying script directly on the original database makes it hard to roll back if it corrupts things)
    • Distribution: Ghidra extension .zip (gradle buildExtension, note the Ghidra version in the README); IDA plugin as a single .py file or packaged, noting the IDA version and Python version; distribution for commercial IDA also has to pass plugin signing (pitfall 3)
    • Acceptance: install from scratch in a clean environment (new project/new IDB) → trigger → output matches the development environment, only then is release complete

Cross-domain combination

  • [[re-binary-core]]: this skill is an extension link in its toolchain (an optional engineering action after decompilation in step 5 of the gateway workflow)
  • [[re-ghidra]]: starting point for Ghidra script/extension development (the script in workflow step 4 is the plugin material)
  • [[re-ida]]: starting point for idapython plugin development (the script in workflow step 4 is the plugin material; how to write headless tests)
  • [[re-deobfuscate]]: Plugin-based deobfuscation scenario (D-810 approach)
  • [[re-crypto-id]]: Plugin-based constant table fingerprint scanning (FindCrypt approach)
  • [[re-format-pe]] / [[re-format-elf]] / [[re-format-macho]]: Target objects of format parsing plugins
  • [[re-binaryninja]]: Binary Ninja scripting API plugin (multi-tool plugin systems can cross-reference each other)
  • Reference [[re-analyze/platform-tips]] static-first principle (plugin development and testing require no sandbox)

Common Pitfalls and Traps

  • API version differences (broken by Ghidra/IDA upgrades): Symptom—the plugin works normally in an older tool version, but after an upgrade it fails to load/errors at runtime/the menu disappears; Cause—Ghidra 11.x has breaking API changes (such as migration of function management classes), and IDA 9.x moves some idc/idaapi functions into reorganized new modules (ida_bytes , etc.); Countermeasure—lock the version in the plugin documentation (state the tested Ghidra/IDA versions), have the test matrix cover old and new versions (Step 5), and after upgrading the tool run read-only scripts before changing code ([[re-ida]] pitfall)
  • Java environment requirements: Symptom—Ghidra extension build or run reports UnsupportedClassVersionError, Python script syntax errors; Cause—JDK version mismatch (Ghidra 11.3+ requires JDK 21, see [[re-ghidra]]), the built-in interpreter is Jython 2.7 (Python 2 syntax, does not support f-strings/walrus operator, and cannot import pip packages); Countermeasure—java -version confirm 21+ and JAVA_HOME is correct; write scripts in Python 2-compatible syntax, and when modern Python is needed use ghidra-bridge to connect to external Python 3 ([[re-ghidra]] pitfall)
  • Plugin signing (IDA commercial edition): Symptom—the plugin is placed in the plugins directory but commercial IDA does not load it (no mention of the plugin in the startup log, no error at all); Cause—commercial IDA performs signature verification on third-party plugins, and unsigned plugins are rejected; Countermeasure—confirm the IDA version (Freeware does not perform signature verification), use Freeware/headless mode for testing during development, and for official distribution go through Hex-Rays' official plugin signing application process; write the "signing status" into the distribution documentation
  • Maintenance cost spirals out of control: Symptom—three months after release the plugin cannot keep up with upgrades/new sample forms, nobody fixes it, and it instead slows down analysis; Cause—a plugin is a long-term commitment (both API upgrades and scenario changes must be tracked), whereas a one-off script does not have this cost; Countermeasure—in Step 1 first judge whether it is worth it: simple logic/fast-changing → script; stable and highly reused → plugin; within the plugin, externalize volatile logic (pattern strings/tables/thresholds) into configuration to reduce the amount of code to change; record the version and corresponding tool version with each release
  • Modifying plugins directly change the database, and damage is irreversible: Symptom—after a batch rename/patch plugin finishes, IDB annotations are scrambled and hard to undo; Cause—skipping read-only verification and not running on a copy; Countermeasure—first run a read-only statistics script to confirm expectations ([[re-ida]] pitfall), verify modification logic first on a copy .i64/.idb or an independent Ghidra project, and only apply it to the official database after acceptance passes
  • Ghidra extension refused due to version range: Symptom—the extension installs into Ghidra with no error but does not appear in the list; Cause—the applicable version range declared in extension.properties does not match the current Ghidra and is rejected by the installer; Countermeasure—first unzip the zip and check the version range in extension.properties (ghidra.version field), and when using GhidraDev to generate the project, create it according to the target version; state the tested Ghidra version in the distribution documentation
  • Headless/batch environments cannot rely on interactive dialogs: Phenomenon—analyzeHeadless or in IDA headless mode ([[re-ida]]), plugin behavior is abnormal/stuck; Cause—batch mode has no UI event loop, ask_* dialog-type APIs and menu-triggered logic are unavailable; Countermeasure—read interactive parameters (paths/thresholds/mode strings) from command-line arguments or a configuration file instead, determine the runtime environment inside the plugin first (whether it is a GUI session) before deciding which branch to take; headless test scripts only verify pure computation logic