# 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 ```