本文为看雪论坛优秀
看雪论坛作者ID:阿碧 文章
效果
对 openat进行跟踪:
对 recvfrom进行跟踪:
在这里感谢珍惜大佬介绍的seccomp机制。
什么是seccomp
seccomp 是 Linux 内核提供的一种应用程序沙箱机制,主要通过限制进程的系统调用来完成部分沙箱隔离功能。seccomp-bpf 是 seccomp 的一个扩展,它可以通过配置来允许应用程序调用其他的系统调用。
如何和frida结合
基本原理
这是一个bpf规则:
struct sock_filter filter[] = {
BPF_STMT(BPF_LD + BPF_W + BPF_ABS,
(offsetof(struct seccomp_data, nr))),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRAP),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
};
如何脚本化安装seccomp规则
const cm = new CModule(`
void hello(void) {
printf("Hello World from CModule\n");
}
`);
const hello = new NativeFunction(cm.hello, 'void', []);
hello();
如何捕获异常
// 异常处理
Process.setExceptionHandler(function (details) {
const current_off = details.context.pc - 4;
// 判断是否是seccomp导致的异常 读取opcode 010000d4 == svc 0
if (details.message == "system error" && details.type == "system" && hex(ptr(current_off).readByteArray(4)) == "010000d4") {
// 上锁避免多线程问题
lock(syscall_thread_ptr)
// 获取x8寄存器中的调用号
const nr = details.context.x8.toString(10);
let loginfo = "n=================="
loginfo += `nSVC[${syscalls[nr][1]}|${nr}] ==> PC:${addrToString(current_off)} P${Process.id}-T${Process.getCurrentThreadId()}`
// 构造线程syscall调用参数
const args = Memory.alloc(7 * 8)
args.writePointer(details.context.x8)
let args_reg_arr = {}
for (let index = 0; index < 6; index++) {
eval(`args.add(8 * (index + 1)).writePointer(details.context.x${index})`)
eval(`args_reg_arr["arg${index}"] = details.context.x${index}`)
}
// 获取手动堆栈信息
loginfo += "n" + stacktrace(ptr(current_off), details.context.fp, details.context.sp).map(addrToString).join('n')
// 打印传参
loginfo += "nargs = " + JSON.stringify(args_reg_arr)
// 调用线程syscall 赋值x0寄存器
details.context.x0 = call_task(syscall_thread_ptr, args, 0)
loginfo += "nret = " + details.context.x0.toString()
// 打印信息
call_thread_log(loginfo)
// 解锁
unlock(syscall_thread_ptr)
return true;
}
return false;
})
还有什么坑
1.syscall调用resume
问题描述:
但这时候会发生个新的问题,因为在主线程开启seccomp后,主线程和其后创建出来的线程都会被seccomp规则约束,在异常处理函数直接调用syscall同样会被seccomp约束再次抛出异常,就形成了”死锁“了。
如何解决:
2.堆栈回溯
问题描述:
如何解决:
function stacktrace(pc, fp, sp) {
let n = 0, stack_arr = [], fp_c = fp;
stack_arr[n++] = pc;
const mem_region = call_thread_read_maps(sp);
while (n < MAX_STACK_TRACE_DEPTH) {
if (parseInt(fp_c.toString()) < parseInt(sp.toString()) || fp_c < mem_region.start || fp_c > mem_region.end) {
break
}
let next_fp = fp_c.readPointer()
let lr = fp_c.add(8).readPointer()
fp_c = next_fp
stack_arr[n++] = lr
}
return stack_arr;
}
3.「Process.findModuleByAddress」「Process.enumerateModules」类的API导致崩溃或找不到Module信息
问题描述:
如何解决:
4.write调用约束下调用Frida的API「send」崩溃
问题描述:
如何解决:
还可以实现什么
GITHUB
https://github.com/Abbbbbi/Frida-Seccomp
如何使用
pip3 install frida
python3 multi_frida_seccomp.py
同时也自动保存到了「包名_pid_时间戳」文件夹内(支持多进程)。
看雪ID:阿碧
https://bbs.pediy.com/user-home-903162.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!
原文始发于微信公众号(看雪学苑):分享一个Android通用svc跟踪以及hook方案