Some checks are pending
Build Ghidra Plugin / build (push) Waiting to run
- Rename src/ghydramcp → src/mcghidra - Rename GhydraMCPPlugin.java → MCGhidraPlugin.java - Update all imports, class names, and references - Update pyproject.toml package name and script entry - Update Docker image names and container prefixes - Update environment variables: GHYDRA_* → MCGHIDRA_* - Update all documentation references
198 lines
5.0 KiB
Markdown
198 lines
5.0 KiB
Markdown
# MCGhidra Docker Setup
|
|
|
|
This directory contains Docker configuration for running MCGhidra in headless mode.
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# Build the image
|
|
docker build -t mcghidra:latest -f docker/Dockerfile .
|
|
|
|
# Analyze a binary
|
|
docker run -p 8192:8192 -v /path/to/binaries:/binaries mcghidra /binaries/sample.exe
|
|
|
|
# Check API health
|
|
curl http://localhost:8192/
|
|
```
|
|
|
|
## Architecture
|
|
|
|
The Docker container includes:
|
|
|
|
1. **Ghidra 11.4.2** - Full headless installation
|
|
2. **MCGhidra Extension** - The Java plugin (installed in Extensions/)
|
|
3. **MCGhidraServer.py** - Headless HTTP server (Jython, full API parity)
|
|
|
|
### Why Two HTTP Servers?
|
|
|
|
The MCGhidra plugin (`MCGhidraPlugin.java`) is a full Ghidra GUI plugin that requires:
|
|
- Ghidra's `PluginTool` framework
|
|
- `ProgramManager` service for program access
|
|
- GUI event handling
|
|
|
|
These GUI services don't exist in headless mode. Instead, the container uses `MCGhidraServer.py`, a Jython script that:
|
|
- Runs via `analyzeHeadless -postScript`
|
|
- Has direct access to `currentProgram` from the script context
|
|
- Provides **full API parity** with the GUI plugin (45 routes)
|
|
- Supports all read and write operations
|
|
|
|
### Available Endpoints (Headless Mode)
|
|
|
|
The headless server implements the complete MCGhidra HTTP API:
|
|
|
|
| Category | Endpoints | Description |
|
|
|----------|-----------|-------------|
|
|
| **Info** | `GET /`, `/info`, `/program` | API info, program metadata |
|
|
| **Functions** | `GET /functions`, `/functions/{addr}`, `/functions/by-name/{name}` | List and detail |
|
|
| **Decompile** | `GET /functions/{addr}/decompile`, `/functions/by-name/{name}/decompile` | C pseudocode |
|
|
| **Disassembly** | `GET /functions/{addr}/disassembly`, `/functions/by-name/{name}/disassembly` | Assembly listing |
|
|
| **Data** | `GET /data`, `/strings` | Defined data and strings |
|
|
| **Memory** | `GET /memory`, `/memory/blocks` | Read bytes, list segments |
|
|
| **Xrefs** | `GET /xrefs` | Cross-references (to/from) |
|
|
| **Structs** | `GET /structs` | Data type structures |
|
|
| **Symbols** | `GET /symbols`, `/imports`, `/exports` | Symbol tables |
|
|
| **Analysis** | `GET /analysis/callgraph`, `/analysis/dataflow` | Static analysis |
|
|
| **Write Ops** | `PATCH /functions/*`, `POST /data`, `POST /structs/*` | Rename, annotate, create |
|
|
|
|
See [GHIDRA_HTTP_API.md](../GHIDRA_HTTP_API.md) for the complete API specification.
|
|
|
|
## Container Modes
|
|
|
|
### Headless Mode (Default)
|
|
|
|
Imports a binary, analyzes it, and starts the HTTP API server:
|
|
|
|
```bash
|
|
docker run -p 8192:8192 \
|
|
-v ./samples:/binaries \
|
|
mcghidra /binaries/sample.exe
|
|
```
|
|
|
|
### Server Mode
|
|
|
|
Opens an existing project and program:
|
|
|
|
```bash
|
|
docker run -p 8192:8192 \
|
|
-e MCGHIDRA_MODE=server \
|
|
-v ./projects:/projects \
|
|
mcghidra program_name
|
|
```
|
|
|
|
### Analyze Mode
|
|
|
|
Imports and analyzes without starting HTTP server:
|
|
|
|
```bash
|
|
docker run \
|
|
-e MCGHIDRA_MODE=analyze \
|
|
-v ./samples:/binaries \
|
|
-v ./projects:/projects \
|
|
mcghidra /binaries/sample.exe
|
|
```
|
|
|
|
### Shell Mode
|
|
|
|
Interactive debugging:
|
|
|
|
```bash
|
|
docker run -it \
|
|
-e MCGHIDRA_MODE=shell \
|
|
mcghidra
|
|
```
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `MCGHIDRA_MODE` | `headless` | Container mode (headless, server, analyze, shell) |
|
|
| `MCGHIDRA_PORT` | `8192` | HTTP API port |
|
|
| `MCGHIDRA_MAXMEM` | `2G` | JVM heap memory |
|
|
| `PROJECT_DIR` | `/projects` | Ghidra project directory |
|
|
| `PROJECT_NAME` | `MCGhidra` | Ghidra project name |
|
|
|
|
## Docker Compose
|
|
|
|
Use docker-compose for easier management:
|
|
|
|
```bash
|
|
# Development mode (hot-reload scripts)
|
|
docker compose --profile dev up mcghidra-dev
|
|
|
|
# Production mode
|
|
docker compose --profile prod up mcghidra
|
|
|
|
# Interactive shell
|
|
docker compose --profile debug run --rm mcghidra-shell
|
|
```
|
|
|
|
## MCP Integration
|
|
|
|
The MCGhidra Python server includes Docker management tools:
|
|
|
|
```python
|
|
# Check Docker status
|
|
await docker_status()
|
|
|
|
# Start container for a binary
|
|
await docker_start(binary_path="/path/to/binary.exe", port=8192)
|
|
|
|
# Wait for container to be ready
|
|
await docker_wait(port=8192, timeout=300)
|
|
|
|
# Automatic mode - starts container if no Ghidra available
|
|
await docker_auto_start(binary_path="/path/to/binary.exe")
|
|
|
|
# Get container logs
|
|
await docker_logs("mcghidra-server")
|
|
|
|
# Stop container
|
|
await docker_stop("mcghidra-server")
|
|
```
|
|
|
|
## Building
|
|
|
|
```bash
|
|
# Using Make
|
|
make build
|
|
|
|
# Using Docker directly
|
|
docker build -t mcghidra:latest -f docker/Dockerfile .
|
|
|
|
# Build with specific Ghidra version
|
|
docker build -t mcghidra:latest \
|
|
--build-arg GHIDRA_VERSION=11.4.2 \
|
|
--build-arg GHIDRA_DATE=20250826 \
|
|
-f docker/Dockerfile .
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Container starts but API doesn't respond
|
|
|
|
Analysis takes time. Monitor progress with:
|
|
```bash
|
|
docker logs -f mcghidra-server
|
|
```
|
|
|
|
### Port already in use
|
|
|
|
Stop existing containers:
|
|
```bash
|
|
docker stop $(docker ps -q --filter "name=mcghidra")
|
|
```
|
|
|
|
### Memory issues with large binaries
|
|
|
|
Increase JVM heap:
|
|
```bash
|
|
docker run -e MCGHIDRA_MAXMEM=4G -p 8192:8192 mcghidra /binaries/large.exe
|
|
```
|
|
|
|
### Permission denied on volumes
|
|
|
|
The container runs as user `ghidra` (UID 1001). Ensure volume permissions:
|
|
```bash
|
|
sudo chown -R 1001:1001 /path/to/binaries
|
|
```
|