Overview of frida-il2cpp-bridge
masterglobal-metadata.dat file to function. It allows developers to interact with the C# runtime, dump classes, methods, and fields, and intercept or replace method calls.repository·master·Indexed 23 days ago
https://github.com/vfsfitvnm/frida-il2cpp-bridgeA Frida module for dumping, tracing, and hijacking Unity Il2Cpp applications at runtime without requiring the global-metadata.dat file. It supports Unity versions 5.3.0 to 6000.3.x across Android, Linux, Windows, iOS, and macOS. The package includes a CLI for extracting application metadata (classes, methods, and fields) into C# code or JSON, and provides APIs to interact with the C# runtime and the Il2Cpp Garbage Collector.
global-metadata.dat file to function. It allows developers to interact with the C# runtime, dump classes, methods, and fields, and intercept or replace method calls.Supports Unity versions in the range 5.3.0 to 6000.3.x.
Note: Only Android and Linux are officially tested; using other platforms may result in breakage.
Starting from version 0.10.0, a Python executable is included with the NPM package. This executable wraps the frida command and adds IL2CPP-specific features. You can invoke it using npx or npm exec.
npx frida-il2cpp-bridge --help
# or
npm exec frida-il2cpp-bridge -- --helpUse the dump subcommand to extract application metadata (classes, methods, etc.) without needing the metadata file. You can specify the output directory and the C# output style.
npm exec frida-il2cpp-bridge -- -f com.example.application dump --out-dir dumpsFor contributors wanting to test changes locally on Linux (x86_64), you can build specific IL2CPP assemblies and run tests.
Prerequisites:
clang and make installed.# Build IL2CPP assembly (GameAssembly.so) for a specific Unity version
make assembly UNITY_VERSION=6000.3.10f1
# Run test on each assembly
make testTo test on non-Linux or different architectures, use the provided Dockerfile. This allows creating a container with the necessary Unity editor artifacts.
Prerequisites:
Specify the Unity version via UNITY_VERSION.
Use make testd to run tests on each Docker image.
# Build Docker image for a specific Unity version
make image UNITY_VERSION=2023.2.20f1
# Run tests on each Docker image
make testdThe base property on an Il2Cpp.Object allows you to access members of the parent class. This is useful when a subclass has shadowed or overridden a member (field or method) and you need to interact with the original implementation in the base class. It behaves similarly to the C# base keyword.
Example
If Bar inherits from Foo and both have a method foo():
const Bar: Il2Cpp.Class = ...;
const bar = Bar.new();
console.log(bar.foo()); // Returns the implementation in Bar
console.log(bar.base.foo()); // Returns the implementation in Fooconst Bar: Il2Cpp.Class = ...;
const bar = Bar.new();
console.log(bar.foo()); // 2
console.log(bar.base.foo()); // 1When working with instance methods, you can use .bind(instance) to create an Il2Cpp.BoundMethod. A bound method is a proxy that automatically passes the assigned instance as the this pointer, allowing you to call .invoke() without manually providing the object every time.
const object: Il2Cpp.Object = Il2Cpp.string("Hello, world!").object;
const GetLength: Il2Cpp.BoundMethod<number> = object.method<number>("GetLength");
// No need to pass the object when invoking!
const length = GetLength.invoke(); // 13The Tracer class uses a fluent builder API to define which methods should be instrumented. You must chain selection methods and terminate with .and() to commit the selection before calling .attach().
thread(thread: Il2Cpp.Thread): Restrict tracing to a specific thread.verbose(value: boolean): If true, duplicate log messages are printed. If false, duplicate messages are filtered using a hash.domain(): Target all methods within the current Il2Cpp.domain.assemblies(...assemblies: Il2Cpp.Assembly[]): Target specific assemblies.classes(...classes: Il2Cpp.Class[]): Target specific classes.methods(...methods: Il2Cpp.Method[]): Target specific methods.You can narrow down targets using filters:
filterAssemblies(filter: (assembly: Il2Cpp.Assembly) => boolean)filterClasses(filter: (klass: Il2Cpp.Class) => boolean)filterMethods(filter: (method: Il2Cpp.Method) => boolean)filterParameters(filter: (parameter: Il2Cpp.Parameter) => boolean)and(): Finalizes the selection criteria and returns the tracer instance, allowing you to call .attach().You can use multi-stage Docker builds to extract only the Unity editor components (Data and GameAssembly.so) without the full image. Use the --target unity-editor flag.
docker build \
--platform linux/amd64 \
--build-arg UNITY_VERSION=2023.2.20f1 \
--target unity-editor \
-t unity:2023.2.20f1 \
testThe dump subcommand accepts the following options:
| Option | Description |
|---|---|
-h, --help | Show this help message and exit |
--out-dir OUT_DIR | Where to save the dump (defaults to current working dir) |
--cs-output {none,stdout,flat,tree} | Style of C# output (defaults to tree). none: do nothing; stdout: print to console; flat: one single file (dump.cs); tree: directory structure with one file per assembly. |
--no-namespaces | Do not emit namespace blocks; prepend namespace name in class declarations |
--flatten-nested-classes | Write nested classes at the same level of their enclosing classes and prepend enclosing class name |
--keep-implicit-base-classes | Write implicit base classes (e.g., class -> System.Object, struct -> System.ValueType, enum -> System.Enum) |
--enums-as-structs | Write enum class declarations as structs |
--no-type-keywords | Use fully qualified names for builtin types instead of keywords (e.g., System.Int32 instead of int) |
--actual-constructor-names | Write actual constructor names (e.g., .ctor and .cctor) |
--indentation-size INDENTATION_SIZE | Indentation size (defaults to 4) |
usage: frida-il2cpp-bridge [options] dump [-h] [--out-dir OUT_DIR] [--cs-output {none,stdout,flat,tree}] [--no-namespaces] [--flatten-nested-classes] [--keep-implicit-base-classes] [--enums-as-structs] [--no-type-keywords] [--actual-constructor-names] [--indentation-size INDENTATION_SIZE]The Application class provides utility methods for interacting with the console and managing the user interface during command execution:
print(*args, **kwargs): Standard printing to the console.update_status(message): Updates the current status line in the console.next_status(): Clears the current status line if the console is in ConsoleState.STATUS mode, allowing for a clean transition to the next output.