声明:文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途给予盈利等目的,否则后果自行承担!如有侵权烦请告知,我会立即删除并致歉。谢谢!
文章有疑问的,可以公众号发消息问我,或者留言。我每天都会看的。
前言
最近加入了知识星球的朋友们,可能知道我最近在做绕过xx企业加固检测Frida的事情。目前还在努力中,本篇文章算是这个过程中的副产物。
本文目的:介绍如何利用stackplz,定位某加固的Frida检测点,然后bypass。
注意:该绕过方式可能不适于最新版本,仅做学习参考。
什么是stackplz?
项目地址:https://github.com/SeeFlowerX/stackplz
stackplz是一款基于eBPF的堆栈追踪工具,目前仅适用于Android平台。
至于eBPF是什么,感兴趣的师傅可以去看https://ebpf.io/zh-hans/what-is-ebpf
我们可以利用stackplz
,打印系统调用syscall的参数,以及调用这些函数的堆栈信息,方便我们定位代码。
环境
-
• Android真机,root权限,系统内核版本5.10+,可 uname -r
查看,我的机子是5.10.168
-
• 某APP 7.76.0版本。其他师傅写的绕过方式:https://bbs.kanxue.com/thread-285893.htm
下载stackplz,push到Android机子/data/local/tmp
路径下
分析过程
监听加载的so文件,Android13 arm64架构中,android_dlopen_ext存放在
/apex/com.android.runtime/lib64/bionic/libdl.so
stackplz命令
./stackplz -n <包名> -l /apex/com.android.runtime/lib64/bionic/libdl.so -w android_dlopen_ext[str] -o tmp.log
解释:
-
• -n
APP包名,分组名(root/system/shell/app/iso) -
• -l
动态库名或者动态库完整路径,配合-w/--point选项使用 -
• -w
执行用户空间的hook -
• [str]
打印参数,以字符串的形式
如果APP检测到Frida特征后会闪退,可以用上面的命令。
另一个APP:
老版本的Frida检测,会通过pthread_create创建一个线程,在线程中检测Frida的特征,不涉及so库的CRC校验、/proc/self/maps格式校验,所以比较简单。
我们直接通过stackplz打印调用pthread_create的堆栈信息
./stackplz -n <包名> -l /apex/com.android.runtime/lib64/bionic/libc.so -w pthread_create --stack -o tmp.log
启动APP,等待stackplz打印完毕,在tmp.log中搜索检测Frida的so文件libmsaoaidsec.so
如果提前终端,相关堆栈信息可能无法显示
我们可以在IDA中验证
因为该so库中对pthread_create文件名进行了一定程度的混淆,但根据pthread_create接收的参数数量和类型,可以得出就是这里。
其他两个同理。
bypass frida 检测
接下来,我们可以用Frida bypass这三处地址,有两种方式。
方法1 返回空函数
一种是hook pthread_create调用的函数,比如上图的地址在0x1c544的函数。将改地址修改为空函数,调用后立刻返回。
function patch_func_ret(addr) {
Memory.patchCode(addr, 8, function (code) {
code.writeByteArray([0xE0, 0x03, 0x00, 0xAA]);
code.writeByteArray([0xC0, 0x03, 0x5F, 0xD6]);
console.log("patch code at " + addr)
});
}
function bypass()
{
let module = Process.findModuleByName("libmsaoaidsec.so")
patch_func_ret(module.base.add(0x1c544))
patch_func_ret(module.base.add(0x1b8d4))
patch_func_ret(module.base.add(0x26e5c))
}
sub_1C544是IDA中的命名规则,sub表示函数,下划线后面的是它在该文件中的偏移地址。
code.writeByteArray中传入两条指令汇编代码是
MOV X0, X0
RET
作用是访问后立即返回。
方法2 patch调用指令
我们在IDA中看到,pthread_create函数是通过BLR X19
来调用的,该指令占用4字节,我们直接将该指令patch为nop不创建函数,而是继续往下走。
function bypass()
{
let module = Process.findModuleByName("libmsaoaidsec.so")
nop_code(module.base.add(0x1d304))
nop_code(module.base.add(0x1be58))
nop_code(module.base.add(0x27718))
}
function nop_code(addr)
{
Memory.patchCode(ptr(addr),4,code => {
const cw =new Arm64Writer(code,{pc:ptr(addr)});
cw.putNop();
// cw.putNop();
cw.flush();
})
}
小结
本文主要目的是介绍基于eBPF的堆栈打印工具stackplz,并通过Frida检测演示如何使用。
文章中的绕过检测方式已经不适合最新的Frida检测了,需要额外的操作进行绕过。
参考资料
-
• https://bbs.kanxue.com/thread-285893.htm -
• https://mgaic.github.io/2024/07/12/stackplz-trace/
欢迎加入知识星球~
原文始发于微信公众号(进击的HACK):通过stackplz定位并bypass Frida检测
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论