* 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]>
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.