frida 发布了新特性, 支持硬件断点, 能更好的对内存区域进行扫描, 并快速定位出哪段代码读写了这片内存区域
感兴趣的可以看下
贴上地址 https://frida.re/news/
docker容器下对运行中python进程调试踩坑记录(mgaic亲踩)
发表于
stackplz hook art 记录
发表于
1 | #include <jni.h> |
上面是我自己写的jni实现.
stackplz hook NewStringUTF 打印堆栈
1 | ./stackplz -n com.zj.my_md5 -l /apex/com.android.art/lib64/libart.so -w _ZN3art3JNIILb1EE17GetStringUTFCharsEP7_JNIEnvP8_jstringPh[str] --stack |
结果如下, 可以看到调用堆栈已经打印出来了.
hook 一下GetStringUTFChars 看看入参?
先查看一下导出函数地址
1 | ./stackplz -n com.zj.my_md5 -l /apex/com.android.art/lib64/libart.so -w GetStringUTFChars --dumpret |
执行结果如下
1 | findBTFAssets btf_file=a12-5.10-arm64_min.btf |
执行结果解析
0x4b7528 是函数最后一条指令的地址. _ZN3art3JNIILb0EE17GetStringUTFCharsEP7_JNIEnvP8_jstringPh 是导出函数名, 0x4b6e60 是导出函数在so中的偏移
我们试试hook _ZN3art3JNIILb0EE17GetStringUTFCharsEP7_JNIEnvP8_jstringPh
1 | ./stackplz -n com.zj.my_md5 -l /apex/com.android.art/lib64/libart.so -w _ZN3art3JNIILb0EE17GetStringUTFCharsEP7_JNIEnvP8_jstringPh[int,str] |
看看结果
1 | idx:0 [/apex/com.android.art/lib64/libart.so] -> sym:_ZN3art3JNIILb0EE17GetStringUTFCharsEP7_JNIEnvP8_jstringPh off:0x0 |
发现并没有调用,说明很可能是调用的另一个函数, 试试另一个函数 _ZN3art3JNIILb1EE17GetStringUTFCharsEP7_JNIEnvP8_jstringPh
1 | ./stackplz -n com.zj.my_md5 -l /apex/com.android.art/lib64/libart.so -w _ZN3art3JNIILb1EE17GetStringUTFCharsEP7_JNIEnvP8_jstringPh[int,str] |
结果如下
乱码 这是为什么呢? 原来 GetStringUTFChars 的入参是jstring, 出参是char * 所以我们要inline hook GetStringUTFChars 的最后一条指令的地址, 然后打印x0的值(arm64调用约定, 返回值一般放在x0寄存器)。
试试看, 代码如下
1 | ./stackplz -n com.zj.my_md5 -l /apex/com.android.art/lib64/libart.so -w 0x51acb8[str:x0] |
执行结果
可以看到 hook成功
同理可以Hook NewStringUTF, NewStringUTF 的入参是 char *, 所以只需要hook 偏移或者导出函数地址就可以了, 不需要hook 函数的最后一条指令的地址
1 | ./stackplz -n com.zj.my_md5 -l /apex/com.android.art/lib64/libart.so -w _ZN3art3JNIILb1EE12NewStringUTFEP7_JNIEnvPKc[int,str] --regs |
亲测可行, 并且不同的so, 可以调用的导出函数并不一样. 例如某音和我自己写的so, 虽然都是调用的 NewStringUTF, 但是对应的导出函数名是不一样的,建议两个都试一下
hook 某音 GetStringUTFChars
1 | ./stackplz -n com.ss.android.ugc.aweme -l /apex/com.android.art/lib64/libart.so -w 0x4b7528[str:x0] |
效果如下
打印的无关信息过多, 试着过滤掉一部分. 只要/data开头的数据. -f 表示filter w:/data 表示 white 白名单. str.f0表示对第一个char* 应用f0过滤策略, 即 w:/data
1 | ./stackplz -n com.ss.android.ugc.aweme -l /apex/com.android.art/lib64/libart.so -w 0x4b7528[str.f0:x0] -f w:/data |
看看结果
hook GetStaticMethodID
1 | ./stackplz -n com.ss.android.ugc.aweme -l /apex/com.android.art/lib64/libart.so -w GetStaticMethodID --dumpret |
结果如下 豁然开朗
硬件断点 hook 0x1e66c 打印调用堆栈
1 | ./stackplz -p `pidof com.zj.my_md5` --brk 0x715adae66c:x --stack |
0x715adae66c 是绝对地址. 通过so基址加偏移得到的.
结果如下
某音six分析记录(mgaic原创)
发表于
hook hashMap put 函数
1 | function hookMap(){ |
结果如下
hook fCw试试, 看看在调用该函数的时候, 六神是否已经生成
hook 代码如下
1 | function hook_intercept(){ |
hook 结果如下
可以看到此处六神已经拿到了, 继续往上游函数摸索.
hook fct函数试试, hookfct函数发现headers 中没有 six
jadx打开看看
看看response fct函数以后, headers有没有增加six 字段
hook脚本如下
1 | function hook_intercept(){ |
结果如下
可以看到 经过 fCt 以后,six就出来了. 重点看看 fCt, tryAddSecurityFactor 很可疑, hook 看看, 要注意Map强转HashMap, 否则打印出来的就是 Obejct
1 | let NetworkParams = Java.use("com.bytedance.frameworks.baselib.network.http.NetworkParams"); |
hook 结果如下, 可以看到 six已经生成了
jadx继续看看 发现调用了 onCallToAddSecurityFactor, 进去看看实现, 发现是个接口
查看交叉引用看看
进入以后 发现调用了 l.a, hook 试试看
1 | Java.perform(function (){ |
结果如下
java层到此结束。实现在native层。 实际测试, frida rpc 几十次后就不返回数据了. 风控很强。
使用 stackplz 辅助分析 anti-frida(亲测可行)
发表于
使用 stackplz 过anti-frida
一般检测frida 比较常用的一个函数是 strstr. 这个函数类似于 isSubString. 判断子串
我们使用 stackplz hook strstr 看看是谁在调用strstr
1 | ./stackplz -n tv.danmaku.bili -l /apex/com.android.runtime/lib64/bionic/libc.so -w strstr --stack |
执行结果如下
看看strstr的参数, 到底是不是针对一些环境的检测
1 | /stackplz -n tv.danmaku.bili -l /apex/com.android.runtime/lib64/bionic/libc.so -w strstr[str:x0,str:x1] -o tmp.log |
结果如下
google 一搜
大概率就是 libmxxxoxxdsec.so 在检测frida
从hook strstr的调用堆栈里我们可以看到是从 thread_start 开始的。 所以我们hook thread_create 看看, 创建线程比较早,所以先关掉app, 执行命令后再打开app
1 | ./stackplz -n tv.danmaku.bili -l /apex/com.android.runtime/lib64/bionic/libc.so -w pthread_create --stack -o tmp.log |
可以看到结果, 有13处
ida打开 看看 0x1d304
F5 看看
这里很像是在创建线程。 我们试试patch, 强行让它不创建。 把 BLR X19 指令改为 nop. 在此之前还有一个问题, patch后会不会崩溃?
arm64 函数调用约定 返回值给x0, 我们看看后续有没有用到x0. 如果没用到我们可以这么改, 用到了程序可能就会崩溃
看汇编
发现并没有用到返回值。 所以我们打开 https://armconverter.com/
看看nop 对应的机器码
用 010editor 把 BL X19 对应的机器码全部改为 1F2003D5