【Abyss】Android平台应用级系统调用拦截框架
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);
03.02 PR_ptrace
因为一个tracee
只能有一个tracer
,所以需要处理该系统调用,在应用本身使用了ptrace
的时候进行仿真。
系统调用进入前,将系统调用替换为PR_void
,不做真正的ptrace
,后续仿真。
退出系统调用后,针对ptrace
的仿真。针对请求是PTRACE_ATTACH
、PTRACE_TRACEME
等做各种不同的处理。同时也处理PTRACE_SYSCALL
、PTRACE_CONT
、PTRACE_SETOPTIONS
、PTRACE_GETEVENTMSG
等各种ptrace
操作。
ptrace
有各种各样的请求,完整的处理逻辑比较复杂(我们还在消化中)。
03.03 PR_wait4、PR_waitpid
配合PR_ptrace
使用,如果当前的tracee
不是一个tracer
,则不处理直接透传给系统。或者wait
的第一个参数不为-1
,则去集合里找看等待的这个线程是否存在并且是否是当前处理线程的tracee
,如果不是,则不处理直接透传给系统。
处理的逻辑如下:
系统调用进入前,将系统调用替换为PR_void
,不实际传给内核。
退出系统调用后,仿真tracer
里wait
的处理逻辑。主要为基于当前处理的这个tracer
(代码里定义为ptracer
),去遍历它的tracee
,看是否有事件需要被处理,如有,则填充好寄存器,唤醒当前正在被处理的这个tracer
。
03.04 PR_execve、PR_execveat
主要是在USE_LOADER_EXE
开启时,将native
程序替换为使用一个固定的loader
来加载程序。
03.05 拦截日志
E INTERCEPT/SYS: vpid 2: got event 7057f E INTERCEPT: vpid 2,secomp_enabled 0, E INTERCEPT/SYS: (null) info: vpid 2: sysenter start: openat(0xffffff9c, 0xb4000073c72fcd60, 0x0, 0x0, 0xb4000073c72fcd88, 0xb4000073c72fcde8) = 0xffffff9c [0x7367d45e80, 0] E INTERCEPT/SYS: vpid 2: open path:/system/fonts/NotoSansMalayalamUI-VF.ttf E INTERCEPT/SYS: syscall_number:216 E INTERCEPT/SYS: vpid 2,openat: /system/fonts/NotoSansMalayalamUI-VF.ttf E INTERCEPT/SYS: (null) info: vpid 2: sysenter end: openat(0xffffff9c, 0xb4000073c72fcd60, 0x0, 0x0, 0xb4000073c72fcd88, 0xb4000073c72fcde8) = 0xffffff9c [0x7367d45e80, 0] E INTERCEPT/SYS: vpid 2: open path:/system/fonts/NotoSansMalayalamUI-VF.ttf E INTERCEPT/SYS: (null) info: vpid 2: restarted using 7, signal 0, tracee pid 32222,app_pid 32162 E/INTERCEPT/SYS: (null) info: vpid 3: sysenter start: close(0x90, 0x0, 0x7492d0d088, 0x6, 0x73b7b82860, 0x73b7b82880) = 0x90 [0x73633faae0, 0] E/INTERCEPT/SYS: syscall_number:41 E/INTERCEPT/SYSW: noting to do,sn:41 E/INTERCEPT/SYS: (null) info: vpid 3: sysenter end: close(0x90, 0x0, 0x7492d0d088, 0x6, 0x73b7b82860, 0x73b7b82880) = 0x90 [0x73633faae0, 0] E/INTERCEPT/SYS: (null) info: vpid 3: restarted using 7, signal 0, tracee pid 32223,app_pid 32162 E/INTERCEPT/SYS: vpid 3: got event 7057f
04. 附
额外模块:
由于本框架会在原应用中增加一个处理进程,并且会trace
到应用进程中,因此在实际使用时,还需要对新增进程和trace
痕迹进行隐藏,防止与应用检测模块冲突,支持完整的应用自身trace
调用的仿真。
这是附加的应用对抗模块,后面会作为单独文章分享给大家。
参考项目:

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
JDK23如约而至,数十种新玩法,你期待哪一种?
9 月 17 日,JDK23 它来了。 JDK23 并非长期支持版,下一个长期支持版是 JDK25,预计明年 9 月份发布。 和松哥一起来看下这次的 JDK23 都有哪些新特性~ 一 Language Previews ➜ 在 instanceof 和 switch 中 支持原始类型(预览) 增强了模式匹配,扩展 instanceof 和 switch 以支持所有原始类型。这是一项预览语言特性。 参见 JEP:455,https://openjdk.org/jeps/455 ➜ 模块导入声明(预览) 增强 Java 编程语言,使其能够简洁地导入模块导出的所有包。这简化了模块库的重用。这是一项预览语言特性。 类似这样去导入模块: import module java.base; import module java.sql; 但是如果同一个模块中出现了同名的类,那么就必须恢复到之前的写法,显式导入了。 参见 JEP476,https://openjdk.org/jeps/476 ➜ 灵活的构造函数体(第二次预览) 在 Java 编程语言中的构造函数中,允许在显式的构造函数调用之前出现语句...
- 下一篇
驭势科技借助 Zadig:实现自动驾驶服务的持续交付与运维优化
驭势科技 UISEE 成立于 2016 年 2 月,是一家专注于自动驾驶的科技型企业,致力于为全行业、全场景提供 AI 驾驶服务,做赋能出行和物流新生态的 AI 驾驶员。驭势科技坚持立足本土研发,根植全球市场。总部和研发中心设立在北京,在上海嘉定和浙江嘉善分别设有研发中心、研发试制和应用创新中心。此外,在新加坡、香港、深圳、武汉、重庆等地均设有分支机构。驭势科技依托自主研发的 U-Drive(®) 智能驾驶平台,在业务上已经形成可规模化部署的 L3-L4 级智能驾驶系统,可以满足多场景、高级别的自动驾驶需求。2019 年, 驭势科技在机场和厂区领域实现了“去安全员” 无人驾驶常态化运营的重大突破,落地“全场景、真无人、全天候”的自动驾驶技术,并由此迈向大规模商用。于 2021 年 9 月荣膺国家专精特新“小巨人”企业殊荣。2024 年 6 月,驭势科技累计真无人自动驾驶里程超 400 万公里。 随着业务扩展和公司成长,我们认识到采用先进工具优化开发和运维流程的重要性。在这一背景下,我们探索了新一代的发布和持续交付工具。Zadig 以其创新理念和强大功能,满足了我们对高效、稳定、灵活的持...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS关闭SELinux安全模块
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程