x-hook 针对 Android 平台 ELF 的 PLT hook 库开源项目

我要开发同款
匿名用户2018年04月25日
50阅读
开发技术C/C++
所属分类手机/移动开发
授权协议MIT

作品详情

爱奇艺开源的一个针对Android平台ELF(可执行文件和动态库)的PLT(ProcedureLinkageTable)hook库。

xhook一直在稳定性和兼容性方面做着持续的优化。

              oooo                            oooo                      `888                            `888          oooo    ooo  888 .oo.    .ooooo.   .ooooo.   888  oooo     `88b..8P'   888P"Y88b  d88' `88b d88' `88b  888 .8P'        Y888'     888   888  888   888 888   888  888888.       .o8"'88b    888   888  888   888 888   888  888 `88b.    o88'   888o o888o o888o `Y8bod8P' `Y8bod8P' o888o o888o特征

支持Android4.0(含)以上版本(APIlevel>=14)。

支持armeabi,armeabi-v7a和arm64-v8a。

支持 ELFHASH 和 GNUHASH 索引的符号。

支持 SLEB128 编码的重定位信息。

不需要ROOT权限。

不依赖于任何的第三方动态库。

纯C的代码。比较小的库体积。

编译

你需要googleNDK来编译xhook。

最新版本的xhook在开发和调试中使用的NDK版本是 r16b。

编译动态库(libxhook.so和其他的用于测试的动态库)

./build_libs.sh

把动态库安装到Demo工程的libs目录中

./install_libs.sh

清除动态库

./clean_libs.shDemocd ./xhookwrapper/./gradlew assembleDebugadb install ./app/build/outputs/apk/debug/app-debug.apkAPI

外部API头文件: libxhook/jni/xhook.h

1.注册hook信息int xhook_register(const char  *pathname_regex_str,                     const char  *symbol,                     void        *new_func,                     void       **old_func);

在当前进程的内存空间中,在每一个符合正则表达式 pathname_regex_str 的已加载ELF中,每一个调用 symbol 的PLT入口点的地址值都将给替换成 new_func。之前的PLT入口点的地址值将被保存在 old_func 中。

new_func 必须具有和原函数同样的函数声明。

成功返回0,失败返回非0。

pathname_regex_str 只支持 POSIXBRE 定义的正则表达式语法。

2.执行hookint xhook_refresh(int async);

根据前面注册的hook信息,执行真正的hook操作。

给 async 参数传 1 表示执行异步的hook操作,传 0 表示执行同步的hook操作。

成功返回0,失败返回非0。

xhook在内部维护了一个全局的缓存,用于保存最后一次从 /proc/self/maps 读取到的ELF加载信息。每次一调用 xhook_refresh 函数,这个缓存都将被更新。xhook使用这个缓存来判断哪些ELF是这次新被加载到内存中的。我们每次只需要针对这些新加载的ELF做hook就可以了。

3.清除缓存void xhook_clear();

清除xhook的缓存,重置所有的全局标示。

如果你确定你需要的所有PLT入口点都已经被替换了,你可以调用这个函数来释放和节省一些内存空间。

4.启用/禁用调试信息void xhook_enable_debug(int flag);

给 flag 参数传 1 表示启用调试信息,传 0 表示禁用调试信息。(默认为:禁用)

调试信息将被输出到logcat,对应的TAG为:xhook。

5.启用/禁用SFP(段错误保护)void xhook_enable_sigsegv_protection(int flag);

给 flag 参数传 1 表示启用SFP,传 0 表示禁用SFP。(默认为:启用)

xhook并不是一个常规的业务层的动态库。在xhook中,我们不得不直接计算一些内存指针的值。在一些极端的情况和环境下,读或者写这些指针指向的内存会发生段错误。根据我们的测试,xhook的行为将导致APP崩溃率增加“一千万分之一”(0.0000001)。(具体崩溃率可能会增加多少,也和你想要hook的库和符号有关)。最终,我们不得不使用某些方法来防止这些无害的崩溃。我们叫它SFP(段错误保护),它是由这些调用和值组成的:sigaction(), SIGSEGV, siglongjmp() 和 sigsetjmp()。

在release版本的APP中,你应该始终启用SFP,这能防止你的APP因为xhook而崩溃。在debug版本的APP中,你应该始终禁用SFP,这样你就不会丢失那些一般性的编码失误导致的段错误,这些段错误是应该被修复的。

应用举例//监测内存泄露xhook_register(".*\\.so$", "malloc",  my_malloc,  NULL);xhook_register(".*\\.so$", "calloc",  my_calloc,  NULL);xhook_register(".*\\.so$", "realloc", my_realloc, NULL);xhook_register(".*\\.so$", "free",    my_free,    NULL);//监控 sockets 生命周期xhook_register(".*\\.so$", "getaddrinfo", my_getaddrinfo, NULL);xhook_register(".*\\.so$", "socket",      my_socket,      NULL);xhook_register(".*\\.so$", "setsockopt"   my_setsockopt,  NULL);xhook_register(".*\\.so$", "bind",        my_bind,        NULL);xhook_register(".*\\.so$", "listen",      my_listen,      NULL);xhook_register(".*\\.so$", "connect",     my_connect,     NULL);xhook_register(".*\\.so$", "shutdown",    my_shutdown,    NULL);xhook_register(".*\\.so$", "close",       my_close,       NULL);//过滤出和保存部分安卓 log 到本地文件xhook_register(".*\\.so$", "__android_log_write",  my_log_write,  NULL);xhook_register(".*\\.so$", "__android_log_print",  my_log_print,  NULL);xhook_register(".*\\.so$", "__android_log_vprint", my_log_vprint, NULL);xhook_register(".*\\.so$", "__android_log_assert", my_log_assert, NULL);//追踪某些调用xhook_register("^/system/.*$", "mmap",   my_mmap,   NULL);xhook_register("^/vendor/.*$", "munmap", my_munmap, NULL);//防御某些注入攻击xhook_register(".*com\\.hacker.*\\.so$", "malloc",  my_malloc_always_return_NULL, NULL);xhook_register(".*/libhacker\\.so$",     "connect", my_connect_with_recorder,     NULL);//修复某些系统 bugxhook_register(".*some_vendor.*/libvictim\\.so$", "bad_func", my_nice_func, NULL);//现在执行 hook!xhook_refresh(1);许可证

Copyright(c)2018-present,爱奇艺,Inc.Allrightsreserved.

xhook中大多数的源码使用MIT许可证,另外的一些源码使用BSD样式的许可证。

详细信息请查看LICENSE文件。

 
声明:本文仅代表作者观点,不代表本站立场。如果侵犯到您的合法权益,请联系我们删除侵权资源!如果遇到资源链接失效,请您通过评论或工单的方式通知管理员。未经允许,不得转载,本站所有资源文章禁止商业使用运营!
下载安装【程序员客栈】APP
实时对接需求、及时收发消息、丰富的开放项目需求、随时随地查看项目状态

评论