Files
reverse-engineering-anything/.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md
T
4ef916da03 feat(pe): inspect import and delay-load tables (#6509)
* feat(pe): inspect import and delay-load tables

Add inspect_pe_imports / inspect-pe-imports to read PE32/PE32+ import
and delay-load directories without executing the image. The report keeps
DLL names, named and ordinal functions, ILT/IAT RVAs, and a pefile
import hash of the standard import table. A missing directory is
observed absence, not proof the image never imported APIs.

* fix(pe): default PE import fixture options

Allow peImportImage() without an argument so CLI and filesystem tests
can use the KERNEL32 sample without repeating an empty options object.

* test(pe): keep import path cases on the dedicated MCP contract

inspect_pe_imports already rejects relative MCP paths in its own
boundary test. Leave the shared absolute-path matrix to tools whose
handler issue projection matches that suite's expected shape.

* fix(native): index virtual-to-file mapping lookups

mappedFileOffset scans every mapping twice per span, so a parser that
translates one span per table entry costs sections x entries. Add
fileMappingLookup, which builds an O(n log n) interval index once and
answers each span in O(log n) with the same accept, reject and
translation results. A differential test checks it against
mappedFileOffset over randomized overlapping mappings and zero fills.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g

* fix(pe): report partial import evidence and exact pefile hashes

- Withhold imphash with an explicit reason whenever the standard import
  table is partial (unreadable names or thunks, missing tables), or when
  pefile 2024.8.26 would hash a different row sequence: invalid or
  truncated names, ordinal 0, descriptors without functions, tables its
  bounds or repeat/spread heuristics discard, and its 8192-thunk import
  symbol cap. Delay-load issues do not withhold it.
- Hash ordinal imports with pefile's complete ordlookup tables and its
  ord<decimal> fallback instead of declining unmapped ordinals.
- Report a nonterminal descriptor whose FirstThunk is zero, and a
  delay-load descriptor whose IAT or INT RVA is zero, as malformed_entry
  partial coverage instead of a complete empty inventory.
- Directory evidence lists the file spans actually consumed for the
  descriptor array and terminator; discontiguous mappings produce
  separate spans and separate Evidence ranges.
- Carry exhausted limits as PeImportLimitFailure.limit and derive
  recovery from it; the fixed 16 MiB retained-text ceiling reports a
  fixed allowance instead of max_file_bytes advice.
- Translate RVAs through the indexed mapping lookup and yield with a
  cancellation check every 1024 table entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g

* fix(pe): read only own ordinal tables for DLL names

DLL names such as constructor and __proto__ pass pefile's name rule but
resolved inherited object members, throwing before the ord<n> fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g

* fix(native): preserve PE import facts and prove hash compatibility

* test(native): verify PE import workflows and measured costs

* refactor(native): narrow PE facts across the container union

* docs(native): record integrated PE import validation

* fix(native): bound every PE import RVA span

* docs(native): measure RVA guard completed workflows

* fix(pe): reconcile import coverage with retained rows

* fix(pe): retain partial imports at descriptor mapping gaps

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 11:44:12 +08:00

34 KiB
Raw Blame History

Native, managed, and packaged artifacts

For release comparisons, export list_procedures Evidence from each target before closing it. Close clears session records: import both bundles after collecting the two targets, or supply portable inline Evidence. match_native_functions pairs unique exact names and, when supplied, complete observed body bytes. Reuse optional same-context list_names, procedure_info, read_bytes and existing analyze_function dossiers as left_observations/right_observations; an MCP analyze_function summary reply contributes its parent_evidence_id as a retained-evidence reference, not the summary itself. Avoid decompiling every function merely to match it. Its summary retains a parent for inspect_analysis_view function-matches collections matches and functions. Select columns, batch IDs and page individual facts; aliases remain unresolved. Unpaired observations do not prove additions/removals. Existing matched dossier pairs include inputs for compare_functions; otherwise analyze just chosen pairs.

Apple app resources

Use open_bundle_resources with the selected app path, then inspect_plist, decode_interface_builder, inspect_asset_catalog, or inspect_keyed_archive. The resource session reads the app without resolving CFBundleExecutable or starting a deep provider. Preserve resource_root provenance, per-resource hashes where reported, and null executable identity; a directory path is not an executable digest. Export retained Evidence before closing or switching roots. Binary analysis snapshots do not apply. Use open_binary to switch to executable analysis, and close_binary to release either session kind.

The four matching CLI commands accept the app path directly. For an archive inside the app, use inspect-keyed-archive APP_PATH RELATIVE_ARCHIVE_PATH. Host requirements for plist and compiled asset/Interface Builder tooling still apply; a resource-only session does not establish provider availability.

Desktop installation directories

When an installation directory is supplied and its runtime is unknown, use inspect_desktop_application with its absolute path. Default MCP summary delivery retains complete Evidence. Read files, omissions, candidates, components or next_probes with inspect_analysis_view kind desktop-application, selecting exact paths, batched file/omission IDs or families and only needed fields and pages. Summary probe_issues retains counts and bounded previews. Select files with has_issues: true and fields path, read_status, issues to retrieve exact failures directly; preview text is display data, while file_id selects full facts. Preserve source coverage, read-range identity and unknowns; directory snapshot identity is not a digest of every file's contents. Component path markers do not establish runtime presence. For compact CLI output, use inspect-desktop-application PATH --detail summary --evidence_output BUNDLE. See desktop installations.

Go build metadata

Use inspect_go_binary for an explicit local ELF, PE or Mach-O (universal files need architecture) when the question concerns the embedded compiler version, module/dependency versions, local replacements or build settings. No open_binary, Go installation or target execution is required. The CLI equivalent is inspect-go-binary PATH. Preserve artifact SHA-256, original file ranges, framed module bytes and every unparsed module-text line. A missing record is an unknown, not proof of a non-Go binary; observed metadata does not authenticate its claims. Function, source and type recovery remain a separate native-analysis question.

Model files

Use inspect_model_artifact (inspect-model-artifact PATH) for local GGUF v2/v3 and safetensors declarations without a model runtime. Header-only mode does not read weights or establish full-file identity. hash: "full" explicitly streams all bytes. Retained model-artifact views page metadata, tensors and derived types, with exact batch filters and selected fields. Arrays retain typed counts and eight-element previews; omitted values, unknown types and runtime behavior stay explicit. See model files.

IL2CPP metadata

Use inspect_il2cpp_metadata for an explicit local Unity global-metadata.dat (versions 24, 27, 29, 31 and 39) when the question concerns assembly images, names, member owners, string literals, namespaces or index ranges. No open_binary, Unity installation or target execution is required. The CLI equivalent is inspect-il2cpp-metadata PATH. MCP defaults to counts with complete retained Evidence. Query sections, images, types, methods, fields, properties, events, parameters or string_literals through inspect_analysis_view; use exact names, batch indices and selected fields. Row indices are scoped by artifact SHA-256 and collection; page offsets count filtered matches. Parameters support batch method_indices to read one method's parameters directly. Historical reports without member collections retain unknown counts rather than empty inventories. Preserve artifact SHA-256 and index widths. Unrecognized magic may mean encryption and is unsupported, not decrypted. Linking names to GameAssembly or UnityFramework code addresses remains a separate native-analysis question. See IL2CPP metadata.

Rust dependency metadata

Use inspect_rust_binary for an explicit local ELF, PE, or Mach-O (universal files need architecture) when the question concerns the cargo-auditable crate list embedded in .dep-v0 (Mach-O: __DATA,.dep-v0). No open_binary, Rust installation, or target execution is required. The CLI equivalent is inspect-rust-binary PATH. Preserve artifact SHA-256, package order, dependency indices, and the section file range. A missing section is null metadata, not proof the binary has no dependencies. An omitted package kind stays null. A rustc commit hash is inferred from a read-only /rustc/<40-hex>/ path and does not by itself identify the compiler. See Rust binaries.

PE Authenticode certificate tables

Use inspect_pe_certificates for an explicit local PE32/PE32+ image when the question concerns the Authenticode certificate table, WIN_CERTIFICATE types, or embedded PKCS#7 signer and X.509 identity fields. No open_binary, Windows SDK, or target execution is required. The CLI equivalent is inspect-pe-certificates PATH. Preserve artifact SHA-256, table file ranges, payload hashes, original validity-time spellings, and subject_key_identifier_hex when the signer uses that form. A missing IMAGE_DIRECTORY_ENTRY_SECURITY directory is observed absence of that table, not proof the image is unsigned in every catalog or overlay sense. Signatures, chains, timestamps, and Authenticode digest coverage remain unobserved. See PE Authenticode certificate tables.

PE import and delay-load tables

Use inspect_pe_imports for an explicit local PE32/PE32+ image when the question concerns imported DLL and function names, ordinals, delay-load descriptors, or the pefile import hash. No open_binary, Windows SDK, or target execution is required. The CLI equivalent is inspect-pe-imports PATH. Preserve artifact SHA-256, directory file ranges, original DLL spellings, and ILT/IAT RVAs. A missing IMAGE_DIRECTORY_ENTRY_IMPORT directory is observed absence of that table, not proof the image never imported APIs through another table or overlay. Bound snapshots, loaded IAT contents, and export-forward resolution remain unobserved. See PE import and delay-load tables.

ELF note tables

Use inspect_elf_notes for an explicit local ELF32/ELF64 image when the question concerns PT_NOTE/SHT_NOTE owners, GNU build-id, or GNU ABI-tag fields. No open_binary or target execution is required. The CLI equivalent is inspect-elf-notes PATH. Preserve artifact SHA-256, table file ranges, descriptor hashes, and original owner spellings. A missing table is observed absence of those declarations, not proof the image never carried notes in another container. See ELF note tables.

CPython pyc files

Use inspect_python_pyc for an explicit local CPython 3.7–3.13 .pyc when the question concerns the header magic, PEP 552 source hash or timestamp, nested code-object names, or bytecode identity. No open_binary, Python installation, or target execution is required. The CLI equivalent is inspect-python-pyc PATH. Preserve artifact SHA-256, the 16-byte header fields, nested code names, and bytecode SHA-256. Bytecode is not decompiled. A decoded header does not prove the matching .py is present. See CPython pyc inspection.

Erlang BEAM files

Use inspect_erlang_beam for an explicit local FOR1/BEAM file when the question concerns IFF chunks, atom names, exports, imports, lambdas, or the Code header. No open_binary, Erlang installation, or bytecode execution is required. The CLI equivalent is inspect-erlang-beam PATH. Preserve artifact SHA-256, chunk file ranges, 1-based atom indices, and original atom spellings. Missing optional tables stay null. See Erlang BEAM files.

SQLite snapshots

Use inspect_sqlite_database with an explicit local database snapshot for its schema and optional rows from one exact ordinary table. It requires Node.js 24.x >=24.15 or 26+ with the native DatabaseSync.limits API. It also consumes the existing sibling -wal; retain both original digests when citing its result. Default output is a compact inventory; a selected table expands only its own schema and samples 20 rows. Select columns to avoid irrelevant or large cells, and request schema_scope: "database" only for complete schema details. Choose row_limit when a finite sample is useful and keep truncation and unspecified row order explicit. Virtual tables, shadow tables and views are schema facts, not row-read targets. REA inspects private copies and leaves the source files untouched; obtain a coherent quiescent database/WAL snapshot before inspection. See SQLite snapshots.

Recorded Linux crashes

Use inspect_recorded_crash with an explicit Linux x86-64 ELF core path to inspect historical thread registers, signals, raw notes and original file ranges. It is independent of the active disassembler target. Source-bound register values and note bytes are observations; missing notes, signal-thread association and current executable/library identity remain unknown. PIDs are historical metadata and never authorize live attach or control.

The optional include_debugger_context facet adds mapping candidates through caller-supplied GDB/pwndbg in an owned core-only session. Display names do not establish current file identity; zero reported flags leave permissions unknown. Requested unavailable context fails with setup guidance. See recorded crashes for exact upstream profiles, bounds and verification coverage.

Offline ELF layout

Use inspect_binary_layout with an explicit local ELF path for file-backed sections, symbols, relocations, linkage names, and static mitigation inferences without opening a disassembler target. When that complete record is already retained, call inspect_analysis_view for a summary, mitigations or linkage facet, one section or symbol, or a stable page. Do not re-run the decoder to read a single object.

Offline WASM

Use inspect_wasm_artifact with caller-supplied WABT for selected local bytes. For counts, validation and WAT identity, select detail: "summary" on the first MCP call. The complete original Evidence stays retained; use normalized_result.parent_evidence_id for exact exports or text pages. Omitted or complete detail keeps the existing complete result. For a completed result, use inspect_analysis_view with its reported retained reference for a summary or view: {kind: "wasm", facet: "exports", offset: 0, limit: 32}. Facets also include sections, imports, candidates, glue, WAT, headers, details and tool profile. Text offsets count UTF-16 code units; follow next_offset. The complete source remains retained after an oversized MCP reply. No target execution or network acquisition is implied, and WAT is decoded representation.

Offline APK signatures

Use inspect_apk_signature for a selected local APK/ZIP/AAB. Default MCP summaries retain complete Evidence. Select view.collection: signers/digests/lineage, with scheme or ID batches, fields and paging; use inspect_analysis_view kind apk-signature for retained reads after deletion. IDs retain artifact/scheme scope and signer links; fields: [] keeps identity links. Empty pages preserve partial decoding reasons and unknown authenticity. CLI compact delivery needs --evidence_output to preserve the complete parent. It reads the APK Signing Block (v2/v3/v3.1) and v1 META-INF signing without executing anything, and reports each signer's certificate facts (for v1, the certificate the PKCS#7 block's SignerInfo names), the declared v3 rotation lineage, the declared source-stamp certificate and, for SHA-256/SHA-512 digests, whether the declared content digest matches the current bytes. That match is not a signature verification: anyone who changes the bytes can recompute the digest. posture summarises v1-only signing (which cannot tell a v1-only APK from one whose v2/v3 block was removed), observed signer agreement across schemes, whether the v1 signer equals the block-scheme signer (false is notable), whether every differing signer appears in a declared (unverified) rotation lineage, and the strongest scheme. It never claims authenticity: no signature or lineage is cryptographically verified.

Native targets

After open_binary, use focused search, procedure, or function tools directly. Use binary_overview when target metadata or inventory context helps answer the question. Prefer literal search, names, decompilation, callers, callees, and cross-references. Addresses and recovered pseudocode are analysis observations, not original source. Provider unavailability and unsupported metadata remain unknown rather than false.

For a completed analyze_function dossier, use inspect_analysis_view with view: {kind: "native", facet: "value_flow_operations", offset: 0, limit: 32} and the exact retained Evidence ID to read selected facts without reanalysis. The default MCP reply is already a summary of that dossier: its normalized_result.parent_evidence_id is the retained ID to page, and its null counts mark facets the provider did not record or declared unavailable. Native facets also include procedure, pseudocode, assembly, basic blocks, comments, callers/callees, references, unresolved calls, referenced strings and names, the native API record, and value-flow summaries. Pseudocode offsets and limits count UTF-16 code units; use the returned next_offset for continuation. Provider limitations and unavailable facts remain explicit; the complete parent Evidence is retained.

inspect_macho on a large framework returns megabytes of imports and exports. Select detail: "summary" for slice identity, UUID and per-collection counts, then page rows with view: {kind: "macho", facet: "exports", offset: 0, limit: 64} and normalized_result.parent_evidence_id. Facets are entrypoints, architectures, build_metadata, load_commands, dependencies, imports, exports, segments and provenance. source_exhaustive: false means unreturned symbols may exist.

To see which functions or Objective-C methods a Mach-O actually calls in one run, use observe_native_calls with explicit breakpoints and a bounded duration_ms/max_events. It launches a new process under LLDB, so the target runs and may change files or use the network. Hardened-runtime targets need the get-task-allow entitlement. Function breakpoints use exact LLDB runtime names: a Darwin C _main static symbol may be main at runtime. REA does not translate names. Set module to the image file name when selecting that image only; otherwise loaded system images also match. Inspect retained locations and module paths before attributing a call.

Use binary_session with no arguments to check the open target, selected provider, and alignment. Its default result.tool_availability carries a complete inventory grouped by shared facts. Expand each group's names and inherit the inventory-level client requirements unless a group overrides them; availability, reasons, remediation, modes, and flags remain inline. The effects and annotations arrays name true flags from fixed vocabularies, so an omitted known flag is false. tools/list remains the canonical source for full tool schemas when target or provider state changes.

Provider capability groups carry provider identity and ordered limitations. Prepend each set's shared_limitations to a group's limitations to recover the operation's full ordered list. Candidate capabilities describe possible providers. Top-level session capabilities describe the current route, and analysis_provider_binding identifies the selected provider.

Ghidra startup deadline recovery

provider_timeout during the first Ghidra query can cover import, auto-analysis, bridge startup, and readiness. The default 330,000 ms is configurable through REA_GHIDRA_STARTUP_TIMEOUT_MS; a smaller query still needs the same cold import.

Preserve useful Evidence before closing the session or restarting REA. Check close_binary and resolve reported cleanup failures. Set a larger startup budget in the environment that launches REA, then restart REA and reconnect the MCP client before reopening the same target. Closing and reopening a binary in the existing server keeps its original configuration and starts import again. Environment changes in an agent's shell do not update an already running MCP server. If its launch configuration cannot be changed, report that constraint and the exact retry setting instead of claiming a fixed technical limit.

The client's tool-call deadline must allow startup plus the requested query; server settings and progress notifications cannot override it. CLI analysis avoids the MCP client deadline, but retains the provider deadline. For example:

REA_GHIDRA_STARTUP_TIMEOUT_MS=1800000 rea analyze /absolute/path/to/app.exe --provider ghidra --json

Thirty minutes is an example budget, not a completion guarantee. Keep host CPU and memory controls in place. Disable specific expensive analyzers only when their missing coverage is acceptable and retain the resulting limitations. Exported C and embedded resources remain useful independent evidence, but a timeout does not establish complete analysis or absence of code. See the deadline and client guide.

Bridge request ceiling

Hopper and Cutter share REA_BRIDGE_MAX_REQUEST_BYTES. Unset, both sides use 16777216 bytes. The payload budget excludes the terminating LF. A decimal integer from 7464 to 536870887 raises or lowers that ceiling. The floor fits the largest bounded symbol-name command. A tight Cutter status still returns its session id and up to 64 completion receipts. Its path is included when it fits, and is unknown when it does not, so an older descriptor path is not paired with the new generation. The maximum is the encoded payload, one byte under Node's string ceiling so the framing LF still fits. Cutter measures, signs, and writes a fitting response in bounded chunks. The bridge searches only the newly read bytes for the framing LF. The client unescapes each socket chunk into one response string before parsing it, so this ceiling does not keep the paged wire frame and another concatenated copy. Invalid values are configuration errors and do not fall back to 16777216. Set the variable in the environment that starts REA, restart REA, and start Hopper or Cutter from that same environment. An out-of-band bridge without the setting stays at 16777216 bytes. The client reports that mismatch during discovery only after the hello proves a live authenticated bridge, and does not send a status request or the command. A stale descriptor is ignored. Discovery fails if any such live ceiling differs, even when another live session matches. A command response discarded for that ceiling stays an unknown execution with output_truncated. A hello that never sends its authenticated frame does not hold the accept loop. At most 8 connection threads run; a further accept is closed, and a failure to start a thread does not stop the listener. completed_connection is the longest prefix of connections that have terminated. Dense scalar replies are encoded in bounded batches. The 25000 ms Cutter request deadline and the 256-candidate discovery budget still have no runtime override.

Static memory and original file bytes

For Ghidra, read_bytes reads initialized analysis memory, including loader fixups; it does not read a running process. Check returned_bytes and complete before decoding a table. An incomplete read is missing coverage, not a zero-filled tail. Use list_segments to inspect the selected block's initialization and address-space facts, and retain unavailable facts as unknown.

Use address_to_file_offset to anchor one observed address to original file bytes. A mapping for the first address does not establish a contiguous mapping for an entire table, and loader fixups can make analysis bytes differ from source bytes. Keep source ranges and analysis-memory observations separate.

A pointer table can refer to writable slots populated by a constructor rather than directly to immutable resources. An uninitialized block or an observed zero does not establish the slot's later runtime value. Follow xrefs and the relevant writer's assembly or pseudocode; distinguish recorded assignments from inferred execution order. Do not replace unreadable bytes with zeros or conclude that a resource is absent without the necessary initialization evidence.

DOS MZ with Ghidra

For an admitted DOS MZ target, use inspect_native_load_image to check measured loaded bytes, file mappings, relocations and the entry against the immutable snapshot. Keep mismatch and unsupported explicit. Verified import covers the reported static image, not runtime DOS or PC-98 hardware behavior.

For Ghidra decompilation, procedure_pseudo_code also accepts procedure: "file-offset:0x..."; CLI rea decompile <path> --file-offset=0x... --provider ghidra resolves the source byte offset internally. An unresolved 0x-prefixed numeric procedure selector also falls back to a unique file mapping. Existing symbols and analysis addresses win; multiple mappings fail as ambiguous. Preserve the returned file-offset and address locations and raw selection observations. ELF virtual addresses are distinct from file offsets; never assume an arbitrary offset plus image base is an analysis address.

Complete function body ranges use inclusive ends and can contain gaps. Do not treat the enclosing span as code. For packed targets, retain the original and separately derived artifact identities; decompiling an unpacking stub does not recover the unpacked program.

When reading Objective-C dispatch metadata, distinguish class implementation methods from protocol requirements: class methods report null requirement flags, while decoded protocol declarations retain required and optional facts. Property attributes remain raw name/value tokens; use the property's atomicity field for the decoded N marker or the default atomic behavior. Null class/meta flags, ivar counts, atomicity, or read-only values mean the selected provider did not establish that fact. Symbol names alone do not prove that a class is a root class or has no ivars.

Managed PE/CLI

Start with inspect_managed_artifact. REA's canonical managed inspection is execution-free: do not claim it loaded, reflected, executed, or resolved the assembly. Keep managed/native boundaries and unavailable reconstruction facts explicit. A bring-your-own reconstruction oracle is separate from the canonical parser and must not become an implicit setup dependency.

For identity/classification questions, inspect_managed_artifact can explicitly select detail: "summary" on the first MCP call. It retains complete metadata and returns a linked overview with full classification/evidence, nullable module/MVID, frameworks, metadata coverage/issues/limitations and returned-row counts. Default complete requests remain unchanged. Read original rows with inspect_analysis_view, source normalized_result.parent_evidence_id, and view: {kind: "managed", collection: "attributes", offset: 0, limit: 16}. Collections are references, resources and attributes. Paging does not repeat parsing. Returned-row exhaustion does not prove complete metadata or absence under partial/unavailable coverage; preserve build-local tokens and their artifact/MVID scope.

inspect_managed_members always returns the assembly-wide member_refs, even for one selected type. For questions about a selected type, select detail: "summary" with type_names; it returns the selection (with unmatched names), coverage and per-collection counts. Page rows with view: {kind: "managed-members", collection: "call_edges", offset: 0, limit: 64} over types, exported_types, fields, methods, member_refs, call_edges, field_accesses or user_strings.

.NET NativeAOT

NativeAOT binaries contain native machine code, so ordinary CIL decompilers cannot recover the original method bodies. When managed metadata/CIL is absent, classify that as a native-analysis route rather than claiming source recovery. Open the native image with the selected deep provider and inspect functions, strings, calls, and references; describe decompiler output as pseudocode and inference.

NativeAOT images can be PE/COFF, ELF, or Mach-O executables and shared libraries. Use file bytes and loader metadata rather than suffixes to identify them. For packaged apps, inventory/extract with REA's artifact tools and retain the exact contained image identity. PDB, ELF debug, or dSYM sidecars are additional evidence only when the provider accepts and matches them.

REA has a built-in read-only snapshot parser for x64 PE targets with .NET 8 RTR 9.1 metadata. An optional headless Ghidra adapter adds database annotations and broader metadata recovery on Linux; it requires an explicitly configured NativeAOT JAR. These are separate routes. The built-in parser also runs on Windows Ghidra P0; read frozen literals from its report, because search_strings does not include them. See the NativeAOT guide for setup, supported layouts, and host restrictions. Preserve binary identity and distinguish derived metadata from Ghidra database observations. Recovered types and native pseudocode are not original C# source. Windows Ghidra P0 has no database mutation authority.

Packages and extraction

Use inspect_artifact for application bundles, archives, ZIP/APK/IPA/MSIX/AppX, ASAR, or DMG inputs when the artifact graph and findings help answer the question. It returns the complete artifact graph inline. Cite graph manifest IDs when using them.

For an IPA or a macOS .app, ZIP, or DMG, pass the inventory Evidence to project_apple_application_graph. It reports application roots and nested bundles by path convention: app extensions, XPC services, frameworks, login items, system and driver extensions, and plug-ins. It also lists privileged helpers, launchd plists, symlinks, and each bundle's info_plist_path and executable candidates. Roles are path conventions, not parsed plists; read the listed plists with inspect_plist.

After open_binary on a .app or Mach-O, use trace_dylib_resolution to see which file each @rpath, @loader_path and @executable_path load reaches for every executable in the bundle. It also lists missing or weak loads and earlier @rpath candidates that are absent. Narrow large bundles with roots or architecture. System paths stay undetermined because the dyld shared cache provides them.

Use extract_artifact when materialized files from a supported format are needed. It extracts the active target and accepts optional integrity_policy; see the MCP contracts. It materializes all regular files into a fresh temporary directory chosen by REA. Symlinks and encrypted entries are inventory facts, not extractable files. The result reports the materialized directory; callers do not choose the destination. No separate permission grant is needed.

Native DMG traversal automatically uses a read-only mount on supported macOS hosts, with an owned temporary mount directory and cleanup. It needs no approval flag. Unsupported hosts or mount failures remain explicit limitations; do not claim child inventory when only root identity is available. DMG extraction is unavailable through extract_artifact. To access DMG files on macOS, create a read-only mount with your own tools, select files from that mount for analysis, and detach the mount you created when finished. REA's inspection mount is temporary, not a retained export of the image's contents.

For headerless DOS COM, explicitly open with format: "dos-com" (CLI --target-format dos-com). Inspect the load image before trusting function analysis: the entry is 0x10100, file offset zero, with imposed real-mode segment context. PSP/stack/device state remains unmodeled. See DOS guide.

Use inspect_byte_entropy to triage high- and low-entropy ranges before extraction.

For other headerless images (embedded firmware without ELF/Mach-O/PE/MZ headers), open with format: "raw-binary", architecture (x86, x86_64, arm, arm64, 6502, or m68k), and entry_point (0x hex). File offset 0 is mapped at that address. Hopper and IDA refuse this interpretation; Ghidra uses BinaryLoader with a generic language: big-endian for m68k, little-endian otherwise. Big-endian ARM, Thumb-only, and Cortex-M variants are unsupported. 6502 selects NMOS 6502; the entry and complete file mapping must fit within 0x0000..0xffff. 65C02, 65816, cartridge containers, bank switching, and mapper semantics are unsupported. m68k requires an even entry and decodes the 68040 superset of the 68000 family; Amiga/Atari containers and vector-table entry discovery are unsupported. Windows Ghidra P0 admits raw images only for 6502. See raw binary guide.

Function annotations in Ghidra

Use annotate_native_function for one function name and/or entry comments, with at least one explicit change. Review its annotation readback and refreshed dossier inline. Changes are atomic and session-scoped; empty comments clear them, omitted fields preserve them. Later MCP calls observe edits until close. CLI annotate-native-function returns the updated analysis before discarding the session. Original executable bytes are unchanged; edits invalidate immutable snapshots. Windows P0 does not admit database mutations. For naming only, set_address_name / set_addresses_names also work with Ghidra: they name function entries or data addresses (primary labels) and return compact per-address success booleans instead of a dossier.

Offline PE resource inventory

Use inspect_pe_resources with an absolute path, or rea inspect-pe-resources ./selected.exe --json, for portable PE32/PE32+ resource inspection without opening a native target. Preserve returned Evidence: type/name/language IDs and UTF-16 names, original directory/data/payload ranges, code pages, payload hashes and static icon-group references. Same-language icon resolution is explicit; missing references and size mismatch remain visible. Other payloads are opaque, and this operation does not decode images or simulate Windows resource loading. Consult the budgets and supported tree profile in offline binary diagnostics.

Offline PE and ELF export tables

Use inspect_native_exports with an absolute path, or rea inspect-native-exports ./libexample.so --json, to read a PE export directory or ELF dynamic symbol table on any host without opening a native target. Ordinal-only, forwarded and hidden-version exports stay distinct; partial or unsupported coverage means the inventory is incomplete, not that exports are absent. Use inspect_macho for Mach-O. See offline binary diagnostics.

For exact core-module import/export differences, use compare_wasm_interfaces with two complete inspection Evidence records (or current-session retained references) and explicit scope. Preserve unknown types/duplicate names; static interface equality is not runtime compatibility. CLI accepts complete inline Evidence in rea compare-wasm-interfaces input.json --json.

Godot PCK

For a standalone PCK, open_binary then inspect_artifact with detail: "summary" retains the complete static inventory. Use the returned parent_evidence_id with inspect_analysis_view inventory occurrences filtered by exact logical_paths or occurrence_ids, and join artifact_id to nodes filtered by artifact_ids. Select only needed fields; identity links remain. Prefer inspect-artifact --detail summary --evidence_output PATH for CLI tasks; the same CLI discovers embedded packs via their EOF trailer without opening a native analysis provider. Normal native opening remains unchanged.

Distinguish declared MD5 from observed SHA-256 and graph/page completeness from source_coverage. Encrypted directories and sparse bundles have unknown entry coverage; encrypted members have unknown content identity. An empty filtered page cannot prove absence in unknown coverage. Retained views are historical, not fresh filesystem checks. No decryption, Godot resource decoding, GDScript decompilation or target execution is provided. See Godot PCK.