frida-il2cpp-bridge

repository·master·Indexed 23 days ago

https://github.com/vfsfitvnm/frida-il2cpp-bridge

A 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.

Tokens
8.9K
Snippets
20
Records
51
Agent score
83%

What's inside frida-il2cpp-bridge

  1. Overview of frida-il2cpp-bridge

    master
    frida-il2cpp-bridge is a Frida module designed to dump, trace, or hijack any Il2Cpp application at runtime. A key advantage is that it does not require the 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.
  2. Use the frida-il2cpp-bridge CLI

    master

    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 -- --help
  3. Dump an Il2Cpp application

    master

    Use 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 dumps
  4. Build and Test (Local Linux x86_64)

    master

    For contributors wanting to test changes locally on Linux (x86_64), you can build specific IL2CPP assemblies and run tests.

    Prerequisites:

    • Linux (x86_64)
    • 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 test
  5. Build and Test using Docker

    master

    To test on non-Linux or different architectures, use the provided Dockerfile. This allows creating a container with the necessary Unity editor artifacts.

    Prerequisites:

    • Docker
    • Emulator/virtualization (optional)

    Build Docker image

    Specify the Unity version via UNITY_VERSION.

    Run tests

    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 testd
  6. Access parent class members using the `base` property

    master

    The 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 Foo
    const Bar: Il2Cpp.Class = ...;
    const bar = Bar.new();
    
    console.log(bar.foo()); // 2
    console.log(bar.base.foo()); // 1
  7. Invoke methods on specific instances using BoundMethod

    master

    When 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(); // 13
  8. Configure Tracer targets using the builder pattern

    master

    The 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().

    Selection Methods

    • 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.

    Filtering 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)

    Committing Selection

    • and(): Finalizes the selection criteria and returns the tracer instance, allowing you to call .attach().
  9. Extract Unity editor from Docker build

    master

    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 \
      test
  10. Reference: dump subcommand options

    master

    The dump subcommand accepts the following options:

    OptionDescription
    -h, --helpShow this help message and exit
    --out-dir OUT_DIRWhere 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-namespacesDo not emit namespace blocks; prepend namespace name in class declarations
    --flatten-nested-classesWrite nested classes at the same level of their enclosing classes and prepend enclosing class name
    --keep-implicit-base-classesWrite implicit base classes (e.g., class -> System.Object, struct -> System.ValueType, enum -> System.Enum)
    --enums-as-structsWrite enum class declarations as structs
    --no-type-keywordsUse fully qualified names for builtin types instead of keywords (e.g., System.Int32 instead of int)
    --actual-constructor-namesWrite actual constructor names (e.g., .ctor and .cctor)
    --indentation-size INDENTATION_SIZEIndentation 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]
  11. Use Application status and printing methods

    master

    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.