Writing an IL2CPP Runtime RE Framework for VRChat
vrc-runtime-re is an IL2CPP runtime memory reverse-engineering framework for the VRChat client. Private repo, authorized research only. The goal is to see clearly what the Il2CppClass / MethodInfo / FieldInfo structures actually look like in memory once Unity is compiled down to IL2CPP. VRChat also layers on Beebyte obfuscation, which scrambles the field order, and it changes with every version. Chasing offsets by hand is too much of a grind, so I turned it into tooling.
The core idea in one line: where the bytes come from and how the bytes are interpreted should not be coupled. So I split them apart. MemoryBackend only produces raw bytes, under one uniform contract: read / modules / regions. Typed reads, pointer chains, C strings, module base lookup, and pattern scanning all sit in the layer above, indifferent to where the bytes came from. The same analysis code then runs unchanged across three backends. minidump is pure standard library, offline, invisible to EAC. Grab a dump and chew on it at your leisure while anti-cheat sees nothing. This is the one I use most. memprocfs reads dumps and VM snapshots, and can also hook into a DMA/FPGA card or Hyper-V guest memory. frida is the live-process backend, at the cost of having to turn EAC off.
On top of the bytes is Il2CppWalker, which resolves module base addresses in an ASLR-safe way, then walks classes/methods/fields. All layout knowledge is collected in one place, Il2CppOffsets, so switching versions only touches this file. Above that sits a pile of probes, each answering exactly one question: recover field names/offsets/types, scan for live instances, dump field values, crawl the object graph N levels along references. A snapshot differ diffs two frozen snapshots directly at the IL2CPP object level, with no hooks attached. Two RAM snapshots are enough to watch changes under EAC.
The most annoying part is that Beebyte reshuffles the layout on every update, so I wrote il2cpp/autodetect.py, which self-heals and re-identifies offsets for new builds. It has been validated against the June 5 baseline so far. The flow: take the EAC-safe path to grab memory, run autodetect to recover the offsets, generate the new Il2CppOffsets for that version, and the backend and walker line up with it without a single line changed.
The core has zero third-party dependencies; minidump only needs the standard library, and you only install the corresponding packages when you want memprocfs / frida. The target is x64 Windows, little-endian. Right now the backend abstraction, walker, offset self-check, and field type recovery all work; the instance scanner is still being polished, and the recovered field types get fed straight back into another static deobfuscation project of mine. String cross-references, singleton lookup, and a unified CLI are still on the way.