Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

il2cpp-decompiler (Il2CppStudio)

Purpose-built IL2CPP decompiler for Unity games — desktop studio + MCP agent.

The goal is not “another Ghidra.” Ghidra is excellent general reverse engineering. This project exists because Unity IL2CPP is a different problem: native x64 wrapped in a known runtime, with full managed metadata sitting next to the binary. A tool that knows that metadata can emit C#-shaped methods with real class/field/call names instead of leaving you in raw assembly and hand-applied structures.

Piece Binary Role
Desktop studio il2cpp_studio Open game folder → dump → browse → disasm + decompile
MCP server il2cpp_mcp Same engine for Cursor / Claude / Grok / etc.
Shared engine src/decompiler/ CFG lift, field recovery, IL2CPP idioms → C# emit
Agent skill skills/il2cpp-decompiler How agents should use the MCP

Status: Passable. Useful for research and modding already; control flow and large methods still need work.

Related projects (same suite)

Repo Role When
Thisil2cpp-decompiler Static IL2CPP decompile (names + C#-shaped methods) Game is IL2CPP
bepinex-mcp Live Unity bridge (get/set/patch/watch) Game is running with BepInEx
gamecode-rag Semantic search over Mono dumped C# Game is Mono (not IL2CPP)

Typical IL2CPP flow: dump → decompile here → patch live with bepinex-mcp.
Typical Mono flow: search gamecode-rag → patch with bepinex-mcp. Do not use this repo for Mono.


Quick start (MCP) — do these in order

The MCP server is a native Windows exe, not a Python script. Building is optional if you grab a prebuilt release.

1. Get il2cpp_mcp.exe (pick one)

Option A — Download (recommended)

  1. Open Releases
  2. Use Continuous build (latest) (updated on every push to master), or a version tag when you want a fixed pin
  3. Download il2cpp_mcp.exe (or the zip il2cpp-decompiler-windows-x64.zip)
  4. Put it somewhere stable, e.g. C:\Tools\il2cpp-decompiler\il2cpp_mcp.exe
Asset Role
il2cpp_mcp.exe MCP server — this is what clients run
il2cpp_studio.exe Optional desktop GUI
smoke_auto.exe Optional headless dump helper

CI builds these on every commit (see .github/workflows/ci.yml). Il2CppDumper is not in the release — get it separately (step 2).

Option B — Build from source (optional)

Only if you want to develop or don’t trust prebuilts:

Need Why
Windows x64 Current builds are Windows-only
Rust (stable) Compile
MSVC C++ build tools Linker / CRT
git clone https://github.com/rkuhn153/il2cpp-decompiler.git
cd il2cpp-decompiler
.\Build-Release.ps1
# or: cargo build --release --bin il2cpp_mcp

Binary: target\release\il2cpp_mcp.exe

2. Dump a game once (Il2CppDumper)

The agent cannot decompile from a bare GameAssembly.dll without a name/address map.

Need Why
Il2CppDumper First-time dump → script.jsonnot shipped here

Option A — GUI

  1. Run il2cpp_studio.exe (from the release or your build).
  2. Set the path to Il2CppDumper.exe if prompted.
  3. Open Game Folder… → pick the game install directory.
  4. Dumps land under:
%LOCALAPPDATA%\Il2CppStudio\Il2CppStudio\dumps\<GameName>\
  script.json
  dump.cs          (if dumper produced it)

Option B — headless

# from a release folder:
.\smoke_auto.exe "D:\SteamLibrary\steamapps\common\YourGame" "C:\path\to\Il2CppDumper.exe"

# or from a source checkout:
cargo run --release --bin smoke_auto -- "D:\path\to\game" "C:\path\to\Il2CppDumper.exe"

Option C — you already have a dump
Skip the dumper. You only need absolute paths to that game’s GameAssembly.dll and script.json.

3. Wire the MCP client

Point command at il2cpp_mcp.exe (absolute path). No args. No Python.

Cursor~/.cursor/mcp.json (or Settings → MCP):

{
  "mcpServers": {
    "il2cpp-decompiler-agent": {
      "command": "C:/Tools/il2cpp-decompiler/il2cpp_mcp.exe",
      "args": []
    }
  }
}

Claude Desktop / similar:

"il2cpp-decompiler-agent": {
  "command": "C:\\Tools\\il2cpp-decompiler\\il2cpp_mcp.exe",
  "args": []
}

Grok / other stdio hosts — same idea: the exe is the server (logs on stderr, JSON-RPC on stdout).

Then restart the client (or reload MCP) so the config loads.

4. First agent session (tool order)

Step Tool What you pass
1 list_dumps (nothing) — lists AppData dumps
2 load_project assembly_path = GameAssembly.dll, script_path = that dump’s script.json
3 search_symbols e.g. Player or TakeDamage
4 get_class_info Fully-qualified class name
5 decompile_method Fully-qualified class + simple method name

If list_dumps is empty, finish step 2 first — do not abandon the MCP.

Optional skill:

# from a git clone:
Copy-Item ".\skills\il2cpp-decompiler" "$env:USERPROFILE\.cursor\skills\il2cpp-decompiler" -Recurse -Force

Common MCP mistakes

Mistake Fix
Pointing MCP at il2cpp_studio.exe Use il2cpp_mcp.exe
Relative paths Always absolute Windows paths
Forgetting a dump Studio Open Game Folder or smoke_auto first
Wrong script.json Prefer the path from list_dumps
Old release after you pull new code Grab the latest continuous build or rebuild

Optional handshake debug: tools/il2cpp_mcp_wrap.py.


Dependency: Il2CppDumper (required for dumps)

This project does not replace Il2CppDumper. You need it (or an equivalent dump) for the name/address map.

Job Tool
Metadata → script.json (+ optional dump.cs) Il2CppDumper (external)
Native method bytes → C#-shaped body This repo
  • Open Game Folder / smoke_auto shell out to Il2CppDumper.exe once per game (or on force re-dump).
  • MCP only needs a dump already on disk: list_dumpsload_project(...). No dumper process if the cache exists.
  • Place Il2CppDumper.exe somewhere the studio can find it (UI field, next to the binary, or %LOCALAPPDATA%\Il2CppStudio\Il2CppStudio\Il2CppDumper\).

Not bundled — download from the Il2CppDumper releases yourself.

Why not just Ghidra?

Ghidra This (IL2CPP-native)
Target Any binary Unity IL2CPP (GameAssembly + metadata)
Names You invent / import them Il2CppDumper / script.json → real C# names
Output P-code / C-ish decomp C#-shaped methods (this.m_field, Class.Method)
IL2CPP calls Look like opaque runtime helpers Folded toward managed call / null-check idioms
Workflow Project setup, scripts, headless optional Open game folder + optional MCP in one tool call
AI agents Custom scripts / plugins First-class decompile_method over stdio

Ghidra still wins for deep malware RE, exotic ISAs, and full program analysis.
For “what does this Unity player method do so I can patch it?” this is the right shape of tool — and that is the bar we are chasing.

Example output

Real decompile from a shipped IL2CPP game (Character.Update, ~150 instructions).
Ghidra on the same function is mostly x64 + unresolved/helper calls until you invest heavily in IL2CPP types. Here the metadata does the naming and the pipeline emits readable C#-like logic:

// Il2CppStudio Decompiler — structured native recovery
// Nested if/else · fields · copy-prop · IL2CPP idioms

void Update(Character this)
{
    NetworkBehaviour.get_IsServerInitialized(this);
    if (result) {
        Character._ServerUpdatePoison(this);
    }
    Character._UpdateRescueMain(this);
    NetworkBehaviour.get_IsServerInitialized(this);
    if (result) {
        Character._UpdateScreenPortal(this);
    }
    if (this.m_mediatorRoom != null) {
        RoomMediator.get_IsNightOrDark(this.m_mediatorRoom);
        if (!result) {
            if (this.m_isLightActive) {
                this.m_isLightActive = 0;
                if (this.m_light != null) {
                    CharacterLight.Hide(this.m_light, this.m_lightTransitionTime);
                    // ...
                    Flashlight.Hide(this.m_flashlight, this.m_lightTransitionTime);
                }
            }
        }
    }
    // emoji input / upgrades / server ticks continue...
}

You can already answer: poison only on server, rescue always, room light tied to night, flashlight hide on transition — without rebuilding the type system by hand.

What still shows we are passable, not finished: leftover Il2CppNullCheck / static init noise, nested if pyramids, occasional goto, and timeouts on huge methods.

MCP tools (il2cpp-decompiler-agent)

Tool Purpose
list_dumps Cached dumps under %LOCALAPPDATA%\Il2CppStudio\...
load_project Load GameAssembly.dll + script.json into the session
search_symbols Class/method substring search
get_class_info Fields (offsets) + method list
decompile_method Structured C# for one method

Desktop workflow (GUI only)

  1. Run il2cpp_studio.exe
  2. Open Game Folder… → finds GameAssembly.dll + global-metadata.dat, runs Il2CppDumper, caches script.json
  3. Browse / search methods, inspect disassembly and decompile view
  4. Dumps under %LOCALAPPDATA%\Il2CppStudio\Il2CppStudio\dumps\

Headless checks:

cargo run --release --bin smoke_load -- "D:\path\GameAssembly.dll" "D:\path\script.json"
cargo run --release --bin smoke_decompile -- "D:\path\GameAssembly.dll" "D:\path\script.json" "SomeClass$$SomeMethod"

Layout

src/
  bin/il2cpp_mcp.rs      # MCP stdio server
  bin/smoke_*.rs         # headless checks
  decompiler/            # CFG lift + C# emit
  main.rs / app.rs       # GUI
skills/il2cpp-decompiler # agent skill
tools/                   # optional helpers
Build-Release.ps1
Cargo.toml

License

MIT — see LICENSE.

About

Purpose-built Unity IL2CPP decompiler (desktop + MCP). Needs Il2CppDumper for dumps.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages