Skip to content
sy99520Public

About

基于qbdi的自用trace小工具

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

xwTrace

本项目聚焦于 Android Native 侧的 so 追踪能力:基于 QBDI(指令级插桩)与 Frida Gum(Hook 能力)构建 libqdbi.so,配套 Frida 脚本用于自动加载与触发 trace。

目录结构

xwTrace/
├── native/                 # libqdbi.so 源码与预编译依赖
│   ├── CMakeLists.txt
│   ├── core/               # 追踪核心与桥接层
│   ├── hook/               # Gum 扩展与 Hook
│   ├── soinfo/             # ELF/符号解析
│   ├── svc_call/           # SVC/系统调用相关
│   ├── include/            # 对外头文件
│   ├── record/             # 记录/输出辅助
│   └── lib/                # 预编译静态库(QBDI / Frida Gum)
├── scripts/                # Frida 脚本
│   ├── trace.js
│   └── hook.js
├── build.sh                # NDK CMake 一键构建脚本(输出到 out/)
└── README.md

环境要求

构建环境(本机)

  • Android SDK(包含 NDK)
  • CMake(脚本会优先使用 $ANDROID_SDK_ROOT/cmake/3.22.1/bin/cmake,找不到则回退到系统 cmake)
  • macOS / Linux

运行环境(设备)

  • Android 设备(arm64)
  • Frida:设备端 frida-server + 本机 frida-tools
  • 需要向 /data/local/tmp 写入文件(常见场景需要 root 或可写权限)

安装与构建

1) 构建 libqdbi.so

在项目根目录执行:

./build.sh

成功后会输出:

out/libqdbi.so

2) 推送到设备

adb push out/libqdbi.so /data/local/tmp/libqdbi.so

基本使用指南(Frida)

1) 使用追踪脚本(scripts/trace.js)

trace 模式与参数由 trace.js 的 Trace.configure() / Trace.start*() 控制;脚本本身不打印任何运行日志,所有 trace 过程日志统一通过 qbdi/native 的 logcat 输出。

Trace 模式(mode)

  • symbol:按符号名追踪(调用 native Trace_symbol / Trace_symbol_replace)
  • offset:按偏移追踪(调用 native Trace_offset / Trace_offset_replace)
  • extcalls:按偏移追踪外部调用(调用 native Trace_offset_extcalls)
  • auto:自动选择(默认):soOffset != 0 则 offset,否则 symbol

关键参数

  • traceSoPath:Trace so 在设备上的路径(默认 /data/local/tmp/libqdbi.so)
  • backend:trace 后端选择(传给 native gqb_set_backend)
  • targetSoName:要追踪的目标 so 名称(用于等待 dlopen 以及传给 native)
  • symbolName:mode=symbol 时的符号名(如 JNI_OnLoad)
  • soOffset:mode=offset/extcalls 时的偏移(十六进制或数字)
  • argCount:目标函数参数个数
  • replaceMode:是否启用 replace 版本(1=replace,0=hook)
  • fullHexdump:详细日志/更大输出(1=开启,0=关闭)
  • startTimes:从第几次命中开始记录(例如 3 表示前两次命中不记录)
  • preserveSp:是否保留 SP(1=开启,0=关闭)
  • autoStart:是否自动在目标 so dlopen 后触发(1/0)
  • autoStartDelayMs:自动触发延迟(毫秒)

启用方式(示例)

脚本加载后可在 Frida 控制台执行:

Trace.configure({
  traceSoPath: "/data/local/tmp/libqdbi.so",
  targetSoName: "libexecmain.so",
  mode: "symbol",
  symbolName: "JNI_OnLoad",
  argCount: 2,
  fullHexdump: 0,
  replaceMode: 0,
  startTimes: 1,
  preserveSp: 0,
  backend: 1,
  autoStart: 1,
  autoStartDelayMs: 0
});

也可手动启动(会立即触发,不依赖 autoStart):

Trace.start();
// 或 Trace.startSymbol("libexecmain.so", "JNI_OnLoad", 2, 1, 0, 0, 0);
// 或 Trace.startOffset("libexecmain.so", 0x1234, 2, 1, 0, 0, 0);

任务结束后(用于触发最终统计输出):

Trace.stop();

注入方式示例:

# 启动目标 App 并注入
frida -U -f com.example.target -l scripts/trace.js --no-pause

# 或附加到已运行进程
frida -U com.example.target -l scripts/trace.js

输出位置与格式

  • trace 文件:默认写入 /sdcard/Download/<soName>_trace.log(若失败则回退到 /data/local/tmp/gqb_trace.log)
  • 运行日志:通过 logcat 输出,包括
    • 每分钟一条:YYYY-MM-DD HH:MM:SS | trace_file=... | size=xx.xx MB | rate=yy.yyyy MB/s | bytes=...
    • 结束汇总:YYYY-MM-DD HH:MM:SS | trace_done | final_size=... | avg_rate=... | total_time=... | path=...

2) 示例 Hook 脚本(scripts/hook.js)

hook.js 是一个偏“定点偏移 hook”的脚本示例(需要自行修改 soName 与 offBlr),适合快速定位某条指令/调用点的回溯与上下文。

常见问题(FAQ)

Q1: 执行 build.sh 提示 SDK_DIR not found

  • 设置 ANDROID_SDK_ROOT 或 ANDROID_HOME
  • 或在根目录创建 local.properties 并写入 sdk.dir=...

Q2: 提示 NDK_DIR not found

  • 安装 NDK,并设置 ANDROID_NDK_HOME(或让 SDK 下存在 ndk/<version> 目录)

Q3: 构建完成但设备上无法加载 libqdbi.so

  • 确认设备架构为 arm64
  • 确认 so 上传路径与 traceSoPath 一致
  • 确认 SELinux/权限允许访问目标路径

About

基于qbdi的自用trace小工具

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages