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.
| Repo | Role | When |
|---|---|---|
| This — il2cpp-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.
The MCP server is a native Windows exe, not a Python script. Building is optional if you grab a prebuilt release.
- Open Releases
- Use Continuous build (latest) (updated on every push to
master), or a version tag when you want a fixed pin - Download
il2cpp_mcp.exe(or the zipil2cpp-decompiler-windows-x64.zip) - 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).
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_mcpBinary: target\release\il2cpp_mcp.exe
The agent cannot decompile from a bare GameAssembly.dll without a name/address map.
| Need | Why |
|---|---|
| Il2CppDumper | First-time dump → script.json — not shipped here |
Option A — GUI
- Run
il2cpp_studio.exe(from the release or your build). - Set the path to
Il2CppDumper.exeif prompted. - Open Game Folder… → pick the game install directory.
- 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.
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.
| 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| 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.
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_autoshell out toIl2CppDumper.exeonce per game (or on force re-dump). - MCP only needs a dump already on disk:
list_dumps→load_project(...). No dumper process if the cache exists. - Place
Il2CppDumper.exesomewhere the studio can find it (UI field, next to the binary, or%LOCALAPPDATA%\Il2CppStudio\Il2CppStudio\Il2CppDumper\).
Not bundled — download from the Il2CppDumper releases yourself.
| 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.
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.
| 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 |
- Run
il2cpp_studio.exe - Open Game Folder… → finds
GameAssembly.dll+global-metadata.dat, runs Il2CppDumper, cachesscript.json - Browse / search methods, inspect disassembly and decompile view
- 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"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
MIT — see LICENSE.