某气骑士 libtprt.so 反 Frida 机制分析与绕过
好久没写博客了,今天打算更新一下,记录一下之前写过的东西,在GitHub上也写了一些小软件,顺便分享一下
本文核心问题:libtprt.so 是通过哪些特征检测 Frida?
方法:对比 frida-server 与 florida-server 差异
一、工具准备
最近写了一些小工具,感觉还是挺好用的,所以分享出来:
EasyHook
https://github.com/RytterMohn/EasyHook
EasyHook 是一个运行在 Windows 桌面端的 Android Frida 脚本 IDE,支持脚本管理、代码编辑、Android 设备 连接、进程选择、Attach/Spawn 注入、运行控制和日志输出,让 Frida 脚本无需手写 Python 启动器即可快速执行。
UsbDetectionBypass
https://github.com/RytterMohn/UsbDetectionBypass
隐藏 Android 应用内 USB 连接与 USB 调试检测信号的 LSPosed/Xposed 模块。
EnvdetectEnvScope
https://github.com/RytterMohn/EnvScope
EnvScope 是一个用于 Android 运行环境自检的 APK,重点探测 Frida、Xposed、LSPosed、EdXposed、Substrate、Riru、Zygisk/Magisk 等动态插桩、Hook 或模块化注入痕迹。
二、前言
在之前的博客中,我分析测试了某气骑士这款游戏(https://www.xuanworld.top/2026/01/09/android-re-knight/),当时遇到了反frida的机制,所以最后是用了xposed插件和termux运行shell脚本实现内存dump的,没有细致的分析如何使用其他方式绕过frida检测,所以这次博客就来实现一下。
首先介绍一下基本情况,某气骑士这款游戏使用了libtprt.so库对游戏进行加固,除了对il2cpp进行加固外,还加入了反frida的机制,如果手机中运行frida-server进程的话,游戏在启动的时候回卡死,il2cpp将不会被加载到内存中,不过在之前的测试中,发现libtprt.so会检测usb连接功能,不过不确定是怎么进行检测的。
1. USB检测绕过
所以现在第一步,需要绕过libtprt的usb检测功能,因为如果不连接usb的话,frida脚本执行会比较麻烦,为此我专门编写了一个可以防usb检测的lsposed模块:UsbDetectionBypass

下载源代码后修改作用域

在手机上启动这个模块,之后在电脑上通过adb查看日志:
shell
adb logcat -s UsbBypass UsbBypassNative UsbDetectionBypassNative
之后运行某气骑士这款游戏,可以看到如下图的日志内容,这说明检测的返回值已经被修改,成功绕过检测:

从日志可以看出,应用在 Java 层通过 BATTERY_CHANGED 广播获取 plugged 状态来判断是否连接 USB,同时在 Native 层通过 __system_property_get 读取 init.svc.adbd、service.adb.tcp.port 和 ro.debuggable 等系统属性来检测 ADB 调试环境;而当前结果中这些值均被成功篡改为"未连接 USB、未开启调试",说明通过 Hook 覆盖了应用的检测路径,从而有效绕过了其 USB/调试环境检测机制。
2. frida检测的绕过
通过上述的方式可以防止libtprt检测我的usb,不过frida还是容易被检测,一旦开启frida-server就会闪退。
这个被检测的原因有很多,因为frida本身有很多检测点,我先换了一个魔改的frida-server测试了一下,魔改的frida-server是这个:
https://github.com/Ylarod/Florida
启动florida-server(报错不用管,嘻嘻)

然后启动游戏观察是否闪退,只要能看到界面就说明il2cpp已经加载进去了:

发现没有闪退,简单写个脚本测试一下,这个IDE是我自己用electron做的**EasyHook**,喜欢可以自己去下载,我感觉还是很方便的:

成功hook,说明florida+UsbDetectionBypass的方案是可以绕过libtprt.so的。
3. frida检测方式的初步分析
其实我最好奇的问题是,某气骑士是如何检测到frida的呢,根据目前的信息,frida是能被检测到,florida是不会被检测到,所以我的思路就是去查看frida和florida有哪些区别,这些地方就是检测点,为此我专门做了一个小软件**EnvScope**,这个软件通过各种各样的监测点去检测当前的环境中是否存在xposed或者frida等特征,然后做一个简单的测试:
首先是florida的检测结果:

然后是frida的检测结果:

从检测结果来看,frida-server 相比 florida-server 暴露了更完整的特征,主要的区别是:
-
frida-server在
/proc/self/maps中可以直接命中libzygisk.so,说明 frida 的注入过程触发了 Zygisk 相关机制,导致系统注入库被加载并被检测到 -
Native 层枚举特征,通过
dl_iterate_phdr、dlsym等方式也能扫描到这些 so,说明不仅 maps 可见,底层模块遍历同样能识别 -
更丰富的 Unix Socket 特征,frida 会产生多个带有明显 "frida" 标识的 socket(如
frida-xxxx),而 florida 对这部分做了一定混淆或减少。
虽然florida也有很明显的特征,但是相比之下frida会有更多的特征,说明这些特征很可能构成其检测规则的一部分,之后我计划自己去魔改frida,检查这个到底是如何被检测到的。
三、 小结
这篇主要是把之前没细做的部分补了一下,重点其实有两个:一是通过 Hook BATTERY_CHANGED 和 __system_property_get 把 USB 和 ADB 相关检测全部"伪装掉",解决 libtprt.so 对调试环境的第一层判断;二是通过对比 frida-server 和 florida-server,去反推它具体是从哪些特征在识别 Frida。
对比下来能明显看到,frida-server 暴露的东西更多,比如 maps 里的 libzygisk.so、Native 层可枚举的 so 以及带 frida 关键字的 socket,这些叠在一起基本就很容易被命中;而 florida 把内存和一部分注入链路特征藏掉了,只剩下端口和少量通信特征,所以能跑起来。
如果这些工具(EasyHook / UsbDetectionBypass / EnvScope)对你有帮助的话,也可以顺手点个 star!球球了!