Skip to main content
Glama

GhidraMCP+ — Ghidra to MCP Bridge with Evidence Capture

An upgraded fork of LaurieWired/ghidraMCP, extended for static malware analysis workflows that require reproducible evidence: annotated screenshots, verifiable findings, and structured reports.

Credit: This project is built on top of LaurieWired/ghidraMCP (Apache 2.0). The original Ghidra plugin and MCP bridge are LaurieWired's work; this fork keeps that foundation and adds the features listed below. Thank you, LaurieWired, for open-sourcing the groundwork.

License

GhidraMCP Evidence Capture

Automatic red highlight on the exact evidence line — the new /evidence endpoint (address-range mode shown).

What This Fork Adds

Feature

Original (LaurieWired)

This fork

Screenshot of the Ghidra window

no

/screenshot

Go to an address (like pressing G)

no

/focus

Red highlight on evidence plus capture in one call

no

/evidence (uses official FieldPanel.getCursorBounds())

Red caption above the box

no

label parameter

Range highlight (multiple lines)

no

to parameter

HTTP server binding

all interfaces

loopback only (127.0.0.1)

Request body limit

none

1 MB max

Output path validation in the bridge

none

blocks /etc, /proc, /sys, /dev, C:\Windows, ..

One-command launcher (Linux/macOS)

no

start-mcp.sh

One-command launcher (Windows)

no

start-mcp.ps1

Wait for the plugin HTTP to be alive

no

polls up to 30 s, has --check mode

Build without Maven

requires Maven

.dsh-build.sh (plain javac + jar)

Low-RAM GUI launcher

no

ghidra-safe.sh (heap capped at 1.2 GB)

Related MCP server: GhidraMCP

Architecture

+-------------+   MCP stdio    +----------------------+   HTTP 127.0.0.1:8080   +------------------+
| dsh/Claude  | -------------> | bridge_mcp_ghidra.py  | ---------------------> | Ghidra GUI       |
| (AI client) |    30 tools    |       (FastMCP)       |   GhidraMCP+ plugin    | + CodeBrowser    |
+-------------+                +----------------------+                        +------------------+
  • The plugin (Java) runs inside the Ghidra GUI. Its HTTP server is only alive while a CodeBrowser tool has a program open; headless mode does not load it.

  • The bridge (Python) exposes 30 MCP tools: decompile, rename, cross-references, strings, segments, imports, and three imaging tools: focus_address, screenshot_tool, capture_evidence.

  • HTTP listens on loopback only; no other machine on the LAN can drive your Ghidra instance.

Installation

Requirements

  • Ghidra (tested with 11.3.1)

  • Python 3.10 or newer

  • JDK 21 (only when building from source)

Step 1 — Build the plugin (no Maven needed)

./.dsh-build.sh
# Output: target/GhidraMCP.jar and target/GhidraMCP-1.0-SNAPSHOT.zip

The script copies the required Ghidra jars into lib/, compiles with javac, and packages the extension zip in the layout Ghidra expects.

Step 2 — Install the extension into Ghidra

GUI route: File -> Install Extensions -> (+) -> select target/GhidraMCP-1.0-SNAPSHOT.zip -> restart Ghidra

Terminal route (Linux):

SETTINGS=~/.config/ghidra/ghidra_11.3.1_PUBLIC
mkdir -p $SETTINGS/Extensions/GhidraMCP/lib
cp target/GhidraMCP.jar $SETTINGS/Extensions/GhidraMCP/lib/
cp src/main/resources/{extension.properties,Module.manifest} $SETTINGS/Extensions/GhidraMCP/

Enable the plugin: File -> Configure -> Developer -> GhidraMCPPlugin.

Step 3 — Run the full pipeline (one command)

# Linux / macOS
./start-mcp.sh                 # waits for the plugin HTTP, then runs the MCP bridge (stdio)

# Windows (PowerShell 5.1+)
.\start-mcp.ps1                # same behavior

Options: --check (verify connectivity, do not run the bridge) | --install-deps (install requests + mcp) | --transport sse (run SSE on port 8081 instead of stdio).

Both launchers pick Python automatically (project .venv, then py -3 / python3, then python), poll http://127.0.0.1:8080/ for up to 30 seconds, and print clear guidance when Ghidra or the CodeBrowser tool is not running yet.

Low-RAM machines

./ghidra-safe.sh        # runs the Ghidra GUI with the heap capped at 1.2 GB (override with _GHIDRA_MAXMEM=800M)

Evidence Capture

The headline feature of this fork: capture a CodeBrowser screenshot with a red highlight box drawn around the exact evidence line. It uses Ghidra's official API (CodeViewerService -> ListingPanel -> FieldPanel.getCursorBounds()), so the box lands on the real address line every time, without guessing.

GET http://127.0.0.1:8080/evidence?address=0x0044c51e&to=0x0044c534&label=EX-01%20Entry&lines=6

Parameter

Purpose

address

evidence address to focus (required); the listing scrolls as if G was pressed

to

end address of a range; the red box then covers the whole range

label

red caption drawn above the box

lines

context lines (default 6)

Returns a PNG of the CodeBrowser window with:

  • a 3 px red border plus a translucent red fill over the evidence line(s)

  • the red caption above the box when label is given

From an MCP client (dsh, Claude, and others), call the tool:

capture_evidence(
    address="0x0044c51e",
    output_path="reports/exhibits/EX-01.png",
    label="Entry stub jmp _CorExeMain",
    to="0x0044c534"   # optional range
)

Evidence single address

Single-line highlight example — the high-entropy IL region (entropy 7.6) from a Lokibot analysis.

RE Workflow Training — How to Drive This Toolchain

This section documents the reverse-engineering methodology this fork was built for. It assumes an AI agent (or a disciplined human analyst) drives Ghidra through the MCP tools. The workflow has six phases.

Phase 0 — Safety first

  • Never execute malware samples on a real machine. Static analysis or an isolated sandbox only.

  • Hash the sample before anything else (md5sum, sha256sum) and reference it by hash, not by filename, in every report.

  • The HTTP endpoints of this plugin can rename and annotate program data. Keep the loopback binding; do not expose it to a network.

Phase 1 — Triage before Ghidra

Do not open the binary in Ghidra first. Triage the raw bytes first:

md5sum sample.exe && sha256sum sample.exe    # record hashes before anything else
file sample.exe                              # PE32? .NET? packed?
strings -n 8 sample.exe | head -50           # quick IOC scan

For .NET binaries, parse the metadata before Ghidra: find the BSJB metadata root, walk the streams (#~, #Strings, #US, #GUID, #Blob), and enumerate MethodDef tokens and resources. Ghidra shows managed code as meaningless x86 data, so the metadata is the real entry point for .NET analysis. A large __StaticArrayInitTypeSize value combined with reflection names (GetTypes, Invoke, InitializeArray) indicates an obfuscator that moved IL bodies into a static array.

Core rule of the whole workflow: every claim must trace back to a real byte region with an address. If you cannot point to it, it does not go in the report.

Phase 2 — Choose the right approach

Match the target to the right technique before touching tools:

Target type

Approach

Native x86/x64 PE

Ghidra MCP tools: list_imports, list_strings, decompile_function, get_xrefs_to

.NET assembly

Python metadata parsing first; Ghidra MCP only for the native stub and embedded data

Packed / obfuscated

Identify the packer layer by layer; each layer gets its own evidence exhibit

APK / mobile

Decompile the managed layer; Ghidra only for native .so libraries

Phase 3 — Evidence collection

Work exhibit-first. For each finding:

  1. Locate the exact address or byte range that proves the claim.

  2. Capture it: capture_evidence(address="0x...", label="F-01 XOR loop", to="0x...").

  3. Verify the capture programmatically: count red pixels in the PNG. A valid evidence image has roughly 500-900 red pixels plus dark text pixels inside the box. Zero red pixels means the fallback banner fired and the highlight failed; retake the shot.

  4. Excerpts from tools go into the report verbatim. Never edit decompiler output; put analyst notes in separate annotation bullets below the code block.

Phase 4 — Analysis discipline

  • Follow the call chain: entry point first, then each hop, collecting one exhibit per meaningful step.

  • Name things as you go: rename_function, rename_local_variable, and set_decompiler_comment make later exhibits self-explanatory.

  • Record what you tried and failed (for example: XOR scan of 256 single-byte keys, RC4 with candidate keys, zlib inflate). Failed decryption attempts are findings too; they tell the next analyst what not to repeat.

  • Time-box static analysis. If a payload cannot be decrypted statically within the box, stop and document the boundary instead of guessing.

Phase 5 — Report structure

A complete RE report has nine sections:

  1. Executive summary — what the sample is, what it does, what remains unknown, plus a capability table with evidence links

  2. Sample information — hashes, type, sections, entry point

  3. Exhibits — each with a repro command, an address, a verbatim excerpt, an annotated screenshot, and an interpretation

  4. Technical analysis — identification, mechanism by phase, crypto/algorithms, dynamic results (or why they are absent)

  5. Findings table — each finding mapped to an exhibit and a MITRE ATT&CK technique, with a confidence level

  6. IOC table — every indicator traced back to an exhibit

  7. Callflow — numbered steps from entry point to final behavior, unverified steps clearly marked

  8. Open questions — everything that did not make it into findings, with next-step proposals

  9. Appendix — environment, full reproduction commands, optional YARA rule

The two hard rules: no finding without an exhibit, and no claim without an address.

HTTP Endpoints

Endpoint

Method

Purpose

/methods

GET

list functions (paginated)

/classes

GET

list namespaces/classes

/segments /imports /exports /strings

GET

list program data

/xrefs /calls

GET

cross-references

/decompile

POST

decompile a function by name

/renameFunction /renameData and related

POST

renames

/comment /setFunctionPrototype

POST

annotations

/focus

GET

scroll the listing to an address (G key)

/screenshot

GET

PNG of the CodeBrowser window

/evidence

GET

red-highlight capture (new)

/windows

GET

debug: list Ghidra windows

See src/main/java/com/lauriewired/GhidraMCPPlugin.java for the complete list.

MCP Tools (30)

Analysis: list_methods | list_classes | list_segments | list_imports | list_exports | list_strings | list_data_items | list_namespaces | decompile_function | disassemble_function | search_functions_by_name | get_xrefs_to | get_xrefs_from | get_function_xrefs | get_callers | get_function_by_address | get_current_address | get_current_function

Editing: rename_function | rename_data | rename_local_variable | rename_global_variable | rename_function_by_address | set_function_prototype | set_decompiler_comment | set_disassembly_comment | set_local_variable_type

Imaging (new): focus_address | screenshot_tool | capture_evidence

Mounting an MCP Client

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "ghidra": {
      "command": "python",
      "args": ["/ABSOLUTE_PATH/bridge_mcp_ghidra.py", "--ghidra-server", "http://127.0.0.1:8080/"]
    }
  }
}

Cline / SSE mode:

python bridge_mcp_ghidra.py --transport sse --mcp-host 127.0.0.1 --mcp-port 8081 --ghidra-server http://127.0.0.1:8080/

Then add the remote server http://127.0.0.1:8081/sse in Cline.

dsh (DeepSeek Harness) — profile row:

- id: mcp-ghidra
  name: '@deepseek-ai/dsh-mcp-client'
  config:
    serverName: ghidra
    transport: stdio
    command: '/path/to/ghidraMCP/.venv/bin/python'
    args: ['/path/to/ghidraMCP/bridge_mcp_ghidra.py', '--ghidra-server', 'http://127.0.0.1:8080/']
    toolCallTimeoutMs: 120000
    failOnStartupError: false

Security Notes

  • Loopback only. The HTTP server binds 127.0.0.1; other machines on the LAN cannot drive Ghidra. Renames and annotations mutate real program data, so do not relax this binding.

  • Body limit. POST bodies over 1 MB are rejected to avoid memory pressure on the Ghidra JVM.

  • Path validation. The bridge refuses to write screenshots to /etc, /proc, /sys, /dev, C:\Windows, any path containing .., and any non-.png output.

Acknowledgments

  • LaurieWired/ghidraMCP — the original plugin and bridge this fork builds on. Apache 2.0.

  • The Ghidra project for the public API, in particular FieldPanel.getCursorBounds(), which made precise evidence highlighting possible.

License

Apache 2.0 — inherited from the original project.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables LLMs to autonomously reverse engineer binaries using Ghidra's capabilities including decompilation, function analysis, automatic renaming, and BSim integration for function similarity matching.
    1
    AGPL 3.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Bridges Ghidra's reverse engineering capabilities with AI tools through 179 specialized tools for automated binary analysis and documentation. It supports full read/write access for function decompilation, renaming, and cross-binary documentation transfer in both GUI and headless modes.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    A headless Ghidra server that enables AI agents to perform deep reverse-engineering tasks such as disassembly, decompilation, and patching via the Model Context Protocol. It supports extensive automation of analysis workflows in sandboxed environments through a catalog of over 200 specialized tools.
    166
    GPL 2.0