读完需要
速读仅需 3 分钟
/ 安卓系统上 eBPF 开发的一些建议 /
很多朋友经常会问,在安卓系统上开发 eBPF 的一般流程与最佳实践是怎样的?下面,将围绕这个话题与大家探讨一二,限本人研究与学习经验,欢迎讨论。
1
万事开头难,在不知道如何开发,如何测试的情况下,环境的搭建更是难上加难。从零开始的学习路径,都是踏着先人学习的足迹摸索。
网络上目前公开最多的方案是 adeb,然后是 weishu 后面开发的 eadb。eadb 在安卓设备上使用 chroot 来运行一套 rootfs,这种方案算是公开的较好的方案了。但问题还是有的,这种环境非原生安卓,程序二进制中存在差异,也不好部署。最后是 FB 发布的一套安卓编译版本的 bpftools 工具。让环境的依赖变得最小了。这个时候,需要把重点放到安卓设备内核的 eBPF 支持上面。内核选项的开启与否,直接关系着设备对 eBPF 的最终支持情况。bcc 的官方 github 上也列出了常用到的内核选项,地址是:https://github.com/iovisor/bcc/blob/master/docs/kernel_config.md。这些选项很多默认安卓设备也是没开的,需要动手编译安卓内核开启之 ( https://github.com/iovisor/bcc/blob/master/docs/kernel_config.md。这些选项很多默认安卓设备也是没开的,需要动手编译安卓内核开启之 )。
1.1
模拟器
于是后面,有了我的第一个环境搭建尝试[安卓 eBPF 开发环境搭建方案]。地址是:https://mp.weixin.qq.com/s?__biz=MzU3MTY5MzQxMA==&mid=2247484267&idx=1&sn=eec5a8d28bd614262271a4ca5d834506 。这个视频中,我采用的运行环境是 cuttlefish 模拟器,之所以选择它是因为它目前支持 arm64 的 kvm 虚拟化,与 AVD 现在内核同源了。而且这个环境搭建也可以使用 AVD 来做,只是配置内核的方法麻烦一点点。
配置好的内核我提供了下载。地址是:https://github.com/feicong/ebpf-course/releases/tag/latest。内核解压密码:qq121212。这里的内核**直接替换 AVD 原内核就可以了**。我也做了相应的展示视频。补丁了安卓 10[**补丁安卓 10 内核完美支持 eBPF 特性**],视频地址:https://mp.weixin.qq.com/s?__biz=MzU3MTY5MzQxMA==&mid=2247484065&idx=1&sn=d3858f002d3a61dd2c7056b76e27935d 。 安卓 11[补丁安卓内核完美支持 eBPF 特性],视频地址:https://mp.weixin.qq.com/s?__biz=MzU3MTY5MzQxMA==&mid=2247484042&idx=1&sn=d0626e14add4b49158324644d355ca1f 。 当然,如果你对如何编译与补丁感兴趣,可以考虑下本文最后的 eBPF 系列视频课程链接。
内核选项开启部分,可以使用bpftool feature来看开启情况,目前最新的主线内核支持的较全面了。我也做了个视频[更新安卓主线内核体验全功能的安卓 eBPF 环境],地址是:https://mp.weixin.qq.com/s?__biz=MzU3MTY5MzQxMA==&mid=2247484360&idx=1&sn=9743d499813893c67bec0ad728d5bfb0 。目前 cuttlefish 在 5.10,5.15 与 6.1 之间切换最是方便,也最适合学习。
在安卓模拟器中可以跑安卓 eBPF 环境,如果想搭建传统的 Linux 的 eBPF 学习环境,最简单的方法是 Ubuntu 系统的电脑,或者虚拟机、WSL2 等都是可以的。当然也可以使用 QEMU 这类模拟器来做。我也做了一个视频[使用 rock5b 开发板配合 qemu 开发 eBPF-附镜像下载],地址是:https://mp.weixin.qq.com/s?__biz=MzU3MTY5MzQxMA==&mid=2247484160&idx=1&sn=c6b257b5aa1b9a9fe19e9c0683f49039 。在这个视频中,主要是对 arm64 架构做了个 eBPF 的环境搭建,TRACING 类型的 eBPF 程序,arm64 架构到了 6.4 版本内核才开始支持,低版本是功能残缺的。我也做了视频[更新 Linux 主线内核测试最新 eBPF 功能],地址是:https://mp.weixin.qq.com/s?__biz=MzU3MTY5MzQxMA==&mid=2247484287&idx=1&sn=c26761bac4e8463d60747cae1c7ca4e2 。
1.2
开发板
开发板是 eBPF 学习环境搭建的另一种方案,开发板通常即可以刷机 Linux,在上面模拟安卓,也可以刷安卓系统镜像,来原生使用安卓,这两种方式都是可行的。在实践中,我更倾向于前者,灵活性高,可配置性高。上面的 cuttlefish 方案我就是跑在上面的。开发板上模拟安卓还有一个方案:redroid 容器方案。这个方案我也做了一个视频[使用 rock5b 开发板运行多个安卓容器环境],地址是:https://mp.weixin.qq.com/s?__biz=MzU3MTY5MzQxMA==&mid=2247484013&idx=1&sn=00c86fe2831c6963c549f28d645a25cf。这种方案依赖于本机的内核配置与 GPU 加速,目前 cuttlefish 方案与 redroid 的 GPU 加速都存在着问题,相信不久以后,官方或社区会解决支持问题的。redroid 由于依赖开发板自己系统的内核,因此内核选项的开启就是为开发板编译修改内核。
目前 5.10 内核的 eBPF 特性支持也算是 8 成可用,我也做了一个视频[rock5b 开发板的 Linux 与安卓 eBPF 开发功能],地址是:https://mp.weixin.qq.com/s?__biz=MzU3MTY5MzQxMA==&mid=2247484020&idx=1&sn=3382a35ded5ce8e17b1444a274850e1a 。一般情况下的学习够用了。RK 预计会在今年第三个季度升级内核到 6.1/6.3,那个时候,安卓容器方案的 eBPF 环境会更加好用。
1.3
手机
选择哪个安卓手机最合适?这个问题最的最多,也是最难回答的。因为这涉及到了 arm64 架构 Linux 内核对 eBPF 的支持情况。简单的讲,5.10 的内核默认情况下,支持较多的特性,最合适的安卓 14 的 6.1 内核目前还没发布,其它情况下的低版本,都是需要补丁内核的。最低的版本测试是 pixel2/pixel2xl 的 4.9 内核,需要打的补丁不少,我做了视频[为安卓老设备 4.9 内核的安卓 10 到 12 打上 eBPF 补丁], 地址是:https://mp.weixin.qq.com/s?__biz=MzU3MTY5MzQxMA==&mid=2247484248&idx=1&sn=41f5305583cd770d06ee1f124d6b4133 。
目前,较为推荐的手机类型是支持刷 GKI 内核的安卓 12 手机,天机 8100 与骁龙 8gen1 以后的 SOC。它们的内核多是 5.10,而安卓 13 的 5.15 的很多内核,是开启不了 kprobes 的目前!这个坑让 eBPF 相应的 kprobes 代码,需要做向 tracepoint/raw_syscalls 的 Hook 点移植,会让很多人感到困惑,具体这里不展开了。
具体的手机型号大家自己摸索,能刷内核改内核就都是合适的。
2
这里涉及一个问题,就是系统是否一定要开 BTF?我个人的回答是的!因为这给编码与运行解决了很多麻烦,libbpf 的 BTF 外部文件传参是通过命令行 opts 设置的,不支持环境变量方式,意味着需要编译编译代码来兼容 BTF 外部文件,而且涉及到 MAP 与全局变量的操作,编译器现在搞事都是直接上 BTF 了。虽然 ebpfgo 很多时候可以不用 BTF 来完成功能,类似有 ecapture 有 nocore 版本,但复杂场景的程序,怎么可能少了 BTF,与其代码兼容它,不如环境兼容它。
编译器方面,虽然 GCC 的 CTF 也是支持 eBPF 开发的,但 LLVM10 以后支持的 BTF 才是官方最认可的开发工具链。做 eBPF 开发时,使用 LLVM 才是最合适的。这里提一嘴,编译安卓内核时,高版本的 GCC 工具链是能正确生成内核 BTF 信息的,RK 官方 SOC 给出的内核编译脚本,就是使用 GCC 来交叉编译的。这其实得益于 pahole 在这几种厂家调试格式(BTF、CTF、DWARF)之间的周旋,对于一般开发人员而言,是透明的。
框架方面,首选 libbpf,这是 Linux 官方与安卓官方用的。安卓自身使用的版本较老,需要自己编译新版本使用。这个框架需要配合 bpftool,目前这个工具可以编译静态版本了,安心使用即可。而开发的环境,可以是 Linux、macOS、Windows。涉及到 bpftool 调用的时候,可以使用 docker 形式调用即可。
其它是 cilium 的 ebpfgo 框架,这是 golang 语言中使用最多最成熟的框架,使用它的前提是对 golang 编程语言熟悉。使用它开发一个最大的好处是跨平台编译方面,不依赖其它任何第三方库。
还有一些 Lua、Rust、WASM 的语言绑定就不说了,我用的不多。
3
libbpf 与 ebpfgo 框架,都可以在 Linux、macOS、Windows 上进行开发。上面也说了,skel 生成依赖 bpftool 的话,docker 方式走一个即可。
我个人使用的 M1 macOS 13,开发 Linux 与 eBPF 的程序都是没问题。
4
上面内容所述,都是我的实践与看法,是开发安卓恶意代码分析沙箱过程中的一点心得与体会,本人在此基础上,开发了一套eBPF安全开发与攻防的视频课程。如下所示的第三季部分
是沙箱开发过程中,关于 agent 安全增强与代码行为捕获功能实践的一些应用。
能力有限,错误难免,欢迎指正。
上面所列出的视频,部分提供了工具下载与原理讲解,部分只提供了效果展示,所有的内容在我的 eBPF 系列视频中有详情讲解,地址是:https://github.com/feicong/ebpf-course ( https://github.com/feicong/ebpf-course ) 。如果看官有什么交流的想法,可以加我微信 feicongcn 交流。