过Frida检测通用思路
0x00:环境
设备:MEIzu21PRO
系统版本:Android 14
Frida-Server:16.4.10
小猿口算:3.93.3
0x01:问题
在我使用frida尝试注入,进程直接被杀
1 | PS D:\frida_hook\xiaoyuan> frida -U -l hook.js -f com.fenbi.android.leo |
0x02:分析
大多数frida检测都是在so层,少部分在java层,我们可以先hook一下dlopen查看一下app加载了哪些so文件。
JS代码:
1 | function hook_dlopen() { |
输出日志:
1 | PS D:\frida_hook\xiaoyuan> frida -U -l hook.js -f com.fenbi.android.leo |
可以看到最终是断在了libmsaoaidsec.so,而且并没有走OnLeave,说明检测函数就在这个so文件里。并且没有执行JNI_OnLoad,说明检测frida的操作是在.init_proc或者.init_array中完成的
linker部分代码:
1 | void* do_dlopen(const char* name, int flags, |
直接看重要的部分:
1 | ProtectedDataGuard guard; |
我们可以看到在dlopen函数调用完成之后.init_xxx已经执行完成了,所以我们要选择一个适当的时机去hook。这里时机的选择有两种方案:
hook call_constructors,并在OnEnter里注入代码
在.init_xxx中寻找一个被调用时机较早的外部函数进行hook
这里为了通用一点,选择方案一。但是由于call_constructors并不是一个导出函数,所以我们在hook的时候需要先得到它相对于linker的偏移地址,这个偏移量不同设备大概是不同的,我们需要自己获取一下
1 | readelf -sW /apex/com.android.runtime/bin/linker64 | grep call_constructors |
输出:
1 | meizu21Pro:/ # readelf -sW /apex/com.android.runtime/bin/linker64 | grep call_constructors |
JS代码:
1 | function hook_linker_call_constructors() { |
确定hook点了之后,接下来定位具体的Frida检测点。对Frida的检测通常会使用openat、open、strstr、pthread_create、snprintf、sprintf、readlinkat等一系列函数。这里选择pthread_create函数,因为要检测就首先会创建线程。所以可以先看看那些函数调用了pthread_create
hook pthread_create
定位检测点
1 | function hook_pthred_create(){ |
输出:
1 | PS D:\frida_hook\xiaoyuan> frida -U -l hook.js -f com.fenbi.android.leo |
可以看到libmsaoaidsec.so在内存中的地址是 —- 0x7656840000
分析日志可知有三个线程是由libmsaoaidsec.so创建的,他们相对so的偏移地址分别是:
0x765685c544 - 0x7656840000 = 0x1c544
0x765685b8d4 - 0x7656840000 = 0x1b8d4
0x7656866e5c - 0x7656840000 = 0x26e5c
知道了偏移地址,我们就可以使用IDA打开so开始分析了
按下G跳转到上述地址,我们可以一个个尝试,比如我们先打开0x1b8d4处的函数
1 | LOAD:000000000001B8D4 ; void __noreturn sub_1B8D4() |
根据交叉引用确定了它在sub_1B924函数中被调用,那么这个函数应该就是frida检测逻辑所在的函数了,我们有两种方式过掉这个检测
直接nop掉pthread_create
直接replace sub_1B924
都很简单,这里选择第二种方式
JS代码:
1 | let isHooked = false; |
0x03:全部代码
1 | function hook_dlopen() { |
0x04:总结&简单过掉libmsaoaidsec.so的方法
总结:
这里直接去查看0x1b8d4是因为我知道它是有问题的函数,正常分析需要三处都去分析一下,当然可以直接尝试nop掉,这样可以节省许多时间,毕竟分析也是很累人的。这只是个过frida检测的例子,实际上有更简单的方法,我只是觉得这种方法比较通用。
简单过掉libmsaoaidsec.so的方法:
可以直接删去/data/app/~~A55TKEnXig6YeUSXhnkLPg==/com.fenbi.android.leo-O_2O3vNIVRfTPnY4TgeayQ==/lib/arm64/libmsaoaidsec.so或者直接在apk包中把这个so删掉。因为这个so纯纯是一个安全相关的so,与app本身的业务逻辑毫无关系,直接删掉就好了(与linker的实现也有关,之前写过一篇详细介绍)。bilibili,爱奇艺之类的很多软件都有这个so
也可以在frida中简易的过掉(本段代码来自看雪论坛):
1 | function hook_dlopen(soName = '') { |