Android平台bpftrace实践
2023-4-24 21:14:21 Author: 哆啦安全(查看原文) 阅读量:80 收藏

Android上的ebpf已经成为现实

  • 维术大佬修改的debian方案挺好,可以直接在android跑bcc、bpftrace等基于ebpf封装的工具

  • 脸哥实践出真知下的 go + c 混合开发ebpf程序的方案挺好,开发环境简单了,运行也不再需要debian环境依赖了,调用栈也有了unix domaian socket和load so的方案,属实方便了许多

    • stackplz 和 estrace 属实挺好,学到很多,脸哥和各位大佬牛逼

  • android上的ebpf实践感觉大多还是基于syscall监测的需求

  • 之前看了一些bpftrace的文章感觉用它来开发类似syscall的需求应该是更快的

    • 需依赖debian环境

    • 脚本化,参数解析之类的简单,很简单,非常简单

    • 当然了,能力不如bcc下的程序和脸哥他们用的方案强,主要是一些api来到bpftrace这边不知道是啥,当然也可能是我的问题,没有发掘出它的实力

    • 接下来搞个简单的bpftrace demo来仿写一丢丢的estrace

设备环境:

推荐钞能力解决,直接上高内核版本设备:小米12内核:5.10.101-android12-9-00005-ga829d48e78bd-ab9206161(原版未改)

开发环境:

eadb debian + vscode remote
当 Xiaomi 12 遇到 eBPF:https://mp.weixin.qq.com/s/h_ixxr1WZ8VqYt-zMrwSDAeBPF on Android之bcc环境准备——eadb简版:https://blog.seeflower.dev/archives/138/60秒学会用eBPF-BCC hook系统调用 ( 2 ) hook安卓所有syscall:https://bbs.kanxue.com/thread-275176.htm
文章看下来并实践的话,你应该已经vscode可以远程开发和跑bcc脚本了

Android Debian bpftrace环境初始化

进入debian环境:/data/eadb/run /data/eadb/debian
vi /etc/apt/sources.listdeb http://ftp.cn.debian.org/debian sid main
apt-get updateapt-get install bpftracebpftrace -Vbpftrace v0.17.0

比着estrace上代码

#!/usr/bin/env bpftrace
struct timespec { long tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ };
BEGIN{ printf("Tracing all system calls... Hit Ctrl-C to end.\n");}

tracepoint:raw_syscalls:sys_enter/uid == $1/{ if (args->id == 221){ // int execve(const char *pathname, char *const argv[], char *const envp[]); printf("comm: %s, nr: %d, ", comm, args->id); printf("execve: path=%s, argv=", str(uptr(args->args[0]))); join(uptr(args->args[1])); }else if (args->id == 281){ // int execveat(int dirfd, const char *pathname, char *const argv[], char *const envp[], int flags); printf("comm: %s, nr: %d, ", comm, args->id); printf("execveat: path=%s, argv=", str(uptr(args->args[1]))); join(uptr(args->args[2])); }else if (args->id == 101){ // int nanosleep(const struct timespec *req, struct timespec *rem); printf("comm: %s, nr: %d, ", comm, args->id); $wait_time = (struct timespec *)uptr(args->args[0]); printf("nanosleep: tv_sec=%ld, tv_nsec=%ld\n", $wait_time->tv_sec, $wait_time->tv_nsec); }else if (args->id == 56){ // int openat(int dirfd, const char *pathname, int flags, mode_t mode); //printf("comm: %s, nr: %d, ", comm, args->id); //printf("openat: path=%s\n", str(uptr(args->args[1]))); @mem["openat", str(uptr(args->args[1]))] = count(); }else if (args->id == 78){ // ssize_t readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); //printf("comm: %s, nr: %d, ", comm, args->id); //printf("readlinkat: path=%s\n", str(uptr(args->args[1]))); @mem["readlinkat", str(uptr(args->args[1]))] = count(); } return;}

代码说明

  • 就搞了一些系统调用号,主要是实践bpftrace的能力,调用号数量不是问题,加就行了,体力活 

    • gpt查下函数原型,比着解析参数就是了

    • 对了,我现在不卖了gpt账号了,买别人的吧

    • https://www.fakabang.com/details/F5DC5860

  • bpftrace的命令行参数解析,比较方便

  • 主要是监测点的参数解析,不论是单个char *还是char *[],解析和输出都非常方便

  • 结构体也是支持的

  • bpf map用起来也是十分的方便,还可以数据统计

  • 总之就是十分的方便

  • 也可以ustack拿到用户空间的调用栈,但好像解析有问题,不能直接显示出具体的文件和偏移,不过感觉问题不大,自己去maps对照下映射文件和偏移也行

  • 修改参数好像有点问题,没找到api,只看到了override

  • 单论syscall监测场景感觉足够了,方便快捷是其他方案无法比拟的

  • 就这样吧

简单跑下代码看看,拿estrace的第一个例子试试

bpftrace开跑:

bpf map用来统计:

bpftrace的开发文档https://github.com/iovisor/bpftrace/blob/master/docs/reference_guide.md

简单实践over

题外话:论如何学好android-ebpf,脸哥已经给了答案


文章来源: http://mp.weixin.qq.com/s?__biz=Mzg2NzUzNzk1Mw==&mid=2247495502&idx=2&sn=a33ad7f919fb295c1721b04234dffe37&chksm=ceb8aa00f9cf231697c094ee4da423e0aca7971f0c85c1bf0483e5da2d2b1326e1bb174bf1d1#rd
如有侵权请联系:admin#unsafe.sh