Android
平台从上到下,无需ROOT/解锁/刷机,应用级拦截框架的最后一环 ——SVC
系统调用拦截。
由于我们虚拟化产品的需求,需要支持在普通的Android
手机运行。我们需要搭建覆盖应用从上到下各层的应用级拦截框架,而Abyss
作为系统SVC
指令的调用拦截,是我们最底层的终极方案。
01. 说明
tracee: 被ptrace
附加的进程,通常为目标应用进程。
tracer: 用来ptrace
其他进程的进程,在该进程里处理系统调用。
本框架利用Android
的Provider
组件启动拦截处理的服务进程,进程启动后创建独立的一个线程循环处理所有拦截的系统调用回调。由于本工程只是演示方案的可行性并打印日志,所以业务逻辑处理比较简单,可以根据需要的自行扩展。
若要接入具体业务,可能需要改成多线程的方式进行处理,提升稳定性。不过我们实测多线切换也有一定损耗,性能提升有限,但确实稳定性有提升,防止某个处理耗时导致应用所有进程阻塞。
02. 处理流程
应用进程tracee
被附加流程如下:
tracer
过程如下:
说明: 使用fork()
的目的是为了让工作线程去附加。ptrace
有严格的限制,只有执行附加attach
的线程才有权限操作对应tracee
的寄存器。
03. 系统调用处理
03.01 忽略库机制
由于业务的需要,为了提升性能,我们需要忽略某些库中的系统调用,如:libc.so
。
在find_libc_exec_maps()
中找到libc.so
可执行代码在maps
中的内存地址区间,需要处理的系统调用:
//enable_syscall_filtering()
FilteredSysnum internal_sysnums[] = {
{ PR_ptrace, FILTER_SYSEXIT },
{ PR_wait4, FILTER_SYSEXIT },
{ PR_waitpid, FILTER_SYSEXIT },
{ PR_execve, FILTER_SYSEXIT },
{ PR_execveat, FILTER_SYSEXIT },
{PR_readlinkat, FILTER_SYSEXIT}, //暂时没有处理
};
set_seccomp_filters
针对不同的arch
,设置系统调用的ebpf
。不同架构的ebpf
语句会填充到一起,ebpf
的组成伪代码如下:
for (每一种架构) {
start_arch_section;
for (每一个当前架构下的系统调用)
add_trace_syscall;
end_arch_section;
}
finalize_program_filter;
start_arch_section;// 架构相关处理的ebpf,包括libc筛选的语句
add_trace_syscall;// 增加匹配要处理系统调用的ebpf语句
end_arch_section;// 尾部的ebpf语句(语句含义:匹配到系统调用则返回)
finalize_program_filter;// 最后面的ebpf语句,杀死其他异常情况下的线程
最终,调用如下语句,设置ebpf
。
status = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &program);