
本文完整记录了我从 APK 分析 → 判断 Unity 架构 → Hook Mono Runtime → 精准拦截死亡函数的全过程。
最终效果:
人物发生碰撞也不会死亡,游戏可正常继续运行。

一、实验环境



frida-server-17.5.1-android-arm64上传到手机:
adb push frida-server-17.5.1-android-arm64 /data/local/tmp/adb shell chmod +x /data/local/tmp/frida-server-17.5.1-android-arm64启动frida-server-17.5.1-android-arm64
adb shell /data/local/tmp/frida-server-17.5.1-android-arm64
二、从 APK 入手:判断游戏架构

apktool d trial.apk重点关注:
AndroidManifest.xmllib/armeabi-v7alib/arm64-v8aassets/在lib/arm64-v8a/目录下发现:
libmono.solibu.so同时:
libil2cpp.solibunity.so(部分 Mono 游戏本来就没有)这是一个 Unity Mono 架构游戏(非 IL2CPP)

三、确认 C# 脚本存在

在:
assets/bin/Data/Managed/中可以看到:
Assembly-CSharp.dllUnityEngine.dll
说明:

四、为什么选择 Hook libmono.so


五、锁定关键函数:mono_runtime_invoke

Unity 物理 / 碰撞 ↓C# 脚本 (Update / OnCollisionEnter) ↓IL Code ↓mono_runtime_invoke ↓Native 执行所有 C# 方法最终都会经过
mono_runtime_invoke
这意味着:
Hook 一个函数,就能观察并控制所有 C# 方法调用。

六、附加进程并 Hook

adb shell ps -A | grep com.galapagossoft.trial输出示例:
u0_a236 19480 ... com.galapagossoft.trialfrida -U -p19480 -l mono_base.js
七、Hook 脚本(核心代码)

console.log("[*] mono_base.js loaded");varmono = Process.findModuleByName("libmono.so");if (!mono) { console.log("libmono.so not found");return;}varmono_method_get_name_ptr = mono.getExportByName("mono_method_get_name");varmono_runtime_invoke_ptr = mono.getExportByName("mono_runtime_invoke");varmono_method_get_class_ptr = mono.getExportByName("mono_method_get_class");varmono_class_get_name_ptr = mono.getExportByName("mono_class_get_name");varmono_method_get_name =new NativeFunction( mono_method_get_name_ptr, "pointer", ["pointer"]);varmono_method_get_class =new NativeFunction( mono_method_get_class_ptr, "pointer", ["pointer"]);varmono_class_get_name =new NativeFunction( mono_class_get_name_ptr, "pointer", ["pointer"]);varorig_mono_runtime_invoke =new NativeFunction( mono_runtime_invoke_ptr,"pointer", ["pointer", "pointer", "pointer", "pointer"]);Interceptor.replace( mono_runtime_invoke_ptr,new NativeCallback(function (method, obj, params, exc) {varklass = mono_method_get_class(method);varclassName = mono_class_get_name(klass).readCString();varmethodName = mono_method_get_name(method).readCString();// 关键:拦截碰撞触发if (className === "Bone" && methodName === "OnCollisionEnter") { console.log("[BLOCK] " + className + "::" + methodName);return ptr(0); }return orig_mono_runtime_invoke(method, obj, params, exc); }, "pointer", ["pointer", "pointer", "pointer", "pointer"]));
八、分析过程与关键突破

日志中依次出现:
Fork::UpdateFork::OnCollisionStayFailController::OnGUIBone::OnCollisionEnterFailController::OnGUI只是 UI 显示失败画面,不是死亡原因
FailController::Start失败后的初始化逻辑
Bone::OnCollisionEnter这正好符合游戏机制:
人物因重力翻转发生碰撞 → 立即失败

九、最终效果

成功拦截后:
✅无需修改 APK✅无需重打包✅精准绕过失败判定

十、总结

本文完整展示了一条Unity Mono 游戏逆向的通用思路:
mono_runtime_invokeOnCollisionEnter实现逻辑绕过理解引擎执行模型,比盲目改代码更重要。
后续我会继续分享更多 Unity / Mono / Frida 实战分析。

看雪ID:我是jet
https://bbs.kanxue.com/user-home-1062757.htm

# 往期推荐


球分享

球点赞

球在看

点击阅读原文查看更多