A local-first AI assistant for reverse engineering. It analyzes decompiled code using a locally running LLM — no data leaves your machine.
Install dependencies and verify your local LLM:
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
pip install -r requirements.txt
python -m src.cli pingpython -m src.cli dashboardThen open http://localhost:5000 and drag/drop your Ghidra-exported .jsonl file.
The dashboard will run LLM analysis and ingest results automatically.
# 1) Analyze
python -m src.cli analyze --input data/input/functions.jsonl --output data/output/results.jsonl
# 2) Ingest for search/dashboard (include decompiled code viewer)
python -m src.cli ingest --input data/output/results.jsonl --source-functions data/input/functions.jsonl
# 3) Dashboard / report / search
python -m src.cli dashboard
python -m src.cli report --input data/output/results.jsonl --out reports/analysis.md
python -m src.cli search --query "crypto"The repo includes test_target.c, a small multi-function sample binary (file I/O, crypto-like XOR, network, process spawn) for exercising the full pipeline. Use it only on systems and binaries you are allowed to analyze.
Use -O0 -g so Ghidra’s decompiler keeps distinct, readable functions (optimization can inline or merge them).
Windows (MinGW-w64 / MSYS2)
gcc -o re_test_target.exe test_target.c -lws2_32 -O0 -gLinux
gcc -o re_test_target test_target.c -O0 -gmacOS
gcc -o re_test_target test_target.c -O0 -gOptional: create a minimal config file next to the binary so read_config has something to open:
server=127.0.0.1
token=0123456789abcdefSave as app.cfg in the same directory you run the program from.
- Install Ghidra (10.x or 11.x).
- File → New Project → Non-Shared Project → choose a folder and name.
- File → Import File → select
re_test_target.exe(or your built binary). - Accept the default format/language when prompted, then Analyze with default options and wait for analysis to finish.
- Copy or symlink this repo’s
ghidra_scripts/folder into Ghidra’s script path, or add it once:- Edit → Tool Options → Script Directories → add the path to
ghidra_scripts/.
- Edit → Tool Options → Script Directories → add the path to
- Open Window → Script Manager.
- Filter for ExportFunctions (menu path: Tools → RE Toolkit → Export Functions to JSONL).
- Run the script.
- When prompted, save as e.g.
data/input/re_test_target.jsonl.
Each line in the file is one JSON object with fields such as functionName, entryPoint, decompiledCode, calledFunctions, and referencedStrings (the Python importer normalizes the last two to callees / strings).
Set GHIDRA_HOME to your Ghidra install folder (the directory that contains support\analyzeHeadless.bat), then run the wrapper from the repo root.
PowerShell (use $env:, not set — set only works in Command Prompt):
$env:GHIDRA_HOME = "C:\path\to\ghidra_12.1_PUBLIC"
.\ghidra_scripts\run_headless_export.ps1 re_test_target.exe data\input\re_test_target.jsonlOr pass the Ghidra path on one line:
.\ghidra_scripts\run_headless_export.ps1 re_test_target.exe data\input\re_test_target.jsonl `
-GhidraHome "C:\path\to\ghidra_12.1_PUBLIC"Command Prompt (cmd):
set GHIDRA_HOME=C:\path\to\ghidra_12.1_PUBLIC
ghidra_scripts\run_headless_export.bat re_test_target.exe data\input\re_test_target.jsonlThis imports the binary, runs analysis, executes ExportFunctions.java, and writes the JSONL path you pass as the second argument.
Headless without the batch file (any OS):
$GHIDRA_HOME/support/analyzeHeadless \
/path/to/ghidra_project_dir HeadlessExport \
-import /path/to/re_test_target \
-postScript ExportFunctions.java /path/to/output.jsonl \
-scriptPath /path/to/ghidra_scripts \
-deleteProjectOn Windows, use analyzeHeadless.bat under %GHIDRA_HOME%\support\.
Dashboard: start python -m src.cli dashboard and drag re_test_target.jsonl onto the page.
CLI:
python -m src.cli analyze \
--input data/input/re_test_target.jsonl \
--output data/output/re_test_results.jsonl
python -m src.cli ingest \
--input data/output/re_test_results.jsonl \
--source-functions data/input/re_test_target.jsonlThis tool sits between a decompiler (e.g. Ghidra, Binary Ninja, IDA) and the analyst. It takes exported decompiled function data, sends it to a local LLM, and returns structured summaries, rename suggestions, and behavioral hypotheses.
Intended users:
- Cybersecurity students and CTF participants
- Reverse engineers and malware analysts working in isolated labs
- Defensive security researchers
- Developers analyzing their own compiled binaries
This tool is designed to assist lawful reverse engineering only.
- Do not use this tool to analyze software you do not have the legal right to reverse engineer.
- All analysis is produced by a language model and may be incorrect. Treat every output as a hypothesis to be validated, not a ground truth.
- The tool does not automatically rename symbols or modify any project files. All suggestions require explicit analyst approval.
- Running analysis locally means no external API calls are made and no decompiled code is sent to third-party services. It is your responsibility to ensure your LLM backend is also running locally and not proxying requests externally.
- Malware analysis should be performed inside an isolated, offline lab environment. This tool does not provide sandboxing.
Decompiler (Ghidra / BN / IDA)
↓ export script
JSON / JSONL function data
↓ import
Local LLM Analyzer ←── local LLM (Ollama / llama.cpp / LM Studio)
↓
Structured JSON analysis
↓
Markdown reports | Rename suggestions | Searchable knowledge base
AI-reverse-engineering-platform/
├── src/ # Core Python package
│ ├── __init__.py
│ ├── cli.py # Entry point (argparse CLI)
│ ├── importer.py # Load JSON/JSONL decompiled function data
│ ├── analyzer.py # Send functions to local LLM, parse responses
│ ├── reporter.py # Generate Markdown reports
│ ├── renamer.py # Generate and display rename suggestions
│ ├── approver.py # Build approved-renames files for Ghidra import
│ ├── db.py # SQLite search database (FTS5 full-text search)
│ ├── dashboard.py # Local Flask web dashboard
│ └── storage.py # Persist analysis results locally
├── web/
│ ├── templates/ # Jinja2 HTML templates (base, index, function detail)
│ └── static/ # CSS — dark theme, category badges, layout
├── data/
│ ├── input/ # Drop exported decompiled function files here
│ └── output/ # JSON analysis results are written here
├── prompts/ # LLM prompt templates
│ ├── summarize.txt
│ ├── rename.txt
│ └── behavior.txt
├── reports/ # Generated Markdown reports
├── ghidra_scripts/ # Ghidra helper scripts
│ ├── ExportFunctions.java # Export decompiled functions to JSONL
│ ├── ImportApprovedRenames.java # Apply approved renames/comments to Ghidra
│ ├── run_headless_export.bat # Headless export wrapper (cmd)
│ └── run_headless_export.ps1 # Headless export wrapper (PowerShell)
├── config.json # Runtime configuration (model, endpoint, limits)
├── requirements.txt
├── .gitignore
└── README.md
Requires Python 3.10+ and a running local LLM backend (e.g. Ollama).
git clone <repo-url>
cd AI-reverse-engineering-platform
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
pip install -r requirements.txtEdit config.json before running:
{
"llm": {
"backend": "ollama",
"base_url": "http://localhost:11434",
"model": "llama3.2:1b",
"timeout_seconds": 120,
"temperature": 0.2
},
"analysis": {
"max_functions_per_run": 0,
"context_window_chars": 8000,
"batch_size": 5
},
"output": {
"report_dir": "reports/",
"data_dir": "data/output/",
"db_path": "data/output/analysis.db"
},
"logging": {
"level": "INFO",
"log_file": "data/output/run.log"
}
}Supported backends: ollama, llamacpp (OpenAI-compatible endpoint).
All commands are run from the project root with the virtual environment activated.
python -m src.cli analyze --input data/input/functions.jsonl --output data/output/results.jsonlpython -m src.cli report --input data/output/results.jsonl --out reports/analysis.mdpython -m src.cli rename --input data/output/results.jsonl# Run the dedicated rename LLM prompt on raw functions
python -m src.cli suggest-renames --input data/input/functions.jsonl \
--output data/output/renames.jsonl
# Or derive suggestions from existing analysis results (no LLM call)
python -m src.cli suggest-renames --from-analysis data/output/results.jsonl \
--output data/output/renames.jsonlpython -m src.cli approve-renames \
--input data/output/renames.jsonl \
--output data/output/approved_renames.json \
--min-confidence mediumThe output is a human-editable JSON file. Review it, then flip any
"approved": false entries to true (or vice-versa) before loading it into
Ghidra. You can also set a custom "comment" on each entry — it will be
written as a plate comment on that function's entry point.
- Open your binary in Ghidra.
- Open the Script Manager (
Window → Script Manager). - Add the
ghidra_scripts/directory to the script paths. - Run
ImportApprovedRenames. - Select your
approved_renames.jsonfile when prompted.
An approved_renames_import_log.jsonl is written alongside the approved file
with a per-function record of what was renamed, skipped, or errored.
Headless execution:
analyzeHeadless <project_root> <project_name> ^
-process <binary_name> ^
-scriptPath ghidra_scripts ^
-postScript ImportApprovedRenames.java ^
data\output\approved_renames.json ^
data\output\import_log.jsonlpython -m src.cli dashboardOpens http://localhost:5000 automatically. Features:
- Function list with live search (no page reload via HTMX)
- Category and confidence filters in sidebar
- Decompiled code viewer with C syntax highlighting
- LLM summary with side effects and uncertainties
- Rename approval buttons — writes directly to
approved_renames.json - Approved Renames page showing pending Ghidra import queue
- Export Report button — generates and downloads a Markdown report
- Drag-and-drop JSONL import — uploads raw function exports, runs LLM analysis in the background, and ingests into SQLite with progress tracking
- Live LLM progress — during import, the progress card shows the current function name, phase (building prompt, waiting on Ollama, parsing response), model badge, elapsed time, and an estimated time remaining. Runtime scales with function count and model speed (local models often take several seconds per function).
- LLM model picker — in the top navigation bar, choose the active Ollama/llama.cpp model, Refresh to reload the model list from your local server, and Apply to save to
config.json. New JSONL imports use the selected model immediately (no dashboard restart). Imports in progress block model changes until they finish.
Options:
python -m src.cli dashboard --port 8080 --no-browserResults are shaped by three layers: model choice, prompts (prompts/summarize.txt), and post-processing (src/postprocess.py).
- Use a code-oriented model for production work (see
config.example.jsonfor a reference setup). Very small models tend to over-report high confidence and mislabel categories. - After each LLM response, post-processing sanitizes rename identifiers, filters Ghidra decompiler noise from uncertainties, reclassifies CRT helpers as runtime, adjusts categories using callee/API signals, calibrates confidence, and disambiguates duplicate suggested names within a batch.
- High confidence means the function has enough code context, no remaining uncertainties, and a valid name — not merely that the model sounded sure.
- Markdown exports omit runtime from high-priority sections and only list rename suggestions that are valid Ghidra identifiers. Re-import JSONL after upgrading to refresh existing SQLite rows.
See change-report-5-29-26.md for the full rationale.
Each batch analysis gets a run ID stored in SQLite (analysis_runs table) and embedded in JSONL output (run_id, model, prompt_version, postprocess_version, analyzed_at). The dashboard header includes an Analysis run selector — switch runs to compare models without overwriting prior results.
python -m src.cli analyze --input data/input/re_test_target.jsonl `
--output data/output/results.jsonl --ingest
python -m src.cli search --stats --run-id <run_id>When analysis.sort_by is "priority" (default in config.example.json), functions are ranked by xref count, human-readable names, security callees, and code size before --limit is applied — so --limit 50 means the top 50 by priority, not the first 50 in the export file.
python -m src.cli analyze --input data/input/re_test_target.jsonl `
--output data/output/results.jsonl --limit 50 --skip-runtimepython -m src.cli reanalyze --entry-point 0x1400016b6 `
--source data/input/re_test_target.jsonl `
--focus "Classify as network; it calls send() and xor_crypt"On the function detail page, use Re-analyze with LLM (optional focus note) to refresh a single row in the current run.
python -m src.cli ingest \
--input data/output/results.jsonl \
--source-functions data/input/functions.jsonlRe-ingesting the same file upserts (updates) existing rows — safe to run after each analysis pass.
If --source-functions is provided, decompiled code is stored and shown in the dashboard code viewer.
# Full-text search (BM25 ranked)
python -m src.cli search --query "file parsing"
python -m src.cli search --query "command dispatcher"
# Filter by category
python -m src.cli search --category crypto
python -m src.cli search --category network
python -m src.cli search --category file_io
# Filter by confidence
python -m src.cli search --confidence low
# Combine filters
python -m src.cli search --query "socket" --category network --limit 10
# Database overview
python -m src.cli search --statsCategory values produced by the LLM: file_io, network, crypto, process,
registry, memory, string_ops, math, error_handling.
python -m src.cli ping1. Export functions from Ghidra
→ ExportFunctions.java → data/input/functions.jsonl
2. Analyze with local LLM
→ python -m src.cli analyze → data/output/results.jsonl
3. Generate report
→ python -m src.cli report → reports/analysis.md
4. Generate rename suggestions
→ python -m src.cli suggest-renames → data/output/renames.jsonl
5. Create approved renames file (review + edit)
→ python -m src.cli approve-renames → data/output/approved_renames.json
6. Import approved renames into Ghidra
→ ImportApprovedRenames.java → (functions renamed in Ghidra)
→ approved_renames_import_log.jsonl
1. Start dashboard
→ python -m src.cli dashboard
2. Drag and drop Ghidra JSONL on the page
→ /api/upload (background LLM analysis + ingest)
→ data/output/analysis.db updated
→ Function list auto-refreshes
3. Review functions and approve/reject renames in UI
→ data/output/approved_renames.json
4. Export report from dashboard
→ reports/dashboard_export_<timestamp>.md
The tool accepts JSON or JSONL files. Canonical function input uses this schema:
{
"functionName": "FUN_00101230",
"entryPoint": "0x00101230",
"decompiledCode": "int FUN_00101230(char *path) { ... }",
"callees": ["strcmp", "malloc"],
"strings": ["error: bad input"],
"xrefCount": 3
}Ghidra export compatibility:
calledFunctionsis normalized tocalleesreferencedStringsis normalized tostrings
Required fields: functionName, entryPoint, decompiledCode.
Each analyzed function produces a JSON object (JSONL line):
{
"function_name": "FUN_00101230",
"entry_point": "0x00101230",
"summary": "Attempts to open a file and returns whether it succeeded.",
"suggested_name": "check_file_exists",
"category": "file_io",
"confidence": "medium",
"side_effects": ["reads filesystem metadata"],
"uncertainties": [],
"raw_response": "{...}",
"analyzed_at": "2026-05-30T02:13:00Z",
"model": "codellama:13b-instruct",
"backend": "ollama",
"prompt_version": "a1b2c3d4e5f6",
"postprocess_version": "1.1.0",
"run_id": "f47ac10b58cc4372a5670e02b2c3d479"
}Dedicated rename suggestions (suggest-renames) are written separately as JSONL with:
entry_point, old_name, new_name, confidence, reason.
| Iteration | Goal | Status |
|---|---|---|
| 0 | Project setup, documentation, repo structure | Done |
| 1 | Core CLI: import → analyze → store | Done |
| 2 | Batch analysis with JSONL streaming and error logging | Done |
| 3 | Markdown report generation | Done |
| 4 | Ghidra export script (ExportFunctions.java) | Done |
| 5 | Rename suggestions with confidence + reasoning | Done |
| 6 | Approved Ghidra import (ImportApprovedRenames.java) | Done |
| 7 | SQLite search: category/confidence filters + FTS5 keyword search | Done |
| 8 | Local web dashboard with code viewer and rename approval | Done |
| 9 | Local embeddings and semantic search | Future |
| 10 | Function clustering, call graph analysis | Future |
| 11 | Multi-model comparison (run history, provenance) | Partial |
MIT — see LICENSE.