feat(ghidra): reuse existing projects through verified copies (#7236)

Reuse selected Ghidra projects through verified private read-only copies, with shared CLI/MCP configuration, committed project identity, import-SHA verification and explicit historical/unknown analysis semantics. Preserve exact cancellation and platform capability boundaries.

Actual Ghidra 12.1.4/JDK21 Linux CLI/MCP investigations matched fresh import on 652-function ls and 14,338-function libcrypto inventories and pseudocode; authenticated complete Evidence, mismatch/staleness refusal, saved historical reports and shared /tmp projects verified. 958 focused tests passed with four platform skips; build/static/docs/format passed. Real macOS/Windows reuse remains unverified; Windows reuse is unavailable. See PR verification for measured whole-task costs and final CI attribution.

Co-authored-by: akushonkamen <akushonkamen@163.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-10-26 22:31:13 +08:00
1 parent 49816235f5
commit 19447516a4
26 files changed
+2215 -136

No files matched your search

+62 -4
View File
@@ -1160,9 +1160,10 @@ This coordinate selects only REA's session-private configuration directory, not
the installation or an existing user configuration directory.
Each verified session uses an ephemeral temporary project and isolated
home/cache/config/temp paths. REA passes `-readOnly`, `-deleteProject`, uses
Ghidra's default analysis settings, and loads its packaged Java
bridge via `-scriptPath`; it never opens an existing user project. Linux and
home/cache/config/temp paths. By default REA passes `-readOnly`, `-deleteProject`,
uses Ghidra's default analysis settings, and loads its packaged Java
bridge via `-scriptPath` into a new ephemeral project; opt-in
[existing-project reuse](#reuse-an-existing-ghidra-project) opens only an owned copy. Linux and
macOS use a current-user-only local bridge socket and descriptor. The
project remains under the selected temporary directory. If its Unix socket
pathname would exceed the host's byte limit, REA allocates a separate owner-only
@@ -1181,7 +1182,7 @@ original process owner for a later cleanup retry.
The experimental Windows transport uses authenticated IPv4 loopback with a
private native-owned bearer descriptor and Job Object process ownership.
Operations begin only after default auto-analysis completes. `open_binary`
In the default fresh-import mode, operations begin only after default auto-analysis completes. `open_binary`
selects and validates the target/provider binding; it does not wait for Ghidra
import and auto-analysis. The first Ghidra-backed query starts that work lazily.
The provider startup deadline is 330,000 ms by default for import, analysis,
@@ -1312,6 +1313,63 @@ not needed for the make step, only for the Ghidra provider. If your toolchain
rejects the inherited `-mmacosx-version-min=10.6` flag, retry the make with
`ADDITIONAL_FLAGS="-w"`.
### Reuse an existing Ghidra project
For repeated investigations, select an expanded local project marker with
`REA_GHIDRA_PROJECT_PATH=/absolute/projects/app-analysis.gpr`. Both CLI and MCP
use this shared selection. `REA_GHIDRA_PROGRAM_NAME` selects one exact program
in the project root; when omitted it defaults to the selected target's filename.
Paths, globs and command flags are not program names. The matching `.rep`
directory must be present; restore `.grez` archives with Ghidra first.
```bash
export REA_ANALYSIS_PROVIDER=ghidra
export REA_GHIDRA_PROJECT_PATH=/absolute/projects/app-analysis.gpr
export REA_GHIDRA_PROGRAM_NAME=app
rea decompile /absolute/target/app --procedure entry --provider ghidra --json
```
Set the same variables in the MCP server environment and restart/reconnect;
`open_binary` still selects the original target file. `rea setup` retains these
explicit settings in a saved registration. Fresh import remains the default
when the project setting is absent. This route supports native ELF, PE and
Mach-O programs on POSIX without provider-pinned import preparation; Windows,
raw/DOS/DOL and special pinned-language import profiles require fresh import.
REA fingerprints only the selected `.gpr`/`.rep` pair, copies it into its owned
runtime, verifies the copied content against the committed analysis profile,
and runs `-process <program> -noanalysis -readOnly`. Ghidra never opens or saves
the original database; REA reads selected files only for fingerprinting and copying.
This mode does not copy unrelated sibling projects, rerun repair scripts, or
admit bridge database edits. Cleanup removes the owned copy.
The bridge checks the program's recorded import SHA-256 against the admitted
target digest; mismatches and project changes fail explicitly. Reopen the target
to resolve a new profile after intentionally changing the source project.
The profile records the caller path, resolved project/name, program and content
fingerprint. Original analysis settings and completeness remain **unknown**;
prior annotations or edits are caller-project state, not fresh REA discoveries.
A matching recorded import digest does not claim that the database is unedited.
Saved REA seed/analyzer reports remain historical facts in retained source Evidence;
they are not interpreted as overrides applied by this session.
Project content participates in snapshot identity, so different project states
cannot reuse the same profile's cached observations.
To prepare a new project explicitly, use your existing Ghidra installation in a
new directory you own (this writes that project; REA does not save it for you):
```bash
mkdir /absolute/new-projects
GHIDRA_HEADLESS_MAXMEM=1536M JAVA_TOOL_OPTIONS=-XX:ActiveProcessorCount=2 \
"$GHIDRA_INSTALL_DIR/support/analyzeHeadless" /absolute/new-projects app-analysis \
-import /absolute/target/app -analysisTimeoutPerFile 600 -max-cpu 2
```
Check that preparation completed successfully before selecting the project.
Preparation time, disk copy/fingerprinting, engine startup and client deadlines
are separate costs; reusing a project avoids import/analysis, not all startup.
Use the [heap/CPU controls](#ghidra-heap-and-cpu-controls) appropriate to the target.
### Ghidra import language and analysis seeds
Ghidra detects the language from the executable header. To set it (for example, Borland C++ PE images):
+6
View File
@@ -1000,6 +1000,12 @@ A successful MCP initialize handshake establishes the REA connection.
that Ghidra has finished importing the target. The first Ghidra-backed query,
such as `binary_overview`, starts the engine and waits for import, default
auto-analysis, bridge connection, and health readiness before returning analysis.
With `REA_GHIDRA_PROJECT_PATH`, shared CLI/MCP configuration instead selects an
[existing project copy](installation.md#reuse-an-existing-ghidra-project), whose
content fingerprint is committed into the profile. Import, auto-analysis and
repair scripts are skipped; original analysis completeness/settings stay unknown,
and bridge database edits are unavailable. The same startup/client deadlines
still cover copy verification, engine launch and the authenticated handshake.
These deadlines have different owners: