Files
rea/docs/ghidra-nativeaot.md
T
morlutoandCursor Agent 5cbf06c7ad fix(ghidra): admit the 12.1 line and the install's JDK range (#840)
* fix(ghidra): admit the 12.1 line and the install's JDK range

The provider treated the verified Ghidra 12.1.4 build and JDK 21 as the only
legal installation, so a working 12.1.x package or a newer JDK was rejected
before analysis started.

Admission now follows the 12.1 release line and application.java.min/max.
A compatible build other than 12.1.4 keeps its observed version and records
that the bridge was verified against 12.1.4.

Fixes #821

* fix(ghidra): stop pinning the NativeAOT build to one version string

The build script still rejected every Ghidra release except the literal
12.1.4 and every javac except major 21. It now accepts the 12.1 line and
javac 21 or newer, compiles with --release 21, and records the observed
Ghidra version. The JADX engine version uses the audited release constant.

* fix(ghidra): report unverified builds on analysis results

Session open uses health only as a startup gate and discards that
execution, so the unverified-build limitation never reached CLI or MCP
results. Attach it to every Ghidra execution for that install.

---------

Co-authored-by: Cursor Agent <[email protected]>
2026-10-07 12:24:36 +08:00

5.6 KiB

Optional NativeAOT metadata recovery

REA integrates Washi1337/ghidra-nativeaot through an optional headless adapter. The original source is an opt-in submodule, pinned to effeb734fc570c32650f88b159608979dc7b423e; its MIT license and existing source notices are retained. No upstream source or algorithms are rewritten.

The initial tested layout is .NET runtime 8.0.22, NativeAOT RTR 9.1, x86-64 ELF and native Windows PE targets analyzed on Linux x64, using Ghidra 12.1.4 and JDK 21. The build accepts any Ghidra 12.1.x release and javac 21 or newer, and it compiles with --release 21. Real verification of this layout remains the Ghidra 12.1.4 and JDK 21 pair. Other NativeAOT layouts, architectures, and hosts are unsupported. Windows Ghidra P0 has no database mutation authority. A PE/CLI or ReadyToRun assembly should use inspect_managed_artifact; it is not NativeAOT.

Build and configure

Bring your own supported Ghidra/JDK installation. This developer build needs existing git, javac and jar; it does not invoke Gradle, download toolchains, or change host configuration:

git submodule update --init third_party/ghidra-nativeaot
npm run build:ghidra:nativeaot
export REA_GHIDRA_NATIVEAOT_JAR="$PWD/_reference/nativeaot-integration/extension/rea-ghidra-nativeaot.jar"

The build requires a clean pinned upstream checkout, compiles unchanged upstream Java plus the REA facade, uses a fresh classes directory, and writes the JAR and build manifest under ignored _reference/. REA_NATIVEAOT_BUILD_ROOT can select another local output directory; REA_NATIVEAOT_SOURCE can select an equivalent clean pinned source checkout. Neither output nor compiled fixture belongs in Git or the npm package. An installed REA accepts an existing explicitly supplied JAR.

REA commits the actual JAR SHA-256 into the analysis profile, copies identical bytes into the owned runtime, rechecks the digest before loading, and closes the classloader/project on session close. Profiles cannot enable code absent from explicit local configuration. JARs execute within Ghidra; supply a build you trust. The producer's reported source revision is build metadata, not an attestation of arbitrary caller-supplied bytes. The bounded loader accepts regular JARs up to 8 MiB to limit startup artifact memory; this does not truncate analysis results.

Use existing tools

Open the executable with provider ghidra. inspect_native_load_image returns optional observations.metadata_recovery inline, including the detected header, layout, recovery status, type category paths/addresses, diagnostics, annotation coverage and derived-memory SHA. The enclosing unsupported load-image status for PE/ELF concerns independent DOS loader verification; metadata recovery has its own status. It is not a failed import.

Pass one returned type path or its typed address to inspect_native_data_type. Its optional metadata_recovery includes related/base type, implemented interfaces and virtual slots with targets and known procedure names. Follow these with analyze_function, string searches and ordinary cross-references. For CLI use:

rea inspect-native-load-image ./NativeAotFixture --provider ghidra --json
rea inspect-native-data-type ./NativeAotFixture --type /NativeAOT/MethodTables/Class_ADDRESS_MT --provider ghidra --json
rea function ./NativeAotFixture 0xADDRESS --provider ghidra --json

No new MCP workflow or approval flag is required. Configuration opts into the adapter; without it ordinary Ghidra profiles/results remain unchanged.

Evidence boundaries

Discovery prefers an imported RTR symbol, otherwise the upstream initialized, non-executable-memory signature heuristic. REA rejects ambiguous candidates, unknown layout versions, malformed directory rows, unsupported flags and unmapped ranges before recovery. It requires the verified dehydrated layout.

The adapter performs rehydration, method-table recovery and frozen-object annotation in one ephemeral Program transaction. Fatal failure/cancellation rolls it back. Recovery may change analysis-memory bytes, never the original executable file. Derived ranges have a digest and no original file offset; they are not captured runtime state. Candidate/committed instance annotation counts distinguish partial frozen-object coverage. Coverage concerns the recovered candidate set, not every possible object or every runtime type.

REA preserves pre-recovery calling conventions and uses the loaded compiler specification default for newly created methods. The upstream universal __thiscall assignment is not treated as x64 ABI authority. Parameters and method prototypes remain inferences; verify them against instructions/call sites.

Type relationships and System.Object/System.String identification use upstream heuristics. Generated names are explicitly marked; original class/member names and custom field layouts remain unknown. Pseudocode is recovered native logic, not original C# source. Unsupported recovery reports its stage and reason; it does not imply that ordinary native disassembly/decompilation is impossible.

Verification

See the dedicated lane. Fixtures are source-built benign .NET programs with inheritance, an interface, virtual dispatch, representative arithmetic and frozen strings. Independent compiler/linker symbols and raw directory bytes provide the oracle. Stripped fixtures exercise heuristic detection. Tests do not execute the resulting NativeAOT binaries. Fixture generation and adapter compilation are optional and never prerequisites of ordinary native analysis or setup.