This repo is currently in development and is not ready for production use.
Windows ONLY
I wrote it in a single day with 15 hours of work.
A lightweight Rust library for discovering and navigating IL2CPP metadata at runtime. It provides a safe-ish Rust façade over the IL2CPP C API, and builds a cache of assemblies, classes, fields, and methods with a modern ownership model for convenient querying and printing.
Note: This repo targets Windows for now and requires using an injected DLL entry for example (
DllMain) to attach to a running IL2CPP process (e.g., a Unity game).
- IL2CPP API bindings (
il2cpp::il2cpp_sys) and ergonomic wrappers (il2cppmodule) - Discovery of:
- Assemblies → Classes → Fields → Methods
- Method signatures: name, flags, parameters, return type
- Field metadata: name, offset, static-ness, type
- Modern ownership model for metadata graph:
Arcshared handles for nodes (Assembly,Class,Field,Method,Type)Weakback-references (e.g.,Field/Method→Class) to avoid cycles- Thread-safe collections via
RwLock<Vec<...>>inClass
- Minimal profiling utilities to time code paths (
profile_scope!,profile_call!)
src/il2cpp/il2cpp_sys: raw FFI to IL2CPP exports (pointers, C-strings). All low-levelIl2Cpp*are represented as*mut u8handles.src/il2cpp/mod.rs: safe-ish wrappers around the FFI that return Rust types (e.g.,String,Vec<...>), and helper functions like:get_domain,thread_attach/thread_detachdomain_get_assemblies,assembly_get_imageimage_get_class_count,image_get_classclass_get_name/namespace/parentclass_get_fields,field_get_name/offset/typeclass_get_methods,method_get_name/flags/params/return_type
src/il2cpp/classes: high-level Rust model types used in the cacheClass = Arc<ClassInner>fields: RwLock<Vec<Field>>methods: RwLock<Vec<Method>>
Field = Arc<FieldInner>class: Weak<ClassInner>backref
Method = Arc<MethodInner>class: Weak<ClassInner>backref,return_type: Type
Type = Arc<TypeInner>(cacheable handle withaddress,name,size)
src/il2cpp_cache.rs: metadata discovery and hydration into the high-level typesCache::parse_assemblies(domain)Cache::parse_class(&mut Assembly, image)Cache::parse_fields(&Class)(populatesfields)Cache::parse_methods(&Class)(populatesmethods)
- Strong edges (Arc):
Assembly→Vec<Class>Class→RwLock<Vec<Field>>,RwLock<Vec<Method>>
- Weak edges (Weak):
Field.class,Method.class→Weak<ClassInner>
- Benefits:
- Avoid cycles (
Class ↔ Field/Method) - Safe cloning of handles (cheap
Arcclones) - Thread-safe reads and targeted writes (
RwLock)
- Avoid cycles (
The crate exposes a tiny profiling module for quick ad-hoc timing in dev builds.
- Scope-based timing:
profile_scope!("Cache::new");
// code to profile...- Single expression timing with result preserved:
let cache = profile_call!("Cache::new", Cache::new(domain));Printed output example:
Cache::new took 1.23ms
Implementation: see src/prof.rs (ScopeTimer) and macros exported at crate root.
- Install and build:
rustup toolchain install stable
cargo build- Standard dev build:
cargo buildExample usage of the library in a dll at https://github.com/ElCapor/il2cpp_rs-example-dll
use il2cpp_rs::il2cpp;
use il2cpp_rs::il2cpp_cache::Cache;
fn entry_point() -> Result<(), String> {
il2cpp::init("GameAssembly.dll")?;
let domain = il2cpp::get_domain()?;
il2cpp::thread_attach(domain)?;
// the cache is the structure that contains all the assemblies, classes, fields, and methods
let cache = Cache::new(domain)?;
// Debug printing is available via Debug impls
// println!("{:?}", cache);
Ok(())
}- The FFI layer manipulates raw pointers (
*mut u8) from IL2CPP. Access patterns assume the underlying engine keeps these pointers valid while attached to the domain. - Do not send handles across threads unless you’ve attached those threads to the IL2CPP domain (
thread_attach). - Avoid storing borrowed C-string pointers; convert to Rust
Stringimmediately (already handled by wrappers). - All
Arc/Weakhandles are Send/Sync only insofar as the contained data is. The raw pointer addresses are opaque and not dereferenced in safe code.
- Run
cargo fmtandcargo clippyon changes - Keep FFI wrappers minimal and well-commented
- Preserve the Arc/Weak ownership model and avoid re-introducing cycles
GNU General Public License v3.0. See LICENSE.MD for details.