这篇文章上次修改于 645 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
前言
尝试站在syscall的视角看root检查,但是eBPF
环境
- Redmi Note 11T Pro
- 使用DirtyPipe-Android提权
- 获取root后卸载了magisk
目标是com.starbucks.cn
,使用DirtyPipe-Android
提权+卸载magisk后,APP还是能发现root
尝试在estrace
基础上做修改,实现root bypass
效果:
记录
使用estrace
对execve
追踪,会得到这样的日志:
syscall_08:37:18 [om.starbucks.cn] type:1 pid:25310 tid:25310 nr:execve {"lr":"0x7dd9e9ebc8","pc":"0x7dd9ee9498","sp":"0x7fd0983a00","x0":"0xb400007f6682a268","x1":"0xb400007f6682a230","x2":"0xb400007f6680b288"}
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:0 arg_str:/system/bin/sh
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:1 arg_str:sh
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:1 arg_str:-c
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:1 arg_str:which su
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:2 arg_str:PATH=/dev/.magisk:/apex/com.android.runtime/bin:/apex/com.android.art/bin:/system_ext/bin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:2 arg_str:ANDROID_BOOTLOGO=1
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:2 arg_str:ANDROID_ROOT=/system
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:2 arg_str:ANDROID_ASSETS=/system/app
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:2 arg_str:ANDROID_DATA=/data
syscall_08:37:18 [om.starbucks.cn] type:2 pid:25310 tid:25310 nr:execve arg_index:2 arg_str:ANDROID_STORAGE=/storage
...
syscall_08:37:18 [bucks.cn:remote] type:1 pid:25552 tid:25552 nr:execve {"lr":"0x7dd9e9ebc8","pc":"0x7dd9ee9498","sp":"0x7fd09833a0","x0":"0x7c9c2c2b40","x1":"0x7cb1922160","x2":"0x7fd0986ae0"}
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:0 arg_str:/system/bin/sh
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:1 arg_str:sh
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:1 arg_str:-c
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:1 arg_str:mount
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:2 arg_str:PATH=/dev/.magisk:/apex/com.android.runtime/bin:/apex/com.android.art/bin:/system_ext/bin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:2 arg_str:ANDROID_BOOTLOGO=1
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:2 arg_str:ANDROID_ROOT=/system
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:2 arg_str:ANDROID_ASSETS=/system/app
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:2 arg_str:ANDROID_DATA=/data
syscall_08:37:18 [bucks.cn:remote] type:2 pid:25552 tid:25552 nr:execve arg_index:2 arg_str:ANDROID_STORAGE=/storage
可以推测which su
是在检查root,而mount
则是检查magisk
Q: 为什么mount可以用来检查magisk
A: 如下:
xaga:/ $ mount | grep magisk
none on /dev/.magisk type tmpfs (rw,seclabel,relatime)
devpts on /dev/.magisk/.magisk/pts type devpts (rw,seclabel,nosuid,noexec,relatime,mode=600,ptmxmode=000)
none on /dev/.magisk type tmpfs (rw,seclabel,relatime)
devpts on /dev/.magisk/.magisk/pts type devpts (rw,seclabel,nosuid,noexec,relatime,mode=600,ptmxmode=000)
如果要使用eBPF的方案实现bypass,我们需要对比参数并对参数内容做出修改
向estrace
中添加下面这样的代码,以实现bypass(mount也是类似处理):
bool need_bypass_check = true;
char target[] = "which su";
for (int i = 0; i < sizeof(target); ++i) {
if (data->arg_str[i] != target[i]) {
need_bypass_check = false;
break;
}
}
if (need_bypass_check) {
char fmt0[] = "execve call which su, lets bypass it, uid:%d\n";
bpf_trace_printk(fmt0, sizeof(fmt0), uid);
char placeholder[] = "which bb";
bpf_probe_write_user((void*)addr, placeholder, sizeof(placeholder));
}
也就是比较execve
的argv
中的参数有没有关键词,如果有,我们就把对应的参数修改为其他的,迫使命令执行得到原预期之外的结果
实际测试之后,发现APP还是崩溃了,但是确实多运行了一会儿
百思不得其解,因为estrace
是基于uid
进行过滤的,不过有没有可能某些检查方案所产生的进程不会归属于当前APP呢?
于是将uid过滤部分去除,再次运行estrace
,这一次APP成功进入首页并且没有闪退
那么这次日志中多出来什么呢?如下:
syscall_10:32:07 [.apkwrapper.r.S] type:1 pid:20211 tid:20211 nr:execve {"lr":"0x7dd9e9ebc8","pc":"0x7dd9ee9498","sp":"0x7fd0984330","x0":"0x7dd9e34390","x1":"0x7fd09841a0","x2":"0x7fd0986ae0"}
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:0 arg_str:/system/bin/sh
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:1 arg_str:sh
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:1 arg_str:-c
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:1 arg_str:which su
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:2 arg_str:PATH=/dev/.magisk:/apex/com.android.runtime/bin:/apex/com.android.art/bin:/system_ext/bin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:2 arg_str:ANDROID_BOOTLOGO=1
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:2 arg_str:ANDROID_ROOT=/system
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:2 arg_str:ANDROID_ASSETS=/system/app
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:2 arg_str:ANDROID_DATA=/data
syscall_10:32:07 [.apkwrapper.r.S] type:2 pid:20211 tid:20211 nr:execve arg_index:2 arg_str:ANDROID_STORAGE=/storage
通过拼手速,终于发现了这个进程:
xaga:/ # ps -ef | grep apkwrapper
u0_i9104 21022 759 7 18:34:17 ? 00:00:00 com.starbucks.cn:bbs:com.secneo.apkwrapper.r.S
这个进程的父进程是zygote64
,查看AndroidManifest.xml
发现原来是isolatedProcess
xaga:/ # ps -ef | grep zygote
root 759 1 0 00:08:26 ? 00:00:20 zygote64
总结
- APP检查root的方案是执行
which su
命令 - APP检查magisk的方案是执行
mount
命令,看看是否存在magisk关键词 - 在此案例中
isolatedProcess
的父进程是zygote64
没有评论