Unity IL2CPP 游戏 无符号 / 无字符串 / 全是 sub_xxx 的 SO 目标:定位死亡逻辑 / 无敌 / 关键状态变量
本文以一个跑酷类神庙逃亡(Temple Run) Unity 游戏为例。

frida-server-17.5.1-android-arm64 复制代码 隐藏代码apktool d game.apk -o game_apk可以用 adb 查看手机 CPU 架构:
复制代码 隐藏代码adb shell getprop ro.product.cpu.abi常见输出:
如果同时存在,可以使用上面的命令查看自己对应的库目录:
优先选择 arm64-v8a
重点关注两个位置libil2cpp.so和global-metadata.dat这两个文件缺一不可。:
复制代码 隐藏代码game_apk/lib/arm64-v8a/libil2cpp.so 复制代码 隐藏代码game_apk/assets/bin/Data/Managed/Metadata/global-metadata.dat 复制代码 隐藏代码./Il2CppDumper libil2cpp.so global-metadata.dat il2cpp_dump生成目录结构如下:
复制代码 隐藏代码il2cpp_dump/├── dump.cs├── script.json├── stringliteral.json├── DummyDll/│ ├── Assembly-CSharp.dll│ └── ...在 dump.cs 中搜索查看关键信息 游戏核心角色类,例如:
复制代码 隐藏代码publicclassCharacterPlayer : CommonPlayer{publicbool IsDead; // 0xD0publicfloat TimeSinceDeath; // 0xD4public DeathTypes DeathType; // 0xD8publicvoidKill(DeathTypes type);publicvoidUpdate();publicvoidStartInvcibility(float duration);}这一步非常重要:
字段偏移 = 后续 Hook / 内存验证的锚点
在 script.json 中可以找到方法对应关系:
复制代码 隐藏代码{"Address":17287964,"Name":"CharacterPlayer$$Kill","Signature":"void CharacterPlayer__Kill (CharacterPlayer_o* __this, int32_t deathType, const MethodInfo* method);"}注意:
Address 复制代码 隐藏代码17287964 (decimal)= 0x107CB1C (hex)1️⃣ 用 IDA 打开 libil2cpp.so2️⃣ 按下键盘 G3️⃣ 输入:
复制代码 隐藏代码0x107CB1C4️⃣ 回车
👉 IDA 会直接跳转到 CharacterPlayer$$Kill 的真实函数实现
IDA 反编译中可以看到:
复制代码 隐藏代码*(_BYTE *)(a1 + 208) = 1; // IsDead = true*(_DWORD *)(a1 + 216) = a2;// DeathType而 dump.cs 中:
复制代码 隐藏代码publicbool IsDead; // 0xD0 (208)public DeathTypes DeathType; // 0xD8 (216)✅ 字段偏移完全一致
说明:
三者已经完全对齐。
在 IL2CPP 游戏中通常存在:
👉 靠猜函数 ≈ 大海捞针
正确思路是:
metadata 给你“地图”,SO 只是实现
目标:让角色始终处于无敌状态。
在script.json中发现:
复制代码 隐藏代码{"Address":17291184,"Name":"CharacterPlayer$$StartInvcibility","Signature":"void CharacterPlayer__StartInvcibility (CharacterPlayer_o* __this, float duration, const MethodInfo* method);","TypeSignature":"vifi"}或 dump.cs中发现:
复制代码 隐藏代码// RVA: 0x107D7B0 Offset: 0x107C7B0 VA: 0x107D7B0publicvoidStartInvcibility(float duration);在 script.json 中查到的"Address": 17291184和dump.cs中查到的RVA: 0x107D7B0,两种都可以:
复制代码 隐藏代码"Address":0x107D7B0在script.json中发现:
复制代码 隐藏代码{"Address":17285176,"Name":"CharacterPlayer$$Update","Signature":"void CharacterPlayer__Update (CharacterPlayer_o* __this, const MethodInfo* method);","TypeSignature":"vii"}或 dump.cs中发现:
复制代码 隐藏代码// RVA: 0x107C038 Offset: 0x107B038 VA: 0x107C038 Slot: 4publicoverridevoidUpdate();在 script.json 中查到的"Address": 17285176和dump.cs中查到的RVA: 0x107C038,两种都可以:函数Update游戏开始后会一直调用,每次调用就调用函数StartInvcibility(player, 9999.0, ptr(0));设置无敌
复制代码 隐藏代码frida -U -p 19480 -l hook.js 复制代码 隐藏代码const base = Process.findModuleByName("libil2cpp.so").base;// CharacterPlayer::StartInvcibilityconstStartInvAddr = base.add(0x107D7B0);// CharacterPlayer::UpdateconstUpdateAddr = base.add(0x107C038);constStartInvcibility = newNativeFunction(StartInvAddr,'void', ['pointer', 'float', 'pointer']);Interceptor.attach(UpdateAddr, {onEnter(args) {const player = args[0];// 每一帧刷新无敌时间StartInvcibility(player, 9999.0, ptr(0)); }});console.log("[+] Invincibility hook installed");效果说明:
![]() | ![]() |