LSPosed_mod Native层Hook实现:基于Dobby的Inline Hook技术应用
【免费下载链接】LSPosed_mod My changes to LSPosed 项目地址: https://gitcode.com/GitHub_Trending/ls/LSPosed_mod
技术架构概述
LSPosed_mod作为Android平台上的模块化Hook框架,其Native层实现基于Dobby内联钩子库构建核心拦截能力。框架通过拦截动态链接器do_dlopen函数实现对目标进程的精确控制,在core/src/main/jni/src/native_api.cpp中定义了完整的钩子注册与回调分发机制。
核心技术组件
- Dobby内联钩子:提供跨架构(ARM/ARM64/x86)的二进制拦截能力
- 符号解析系统:基于ELF文件格式分析实现动态符号定位(core/src/main/jni/include/elf_util.h)
- 内存保护机制:通过
mmap创建受保护内存页存储API入口表(core/src/main/jni/src/native_api.cpp#L56-L58)
Inline Hook实现原理
钩子注册流程
框架在初始化阶段通过InstallNativeAPI函数完成关键系统函数的Hook安装:
bool InstallNativeAPI(const lsplant::HookHandler & handler) {
auto *do_dlopen_sym = SandHook::ElfImg("/linker").getSymbAddress(
"__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv");
LOGD("InstallNativeAPI: {}", do_dlopen_sym);
if (do_dlopen_sym) [[likely]] {
HookSymNoHandle(handler, do_dlopen_sym, do_dlopen);
return true;
}
return false;
}
这段代码实现了三个关键步骤:
- 解析链接器(
/linker)的ELF符号表定位do_dlopen函数 - 使用Dobby引擎创建内联钩子
- 将目标函数重定向至自定义实现
do_dlopen(core/src/main/jni/src/native_api.cpp#L135-L144)
内存保护设计
为确保API入口表安全,框架采用内存页保护机制:
std::unique_ptr<void, std::function<void(void *)>> protected_page(
mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0),
[](void *ptr) { munmap(ptr, 4096); });
const auto[entries] = []() {
auto *entries = new(protected_page.get()) NativeAPIEntries{
.version = 2,
.hookFunc = &HookFunction,
.unhookFunc = &UnhookFunction,
};
mprotect(protected_page.get(), 4096, PROT_READ);
return std::make_tuple(entries);
}();
通过mmap创建可读写内存页存储API结构体,初始化完成后立即通过mprotect设置为只读模式,防止恶意篡改(core/src/main/jni/src/native_api.cpp#L56-L69)。
模块化Hook机制
模块加载回调系统
框架实现了基于白名单的模块加载监控机制,在do_dlopen钩子中:
for (std::string_view module_lib: moduleNativeLibs) {
if (hasEnding(ns, module_lib)) [[unlikely]] {
LOGD("Loading module native library {}", module_lib);
void *native_init_sym = dlsym(handle, "native_init");
if (native_init_sym == nullptr) [[unlikely]] {
LOGD("Failed to get symbol \"native_init\" from library {}", module_lib);
break;
}
auto native_init = reinterpret_cast<NativeInit>(native_init_sym);
auto *callback = native_init(entries);
if (callback) {
moduleLoadedCallbacks.push_back(callback);
return handle;
}
}
}
当系统加载目标模块时,会自动调用模块导出的native_init函数,并注册模块回调函数(core/src/main/jni/src/native_api.cpp#L108-L125)。
多回调管理
框架支持同时注册多个模块回调,通过链表结构维护:
std::list<NativeOnModuleLoaded> moduleLoadedCallbacks;
// ...
for (auto &callback: moduleLoadedCallbacks) {
callback(name, handle);
}
每个新加载的共享库都会触发所有已注册回调,实现模块化的钩子逻辑扩展(core/src/main/jni/src/native_api.cpp#L129-L131)。
关键实现文件
技术优势分析
- 兼容性设计:通过动态符号解析适配不同Android版本链接器实现
- 安全性保障:内存页保护与权限控制防止恶意篡改
- 模块化架构:支持多模块并行Hook,独立回调互不干扰
- 性能优化:使用Dobby内联钩子技术,相比传统PLT Hook减少性能开销
使用指南
开发环境配置
- 克隆项目仓库:
git clone https://gitcode.com/GitHub_Trending/ls/LSPosed_mod
- 配置NDK开发环境,确保支持C++17标准
模块开发示例
#include "native_api.h"
void native_init(void *api) {
auto *entries = static_cast<NativeAPIEntries *>(api);
// 注册自定义Hook回调
entries->registerModuleLoadedCallback([](const char *name, void *handle) {
LOGD("Module loaded: %s", name);
// 实现自定义Hook逻辑
});
}
在模块的Android.mk中声明导出符号:
LOCAL_LDFLAGS += -Wl,--version-script=$(LOCAL_PATH)/exports.lds
总结与展望
LSPosed_mod的Native层Hook架构通过Dobby内联钩子技术构建了高效、安全的二进制拦截系统。其核心优势在于模块化设计与跨版本兼容性,使得开发者能够专注于业务逻辑实现而非底层Hook细节。
未来版本将重点优化:
- 钩子冲突检测机制
- 多架构支持完善
- 内存占用优化
完整实现细节可参考项目源码,特别是core/src/main/jni目录下的相关文件。
【免费下载链接】LSPosed_mod My changes to LSPosed 项目地址: https://gitcode.com/GitHub_Trending/ls/LSPosed_mod
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



