Skip to content

il2cpp: wire-layout, Thumb, Frida stubs, fix-analysis, version guard, name→RVA map - #17

Closed
Diphome wants to merge 2 commits into
masterfrom
il2cpp-wire-and-frida
Closed

Diphome wants to merge 2 commits into
masterfrom
il2cpp-wire-and-frida

Conversation

@Diphome

@Diphome Diphome commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Implements the prioritized reversing-tooling list. All reuse the generated package; CLI (-m il2cpp) + MCP.

Shipped

#1/#2 — On-the-wire layout & serialization order (--il2cpp-wire-layout, Il2CppWireLayout)
Reconstructs a Request/Response layout from a decompiled Serialize/Deserialize: the ordered Write/Read/Serialize sequence (≠ field offsets), which entries are list/array elements (loop-nested), and integer length/count prefixes read ahead of a loop. The .c is symbolized first (so calls carry managed names). Dummy DLLs have no method bodies, so this reads the Ghidra decompilation — heuristic by design (reports what the code executes; bare Write/Read show ?).

#4 — ARM Thumb (exporter + index + lookup)
Method-pointer bit0 is recorded as a Thumb flag; Address is the clean even RVA and function starts are masked, so Ghidra lands correctly. Lookups surface thumb: true.

#5 — Frida stubs (--il2cpp-frida, enhanced)
Thumb-aware Interceptor.attach (.or(1)), typed arg logging from the signature, System.String decoding, self-resolved module base.

#6 — Robust Ghidra import (ghidra/il2cpp_fix_analysis.py, bundled)
Clears the bogus no-return on IL2CPP init helpers (codegen_initialize / runtime_class_init / object_new / GC_*) and re-disassembles the bodies they truncated — the classic no-return trap.

#7 — Version guardrail
il2cpp_info.json now records the binary's SHA-256, name, and size, to compare against the program open in Ghidra (get_metadata) before trusting a translation.

#8 — Compact name→RVA map (--il2cpp-map)
{name: rva} JSON (Thumb methods under a separate set) for a hook script to consume directly.

MCP: new il2cpp_map, il2cpp_wire_layout; il2cpp_frida gains Thumb handling. Server → 0.7.0. README, MCP reference, and the agent playbook updated.

Deferred (needs a real target to verify)

#3 — Custom attributes ([DataMember] / [JsonProperty] / Name=). Correct that Cpp2IL strips these from the dummy DLLs, so they must come from IL2CPP metadata (readable as a blob only on metadata v29+). That needs a LibCpp2IL metadata-attribute API I can't verify without a real v29+ game, and it touches the exporter (build risk). Planned as a focused follow-up.

Notes for reviewer

  • #1/#2 and #5 are heuristic and I couldn't run them against a real game locally — they need a smoke test on an actual target (the wire-layout verb/loop detection and the Frida ABI arg mapping especially).
  • Thumb only affects 32-bit ARM; 64-bit is unchanged.
  • Managed compile passes; the local build's only failure is the pre-existing UnityRiftFBXNative.dll copy step (binaries come from CI).

🤖 Generated with Claude Code

Diphome and others added 2 commits September 12, 2026 13:59
…lysis, version guard, map

Batch of reversing-comprehension features (CLI -m il2cpp + MCP), reusing the
generated package:

- Wire layout (--il2cpp-wire-layout, Il2CppWireLayout): reconstruct a Request/Response
  on-the-wire layout from a decompiled Serialize/Deserialize — the ordered Write/Read/
  Serialize sequence, list elements (loop-nested), and integer length/count read-aheads.
  Symbolizes the .c first; heuristic (reports what the code executes). Covers the "wire
  layout" and "serialization order != field offsets" asks.
- Thumb (exporter + index + lookup): ARM32 method pointers' bit0 is recorded as a Thumb
  flag; Address is the clean even RVA; function starts are masked. Lookups surface thumb.
- Frida stubs (--il2cpp-frida, enhanced): Thumb-aware Interceptor.attach (.or(1)), typed
  arg logging from the signature, System.String decoding, self-resolved module base.
- il2cpp_fix_analysis.py (bundled Ghidra script): clears the bogus no-return on IL2CPP
  init helpers and re-disassembles truncated bodies — the classic no-return trap.
- Version guard: SHA-256 + name + size of the binary in il2cpp_info.json, to compare with
  the program open in Ghidra.
- Compact name->RVA map (--il2cpp-map): Thumb methods listed separately, for hook scripts.

MCP: il2cpp_map, il2cpp_wire_layout; frida gains Thumb handling. Server 0.7.0.
Docs + agent playbook updated.

NOT included (needs a real v29+ game to verify the LibCpp2IL metadata-attribute API):
custom-attribute extraction ([DataMember]/[JsonProperty]/Name=). Cpp2IL strips these from
the dummy DLLs, so they must come from IL2CPP metadata — planned as a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
UnityRift now focuses on reading and converting Unity content (assets, scenes,
effects, Godot pipeline, .NET/IL2CPP inspection as C# stubs). All native
reverse-engineering of the compiled binary moves to a separate project
(unityWyvern): the Ghidra/Il2CppDumper package, decompilation helpers, Frida
hooks, and protocol/wire-layout analysis.

Removed:
- UnityRiftUtility/Il2Cpp/{Il2CppGhidraExporter, Il2CppSymbolIndex,
  Il2CppConstantResolver, Il2CppDecompCleaner, Il2CppTypesJson,
  Il2CppFridaGenerator, Il2CppWireLayout, Il2CppHeaderConstants}
- UnityRiftCLI Studio.Il2Cpp.cs, the `-m il2cpp` mode + WorkMode.Il2Cpp, and all
  --il2cpp-* analysis options (lookup/strings/decode/data/clean/suggest/field/
  enum/frida/apply-plan/map/wire-layout/fuzzy/clean-raw/dummy-dll)
- tools/ghidra/* and docs/AGENT_GHIDRA_PLAYBOOK.md
- the il2cpp_* MCP tools and the Ghidra EmbeddedResources
- the GUI "Export Ghidra / Il2CppDumper package" action

Kept (asset/Godot dependency, not reverse):
- Cpp2IL dummy-assembly generation (`--il2cpp`, Il2CppAssemblyProvider) for the
  .NET explorer, MonoBehaviour field parsing and Godot script stubs. The Ghidra
  package generation is decoupled from dummy generation.
- Dummy DLL export via `-m dotnet --dotnet-export-dll`.

CLI + GUI compile clean. The removed reverse code stays in git history and lives
in the unityWyvern project. MCP server -> 0.8.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Diphome

Diphome commented Sep 12, 2026

Copy link
Copy Markdown
Owner Author

Closing: these reverse-engineering features are moving out of public UnityRift and are maintained separately, per the assets-vs-reverse split. Preserved in git history; UnityRift's removal of the reverse layer is #18.

@Diphome Diphome closed this Sep 12, 2026
@Diphome
Diphome deleted the il2cpp-wire-and-frida branch September 14, 2026 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant