安卓游戏逆向--FridaHook绕过碰撞死亡判定"

admin 2026-10-18 21:36:17 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

安卓游戏逆向 -- Frida Hook 绕过碰撞死亡判定

jet58
jet58

逆向有你

2026年6月30日 11:28
河南

在小说阅读器读本章

去阅读

Android安卓游戏Unity Mono 游戏逆向实战:从 APK 到 Hook libmono.so 绕过死亡判定

前言

最近在分析一款 极限摩托基于手机重力控制的 Unity 游戏:

  • 通过手机 前后翻转控制角色
  • 人物只要 发生碰撞(翻车 / 头部触地)就会立即失败
  • 没有明显的数值判定,属于典型的 物理 + 碰撞触发死亡

本文完整记录了我 从 APK 分析 → 判断 Unity 架构 → Hook Mono Runtime → 精准拦截死亡函数 的全过程。

最终效果:

人物发生碰撞也不会死亡,游戏可正常继续运行。


一、实验环境

游戏截图

我使用的设备 & 工具版本

  • Android 10 真机(arm64)
  • Frida版本

:17.5.2
* Frida Server版本

:frida-server-17.5.1-android-arm64
* Python版本

:3.10.0
* 手机不方便可以使用手机模拟器

#### Frida Server 启动

上传到手机:

复制代码 隐藏代码 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 入手:判断游戏架构

1️⃣ 解包 APK

 复制代码 隐藏代码
apktool d trial.apk

重点关注:

  • AndroidManifest.xml
  • lib/armeabi-v7a

/ lib/arm64-v8a
* assets/


2️⃣ 查看 so 文件(关键判断点)

在 lib/arm64-v8a/ 目录下发现:

 复制代码 隐藏代码
libmono.so
libu.so

同时:

  • ❌ 不存在 libil2cpp.so
  • ❌ 不存在 libunity.so(部分 Mono 游戏本来就没有)

✅ 结论

这是一个 Unity Mono 架构游戏(非 IL2CPP)


三、确认 C# 脚本存在

在:

 复制代码 隐藏代码
assets/bin/Data/Managed/

中可以看到:

 复制代码 隐藏代码
Assembly-CSharp.dll
UnityEngine.dll
Assembly-CSharp.dll 可以使用ILSpy工具打开,可以直接看到关键代码Bone::OnCollisionEnter,进行分析

说明:

  • 游戏逻辑由 C# 编写
  • 运行在 Mono VM
  • 实际执行发生在 libmono.so

四、为什么选择 Hook libmono.so

❌ 不直接修改 DLL 的原因

  • 需要重打包 APK
  • 可能触发签名 / 完整性校验
  • 不利于动态调试

✅ Hook Mono Runtime 的优势

  • 不修改 APK
  • 可实时观察 C# 函数调用
  • 能拦截 Unity 生命周期 / 碰撞函数

五、锁定关键函数:mono\_runtime\_invoke

Mono 执行模型简化图

 复制代码 隐藏代码
Unity 物理 / 碰撞
        ↓
C# 脚本 (Update / OnCollisionEnter)
        ↓
IL Code
        ↓
mono_runtime_invoke
        ↓
Native 执行

所有 C# 方法最终都会经过 mono_runtime_invoke

这意味着:

Hook 一个函数,就能观察并控制所有 C# 方法调用。


六、附加进程并 Hook

1️⃣ 查找游戏 PID

 复制代码 隐藏代码
adb shell ps -A | grep com.galapagossoft.trial

输出示例:

 复制代码 隐藏代码
u0_a236   19480   ...   com.galapagossoft.trial

2️⃣ Frida Attach

 复制代码 隐藏代码
frida -U -p 19480 -l mono_base.js

七、Hook 脚本(核心代码)

 复制代码 隐藏代码
console.log(\" mono_base.js loaded\");

var mono = Process.findModuleByName(\"libmono.so\");
if (!mono) {
    console.log(\"libmono.so not found\");
    return;
}

var mono_method_get_name_ptr = mono.getExportByName(\"mono_method_get_name\");
var mono_runtime_invoke_ptr = mono.getExportByName(\"mono_runtime_invoke\");
var mono_method_get_class_ptr = mono.getExportByName(\"mono_method_get_class\");
var mono_class_get_name_ptr = mono.getExportByName(\"mono_class_get_name\");

var mono_method_get_name = newNativeFunction(
    mono_method_get_name_ptr, \"pointer\", [\"pointer\"]
);

var mono_method_get_class = newNativeFunction(
    mono_method_get_class_ptr, \"pointer\", [\"pointer\"]
);

var mono_class_get_name = newNativeFunction(
    mono_class_get_name_ptr, \"pointer\", [\"pointer\"]
);

var orig_mono_runtime_invoke = newNativeFunction(
    mono_runtime_invoke_ptr,
    \"pointer\",
    [\"pointer\", \"pointer\", \"pointer\", \"pointer\"]
);

Interceptor.replace(
    mono_runtime_invoke_ptr,
    newNativeCallback(function (method, obj, params, exc) {

        var klass = mono_method_get_class(method);
        var className = mono_class_get_name(klass).readCString();
        var methodName = mono_method_get_name(method).readCString();

        // 关键:拦截碰撞触发
        if (className === \"Bone\" && methodName === \"OnCollisionEnter\") {
            console.log(\"[BLOCK] \" + className + \"::\" + methodName);
            returnptr(0);
        }

        returnorig_mono_runtime_invoke(method, obj, params, exc);

    }, \"pointer\", [\"pointer\", \"pointer\", \"pointer\", \"pointer\"])
);

八、分析过程与关键突破

1️⃣ 先打印观察调用

日志中依次出现:

 复制代码 隐藏代码
Fork::Update
Fork::OnCollisionStay
FailController::OnGUI
Bone::OnCollisionEnter

2️⃣ 排除错误目标

  • FailController::OnGUI
    👉 只是 UI 显示失败画面,不是死亡原因
  • FailController::Start
    👉 失败后的初始化逻辑

3️⃣ 真正的死亡触发点

 复制代码 隐藏代码
Bone::OnCollisionEnter

这正好符合游戏机制:

人物因重力翻转发生碰撞 → 立即失败


九、最终效果

成功拦截后:

  • 人物发生碰撞 不再死亡
  • 物理系统正常
  • 游戏流程可继续

✅ 无需修改 APK
✅ 无需重打包
✅ 精准绕过失败判定


十、总结

本文完整展示了一条 Unity Mono 游戏逆向的通用思路:

  1. 从 APK 判断 Unity 架构
  2. 确认 Mono 而非 IL2CPP
  3. 锁定 libmono.so
  4. Hook mono_runtime_invoke
  5. 通过 Runtime 级分析定位关键 C# 方法
  6. 精准拦截 OnCollisionEnter 实现逻辑绕过

理解引擎执行模型,比盲目改代码更重要。


后记

这套方法同样适用于:

  • Unity Mono 手游
  • 碰撞 / 判定 / 失败逻辑分析
  • 无源码、无符号环境下的动态逆向

后续我会继续分享更多 Unity / Mono / Frida 实战分析。

·今 日 推 荐·


安卓游戏逆向--FridaHook绕过碰撞死亡判定" 网络安全文章

安卓游戏逆向--FridaHook绕过碰撞死亡判定"

本文详细记录了逆向分析一款UnityMono架构安卓游戏的全过程,通过FridaHooklibmono.so中的mono_runtime_invoke函数,精准拦截Bone::OnCollisionEnter碰撞检测方法,成功实现绕过游戏死亡判定。关键步骤包括APK架构判断、Mono运行时分析、动态Hook脚本编写,最终达成不修改APK即可让角色碰撞不死亡的效果。
苹果和特斯拉没被攻破,机密却流到了暗网" 网络安全文章

苹果和特斯拉没被攻破,机密却流到了暗网"

苹果和特斯拉的商业机密经由其印度代工厂塔塔电子泄露。黑客组织WorldLeaks入侵了塔塔电子,窃取并公开了大量数据,其中包含苹果iPhone18Pro的零件清单与设计线索,以及特斯拉改款Model3的工程图纸等。值得注意的是,苹果和特斯拉自身网络并未被攻破,泄露的是它们委托供应商保管的机密。此次事件凸显了供应链安全的脆弱性,即便是顶尖企业,其安全也依赖于整条供应链的防御能力。
启明星辰荣获中关村科学城企业党委“两优一先”多项荣誉" 网络安全文章

启明星辰荣获中关村科学城企业党委“两优一先”多项荣誉"

启明星辰集团在中关村科学城企业党委`两优一先`表彰中获多项荣誉:周涛获评优秀共产党员,吴谦获评优秀党务工作者,党委获先进基层党组织称号,潘柱廷被授予党建挚友称号。文档重点介绍了各获奖者在技术创新、党务建设、党建与业务融合方面的具体贡献,并强调企业将持续以高质量党建引领网络安全核心技术攻关与服务国家战略。
一台HTB靶机学会gMSA/RBCD/SPN三大攻击技巧" 网络安全文章

一台HTB靶机学会gMSA/RBCD/SPN三大攻击技巧"

该文档详细记录了针对HTB靶机pirate.htb的内网渗透过程,涉及gMSA密码提取、NTLM中继攻击和基于资源的受限委派(RBCD)利用。通过BloodHound分析域内权限关系,利用MS01$计算机账户读取gMSA服务账户密码,再通过PetitPotam触发NTLM中继在域内创建可控计算机账户ATTACKER$,最终通过S4U2Proxy攻击获取WEB01主机Administrator权限。文档提供了完整的攻击链实操命令和调试技巧。
评论:0   参与:  0