ebpf在安卓中的使用

前置条件

  • 电脑端:Linux 环境(Ubuntu),安装了 adb, git, debootstrap, qemu-user-static

  • 手机端:已 Root,开启 USB 调试,内核版本 ≥ 4.14(推荐 Android 10+)。


构建 Debian 镜像

  1. 获取源代码

    git clone https://github.com/joelagnel/adeb.git
    cd adeb
    
    • 坑点 \(1\):国外源无法下载

      现象:运行构建脚本时,卡在下载阶段,或者报 Failed getting release file

      原因:默认的 ftp.us.debian.org 在国内无法访问。

      解决:修改 buildstrap 文件,将源替换为清华源。

    • 坑点 \(2\)Debian 10 (Buster) 版本过旧

      现象:即使换了源,下载依然报错,或者找不到 Release 文件。

      原因:Debian 10 已停止常规支持,源的路径结构发生了变化。

      解决:升级到 Debian 11 (Bullseye)
      修改 androdeb 文件(注意不是 buildstrap,这是参数传递的源头):
      找到 DISTRO=buster 改为 DISTRO=bullseye

    • 坑点 \(3\) :软件包名不兼容

      现象:报错 Couldn't find these debs: llvm-7-dev, python...

      原因:Debian 11 淘汰了旧版包名(如 clang-7, python),必须用新名(clang, python3)。

      解决:编辑 packages/bcc 文件。
      清空内容,填入适配 Debian 11 的新列表(包含 llvm-dev, python3, clang 等)。

    • 坑点 \(4\) :备份文件导致冲突

      现象:修改了 packages/bcc 后依然报错,提示新旧包名混杂。

      原因:ADEB 脚本会读取 packages/ 目录下所有文件。你备份的 bcc.bak 和默认自带的 compilers 等文件里依然包含旧包名,被脚本误读了。

      解决:只保留 packages/bcc 这一个文件。删除或移走所有其他文件(bcc.bak, compilers, editors 等)。

    • 坑点 \(5\):幽灵挂载

      现象:构建失败后,无法删除 /data/androdeb,提示 Read-only file system

      原因:上次失败的构建残留了/proc, /sys 的挂载,导致无法直接删除文件夹。

      解决:重启手机(最稳妥),然后 adb shell rm -rf /data/androdeb

  2. 解决坑点

    • 步骤\(1\) : 把默认的 Debian 10 (Buster) 升级为 Debian 11 (Bullseye)

      adeb 文件中 DISTRO=buster 改为 DISTRO=bullseye

    • 步骤\(2\) : 修改下载源

      buildstrap 文件中 http://ftp.us.debian.org/debian/http://mirrors.aliyun.com/debian/ 替换成 http://mirrors.tuna.tsinghua.edu.cn/debian/

    • 步骤\(3\) : 把旧的 clang-7, python 替换为 Debian 11 支持的新包名。

      packages/bcc 中的内容全部删除,复制下述内容。

      PACKAGES+="
      llvm-dev
      libclang-dev
      libelf-dev
      libfl-dev
      libunwind-dev
      libdw-dev
      git
      gcc
      libtool
      autoconf
      make
      cmake
      iperf
      arping
      ethtool
      flex
      bison
      python3
      clang
      python3-netaddr
      python3-pyroute2
      python3-distutils
      "
      
      INSTALL_BCC=1
      
    • 步骤 \(4\) : 移除 packages/ 目录下所有可能包含旧配置的文件,只留我们改好的 bcc

       # 先创建一个临时文件夹存放旧文件
      mkdir -p ~/adeb_old_packages
      
      # 把除了 bcc 以外的所有文件都移走(包括 compilers, editors 以及你可能备份的 bcc.bak)
      mv packages/compilers packages/editors packages/others packages/scheduler packages/tracers ~/adeb_old_packages/
      
      # 如果你有备份文件,也删掉或移走
      rm -f packages/*.bak packages/*~
      
    • 步骤 \(5\) : 清除之前的“幽灵挂载”,开始正式下载和推送。

      1. 重启手机

        adb reboot
        # 等待手机开机并连接
        adb wait-for-device
        
      2. 删除手机的旧目录

        adb shell rm -rf /data/androdeb
        
      3. 执行最终构建命令 (前两步的执行都建立到 3. 的执行失败)

        sudo ./adeb prepare --build --arch arm64 --full
        

打通网络与权限 (ADEB 内部操作)

  1. 进入环境

    ./adeb shell
    
  • 坑点 \(6\)DNS 解析失败

    现象:ping mirrors.tuna.tsinghua.edu.cn 提示 Temporary failure in name resolution

    原因:/etc/resolv.conf 丢失或为空。

    解决:手动写入 DNS

    echo "nameserver 223.5.5.5" > /etc/resolv.conf
    
  • 坑点 \(7\):无网络权限

    现象:ping 223.5.5.5 报错 Network is unreachable

    原因:安卓内核限制只有特定 GID (Group ID) 的用户才能联网。Debianroot 用户默认不在安卓的“上网组”里。

    解决:添加安卓用户组。

    groupadd -g 3003 aid_inet
    groupadd -g 3004 aid_net_raw
    usermod -a -G aid_inet,aid_net_raw root
    

    关键动作:执行完必须 exit 退出并重新进入 ADEB,权限才生效。

  • 坑点 \(8\)SELinux 拦截

    现象:即使用了正确的 GID,依然 Ping 不通。

    原因:安卓的防火墙 (SELinux) 处于 Enforcing 模式,拦截了陌生环境的请求。

    解决:在电脑端执行 adb shell su -c setenforce 0

  • 坑点 \(9\)DNS 依然不稳定

    现象:IP 能通,但域名解析时好时坏。

    解决:绕过 DNS,直接改 Hosts

    echo "101.6.15.130 mirrors.tuna.tsinghua.edu.cn" >> /etc/hosts
    
  1. 软件最终安装成功

    apt update
    apt install bpftrace bpfcc-tools linux-perf xz-utils
    

挂载内核接口(eBPF 运行环境)

软件装好了,但 bpftrace 报错。
  • 坑点 \(10\)Debugfs 未挂载

    现象:运行 bpftraceNo such fileopen(/sys/kernel/debug/...): failed

    原因:手机内核默认没挂载调试文件系统,eBPF 没法通过文件系统和内核对话。

    解决:手动挂载。

    mount -t debugfs debugfs /sys/kernel/debug
    
  • 坑点 \(11\)Tracepoint 找不到 (通讯录丢失)

    现象:能运行 interval(打点),但 tracepoint:syscalls:... 报错 not found,且列表为空。

    原因:新版安卓内核把 tracing 独立为 tracefs,需要单独挂载,且需要手动创建挂载点。

    解决:

    mkdir -p /sys/kernel/debug/tracing
    mount -t tracefs nodev /sys/kernel/debug/tracing
    
  • 坑点 \(12\):内核阉割了 \(Syscalls\) 分类

    现象:挂载都对了,但 tracepoint:syscalls:sys_enter_openat 还是报错。

    原因:安卓生产版内核为了精简,移除了标准的 syscalls 分类。

    解决:使用 raw_syscalls(原始入口)或 kprobe(动态探针)。

    # 成功方案
    bpftrace -e 'tracepoint:raw_syscalls:sys_enter { ... }'
    

最终成果

为了防止重启手机后还要把上面那些挂载命令重敲一遍,我们在adeb主文件夹下保存了 run.sh

#!/bin/bash

echo "[+] 正在获取 Root 权限..."
adb root
adb wait-for-device

echo "[+] 正在关闭防火墙 (SELinux)..."
adb shell setenforce 0

echo "[+] 正在挂载内核调试系统..."
adb shell mount -t debugfs debugfs /sys/kernel/debug
adb shell mkdir -p /sys/kernel/debug/tracing
adb shell mount -t tracefs nodev /sys/kernel/debug/tracing

echo "[+] 准备完毕,正在进入 ADEB..."
./adeb shell

只需要运行 ./run.sh,进去直接运行。


测试查看

  1. bpftrace -e 'kprobe:vfs_read { @[comm] = count(); }'

    玩法:运行后,操作手机打开几个 APP,等待 5 秒,按 Ctrl+C 结束。

    看点:它会打印一个排行榜,告诉你刚才谁读文件次数最多(通常 logdsystem_server 会排前面)。


posted @ 2025-11-20 21:12  xqy2003  阅读(3)  评论(0)    收藏  举报