Some checks are pending
Build Ghidra Plugin / build (push) Waiting to run
Wire GHIDRA_LANGUAGE, GHIDRA_BASE_ADDRESS, GHIDRA_LOADER through the Docker entrypoint and MCP tools so raw binaries (e.g., ARM7TDMI firmware) get the correct processor, memory map, and loader instead of relying on auto-detection. Auto-sets BinaryLoader when language is specified. Input validation at both Python and bash layers prevents malformed values from reaching analyzeHeadless.
179 lines
6.4 KiB
Bash
Executable File
179 lines
6.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# MCGhidra Docker Entrypoint
|
|
# Starts Ghidra in headless mode with HTTP API server
|
|
|
|
set -e
|
|
|
|
MCGHIDRA_MODE=${MCGHIDRA_MODE:-headless}
|
|
MCGHIDRA_PORT=${MCGHIDRA_PORT:-8192}
|
|
MCGHIDRA_MAXMEM=${MCGHIDRA_MAXMEM:-2G}
|
|
GHIDRA_HOME=${GHIDRA_HOME:-/opt/ghidra}
|
|
# User scripts directory - Python scripts don't need OSGi bundle registration
|
|
SCRIPT_DIR=${SCRIPT_DIR:-/home/ghidra/ghidra_scripts}
|
|
|
|
# Project settings
|
|
PROJECT_DIR=${PROJECT_DIR:-/projects}
|
|
PROJECT_NAME=${PROJECT_NAME:-MCGhidra}
|
|
|
|
echo "=============================================="
|
|
echo " MCGhidra Docker Container"
|
|
echo "=============================================="
|
|
echo " Mode: ${MCGHIDRA_MODE}"
|
|
echo " Port: ${MCGHIDRA_PORT}"
|
|
echo " Memory: ${MCGHIDRA_MAXMEM}"
|
|
echo " Project: ${PROJECT_DIR}/${PROJECT_NAME}"
|
|
echo "=============================================="
|
|
|
|
# Ensure directories exist
|
|
mkdir -p "${PROJECT_DIR}"
|
|
|
|
# Handle different modes
|
|
case "${MCGHIDRA_MODE}" in
|
|
headless)
|
|
# Headless mode: Import a binary and start HTTP server
|
|
|
|
if [ $# -eq 0 ]; then
|
|
echo ""
|
|
echo "Usage: docker run mcghidra:latest [binary_path] [options]"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " # Analyze a binary mounted at /binaries/sample.exe"
|
|
echo " docker run -p 8192:8192 -v ./samples:/binaries mcghidra /binaries/sample.exe"
|
|
echo ""
|
|
echo " # With custom project name"
|
|
echo " docker run -p 8192:8192 -v ./samples:/binaries -e PROJECT_NAME=malware mcghidra /binaries/sample.exe"
|
|
echo ""
|
|
echo "Environment variables:"
|
|
echo " MCGHIDRA_PORT - HTTP API port (default: 8192)"
|
|
echo " MCGHIDRA_MAXMEM - Max JVM heap (default: 2G)"
|
|
echo " PROJECT_NAME - Ghidra project name (default: MCGhidra)"
|
|
echo " PROJECT_DIR - Project directory (default: /projects)"
|
|
echo " GHIDRA_LANGUAGE - Processor language ID (e.g., ARM:LE:32:v4t)"
|
|
echo " GHIDRA_BASE_ADDRESS - Base address for raw binaries (e.g., 0x00000000)"
|
|
echo " GHIDRA_LOADER - Loader type (e.g., BinaryLoader for raw firmware)"
|
|
echo ""
|
|
echo "Starting in wait mode..."
|
|
echo "Container will stay running for debugging or manual operation."
|
|
echo "You can exec into this container to run analyzeHeadless manually."
|
|
echo ""
|
|
|
|
# Keep container alive for debugging/manual operation
|
|
tail -f /dev/null
|
|
else
|
|
BINARY_PATH="$1"
|
|
shift
|
|
|
|
if [ ! -f "${BINARY_PATH}" ]; then
|
|
echo "ERROR: Binary not found: ${BINARY_PATH}"
|
|
echo "Make sure to mount the binary directory with -v /host/path:/binaries"
|
|
exit 1
|
|
fi
|
|
|
|
BINARY_NAME=$(basename "${BINARY_PATH}")
|
|
echo "Importing and analyzing: ${BINARY_NAME}"
|
|
echo ""
|
|
|
|
# Build the analyzeHeadless command
|
|
ANALYZE_CMD="${GHIDRA_HOME}/support/analyzeHeadless"
|
|
ANALYZE_ARGS=(
|
|
"${PROJECT_DIR}"
|
|
"${PROJECT_NAME}"
|
|
-import "${BINARY_PATH}"
|
|
-max-cpu 2
|
|
-scriptPath "${SCRIPT_DIR}"
|
|
-postScript "MCGhidraServer.py" "${MCGHIDRA_PORT}"
|
|
)
|
|
|
|
# Optional: processor/language for raw binaries
|
|
if [ -n "${GHIDRA_LANGUAGE}" ]; then
|
|
if ! echo "${GHIDRA_LANGUAGE}" | grep -qE '^[A-Za-z0-9_]+:[A-Z]{2}:[0-9]+:[A-Za-z0-9._-]+$'; then
|
|
echo "ERROR: Invalid GHIDRA_LANGUAGE format: ${GHIDRA_LANGUAGE}"
|
|
echo "Expected: ARCH:ENDIAN:SIZE:VARIANT (e.g., ARM:LE:32:v4t)"
|
|
exit 1
|
|
fi
|
|
ANALYZE_ARGS+=(-processor "${GHIDRA_LANGUAGE}")
|
|
fi
|
|
|
|
# Optional: base address
|
|
if [ -n "${GHIDRA_BASE_ADDRESS}" ]; then
|
|
if ! echo "${GHIDRA_BASE_ADDRESS}" | grep -qE '^(0x)?[0-9a-fA-F]+$'; then
|
|
echo "ERROR: Invalid GHIDRA_BASE_ADDRESS format: ${GHIDRA_BASE_ADDRESS}"
|
|
echo "Expected hex: 0x00000000 or 00000000"
|
|
exit 1
|
|
fi
|
|
ANALYZE_ARGS+=(-loader-baseAddr "${GHIDRA_BASE_ADDRESS}")
|
|
fi
|
|
|
|
# Optional: explicit loader (e.g., BinaryLoader for raw firmware)
|
|
if [ -n "${GHIDRA_LOADER}" ]; then
|
|
if ! echo "${GHIDRA_LOADER}" | grep -qE '^[A-Za-z0-9_]+$'; then
|
|
echo "ERROR: Invalid GHIDRA_LOADER format: ${GHIDRA_LOADER}"
|
|
echo "Expected alphanumeric name (e.g., BinaryLoader)"
|
|
exit 1
|
|
fi
|
|
ANALYZE_ARGS+=(-loader "${GHIDRA_LOADER}")
|
|
fi
|
|
|
|
# Add any extra arguments passed
|
|
ANALYZE_ARGS+=("$@")
|
|
|
|
echo "Running: ${ANALYZE_CMD} ${ANALYZE_ARGS[*]}"
|
|
echo ""
|
|
|
|
exec "${ANALYZE_CMD}" "${ANALYZE_ARGS[@]}"
|
|
fi
|
|
;;
|
|
|
|
server)
|
|
# Server mode: Open existing project with HTTP server
|
|
echo "Starting MCGhidra server on existing project..."
|
|
|
|
if [ $# -eq 0 ]; then
|
|
echo "Usage: docker run -e MCGHIDRA_MODE=server mcghidra [program_name]"
|
|
echo ""
|
|
echo " program_name: Name of program in the project to open"
|
|
exit 1
|
|
fi
|
|
|
|
PROGRAM_NAME="$1"
|
|
shift
|
|
|
|
exec "${GHIDRA_HOME}/support/analyzeHeadless" \
|
|
"${PROJECT_DIR}" "${PROJECT_NAME}" \
|
|
-process "${PROGRAM_NAME}" \
|
|
-noanalysis \
|
|
-scriptPath "${SCRIPT_DIR}" \
|
|
-postScript "MCGhidraServer.py" "${MCGHIDRA_PORT}" \
|
|
"$@"
|
|
;;
|
|
|
|
analyze)
|
|
# Analyze mode: Import and analyze, then exit (no HTTP server)
|
|
if [ $# -eq 0 ]; then
|
|
echo "Usage: docker run -e MCGHIDRA_MODE=analyze mcghidra [binary_path]"
|
|
exit 1
|
|
fi
|
|
|
|
BINARY_PATH="$1"
|
|
shift
|
|
|
|
echo "Analyzing binary: ${BINARY_PATH}"
|
|
exec "${GHIDRA_HOME}/support/analyzeHeadless" \
|
|
"${PROJECT_DIR}" "${PROJECT_NAME}" \
|
|
-import "${BINARY_PATH}" \
|
|
-max-cpu 2 \
|
|
"$@"
|
|
;;
|
|
|
|
shell)
|
|
# Interactive shell
|
|
exec /bin/bash
|
|
;;
|
|
|
|
*)
|
|
echo "Unknown mode: ${MCGHIDRA_MODE}"
|
|
echo "Valid modes: headless, server, analyze, shell"
|
|
exit 1
|
|
;;
|
|
esac
|