Initial public release: dockerized reverse-engineering workbench

ChipBench packages Ghidra, radare2, binwalk, chip-programming tools,
simulators, and firmware-unpacking utilities into one reproducible container
for analyzing raw chip dumps entirely from the command line or an AI CLI.
Headless Jython scripts drive import, forced-disassembly sweeps, live
queries, and bulk decompilation exports without any GUI.

Derived from a private engagement environment, generalized for public
release under AGPLv3. No engagement-specific artifacts are included.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
This commit is contained in:
2026-08-18 11:15:05 -05:00
commit 1b447b77ad
28 changed files with 1860 additions and 0 deletions
+144
View File
@@ -0,0 +1,144 @@
# ChipBench — Dockerized reverse-engineering workbench for chip dumps
A fully self-contained firmware reverse-engineering environment that
installs **nothing on your host** (Docker only). Drop a flash/EEPROM/ROM
dump into `artifacts/` and analyze it **entirely from your terminal or from
an AI CLI** — no GUI required. Headless Ghidra scripts (Jython) plus
radare2, binwalk, capstone/unicorn, chip-programmer tools, simulators, and
firmware-unpacking utilities.
Built and battle-tested on real engagements (8-bit embedded controllers
with no symbols, no map files, and no mercy).
## Quick start (headless, no GUI)
```bash
./re-build # one-time image build
# put your dump in artifacts/dump.bin, then:
./re-analyze dump.bin -processor "8051:BE:16:default"
./re-q dump.bin info # query it (commands below)
./re-export dump.bin # bulk-export everything to output/
```
`./re-analyze`, `./re-q`, `./re-export` use one-shot containers (`tools`
service) — **no desktop stack needs to be running**. Build once with
`./re-build`; you never need `./re-up` unless you want the GUI.
## Headless query interface — `re-q`
```
./re-q <program> <command> [args...]
```
`<program>` is the domain-file name in the project (usually the artifact's
basename, e.g. `dump.bin`). Commands:
| Command | Args | What it returns |
|---|---|---|
| `info` | — | name, language, image base, size, function count, segments |
| `segments` | — | memory segments (name, range, perms) |
| `funcs` | `[offset] [limit] [filter]` | function list: `name @ entry` |
| `search` | `<query> [limit]` | functions whose name contains query |
| `func` | `<addr>` | one function's metadata (signature, body, size) |
| `decompile` | `<name\|addr>` | decompiled C of a function |
| `disasm` | `<addr>` | disassembly of the function at/containing addr |
| `xrefs-to` | `<addr> [limit]` | references TO an address (callers etc.) |
| `xrefs-from` | `<addr> [limit]` | references FROM an address |
| `func-xrefs` | `<name> [limit]` | references to a function by name |
| `strings` | `[filter] [limit]` | defined strings with addresses |
| `data` | `[offset] [limit]` | defined data items |
| `mem` | `<addr> <len>` | raw hex+ASCII dump of `<len>` bytes |
| `exports` / `imports` | `[limit]` | external entry points / symbols |
Addresses accept Ghidra's form (`00102030`) or `0x`-prefixed. Each query
spins up a short-lived Ghidra JVM (~10 s) reading the already-analyzed
program (read-only).
## Bulk export — `re-export`
```
./re-export <program>
```
One Ghidra run writes, to `output/`: `*.info.txt`, `*.functions.txt`,
`*.strings.txt`, `*.segments.txt`, `*.data.txt`, `*.decompiled.c`.
Read/grep these instantly for most questions; use `re-q` for targeted
live queries.
## Architecture forcing
Let Ghidra auto-detect, or force with `-processor` (see `re-analyze -h`
comment header). Raw 8051 dumps get automatic vector+sweep disassembly via
`Analyze8051.py` (override with `RE_NO_SWEEP=1`).
## What's inside
| Category | Tools |
|---|---|
| Decompiler / RE workbench | **Ghidra 11.3.2** + GhidraMCP 1.4 plugin |
| Headless scripts (Jython) | Query.py, ExportAll.py, Analyze8051.py, MakeFuncs.py, AutoFuncs.py |
| CLI disassemblers | **radare2** (r2/rabin2), binutils-multiarch, binutils-avr, gputils (gpdasm), sdcc, z80dasm |
| Firmware scanning / unpacking | **binwalk v3**, 7-zip, cabextract, lzma, cpio, squashfs-tools, unar, u-boot-tools (mkimage), device-tree-compiler |
| Chip programming / debug | **flashrom**, **avrdude**, **openocd**, stlink-tools, esptool |
| Simulators | simavr (AVR), gpsim (PIC) |
| EPROM/SREC/HEX wrangling | srecord (srec_cat & co.) |
| Serial consoles | tio, picocom (pyserial in the venv) |
| Python RE libs | capstone, unicorn, keystone (in /opt/venv) |
| Desktop (optional) | Xvfb + fluxbox + x11vnc + noVNC |
Optional extras not packaged (build from source if needed): `minipro`
(TL866 programmers), `stm8flash`.
## GUI + MCP bridge (optional)
`./re-up` boots a headless desktop with Ghidra:
| URL / port | What |
|---|---|
| http://localhost:6080/vnc.html | Ghidra GUI in a browser (VNC pw `chipbench`) |
| localhost:5900 | raw VNC |
| http://localhost:8081/sse | GhidraMCP bridge (MCP over SSE) |
The MCP bridge only serves data once a program is opened in the CodeBrowser
tool AND the GhidraMCP plugin is enabled there (one-time manual GUI step).
The headless `re-q`/`re-export` interface covers the same ground without
any GUI interaction.
## Known issues
- **Use the Jython (.py) scripts.** In-process `javac` for Ghidra `.java`
user scripts has broken across JDK point releases in Ubuntu images
("class could not be found" at script load). The .py scripts are immune.
- GhidraMCP's Module.manifest emits harmless warnings at headless startup.
- Ghidra 11.3.2 is pinned (latest GhidraMCP 1.4 supports).
## Layout
```
ChipBench/
├── docker/
│ ├── Dockerfile # two-stage build (binwalk builder + main)
│ ├── conf/ # supervisord, profile.d, entrypoint
│ └── scripts/ghidra-scripts/ # Jython headless scripts (host-mounted)
├── docker-compose.yml # ghidra (GUI) + tools (CLI) services
├── re-build # build the image
├── re-analyze re-q re-export # headless chat-driven workflow
├── re-identify re-binwalk re-shell # triage / shell
└── re-up re-down re-mcp-test # optional GUI/MCP
```
Directories `artifacts/` (read-only mount), `work/`, `output/` are created
on first use.
## License
AGPLv3 — see [LICENSE](LICENSE). The Dockerfile pulls third-party tools at
build time under their own licenses (Ghidra: Apache-2.0; GhidraMCP and
binwalk: MIT; radare2: LGPL-3.0; etc.). No binaries are hosted here.
## Contributing
Issues and PRs welcome — especially additional headless Jython recipes
(per-architecture sweep scripts, NVM/checksum scanners) and tested tool
additions. Keep the image reasonably lean; heavy/specialized tools belong
in documented `pip`/`apt` side-notes rather than the base image.