srx_inline_hook 是面向 Android 运行时的纯 Rust inline hook 引擎,提供 Rust API 与 srx_inline_hook_* C ABI。
原参考项目 Git 地址:https://github.com/bytedance/android-inline-hook
- 架构:
aarch64-linux-android、x86_64-linux-android - ABI:
arm64-v8a、x86_64 - 最低构建 API:Android API 31(Android 12)
- 目标系统版本:Android 12–17
- 按函数地址安装 hook:
hook_single/srx_inline_hook_hook_func_addr - 按符号地址安装 hook:
hook_sym_addr/srx_inline_hook_hook_sym_addr - 按 so 名和符号名安装 hook:
hook_sym_name/srx_inline_hook_hook_sym_name - 获取原函数跳板:
prev_func、hook_with_orig、SRX_INLINE_HOOK_CALL_PREV - 指令级 intercept:
intercept_func_addr、intercept_sym_addr、srx_inline_hook_intercept_* - 记录与诊断:
dump_records、list_hooks、diagnose、trampoline_stats - linker 辅助:符号查找、加载/卸载回调、pending hook / intercept
use core::ffi::c_void;
use std::sync::Mutex;
use srx_inline_hook::{HookMode, HookStub, hook_single, init, prev_func, unhook};
static STUB: Mutex<Option<HookStub>> = Mutex::new(None);
extern "C" fn target_add(a: i64, b: i64) -> i64 {
a + b
}
extern "C" fn replacement_add(a: i64, b: i64) -> i64 {
let stub = STUB.lock().unwrap().unwrap();
let prev = unsafe { prev_func(stub).unwrap() };
let prev_fn: extern "C" fn(i64, i64) -> i64 = unsafe { core::mem::transmute(prev) };
prev_fn(a, b) + 1000
}
fn main() {
init(HookMode::Unique, false).unwrap();
let stub = unsafe {
hook_single(
target_add as *mut c_void,
replacement_add as *const c_void,
)
.unwrap()
};
*STUB.lock().unwrap() = Some(stub);
assert_eq!(target_add(1, 2), 1003);
unsafe { unhook(stub).unwrap() };
*STUB.lock().unwrap() = None;
assert_eq!(target_add(1, 2), 3);
}头文件位于 include/srx_inline_hook.h。
#include "srx_inline_hook.h"
#include <stdint.h>
#include <string.h>
static void *g_stub = 0;
typedef size_t (*strlen_t)(const char *s);
static size_t replacement_strlen(const char *s) {
strlen_t orig = (strlen_t)srx_inline_hook_get_prev_func(g_stub);
return orig(s) + 100;
}
void install_hook(void) {
int rc = srx_inline_hook_init(SRX_INLINE_HOOK_MODE_UNIQUE, false);
if (rc != SRX_INLINE_HOOK_ERRNO_OK) return;
g_stub = srx_inline_hook_hook_sym_name(
"libc.so",
"strlen",
(void *)replacement_strlen,
0);
}
void uninstall_hook(void) {
if (g_stub != 0) {
srx_inline_hook_unhook(g_stub);
g_stub = 0;
}
}需要安装 Android SDK、Android NDK 和 cargo-ndk。
cargo install cargo-ndk
rustup target add aarch64-linux-android x86_64-linux-android双架构 release 构建:
ANDROID_HOME=<android-sdk> ANDROID_NDK_HOME=<android-ndk> \
RUSTFLAGS="-C force-frame-pointers=yes" \
cargo ndk -t arm64-v8a -t x86_64 --platform 31 build \
--workspace --release产物位置:
target/aarch64-linux-android/release/libsrx_inline_hook.sotarget/aarch64-linux-android/release/hook-testtarget/aarch64-linux-android/release/libctor_dtor_probe.sotarget/x86_64-linux-android/release/libsrx_inline_hook.sotarget/x86_64-linux-android/release/hook-testtarget/x86_64-linux-android/release/libctor_dtor_probe.so
格式检查:
cargo fmt --all -- --checkHost 单元测试只覆盖纯计算逻辑,例如指令长度解码、指令重写和位域编解码:
cargo test --workspace --libAndroid 双架构编译检查:
RUSTFLAGS="-C force-frame-pointers=yes" cargo check --workspace --target aarch64-linux-android
RUSTFLAGS="-C force-frame-pointers=yes" cargo check --workspace --target x86_64-linux-androidhook-test 是 Android 集成测试程序。它会按固定顺序运行所有场景,成功时输出:
hook-test: ALL PASS
REMOTE_DIR=/data/local/tmp/srx_inline_hook_test
adb -s <arm64-device-id> shell "rm -rf ${REMOTE_DIR} && mkdir -p ${REMOTE_DIR}"
adb -s <arm64-device-id> push target/aarch64-linux-android/release/hook-test ${REMOTE_DIR}/
adb -s <arm64-device-id> push target/aarch64-linux-android/release/libctor_dtor_probe.so ${REMOTE_DIR}/
adb -s <arm64-device-id> push target/aarch64-linux-android/release/libsrx_inline_hook.so ${REMOTE_DIR}/
adb -s <arm64-device-id> shell "chmod 755 ${REMOTE_DIR}/hook-test && cd ${REMOTE_DIR} && LD_LIBRARY_PATH=. ./hook-test"REMOTE_DIR=/data/local/tmp/srx_inline_hook_test
adb -s <emulator-id> shell "rm -rf ${REMOTE_DIR} && mkdir -p ${REMOTE_DIR}"
adb -s <emulator-id> push target/x86_64-linux-android/release/hook-test ${REMOTE_DIR}/
adb -s <emulator-id> push target/x86_64-linux-android/release/libctor_dtor_probe.so ${REMOTE_DIR}/
adb -s <emulator-id> push target/x86_64-linux-android/release/libsrx_inline_hook.so ${REMOTE_DIR}/
adb -s <emulator-id> shell "chmod 755 ${REMOTE_DIR}/hook-test && cd ${REMOTE_DIR} && LD_LIBRARY_PATH=. ./hook-test"可以用 HOOK_TEST_SCENARIO 过滤场景:
adb -s <device-id> shell \
"cd /data/local/tmp/srx_inline_hook_test && \
HOOK_TEST_SCENARIO=capi_intercept_addr LD_LIBRARY_PATH=. ./hook-test"