Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Unity IL2CPP game reversing — Il2CppDumper metadata recovery, global-metadata.dat decryption, IDA/Ghidra symbol restore via generated scripts, Frida method hooking, IAP/license bypass, and zygisk-il2cpp-dumper for obfuscated metadata.
allowed-tools
Bash Read Write
metadata
{"subdomain":"mobile","when_to_use":"unity il2cpp libil2cpp.so global-metadata.dat il2cppdumper il2cppinspector mono game reversing anti-cheat license iap inapp purchase ghidra ida symbol restore zygisk","tags":"unity, il2cpp, game, reverse-engineering, il2cppdumper, global-metadata, ghidra, frida, iap, anti-cheat","mitre_attack":"T1635, T1406, T1407"}
Unity IL2CPP Game Reversing Playbook
Unity IL2CPP compiles C# to C++ then to native libil2cpp.so. The
managed bytecode is stripped — jadx and apktool expose only the
thin Java bootstrap and reveal nothing of game logic. This playbook
recovers readable symbols and hooks runtime methods for license/IAP
bypass and vulnerability assessment.
Prerequisites
APK obtained (see mobile/android/SKILL.md for pull methods).
unzip -o base.apk -d /tmp/apk-out/
# Confirm IL2CPP backendls /tmp/apk-out/lib/arm64-v8a/
# Must contain: libil2cpp.sols /tmp/apk-out/assets/bin/Data/Managed/Metadata/
# Must contain: global-metadata.dat# If only libmono.so present → Mono backend (smali/jadx works; this skill N/A)# If libil2cpp.so present but no global-metadata.dat → encrypted/obfuscated (go to Step 5)
file /tmp/apk-out/lib/arm64-v8a/libil2cpp.so
# output: ELF 64-bit LSB shared object, ARM aarch64
Step 2: Recover Symbols with Il2CppDumper
# Extract libs from APKcp /tmp/apk-out/lib/arm64-v8a/libil2cpp.so /tmp/
cp /tmp/apk-out/assets/bin/Data/Managed/Metadata/global-metadata.dat /tmp/
# Run Il2CppDumper (mono CLI on Linux/macOS)
mono Il2CppDumper.exe /tmp/libil2cpp.so /tmp/global-metadata.dat /tmp/dump-output/
# Windows .NET:# Il2CppDumper.exe <libil2cpp.so> <global-metadata.dat> <output-dir>
Output files:
File
Content
dump.cs
All C# class/method/field definitions with offsets
script.json
Machine-readable symbol map (used by IDA/Ghidra scripts)
il2cpp.h
C-style struct definitions for IL2CPP internals
stringliteral.json
All managed string literals with addresses
# Quick scan of dump.cs for interesting classes
grep -i "licen\|premium\|iap\|purchase\|unlock\|cheat\|anti\|integrity" /tmp/dump-output/dump.cs | head -30
# Find method offsets for hooks
grep -A2 "IsPremium\|CheckLicense\|VerifyReceipt\|IsSubscribed" /tmp/dump-output/dump.cs
# Output: // RVA: 0x<offset> — this is the function RVA in libil2cpp.so
Step 3: Apply Symbols in Ghidra / IDA
Ghidra (via MCP ghidra server — batch mode)
# 1. Import libil2cpp.so into Ghidra project
# 2. Run auto-analysis (aarch64)
# 3. Execute the Il2CppDumper Ghidra script:
# Script: ghidra_with_struct.py (from Il2CppDumper/tools/)
# Input: script.json + il2cpp.h
# 4. All methods now have their managed C# names
# In IDA scripting console (Python):# Run ida_with_struct_py3.py from Il2CppDumper/tools/# File → Script File → ida_with_struct_py3.py# Provide path to script.json when prompted# IDA applies all function names + struct types
After symbol restore, navigate to IsPremiumUser, CheckLicense,
VerifyIAP, IsCheatDetected, etc. by name.
Step 4: Frida Runtime Hooking
Hook via RVA from dump.cs
// Read RVA from dump.cs comment line: // RVA: 0x<hex>// Base address of libil2cpp.so changes per run; use Module.findBaseAddressvar il2cpp_base = Module.findBaseAddress("libil2cpp.so");
// Example: hook IsPremiumUser at RVA 0x1A4F80varRVA = 0x1A4F80;
var isPremium = il2cpp_base.add(RVA);
Interceptor.attach(isPremium, {
onEnter: function(args) {
console.log("[+] IsPremiumUser called");
},
onLeave: function(retval) {
console.log("[+] Original return:", retval.toInt32());
retval.replace(ptr(1)); // return trueconsole.log("[+] Replaced with: 1");
}
});
Some apps (particularly heavily monetized games) encrypt or obfuscate
global-metadata.dat to frustrate IL2CPP reversing.
Detect obfuscation
# Check magic bytes — valid global-metadata starts with: AF 1B B1 FA
xxd /tmp/global-metadata.dat | head -2
# If first 4 bytes ≠ AF 1B B1 FA → encrypted/custom header
Common obfuscation patterns
Pattern
Detection
Counter
XOR with static key
First 4 bytes XOR'd from AF 1B B1 FA
Brute short key or key in libil2cpp.so strings
Custom header / prepended garbage
File larger than expected; magic at offset N
Scan for \xAF\x1B\xB1\xFA pattern in file
RC4/AES at init
libil2cpp.so contains crypto init before metadata load
Frida hook on il2cpp_codegen_initialize_method
# Search libil2cpp.so for crypto key material near metadata init
r2 -qc 'iz~metadata\|iz~global' /tmp/libil2cpp.so | head -20
strings /tmp/libil2cpp.so | grep -iE "meta|key|init" | head -20
zygisk-il2cpp-dumper (runtime dump, bypasses all static obfuscation)
# Install Zygisk-Il2CppDumper module via Magisk Manager# Flash zip: ZygiskIl2CppDumper-v<version>.zip# Configure target package in /data/adb/modules/zygisk_il2cpp_dumper/config.jsoncat /data/adb/modules/zygisk_il2cpp_dumper/config.json
# { "package_name": "com.unity.targetgame" }# Launch the target app
adb shell am start -n com.unity.targetgame/.MainActivity
# Dumped files appear in /data/local/tmp/il2cpp_dump/
adb pull /data/local/tmp/il2cpp_dump/
ls il2cpp_dump/
# global-metadata.dat libil2cpp.so (decrypted at runtime)
Feed the runtime-dumped files to Il2CppDumper per Step 2.
dump.cs excerpt showing IsPremiumUser with RVA comment.
Screenshot/screen-recording of the patched/hooked app with
premium features unlocked or anti-cheat bypassed.
Frida console output showing hook fired + return value replaced.
OPSEC Notes
Il2CppDumper runs entirely offline on extracted APK files. No
network activity required for analysis.
Static patching changes the APK signature; Play Integrity / SafetyNet
will flag it. Use Frida hooks on a rooted device for non-persistent
testing.
zygisk-il2cpp-dumper requires Zygisk (Magisk Delta or native Zygisk).
It runs in the app process at startup and can be detected by some
anti-cheat engines (EAC, BattlEye mobile). Use only in scope.
Dumped dump.cs may contain plaintext user-data class names that
reveal the developer's internal naming conventions — treat as
sensitive during an engagement.