Rev·Deck AI-Assisted Reverse Engineering Workstation

repository·main·Indexed 41 days ago

https://github.com/biniamf/ai-reverse-engineering

An AI-assisted reverse engineering workstation combining a web-based evidence viewer with an LLM copilot. It utilizes a headless Ghidra service to provide deterministic binary analysis—including functions, strings, and imports—to an assistant that cites its evidence. Supports OpenAI-compatible endpoints (Ollama, OpenRouter, OpenAI, vLLM) and features autonomous workflows for program triage, vulnerability hypothesis, and call chain exploration.

Tokens
6K
Snippets
19
Records
31
Agent score
51%

What's inside Rev·Deck

  1. Using Focused Sub-investigations

    main

    To perform isolated tasks without polluting the main chat context, use New sub-investigation.

    1. Enter a one-line briefing for the sub-thread.
    2. Work with a fresh conversation context over the same binary.
    3. When finished, choose Return conclusion to parent.

    Behavior: Rev·Deck makes one bounded model call to validate evidence citations and adds a provenance-marked conclusion card to the parent chat. The full sub-thread transcript is not added to the parent, only the compact conclusion. If a conclusion has no validated citations, it is marked as unverified.

  2. Quick Start with Docker Compose

    main

    The fastest way to run Rev·Deck is using Docker Compose. This starts both the web application and the Ghidra service.

    1. Copy the example environment file to .env.
    2. Edit .env to set API_BASE and MODEL_NAME (and API_KEY if required).
    3. Run docker compose up --build.
    4. Access the UI at http://127.0.0.1:5000.

    Note: Docker Compose will fail early if API_BASE or MODEL_NAME are missing.

    cp .env.example .env      # set API_BASE and MODEL_NAME; set API_KEY if required
    docker compose up --build
  3. Configure LLM Providers

    main

    Rev·Deck supports any OpenAI-compatible Chat Completions endpoint. Configuration is handled by setting API_BASE, API_KEY, and MODEL_NAME in your .env file.

    Ollama

    API_BASE=http://127.0.0.1:11434/v1
    API_KEY=not-used
    MODEL_NAME=qwen3:8b

    OpenRouter

    API_BASE=https://openrouter.ai/api/v1
    API_KEY=replace-with-your-key
    MODEL_NAME=anthropic/claude-opus-4.8

    OpenAI

    API_BASE=https://api.openai.com/v1
    API_KEY=replace-with-your-key
    MODEL_NAME=replace-with-a-supported-model-id

    LM Studio, vLLM, or llama.cpp

    API_BASE=http://127.0.0.1:1234/v1
    API_KEY=not-used
    MODEL_NAME=replace-with-the-served-model-id
  4. How to use Rev·Deck for Binary Analysis

    main

    After uploading a binary, you can use two main workspace tabs:

    1. Analysis Tab

    Provides deterministic evidence views:

    • Summary, Functions, Imports, Strings, Query View
    • Function Inspector: Pseudocode, cross-references, bounded call graph, and hexdump.
    • Advanced (if supported by Ghidra service): Types, globals, sidecar annotations, and Attack Surface ranking.

    2. Chat Tab

    Interact with the LLM in two modes:

    • Copilot (Default): One bounded step/tool call per message for ad-hoc questions.
    • Autonomous: Runs a named, budgeted workflow with a live activity timeline.

    Note on Budgets: Both modes use a step budget. If a run reaches its budget, you can select Continue to resume the conversation using existing evidence without redoing completed tool calls.

  5. Run the Ghidra Headless REST service manually

    main

    If you want to run only the Ghidra service via Docker, use the following command. Ensure you map a local directory to /data/ghidra_projects to persist your analysis data.

    docker run --rm \
      -p 127.0.0.1:9090:9090 \
      -v "$(pwd)/data:/data/ghidra_projects" \
      --security-opt no-new-privileges:true \
      biniamfd/ghidra-headless-rest:latest
  6. Running Rev·Deck from Source

    main

    To run without Docker, you need Python 3.10+ and Node.js 18+.

    1. Set up a virtual environment and install dependencies:
      python -m venv .venv && source .venv/bin/activate
      pip install -r requirements.txt
    2. Vendor the Mermaid runtime:
      npm ci && npm run vendor
    3. Configure environment variables (Note: Python does not load .env automatically, so you must export them):
      cp .env.example .env
      set -a; source .env; set +a
    4. Start the Ghidra service separately, then start the web UI:
      python webui/app.py
    python -m venv .venv && source .venv/bin/activate
    pip install -r requirements.txt
    npm ci && npm run vendor
    
    cp .env.example .env
    set -a; source .env; set +a
    
    # Start the separate Ghidra service, then:
    python webui/app.py
  7. Essential Environment Variables

    main

    Rev·Deck is configured via environment variables. You must copy .env.example to .env and populate the required fields.

    VariableDefaultMeaning
    API_BASErequiredOpenAI-compatible base URL (http/https).
    API_KEYnot-usedProvider key. not-used is valid for local/keyless providers.
    MODEL_NAMErequiredModel id expected by the configured endpoint.
    LLM_STREAMautoStreaming transport: auto (stream with fallback), true (always stream), false (always blocking).
    GHIDRA_API_BASEhttp://127.0.0.1:9090Ghidra service base URL.
    GHIDRA_IMAGEbiniamfd/ghidra-headless-rest:1.2.1@sha256:971591a3...Ghidra service image.
    HOST / PORT127.0.0.1 / 5000Dev-server bind.
    MAX_UPLOAD_BYTES104857600Upload size cap.
    CHATS_DIRwebui/chatsChat history directory.
  8. How the Job Lifecycle and Workspace state work

    main

    The application manages a workspace that transitions between an 'empty' state and an 'active' state based on the selected job.

    Workflow:

    1. Job Selection: When a job is selected via the jobs controller, the system checks if the analysis is ready using isAnalysisReady(job.status).
    2. Empty State: If the job is not ready (e.g., still queued or running), showJobState(job) is called. This hides the workspace and shows a placeholder title/body.
    3. Active State: Once the job status indicates analysis is ready, activateCompletedJob(jobId) is called. This:
      • Hides the empty state.
      • Shows the workspace.
      • Enables the Chat Composer.
      • Resets the Analysis controller.
      • Loads the chat threads for that specific jobId.
    4. Removal: Removing a job resets the selectedJob in the store and returns the UI to the 'No job selected' empty state.
  9. Troubleshooting Rev·Deck

    main

    Common issues and solutions:

    • "Service offline" / /readyz returns 503: The Ghidra service is unreachable at GHIDRA_API_BASE, or API_BASE/MODEL_NAME is unset.
    • Types/Globals/Annotations show "requires v1": The connected Ghidra service is an older version that doesn't support these features.
    • Chat errors immediately: Verify API_BASE, API_KEY, and MODEL_NAME are correct and the provider is reachable within LLM_TIMEOUT.
    • Upload rejected as too large: Increase the MAX_UPLOAD_BYTES environment variable.
    • Large analysis times out: Increase the Ghidra container's ANALYSIS_TIMEOUT (e.g., 5400 for large binaries) and re-upload.
    • A citation shows "(unverified)": The model cited evidence it never actually retrieved; treat this as an unconfirmed hypothesis.
  10. Configure the Web UI and LLM provider

    main

    The web service manages the user interface and LLM interactions. The following environment variables are required or highly recommended in your .env file:

    Required LLM Settings

    • API_BASE: The endpoint for your LLM provider (e.g., Ollama, OpenAI, OpenRouter). This must be set.
    • MODEL_NAME: The specific model to use. This must be set.

    LLM & API Configuration

    • API_KEY: API key for the provider. Optional for local/keyless endpoints (defaults to not-used).
    • LLM_STREAM: Controls streaming behavior. Defaults to auto.
    • CONNECT_TIMEOUT: Connection timeout in seconds. Default is 5.
    • READ_TIMEOUT: Read timeout in seconds. Default is 30.
    • LLM_TIMEOUT: Timeout for LLM requests in seconds. Default is 60.

    Agent & Context Limits

    • MAX_UPLOAD_BYTES: Maximum upload size in bytes. Default is 104857600 (~100MB).
    • MAX_RESPONSE_BYTES: Maximum response size in bytes. Default is 26214400 (~25MB).
    • MAX_TOOL_RESULT_CHARS: Maximum characters for tool results. Default is 20000.
    • MAX_CONTEXT_CHARS: Maximum characters for the LLM context. Default is 100000.
    • MAX_AGENT_TURNS: Maximum number of turns an agent can take. Default is 5.
    • MAX_AUTONOMOUS_STEPS: Maximum autonomous steps. Default is 12.
    • MAX_STEP_BUDGET: Maximum budget per step. Default is 50.

    Cache & Logging

    • SUMMARY_CACHE_TTL: Time-to-live for summary cache in seconds. Default is 300.
    • SUMMARY_CACHE_MAX_ENTRIES: Maximum number of cache entries. Default is 128.
    • LOG_LEVEL: Logging verbosity (e.g., INFO). Default is INFO.
    • LOG_MAX_BYTES: Maximum log file size in bytes. Default is 5245786.
    • LOG_BACKUP_COUNT: Number of log backups to keep. Default is 3.

    Gunicorn (Web Server) Settings

    • GUNICORN_WORKERS: Number of worker processes. Default is 2.
    • GUNICORN_THREADS: Number of threads per worker. Default is 4.
    • GUNICORN_TIMEOUT: Worker timeout in seconds. Default is 120.
    • GUNICORN_GRACEFUL_TIMEOUT: Graceful shutdown timeout. Default is 30.
    • GUNICORN_KEEPALIVE: Keepalive timeout. Default is 5.
  11. Configure the Ghidra service via environment variables

    main

    The ghidra service provides the headless REST API for Ghidra. You can customize its behavior using the following environment variables in your .env file:

    • GHIDRA_IMAGE: The Docker image to use. Defaults to biniamfd/ghidra-headless-rest:1.2.1@sha256:971591a3a8448d8ed969079b452306e806f36079c3ddd298f4a618d6e2f1442d.
    • ANALYSIS_TIMEOUT: The wall-clock cap for a single headless analysis in seconds. Default is 1800 (30 minutes). Increase this for large binaries (e.g., 10k+ functions).
    • DECOMPILE_TIMEOUT: Timeout for decompilation in seconds. Default is 30.
    # Example .env configuration for Ghidra
    GHIDRA_IMAGE=biniamfd/ghidra-headless-rest:1.2.1
    ANALYSIS_TIMEOUT=3600
    DECOMPILE_TIMEOUT=60
  12. Available Autonomous Workflows

    main

    When using the Autonomous chat mode, you can trigger specific workflows. Some workflows require a target function address.

    WorkflowPurposeRequires target address?
    program_triageSummarize program purpose from metadata, imports, strings, and functions.No
    suspicious_behaviorSurface deterministic indicators and bounded hypotheses.No
    selected_functionDecompile and explain a function with its callers/callees.Yes
    call_chainExplore a bounded native/synthesized call-graph neighborhood.Yes
    attack_surface_triageInspect top-K candidates from deterministic scores.No
    vulnerability_hypothesisPresent evidence and counter-evidence for a candidate.No