oofz/Ghidrust

GitHub: oofz/Ghidrust

Ghidrust 是一个用 Rust 全新编写的逆向工程工具包,提供反汇编、反编译和自动化分析能力,旨在以高性能和可审计的独立核心对标 Ghidra。

Stars: 2 | Forks: 0

# Ghidrust Hand-rolled **Rust** reverse-engineering toolkit inspired by [Ghidra](https://github.com/NationalSecurityAgency/ghidra). Ghidrust loads PE/ELF (and raw blobs), produces Capstone-class multi-arch listings (23 ISAs; x86-64 primary analyze/decompile pipeline), runs Auto Analysis, decompiles to pseudo-C, parses IL2CPP metadata / Unity install inventory, and saves durable projects — from a CLI, an MCP server for agents, or an egui CodeBrowser-style GUI. It is **not** a Ghidra fork or wrapper. Analysis logic (loaders, decode, analyzers, decompile) is written in-tree so the core stays small, auditable, and freestanding. ## What it aims to achieve | Goal | Meaning in practice | |------|---------------------| | **Surpass Ghidra (measurable)** | On x86-64 PE/ELF: faster Auto Analysis + decompile-all wall clock than Ghidra headless on the same machine/binary; ≥ Ghidra F1 on function discovery; structured typed C with expression folding (not mnemonic scaffolding); differential correctness vs Ghidra on a fixed corpus — **target**, not a claim of today’s quality. Human rubric: [docs/READABILITY_RUBRIC.md](docs/READABILITY_RUBRIC.md). Hex-Rays-class display is the ceiling after the Ghidra bar. | | **Ghidra-shaped workflow** | Familiar labels and surfaces (Auto Analysis names, project import/analyze/export, listing + click FUN → decompile) without depending on the Ghidra JVM stack | | **Custom core** | PE/ELF, Capstone-class multi-arch decode (`ghidrust-decode`), x86-64 RTTI/analyzers, and the IR → SSA → structure → typed-C pipeline implemented in Rust — third-party RE libraries are avoided at runtime; Ghidra sources are reference-only | | **CPU-correct first** | CPU paths are the oracle; optional GPU paths must match or enrich them, not replace honesty with speed claims | | **Agent-ready** | Headless CLI + stdio MCP with artifact spill/drain, program identity (`path` or `project`+`file_id`), PE install inventory, RTTI catalog query, UTF-16 xref support, function create / bounded disasm / call graphs, IL2CPP touch-map + body proof, live process bridge (Windows), and egui panes for every surface. **2026-07-19:** Windows agent disasm pipeline + bounds honesty (`--brief`/`--pretty`, `bounds_suspect`, `listing_text`) — see [CHANGELOG.md](CHANGELOG.md) | | **Practical projects** | Create a workspace, import binaries, run analyzers, persist results (`analysis.bin`), reopen later | ## Experimental GPU feature Ghidrust includes an **experimental** GPU path (wgpu / Vulkan) for two roles: 1. **Bulk RE** — parallel printable / pattern / RTTI-style scans where SIMT helps 2. **GPU-resident decompile** — multipass decompile kernels that keep mid-pipeline IR in **VRAM** (upload code once → device passes → download a `.gdecomp` dump) Enabled by default on the CLI / decomp crates via the `gpu` feature. Without a Vulkan adapter, those paths fall back or report unavailability; **CPU decompile and analysis still work**. Honest performance note: on small fixtures, GPU decompile is often **correct but slower wall-clock** than CPU because of adapter init and PCIe transfer — residency mid-pipeline is the research win, not automatic speedups. Details: [docs/GPU_DECOMPILER_RESEARCH.md](docs/GPU_DECOMPILER_RESEARCH.md), [docs/GPU_DECOMPILE_PROCESS.md](docs/GPU_DECOMPILE_PROCESS.md), [docs/GPU_ANALYZER_MATRIX.md](docs/GPU_ANALYZER_MATRIX.md). ## Build **Requirements:** Rust stable (edition 2021), Windows / Linux / macOS. GPU features need a Vulkan-capable GPU when you use the default `gpu` build. # Clone and enter the repo, then: # Debug (fast compile) cargo build --workspace # Release (recommended for GUI and large binaries) cargo build --workspace --release Binaries: | Binary | Path (after release build) | |--------|----------------------------| | CLI | `target/release/ghidrust` (`.exe` on Windows) | | GUI | `target/release/ghidrust-gui` | # CLI only cargo build -p ghidrust-cli --release # GUI only cargo build -p ghidrust-gui --release # Explicit GPU decomp + core bulk features cargo build -p ghidrust-cli --release --features ghidrust-core/gpu | Feature | Where | Purpose | |---------|--------|---------| | `gpu` (default on decomp / CLI) | `ghidrust-decomp` | GPU-resident decompile + related kernels | | `gpu` | `ghidrust-core` | Bulk string / pattern GPU path | # Run the test suite cargo test --workspace cargo test -p ghidrust-decomp ## Quick start # Help cargo run -p ghidrust-cli --release -- help # or: ./target/release/ghidrust help # Load / disassemble fixtures (Capstone-class engine; bounded by function end by default) ./target/release/ghidrust load fixtures/tiny_x64.pe ./target/release/ghidrust disasm fixtures/tiny_x64.pe --count 16 ./target/release/ghidrust decode-support --json ./target/release/ghidrust decode-query --query insn_name --arch x86 --id 1 --json ./target/release/ghidrust disasm fixtures/tiny_x64.pe --addr 0x140001000 --count 32 --detail --syntax intel --json # Lookups (no helper scripts required) ./target/release/ghidrust strings fixtures/analysis_lab.pe --encoding all --filter WideLab --json ./target/release/ghidrust xrefs fixtures/analysis_lab.pe --string ExitProcess --json ./target/release/ghidrust imports fixtures/analysis_lab.pe --json ./target/release/ghidrust function-at fixtures/analysis_lab.pe --addr 0x140001004 --json # Auto Analysis ./target/release/ghidrust analyzers ./target/release/ghidrust analyze fixtures/analysis_lab.pe --analyzers "Function ID,Stack" --json # CPU (Stage-1 default) vs experimental GPU decompile ./target/release/ghidrust decompile fixtures/tiny_x64.pe ./target/release/ghidrust gpu-decompile fixtures/tiny_x64.pe --out entry.gdecomp --metrics metrics.log --json # GUI cargo run -p ghidrust-gui --release Windows PowerShell: use `.\target\release\ghidrust.exe` and `.\target\release\ghidrust-gui.exe`. `--json` stdout is UTF-8 **without BOM** (safe for `ConvertFrom-Json`). Fixtures live under [`fixtures/`](fixtures/) (`tiny_x64.pe`, `analysis_lab.pe`, `tiny_x64.elf`, plus `decode_continuity.bin` for disasm `--skip-bad` tests). They are **committed test corpus** — keep them in git; put large private samples under gitignored `dev/`. ## Capabilities Every row below is exercised end-to-end (CLI + oracle) by [`crates/ghidrust-cli/tests/eval_analysis_decompile.rs`](crates/ghidrust-cli/tests/eval_analysis_decompile.rs); the report lands in [`dev/EVAL_ANALYSIS_DECOMPILE_REPORT.md`](dev/EVAL_ANALYSIS_DECOMPILE_REPORT.md) and machine-readable form at `dev/eval_analysis_decompile.json`. Rerun with: cargo test -p ghidrust-cli --test eval_analysis_decompile -- --nocapture Analyzer names are the exact strings from `ghidrust analyzers` and from the Auto Analysis screenshot Ghidra ships with. Outputs are honest: no fabricated symbols, no Hex-Rays / Ghidra C mimicry — you get structured JSON fields plus one human-readable status line per analyzer. ### Auto Analysis (21) Common invocation shapes: ghidrust analyze --analyzer "" --json ghidrust analyze --analyzers "," --gpu --json The columns below reference fields on `AnalyzerOutput` (per-analyzer entry inside `analysis.results[*]` in `--json` output). | # | Name (exact) | What it does | `--json` output fields | Human message | |---|---|---|---|---| | 1 | `ASCII Strings` | Bulk scan of executable + data blocks for ≥4-char printable ASCII runs using the preferred bulk backend (Sequential / ParallelCpu / GpuOrFallback). | `strings: [{va, value, length, encoding: "ascii"}]` | `found N ASCII string(s) [BulkScanMode…]` | | 2 | `Unicode Strings` | UTF-16LE printable runs across mapped blocks (even-aligned, NUL-terminated, mostly-ASCII wide strings). Also available via `ghidrust strings --encoding utf16`. | `strings: [{va, value, length, encoding: "utf16le"}]` | `found N UTF-16LE string(s)` | | 3 | `Aggressive Instruction Finder` | Fills real code gaps (bytes not covered by any known function): validates a decodable prologue-shaped run, adds new `FunctionInfo` and a `DiscoveredRange`. Never fabricates when there is no gap. | `recovered_ranges: [{start, end}]` (+ new entries in `functions`) | `found N recovered code range(s)` | | 4 | `Call Convention ID` | Tags every discovered function with a calling-convention heuristic (Win64 x64 default, cdecl / stdcall / thiscall fallbacks). | `conventions: [[va, name], …]` (+ `functions[*].calling_convention`) | `identified N calling convention(s)` | | 5 | `Call-Fixup Installer` | Detects Windows security cookie / import-thunk stubs and records a fixup entry with the stub VA. | `call_fixups: [{fixup_name, call_va}]` | `installed N call fixup(s)` | | 6 | `Create Address Tables` | Recovers jump/vtable-style contiguous VA tables inside `.rdata`/data and lists their entries. | `address_tables: [{base, count, entries: [va,…]}]` | `found N address table(s)` | | 7 | `Decompiler Parameter ID` | Scans each function for arg-register spills (`mov [rbp+…], rcx/rdx/…`) and attaches typed `arg0:rcx` / `arg1:rdx` slots — no invented parameters on bare bodies. | `functions: [{entry, parameters: ["arg0:rcx", …]}]` | `recovered parameters for N function(s)` | | 8 | `Decompiler Switch Analysis` | Turns jump-table address tables into switch structures with `(case_value, target_va)` pairs. | `switches: [{jump_va, cases: [[val, target], …]}]` | `recovered N switch table(s)` | | 9 | `Demangler Microsoft` | Parses PE symbols in the MSVC (`?...@@`) mangling scheme, records demangled name alongside the raw symbol. | `symbols: [{name, va, demangled?}]` | `demangled N symbol(s)` | | 10 | `Embedded Media` | Scans data for well-known magic prefixes (PNG, JPG, GIF, WAV, …) and records their VA + kind. | `media: [{kind, va}]` | `found N media signature(s)` | | 11 | `Function ID` | Hashes each function's prologue window and matches it against the shipped FID catalog (`fid_*` names). | `fid_matches: [{entry, matched_name}]` | `matched N FID signature(s)` | | 12 | `Function Start Search` | Seeds functions from entry, symbol table, exact `55 48 89 e5` prologues, and orphan `sub rsp, imm8` starts. Grows each body (skips small decode holes) until `ret`. Drops mid-body seeds. Prefer `ghidrust function-at` to map a VA → containing function. | `functions: [{entry, end, name}]` | `identified N function start(s)` | | 13 | `Non-Returning Functions - Discovered` | Marks functions ending in `int3` without a `ret`, plus known no-return imports (`ExitProcess`, `abort`, …). | `noreturn_entries: [va, …]` (+ `functions[*].noreturn`) | `marked N noreturn function(s)` | | 14 | `PDB MSDIA` | Portable PDB (MSF7) reader tuned to the MSDIA symbol shapes (`S_PUB32`, `S_GPROC32` names). | `symbols: [{name, va}]` | `parsed N PDB symbol(s) (msdia→universal)` | | 15 | `PDB Universal` | Same MSF7 reader without MSDIA-specific filtering — surfaces every stream symbol it can find (`MSF7` marker included as a sentinel symbol). | `symbols: [{name, va}]` | `parsed N PDB symbol(s) (universal)` | | 16 | `Shared Return Calls` | Finds sites where multiple callers reuse the same epilogue block (tail-call / shared-return pattern). | `shared_returns: [va, …]` | `marked N shared return site(s)` | | 17 | `Stack` | Per-function frame recovery: reads `sub rsp, imm` / `push rbp; mov rbp, rsp` to compute `frame_size=0x…`, then attaches `param_…` slots. Won't pollute functions that have no real frame. | `stack_frames: [[va, ["frame_size=0x20", "param_rcx@0x8", …]], …]` | `recovered N stack frame(s)` | | 18 | `Variadic Function Signature Override` | Ensures API symbols matching `printf` / `sprintf` / `scanf` families exist, tags them `varargs=true` cdecl and gives them a `format` param. | `varargs_entries: [va, …]` (+ `functions[*].varargs`) | `applied varargs to N function(s)` | | 19 | `WindowsPE x86 PE RTTI Analyzer` | MSVC C++ RTTI recovery: locates COL / class-hierarchy / type-info descriptors, links them to vtables, extracts demangled class names. | `rtti: {classes: [{name, type_info_va, vtable_va, col_va, kind}], notes: [str,…]}` | `recovered N RTTI class record(s)` | | 20 | `Windows x86 Propagate External Parameters` | Applies known prototypes to imported Windows APIs (`ExitProcess(UINT)`, `GetProcAddress`, …) so calls resolve typed args. | `external_params: [[va, prototype], …]` | `applied N external parameter prototype(s)` | | 21 | `WindowsResourceReference` | Parses `.rsrc` and records resource records (`VERSION`, `RT_ICON`, …) with their VA. | `resources: [{name, va}]` | `parsed N resource record(s)` | Defaults (empty `--analyzer` list): **ASCII Strings**, **Unicode Strings**, **WindowsPE x86 PE RTTI Analyzer**, **Function Start Search**, **Create Address Tables**, **Embedded Media**, **Demangler Microsoft**. Notes: - `--gpu` on `analyze` runs each selected CPU analyzer, then per-analyzer GPU seed kernels; the CPU output above is unchanged, but the human message is appended with `gpu_enrich hits_merged=… backend=…`. - Every entry above is a **PASS** in [`dev/EVAL_ANALYSIS_DECOMPILE_REPORT.md`](dev/EVAL_ANALYSIS_DECOMPILE_REPORT.md); the `analysis_lab.pe` / `tiny_x64.pe` fixtures pin known VAs (e.g. `printf@0x140002010`, `PNG@0x140002050`, `VERSION@0x140002090`, `WideLabString` UTF-16, `Widget` RTTI class). ### Lookups (CLI + MCP) First-class commands for the queries agents used to need ad-hoc scripts for. Same capabilities are exposed as MCP tools (see [MCP tools](#3-tools-the-server-exposes)). | Command | Purpose | Key flags | |---------|---------|-----------| | `ghidrust load ` | Load PE/ELF; JSON includes `resolved_path`, `sections`, informational `section_notes` | `--json`, `--out` | | `ghidrust strings ` | Scan ASCII and/or UTF-16LE strings (PE/ELF or `--raw` blob) | `--encoding`, `--filter`, `--match substr\|token\|whole\|glob`, `--limit N`, `--out FILE`, `--raw`, `--json` | | `ghidrust xrefs ` | Cross-references (absolute + RIP-relative; string encoding modes); call edges | Exactly one of: `--to` / `--from` / `--string` / `--import` / `--calls`; `--encoding ascii\|utf16le\|all`; `--skip-stubs` / `--classify` | | `ghidrust imports ` | PE import directory → DLL + symbol + IAT VA | `--dll NAME`, `--name NAME`, `--json` | | `ghidrust function-at --addr HEX` | Containing analyzed function for a body VA (runs Function Start Search if needed); JSON includes `seed_kind` | `--json` | | `ghidrust function create --addr HEX` | Create/heal a function at VA (pdata/export/FSS complements; may synthesize) | `--end HEX`, `--json` | | `ghidrust decompile ` | Containing-fn resolve + Stage-1 pseudo-C | `--addr` (mid-body ok), `--follow-stub`, `--json` | | `ghidrust gpu-decompile ` | GPU multipass at resolved entry; metrics JSON primary; `.gdecomp` opaque | `--addr`, `--metrics`, `--json` | | `ghidrust rtti ` | RTTI catalog (filter/exact/match; multi-vtable honest) | `--filter`/`--name`/`--exact`, `--match`, `--json` | | `ghidrust inventory ` | Generic PE install inventory (exe/dll + VERSIONINFO; artifact if large) | `--max-depth`, `--hash`, `--json` | | `ghidrust tree ` | Bounded file tree index (existence/size; no unpack) | `--max-depth`, `--ext`, `--name`, `--json` | | `ghidrust artifact get\|query\|list` | Drain spilled analysis artifacts (`next_offset`) | `--offset`, `--limit`, `--json` | | `ghidrust process list\|attach\|launch\|…\|break\|wait\|scan\|watch` | Live Process Bridge (Windows; observe default, `mode=debug` for BP/step; `tool_surface` 7) | session_id / `-mode` / `--args` / `--cwd` / `--addr` / `--module` / `--rva` | | `ghidrust il2cpp meta\|map\|touch-map\|stubs\|icalls` | IL2CPP metadata + touch-map + method map (body proof / baseline) + stubs + icalls | See [docs/IL2CPP.md](docs/IL2CPP.md) | | `ghidrust unity-inventory ` | Unity player layout (reuses PE VERSIONINFO helpers) | `--json`, `--out FILE` | | `ghidrust disasm ` | Capstone-class listing; bounded by function end by default; `decode_gaps` when `--skip-bad`; JSON `stop_reason` | `--addr HEX`, `--count N` (default 16), `--skip-bad`, `--linear`/`--flow`, `--arch`, `--mode`, `--syntax`, `--detail`/`--no-detail`, `--detail-real`, `--skipdata`, `--skipdata-mnemonic`, `--skipdata-size`, `--unsigned-imm`, `--only-offset-branch`, `--litbase`, `--mnem-override ID:MNEMONIC`, `--out`, `--json` | | `ghidrust decode-support` | Engine version, 23 supported arches, options, syntax values, compile features | `--json` | | `ghidrust decode-query` | Engine introspection (`insn_name`, `reg_name`, `group_name`, `insn_group`, `reg_read`, `reg_write`, `op_count`, `op_index`, `regs_access`) | `--query NAME`, `--arch`, `--mode`, `--id`, `--index`, `--bytes HEX`, `--addr HEX`, `--detail`, `--json` | # Wide + ASCII string search (token match + limit; BOM-free --out) ghidrust strings app.exe --encoding all --filter Config --match token --limit 50 --json ghidrust strings huge.bin --raw --filter Camera --out camera_strings.json --json # Code sites that reference a string (RIP-relative LEA included; hide IL2CPP resolve stubs) ghidrust xrefs app.exe --string ResolutionWidth --skip-stubs --json # Import call-sites (IAT slot + FF15/RIP refs) ghidrust imports app.exe --name ShellExecuteW --json ghidrust xrefs app.exe --import ShellExecuteW --json # Body VA → function interval (seed_kind: pdata|export|method_pointer|prologue|manual|synthesized) ghidrust function-at app.exe --addr 0x14000d8ad --json # Create/heal a missing function (optional end; orphan resolve may synthesize SYNTH_*) ghidrust function create app.exe --addr 0x14000d8ad --json # Bounded disasm (default); --linear escapes function-end clamp; JSON includes stop_reason ghidrust disasm app.exe --addr 0x14000d890 --count 40 --skip-bad ghidrust disasm app.exe --addr 0x14000d890 --count 40 --linear --json # Callee edges inside a function ghidrust xrefs app.exe --calls 0x14000d8ad --json # Unity / IL2CPP (see docs/IL2CPP.md) ghidrust unity-inventory /path/to/GameDir --json ghidrust il2cpp touch-map --meta /path/to/*_Data/il2cpp_data/Metadata/global-metadata.dat --filter Camera --json ghidrust il2cpp meta /path/to/*_Data/il2cpp_data/Metadata/global-metadata.dat --filter Camera --json ghidrust il2cpp map --binary /path/to/GameAssembly.dll --meta /path/to/.../global-metadata.dat --baseline prev_map.json --json ghidrust il2cpp stubs --binary /path/to/GameAssembly.dll --json ghidrust decompile /path/to/GameAssembly.dll --addr 0x180012345 --follow-stub ### Decompile methods | Method | CLI | What it emits | Outputs / where to see them | |---|---|---|---| | **Stage-1** (**default**) | `ghidrust decompile [--addr HEX] [--count N] [--follow-stub] [--verbose]` | Expression-folded SSA + structure + types (`--follow-stub` for IL2CPP resolve thunks): nested arith temps collapsed, named import/function calls when known, `this` on `Class::method`, float seeds from SSE notes, single-field structs when base is already `Ptr`, early-exit `return` polish, emit-time tokens for GUI nav. Still: recovered prototype / `local_` / `p->field_` / `switch` / `&&` `\|\|` / `break` `continue` (lab goto_rate <0.15). Mid-body `--addr` resolves to containing function. Readability rubric: [docs/READABILITY_RUBRIC.md](docs/READABILITY_RUBRIC.md). | stdout: `pseudo_c`. `--verbose`: `[name] stage=1 … fold=N tokens=N goto=… lift=…%`. `--json`: `{decompile, resolve, stage1: {loops, phis, locals, params, structs, lift_ratio, goto_rate, folded_temps, token_count, return_type, prototype, total_ops}}`. | | **Stage-0** (oracle) | `ghidrust decompile --stage0 [--addr HEX] [--count N] [--verbose]` | CFG-driven pseudo-C: `void FUN_() { block_0: … goto/return; }` — mnemonic-style scaffolding, no fabricated locals or types. Kept as regression oracle only. | stdout: `pseudo_c`. Metrics on stderr only with `--verbose`. `--json`: full `Decompile { name, blocks[], edges[], insn_count, pseudo_c }`. | | **Stage-0.5 IR** (oracle) | `ghidrust decompile --stage05 [--addr HEX] [--count N] [--verbose]` | IR-informed emit from the hand-rolled x86-64 lifter → `ghidrust-ir`: `xor a,a → a=0`, `add/sub/or/and/xor/shl/shr` augmented-assign, `push`/`pop`, direct `call`, flag-driven `jcc`. Falls back to Stage-0 scaffolding for uncovered ops. | stdout: `pseudo_c`. Metrics on stderr only with `--verbose`. `--json`: `{decompile: …, lift_coverage: {total_ops, unimplemented_ops, source_instructions, ratio}}`. | | **decompile-bench** | `ghidrust decompile-bench [--functions N] [--count N] [--stage1] [--parallel] [--out FILE]` | Runs default analyzers, then benches Stage-0/0.5 (default) or Stage-1 (`--stage1`) across every discovered function; `--parallel` fans out per-entry Stage-1 across a rayon thread pool. | Text table (or JSON via `--json`); optional `--out FILE`. Report carries per-function `stage0_us`, `stage05_us`, `stage1_us`, `stage1_goto_count`, `stage1_leaf_count`, and per-function `pseudo_c` when Stage-1 is on. | | **ghidra-headtohead** | `ghidrust ghidra-headtohead [--functions N] [--count N] [--ghidra DIR] [--captured JSON] [--out FILE]` | Fair Ghidra oracle: shared-entry intersection with Ghidra `DecompInterface` output, per-row Stage-1 vs Ghidra normalized-token similarity, per-entry Stage-1 wall time. Without `--ghidra` / `--captured` the report is methodology-only. | Text or JSON; each row carries `token_similarity`, `ghidrust_stage1_us`, `ghidra_wall_us`. See [`docs/GHIDRA_HEADTOHEAD.md`](docs/GHIDRA_HEADTOHEAD.md). | | **gpu-decompile** | `ghidrust gpu-decompile [--addr HEX] [--out FILE] [--metrics FILE]` | Full **GPU-resident** VRAM multipass decompile at containing-fn resolve (mid-body `addr` ok): decode → leaders → blocks → emit kernels; single final download; asserts `mid_pipeline_host_reads == 0` and multipass-CPU equivalence. Metrics JSON is primary; `.gdecomp` is opaque. | `.gdecomp` binary dump at `--out`. stdout: pseudo-C. `--json` / `--metrics FILE` produces `{resolve, resolved_entry, gpu_backend, gpu_device, gpu_ms, mid_pipeline_host_reads, kernels, dump_path, dump_bytes, gpu_ir_count, gpu_block_count, gpu_edge_count, equivalence_multipass, pseudo_c_head}`. Non-zero exit if equivalence fails or a mid-pipeline host read is observed. | | **re-bench** | `ghidrust re-bench [--out FILE]` | CPU decompile of the entry + bulk RE on a padded haystack, once on CPU (parallel) and once on GPU / fallback; asserts equal bulk hit counts. | Text report to stdout (or JSON with `--json` / `--out`). Fields: `decompile_cpu {backend, ms, entry, name, blocks, edges, insns, lines, chars, pseudo_c_head}`, `bulk_cpu`, `bulk_gpu` (each: `mode, backend, ms, hits, haystack_bytes`), plus `note` explaining that decompile stays on CPU. | Two more benches are shipped and callable from the CLI even though they are not part of the analyzer/decompile eval sweep — they measure how the analyzer and RTTI GPU strategies compare against their CPU oracles: | Method | CLI | Purpose | |---|---|---| | `analyzer-bench` | `ghidrust analyzer-bench [--large] [--out FILE] [--json]` | All analyzers + a GPU-decompile row: CPU wall-time vs GPU `pcie_upload` / `device_ms` / `pcie_download` split, with a per-analyzer `equal` correctness flag. | | `analyzer-bench-matrix` | `ghidrust analyzer-bench-matrix` | Print the static analyzer → GPU-strategy matrix (e.g. `ASCII Strings → printable_run`, `Unicode Strings → cstr_multi`, `WindowsPE x86 PE RTTI Analyzer → rtti_scan`). | | `bulk-bench` | `ghidrust bulk-bench [--json]` | Sequential vs parallel-CPU vs GPU/fallback bulk-string timings on the program's own bytes + a padded haystack. | | `rtti-gpu-bench` | `ghidrust rtti-gpu-bench [--out FILE] [--json]` | CPU `recover_rtti` vs GPU `rtti_scan` seed with `pcie_upload / device_ms / pcie_download` split and a plain-English performance-model note. | ## Using the three surfaces Ghidrust exposes the **same analysis core** three ways. Pick one (or mix them): | Surface | Best for | Entry point | |---------|----------|-------------| | **CLI** | Scripts, CI, one-shot RE, benches | `ghidrust …` | | **GUI** | Interactive CodeBrowser-style work | `ghidrust-gui` | | **MCP** | AI agents / IDEs that speak Model Context Protocol | `ghidrust mcp` (stdio) | Build both binaries first (`cargo build --workspace --release`), then use the sections below. ## CLI — full usage The CLI is the `ghidrust` binary from `ghidrust-cli`. Prefer **absolute paths** to binaries and project dirs when scripting. # After release build ./target/release/ghidrust help # Windows .\target\release\ghidrust.exe help ### Everyday commands # Map a binary (path OR project + file_id) ghidrust load /path/to/app.exe --json ghidrust load --project ./MyProject --file-id --json # Install / tree inventory (no OS shell needed) ghidrust inventory /path/to/InstallRoot --max-depth 8 --json ghidrust tree /path/to/GameDir --ext dll,dat --name "*meta*" --json # Listing (bounded by fn end by default; --linear escapes; optional --skip-bad) ghidrust disasm /path/to/app.exe --count 32 ghidrust disasm /path/to/app.exe --addr 0x140001000 --count 64 --skip-bad ghidrust disasm /path/to/app.exe --addr 0x140001000 --count 64 --linear --json # Strings / xrefs / imports / containing function ghidrust strings /path/to/app.exe --encoding all --filter SomeName --match token --limit 50 --json ghidrust strings /path/to/blob.dat --raw --filter Camera --out camera.json --json ghidrust xrefs /path/to/app.exe --string SomeName --encoding all --skip-stubs --classify --json ghidrust xrefs /path/to/app.exe --to 0x140002010 --json ghidrust xrefs /path/to/app.exe --calls 0x140001000 --json ghidrust imports /path/to/app.exe --json ghidrust xrefs /path/to/app.exe --import CreateFileW --json ghidrust function-at /path/to/app.exe --addr 0x140001234 --json ghidrust function create /path/to/app.exe --addr 0x140001234 --json ghidrust rtti /path/to/app.exe --filter Widget --json # Artifacts (drain large spilled dumps) ghidrust artifact list --json ghidrust artifact query --offset 0 --limit 64 --json # Live process (Windows; observe default, debug opt-in; tool_surface >= 7) ghidrust process list --json ghidrust process attach -mode observe ghidrust process attach -mode debug ghidrust process launch C:\path\to\app.exe -mode debug -break-at-entry --json ghidrust process modules --json ghidrust process resolve --module app.exe --rva 0x1234 --json ghidrust process break set -addr 0x7ff… ghidrust process continue ghidrust process wait -timeout 5000 ghidrust process stack ghidrust process scan -aob "48 8b ?? 90" ghidrust process watch "app.exe+0x1234->*+0x10" ghidrust process read --addr 0x7ff… --size 64 --json ghidrust process detach # Unity player inventory + IL2CPP touch-map / metadata / stubs / method map ghidrust unity-inventory /path/to/GameDir --json ghidrust il2cpp touch-map --meta /path/to/Game_Data/il2cpp_data/Metadata/global-metadata.dat --filter Camera --json ghidrust il2cpp meta /path/to/Game_Data/il2cpp_data/Metadata/global-metadata.dat --filter Camera --json ghidrust il2cpp map --binary /path/to/GameAssembly.dll --meta /path/to/.../global-metadata.dat --json ghidrust il2cpp stubs --binary /path/to/GameAssembly.dll --json ghidrust il2cpp icalls --binary /path/to/UnityPlayer.dll --filter Camera --json # List Auto Analysis names (Ghidra-compatible labels) ghidrust analyzers # Run analyzers (comma list or repeatable --analyzer) ghidrust analyze /path/to/app.exe --analyzers "Function Start Search,ASCII Strings,Unicode Strings" --json ghidrust analyze /path/to/app.exe --analyzer "Stack" --analyzer "Function ID" --gpu --json # CPU decompile — Stage-1 default; oracles via --stage0 / --stage05; IL2CPP --follow-stub ghidrust decompile /path/to/app.exe # Stage-1; quiet stderr ghidrust decompile /path/to/app.exe --verbose # + metrics line on stderr ghidrust decompile /path/to/app.exe --addr 0x140001000 --json ghidrust decompile /path/to/app.exe --stage05 --json # IR oracle + lift-coverage JSON ghidrust decompile /path/to/GameAssembly.dll --addr 0x180012345 --follow-stub # Wall-clock + lift-coverage bench across all discovered functions ghidrust decompile-bench /path/to/app.exe --functions 32 --count 128 --out bench.txt # Experimental GPU decompile (mid-body addr resolves to containing entry) ghidrust gpu-decompile /path/to/app.exe --addr 0x140001234 --out entry.gdecomp --metrics metrics.log --json **`--gpu` on `analyze`** turns on GPU bulk strings (when available) and per-analyzer GPU seed enrichment. It is **not** the same as `gpu-decompile` (full VRAM multipass decompile). ### Durable projects ghidrust project create ./MyProject --name Case1 ghidrust project import ./MyProject /path/to/app.exe ghidrust project list ./MyProject ghidrust project analyze ./MyProject \ --analyzer "Function Start Search" \ --analyzer "ASCII Strings" \ --gpu ghidrust project export ./MyProject Layout on disk: MyProject/ ghidrust.project.json imports/ # copied binaries results// analysis.bin # primary (fast bincode) summary.json analysis.json exports/ ### Command reference | Command | What it does | |---------|----------------| | `ghidrust load [--json]` | Load PE/ELF; JSON includes `resolved_path`, `sections`, informational `section_notes` | | `ghidrust disasm [--addr HEX] [--count N] [--skip-bad] [--linear\|--flow] [--arch ARCH] [--mode MODE] [--syntax SYNTAX] [--detail] [--detail-real] [--skipdata] [--skipdata-mnemonic S] [--skipdata-size N] [--unsigned-imm] [--only-offset-branch] [--litbase HEX] [--mnem-override ID:MNEM]… [--json]` | Capstone-class listing; bounded by function end by default; `--linear` escapes; JSON `stop_reason` + `decode_gaps` | | `ghidrust decode-support [--json]` | Decode engine catalog (version, arches, options, syntax values) | | `ghidrust decode-query [--query NAME] [--arch ARCH] [--mode MODE] [--id N] [--index N] [--bytes HEX] [--addr HEX] [--detail] [--json]` | Engine introspection queries | | `ghidrust bytes --addr HEX [--count N] [--json]` | Raw VA hex dump | | `ghidrust strings [--raw] [--encoding …] [--filter SUB] [--match MODE] [--limit N] [--out FILE] [--json]` | String scan (blob-capable) | | `ghidrust xrefs (--to\|--from\|--string\|--import\|--calls) [--encoding ascii\|utf16le\|all] [--skip-stubs] [--classify] [--json]` | RIP-aware xrefs; `--calls` = callee edges; attribution fields when functions exist | | `ghidrust imports [--dll NAME] [--name NAME] [--json]` | PE import / IAT slots | | `ghidrust function-at --addr HEX [--json]` | Containing function for a body VA (`seed_kind`) | | `ghidrust function create --addr HEX [--end HEX] [--json]` | Create/heal function at VA (pdata/export/FSS; may synthesize) | | `ghidrust inventory [--max-depth N] [--hash] [--json]` | Generic PE install inventory (exe/dll + VERSIONINFO) | | `ghidrust tree [--max-depth N] [--ext LIST] [--name GLOB] [--json]` | Bounded file tree index (existence/size; no unpack) | | `ghidrust artifact get\|query\|list …` | Drain / list spilled analysis artifacts (`next_offset`) | | `ghidrust process list\|attach\|launch\|resume\|detach\|modules\|read\|resolve\|regions …` | Live Process Bridge (Windows; read-only MVP; launch = CREATE_SUSPENDED) | | `ghidrust il2cpp meta\|map\|touch-map\|stubs\|icalls …` | IL2CPP metadata / touch-map / RVA map (`body_class`, `--baseline` → `build_skew`, `--meta-sections`) / stubs / icalls ([docs/IL2CPP.md](docs/IL2CPP.md)) | | `ghidrust unity-inventory [--out FILE] [--json]` | Unity player install inventory | | `ghidrust rtti [--filter\|--name\|--exact] [--match MODE] [--json]` | RTTI catalog (filter/exact; multi-vtable honest) | | `ghidrust analyzers [--json]` | List Auto Analysis names | | `ghidrust analyze [--analyzers a,b \| --analyzer NAME …] [--gpu] [--json]` | Run analyzers; `--gpu` = bulk strings + seed enrich | | `ghidrust decompile [--addr HEX] [--count N] [--stage0\|--stage05\|--stage1] [--follow-stub] [--verbose] [--json]` | **CPU** decompile (**Stage-1** default; containing-fn resolve; `--follow-stub` for IL2CPP) | | `ghidrust decompile-bench [--functions N] [--count N] [--stage1] [--parallel] [--out F]` | Per-function wall-clock + lift-coverage across stages | | `ghidrust gpu-decompile [--addr HEX] [--out FILE] [--metrics FILE]` | **GPU-resident** multipass at resolved entry; metrics JSON; `.gdecomp` opaque | | `ghidrust bulk-bench ` | Seq / parallel CPU / GPU bulk string timings | | `ghidrust re-bench [--out FILE]` | CPU decompile + bulk CPU then GPU metrics | | `ghidrust analyzer-bench [--large] [--out FILE]` | All analyzers + decompile: CPU vs GPU | | `ghidrust analyzer-bench-matrix` | Print GPU strategy class per analyzer | | `ghidrust rtti-gpu-bench [--out FILE]` | CPU RTTI vs GPU `rtti_scan` | | `ghidrust project create\|import\|list\|analyze\|export …` | Durable projects | | `ghidrust version` / `--version` / `-V` `[--json]` | Package version + `tool_surface` (matches MCP / egui About) | | `ghidrust mcp` | Stdio MCP server for agents | `--json` and `--out FILE` write UTF-8 **without BOM**. Prefer `--out` over shell redirection when filters contain `:` (Windows path hazard). Decompile status lines go to stderr only with `--verbose` (avoids PowerShell `NativeCommandError` noise when scripting). Recommended early path: **strings / imports / xrefs** for orientation → Exception Directory / `.pdata` seeds + **Function Start Search** → `function create` for orphans → bounded `disasm` / `xrefs --calls` → address tables → conventions/stack → RTTI → `decompile`. For Unity IL2CPP players: **`unity-inventory`** → **`il2cpp touch-map`** (names) → **`il2cpp map`** (`body_class` / shared stubs; `--baseline` for `build_skew`) → stubs / `--follow-stub` as needed. ## GUI — full usage cargo run -p ghidrust-gui --release # or ./target/release/ghidrust-gui # Windows: .\target\release\ghidrust-gui.exe Typical session: 1. **Project picker** — open/create a project folder, pick a recent one, or continue without a project. 2. **Browse… / Import** a PE or ELF into the project tree. 3. **Double-click** a file to load listing / saved analysis into Overview. 4. **Analyze…** — check analyzers (Defaults / All / None), optionally enable **GPU (strings bulk + per-analyzer seed kernels)**, then **Run Analysis**. 5. Results persist under `results//` (`analysis.bin` for fast reopen, plus `summary.json`). The GUI is for humans. Agents should use the **CLI** or **MCP**, not drive the UI. ## MCP — setup in AI tools `ghidrust mcp` is a **stdio** MCP server (JSON-RPC). Your AI client starts the binary and talks over stdin/stdout — there is no separate HTTP port. ### 1. Build the CLI once cargo build -p ghidrust-cli --release Note the absolute path to the binary, e.g. `C:\path\to\Ghidrust\target\release\ghidrust.exe` on Windows or `/path/to/Ghidrust/target/release/ghidrust` on Linux/macOS. ### 2. Register it in your client **Cursor** — user or project MCP config (e.g. `~/.cursor/mcp.json` or a local `.cursor/mcp.json`). Keep project-local `.cursor/` gitignored — it is machine-specific IDE config, not product source: { "mcpServers": { "ghidrust": { "command": "C:/path/to/Ghidrust/target/release/ghidrust.exe", "args": ["mcp"] } } } **Claude Desktop** — in `claude_desktop_config.json`: { "mcpServers": { "ghidrust": { "command": "C:/path/to/Ghidrust/target/release/ghidrust.exe", "args": ["mcp"] } } } **Other MCP clients** — same pattern: command = absolute path to `ghidrust` / `ghidrust.exe`, args = `["mcp"]`. Restart the client after editing config. After rebuild/restart, confirm the binary matches the skill: `ghidrust --version` (package + `tool_surface`), and MCP `server_info` / `tools/list` includes `process_list` and `server_info`. If those tools are missing, the client is still running a stale binary — rebuild and restart MCP; do not treat that as “live process unsupported.” On Linux/macOS: { "mcpServers": { "ghidrust": { "command": "/path/to/Ghidrust/target/release/ghidrust", "args": ["mcp"] } } } ### 3. Tools the server exposes | Tool | Args | Purpose | |------|------|---------| | `server_info` | — | Package `version`, monotonic `tool_surface`, features, live session_model | | `load` | `path` **or** `project`+`file_id` | Load PE/ELF; `resolved_path`, `sections`, `section_notes` | | `decode_support` | — | Engine version, 23 arches, options, syntax values, compile features | | `decode_query` | `query`, optional `arch`, `mode`, `id`, `index`, `bytes`, `addr`, `detail` | Introspection: `insn_name`, `reg_name`, `group_name`, `insn_group`, `reg_read`, `reg_write`, `op_count`, `op_index`, `regs_access` | | `disassemble` | `path`, optional `addr`, `count`, `skip_bad`, `linear`, `flow`, `arch`, `mode`, `syntax`, `detail`, `detail_real`, `skipdata`, `skipdata_mnemonic`, `skipdata_size`, `unsigned_imm`, `only_offset_branch`, `litbase`, `mnem_overrides` | Bounded by function end by default; `linear:true` escapes; JSON `stop_reason` + `decode_gaps` | | `rtti` | `path` | Full RTTI recover dump | | `rtti_query` | `path`, optional `filter`, `exact`, `match` | Catalog query; multi-vtable; artifact if large | | `artifact_get` / `artifact_query` / `artifact_list` | `id` / optional `offset`/`limit` / optional `max` | Drain or list spilled results (`next_offset`) | | `inventory` | `path`, optional `max_depth`, `hash` | Generic PE dir inventory + VERSIONINFO | | `list_tree` | `path`, optional `max_depth`, `extensions`, `name_glob` | Bounded tree index | | `list_analyzers` | — | Auto Analysis option names | | `analyze` | `path`, optional `analyzers[]`, optional `gpu` | Run analyzers (+ GPU enrich if `gpu: true`) | | `list_strings` / `search_strings` | `path`, optional `encoding` (`ascii`\|`utf16`\|`all`), `filter`, `match` (`substr`\|`token`\|`whole`\|`glob`), `min`, `limit`, `raw` | ASCII / UTF-16LE strings; `raw:true` for non-PE/ELF blobs | | `get_xrefs_to` | `path`, `addr`, optional `skip_stubs`, `classify` | Xrefs **to** a VA; IL2CPP resolve-stub filter/label; `to_entry` when known | | `get_xrefs_from` | `path`, `addr`, optional `count` | Xrefs **from** a VA; `from_entry` / `from_function` / `to_entry` when known | | `get_calls_from` | `path`, `addr` | Callee edges (`call`/`jmp`) inside the containing function | | `get_string_xrefs` | `path`, `filter`, optional `encoding` | String xrefs with `ascii`\|`utf16le`\|`all` | | `list_imports` | `path`, optional `dll` / `name` | PE IAT slots | | `get_import_xrefs` | `path`, `name` | Code sites that reference an import IAT slot | | `function_at` / `get_function_by_address` | `path`, `addr` | Containing function for a body VA (`seed_kind`) | | `read_bytes` | `path`, `addr`, optional `count` | Raw VA hex dump | | `il2cpp_meta` | `path`, optional `filter` | Parse `global-metadata.dat` (v27/29/31); fail closed if encrypted | | `il2cpp_map` | `binary`, `meta` or `meta_sections`, optional `filter`, `baseline` | Metadata ↔ RVA + `body_class` / `shared_stubs` / `semantics_mismatch` / optional `build_skew` | | `il2cpp_touch_map` | `filter`, `meta` or `meta_sections`, optional `binary` | Substring touch-map over metadata heaps | | `il2cpp_stubs` | `binary`, optional `filter`, `max` | List IL2CPP resolve stubs by icall name | | `il2cpp_icalls` | `binary`, optional `filter` | Engine icall name↔fn tables | | `function_create` | `path`, `addr`, optional `end` | Create/heal a function at VA (pdata/export/FSS; may synthesize `SYNTH_*`) | | `unity_inventory` | `path` | Unity player dir → assemblies, plugins, metadata, PE versions | | `decompile` | `path`, optional `addr`, `count`, `stage`, `follow_stub` | Containing-fn resolve + Stage-1 expression-folded C; JSON includes `folded_temps`, `token_count`, `goto_rate`, `resolve` | | `list_gpu_strategies` | — | Per-analyzer GPU strategy matrix | | `gpu_decompile` | `path`, optional `addr`, `out` | GPU decompile at VA; metrics JSON; dump opaque | | `rtti_gpu_bench` | `path` | CPU vs GPU RTTI with PCIe/device split | | `process_list` / `process_attach` / `process_launch` / … / `process_break_*` / `process_wait` / `process_scan` / `process_watch_expr` | session / pid / mode / image / module / rva / max | Live Process Bridge (Windows; observe default; debug opt-in; `tool_surface` ≥ 7) | #### Live process (Windows) Default **observe** = read-only (`PROCESS_VM_READ`): `process list` → `attach [-mode observe]` → `modules` → `resolve --module NAME --rva HEX` → `read` / `scan` / `watch` → `detach`. **Debug** (`-mode debug`, requires `tool_surface >= 7`): attach or launch with debug rights → `break set` → `continue` / `wait` → registers (`regs`) + `stack` → optional `scan` / `watch` → `snapshot` → `detach`. Observe **launch** still uses `CREATE_SUSPENDED` + `resume`. Debug launch uses Windows debug APIs (initial break). Multi-step work **must** stay in one MCP/GUI process — CLI one-shot cannot reuse `session_id`. Bytes ≠ types. Anti-cheat: advisory only; access denied is explicit. **GUI Debugger walkthrough** 1. **Debugger → Attach…** (or **Launch…**) 2. **Targets:** set **Mode = debug**, Attach PID (or Launch with **Break at entry**) 3. **Modules:** static map `module + RVA` → live VA 4. **Breakpoints:** paste live VA → **Add** 5. **Continue (F5)** / **Wait stop** → Registers + Stack update 6. **Watches:** add `module+rva->*+0x10` → **Refresh**; optional AOB **Scan** 7. **Console → Export snapshot** → **Detach** Versioning: `ghidrust --version`, MCP `initialize`/`server_info`, and egui Help → About / window title all report the same workspace package version. Agents also check `tool_surface`: **minimum `3`** (touch-map / body_class / function_create); **prefer `>= 4`** for bounded disasm / `get_calls_from`; **require `>= 5`** for `decode_support`, `decode_query`, and extended `disassemble` decode flags; **`>= 6`** for crypto recover/bake; **`>= 7`** for live debug break/step/scan/watch; **current is `7`**. `server_info.decode` mirrors `decode-support`; `server_info.live_process` lists modes + capabilities. #### Analysis artifacts Large MCP/CLI dumps spill to `%TEMP%/ghidrust-artifacts/`. Tool envelopes include `entry_count`, preview, `artifact_id`, and `next_offset`. Drain with `artifact_query` until `next_offset` is null — never treat truncated host UI text as complete. #### GUI Window homes (§13) | Capability | Window / pane | |---|---| | IL2CPP meta / methods / icalls | **IL2CPP Metadata**, **IL2CPP Methods**, **IL2CPP ICalls** | | PE / Unity inventory | **Install Inventory** | | Tree index | **File System Browser** | | Artifact spill | **Analysis Artifacts** | | GPU decompile | Analysis → **GPU Decompile…** | | Encoding / xrefs / RTTI / notes | Defined Strings, Symbol References, Symbol Tree Classes, Memory Map | | Live process | **Debugger** (tabbed): Targets / Modules / Memory Bytes / Regions / Breakpoints / Threads / Registers / Stack / Watches (live APIs under mode=debug) | IL2CPP version matrix and Unity inventory schema: [docs/IL2CPP.md](docs/IL2CPP.md). Example agent-facing call shapes (conceptual): { "name": "list_strings", "arguments": { "path": "…/app.exe", "encoding": "all", "filter": "Camera", "match": "token", "limit": 50 } } { "name": "list_strings", "arguments": { "path": "…/global-metadata.dat", "raw": true, "filter": "UnityEngine", "limit": 20 } } { "name": "get_xrefs_to", "arguments": { "path": "…/GameAssembly.dll", "addr": "0x180012345", "skip_stubs": true, "classify": true } } { "name": "get_string_xrefs", "arguments": { "path": "…/app.exe", "filter": "ResolutionWidth" } } { "name": "get_import_xrefs", "arguments": { "path": "…/app.exe", "name": "ShellExecuteW" } } { "name": "function_at", "arguments": { "path": "…/app.exe", "addr": "0x14000d8ad" } } { "name": "function_create", "arguments": { "path": "…/app.exe", "addr": "0x14000d8ad" } } { "name": "decode_support", "arguments": {} } { "name": "decode_query", "arguments": { "query": "insn_name", "arch": "x86", "id": 1 } } { "name": "disassemble", "arguments": { "path": "…/app.exe", "addr": "0x14000d890", "count": 40, "detail": true, "syntax": "intel" } } { "name": "get_calls_from", "arguments": { "path": "…/app.exe", "addr": "0x14000d8ad" } } { "name": "unity_inventory", "arguments": { "path": "…/GameDir" } } { "name": "il2cpp_touch_map", "arguments": { "meta": "…/global-metadata.dat", "filter": "Camera" } } { "name": "il2cpp_meta", "arguments": { "path": "…/global-metadata.dat", "filter": "Camera" } } { "name": "il2cpp_map", "arguments": { "binary": "…/GameAssembly.dll", "meta": "…/global-metadata.dat", "baseline": "…/prev_map.json" } } { "name": "il2cpp_stubs", "arguments": { "binary": "…/GameAssembly.dll", "filter": "Camera" } } { "name": "decompile", "arguments": { "path": "…/GameAssembly.dll", "addr": "0x180012345", "follow_stub": true } } { "name": "analyze", "arguments": { "path": "…/app.exe", "analyzers": ["ASCII Strings", "Unicode Strings"], "gpu": true } } { "name": "inventory", "arguments": { "path": "…/InstallRoot", "max_depth": 8 } } { "name": "list_tree", "arguments": { "path": "…/GameDir", "extensions": "dll,dat" } } { "name": "rtti_query", "arguments": { "path": "…/app.exe", "filter": "Widget" } } { "name": "artifact_query", "arguments": { "id": "", "offset": 0, "limit": 64 } } { "name": "process_list", "arguments": {} } { "name": "process_attach", "arguments": { "pid": 1234 } } { "name": "process_launch", "arguments": { "image": "C:/path/to/app.exe", "args": "--flag", "cwd": "C:/path/to" } } { "name": "process_resume", "arguments": { "session_id": "…" } } { "name": "process_resolve", "arguments": { "session_id": "…", "module": "app.exe", "rva": "0x1234" } } ### 4. Optional: agent skill For tools that load skill files (Cursor, Grok, etc.), also install [skill/SKILL.md](skill/SKILL.md) so the model knows *when* to call CLI vs MCP. See [skill/README.md](skill/README.md). ### 5. Smoke-test without an IDE # Manual stdio check: start the server, then send JSON-RPC lines from your client. ./target/release/ghidrust mcp You should not need to type JSON by hand day-to-day — the IDE/agent does that once the server is registered. ## Decrypt and crypto discovery Use the discovery order **Find Crypt → recover strings → capabilities → recipe peel**. Results are evidence-based; a successful GCM recipe returns the counter-mode plaintext path but does not authenticate a tag. # Locate known cryptographic tables and likely decrypt/encoding sites ghidrust crypt-constants PATH --algo AES --json ghidrust recover-strings PATH --only stack,tight,decoded --json ghidrust crypto-capabilities PATH --tag decrypt --json # Peel explicit data or ask the bounded heuristic to try common transforms ghidrust decode bake -b64 SGVsbG8= -op FromBase64 --json ghidrust decode bake -hex CIPHERTEXT -op AESDecrypt -key-hex KEY -iv-hex IV -mode cbc --json ghidrust decode magic -b64 SGVsbG8= -depth 3 -crib Hello --json MCP equivalents are `crypt_constants`, `recover_strings`, `list_crypto_capabilities`, `decode_bake`, and `decode_magic`. See [skill/decrypt-feature-test-log.md](skill/decrypt-feature-test-log.md) for the tested feature matrix. ## Architecture ┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ ghidrust-gui│ │ ghidrust-cli │ │ MCP stdio │ └──────┬──────┘ └────────┬─────────┘ └────────┬────────┘ ▼ ┌─────────────────┐ │ ghidrust-core │ loaders, disasm, analyzers, bulk GPU └────────┬────────┘ ▼ ┌──────────────┬─────┴──────┬──────────────┐ │ │ │ │ ┌──────────┐ ┌─────────────┐ ┌────────────┐ ┌──────────────┐ │ decode │ │ lift │ │ ir │ │ ssa │ hand-rolled │ Capstone-│→│ x86-64→IR │→│ pcode-like │→│ cfg/dom/DF/ │ decompile │ class 23 │ │ + flag model│ │ ops+varnode│ │ phi placement│ pipeline │ ISAs │ │ │ │ │ │ │ └──────────┘ └─────────────┘ └────────────┘ └──────────────┘ │ ▼ ┌─────────────────┐ │ ghidrust-decomp │ Stage-0 CFG→pseudo-C (oracle) │ │ Stage-0.5 IR-informed emit │ │ GPU VRAM multipass (experimental) └─────────────────┘ | Crate | Role | |-------|------| | `ghidrust-core` | PE/ELF/blob, x86-64, analyzers, imports/IAT, xrefs, projects, bulk scan | | `ghidrust-decode` | Hand-rolled Capstone-class multi-arch `Engine` (23 ISAs); no Capstone/iced/zydis at runtime | | `ghidrust-ir` | Architecture-neutral pcode-like IR (varnodes, ops, tagged blocks, address spaces) | | `ghidrust-lift` | x86-64 → IR semantics with flag model + `LiftCoverage` reporting | | `ghidrust-ssa` | CFG-on-IR, Cooper–Harvey–Kennedy dominators, Cytron dominance frontiers, phi placement | | `ghidrust-decomp` | Stage-0 CFG → pseudo-C (regression oracle), Stage-0.5 IR-informed emit (`ir_emit`), decompile-bench harness, experimental GPU VRAM multipass | | `ghidrust-il2cpp` | IL2CPP `global-metadata.dat` + CodeRegistration correlation + resolve stubs | | `ghidrust-unity-inventory` | Unity player layout inventory (assemblies, plugins, metadata) | | `ghidrust-cli` | CLI + MCP + benches / `gpu-decompile` / `decompile-bench` | | `ghidrust-gui` | CodeBrowser-style UI | ## Docs | Doc | Topic | |-----|--------| | [docs/GPU_DECOMPILER_RESEARCH.md](docs/GPU_DECOMPILER_RESEARCH.md) | Research paper: GPU decompile method + results | | [docs/GPU_DECOMPILE_PROCESS.md](docs/GPU_DECOMPILE_PROCESS.md) | Multipass dataflow + dump format | | [docs/GPU_ANALYZER_MATRIX.md](docs/GPU_ANALYZER_MATRIX.md) | Per-analyzer GPU strategy + bench CLI | | [docs/PARALLEL_RE_RESEARCH.md](docs/PARALLEL_RE_RESEARCH.md) | CPU pool vs GPU bulk RE | | [docs/IL2CPP.md](docs/IL2CPP.md) | IL2CPP metadata matrix + Unity player inventory | | [skill/README.md](skill/README.md) | Agent skill install | ## License [Apache License 2.0](LICENSE) — same license as [Ghidra](https://github.com/NationalSecurityAgency/ghidra).
标签:Rust, 二进制分析, 云安全运维, 云资产清单, 信息收集, 反编译器, 可视化界面, 网络流量审计, 逆向工程, 通知系统