赞
踩
有时程序员需要完成这类任务: 假如你有一个二进制版的系统,例如现在流行的android,你需要为这个系统开发一个软件。这个软件牵涉到系统行为,因此需要对系统做修改。然而你并没有这个系统的所有源码( Nexus S的源码不一定与 android 官方版本一模一样),或者是你只有这个系统的头文件。当你需要修改部分系统行为的时候,你不可能用源码重新编译一个共享库来替换系统文件。此时,就需要利用 dlfcn.h 运行时动态链接库来实现我们的目标。利用dlopen(),dlsym(),dlerror(),dlclose()这四个函数,可以实现类似 Windows 平台 Api Hook 机制的效果。 把它改成其他名字,比如,改为 libwuxiao_orig.so。 假如这个共享库的源码如下: #include <stdio.h> 编译一下, gcc -shared -fPIC -o libwuxiao.so wuxiao.c 可以写一个可执行程序来测试一下这个共享库。之后,你可以看到我们完全不修改这个可执行文件,让这个可执行文件执行我们增加的代码。 #include <stdio.h> extern void func_a(int a, int b); int main(int argc, char* argv) gcc -o wuxiao_test main.c -lwuxiao -L/path/to/libwuxiao.so a) 先调用dlopen(),返回libwuxiao_orig.so的句柄,再从句柄中查找想要的函数 static void* libwuxiao_handle = NULL; __attribute__((constructor)) _init_wuxiao() __attribute__((destructor)) void _fini_wuxiao() int func_c() } 链接方法: gcc -shared -fPIC -o libwuxiao.so -ldl -lwuxiao_orig -L/path/to/libwuxiao_orig.so (编译完上面的伪装共享库之后,执行一下 main_test,看看增加的代码有没有被执行。) 上面代码中,原共享库的 func_c 就是我们想要修改的函数。 这里写了一个相同的 func_c,它查找到原函数的地址,先执行 hook 代码,然后执行原 func_c 函数, 因而不会影响原函数的执行,只不过多执行了我们的代码。 随后 “伪装”成为libwuxiao.so,系统在执行程序的时候,就会查找伪造的 libwuxiao.so, 而伪造的libwuxiao.so又会去加载真正的 libwuxiao_orig.so。 1、保证原libwuxiao.so中的所有函数不会丢失 2、在调用原libwuxiao.so中的函数的时候能够执行我自己的代码。 b) 这里的方法更简单,原理与上面的相同,都是通过在伪造的libwuxiao.so中链接原libwuxiao_orig.so, 然后再定义同型函数,查找原函数地址,然后调用原函数的方法。这里的方法仅对GNU版本的系统有效。 #include <stdio.h> int func_c() // find func_c() in another shared object(with the same name) dlerror(); if ( func_c_ptr != NULL ) 编译: gcc -shared -fPIC -o libwuxiao.so -ldl -lwuxiao_orig -L. -D_GNU_SOURCE 这种方法虽然更简单,但只对GNU有效,如果你的代码要放在非GNU的系统上执行,那还是用a)中的方法吧。 1、这里实现的wrapper的局限性就在于,你必须知道原来的共享库中的函数原型,但是你不必知道所有函数的原型。 你只需要知道其中你需要的函数原型即可。 2、如果你遇到一个共享库,里面的符号是强符号(不能再定义一个同名函数了),则这里的方法不再有用了。 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。