攔截 link stage 階段包進去的 dynamic library
這些 library 可以夠過 ldd 看到
不過有時候 dynamic library 是透過 dlfcn.h 下的 dlopen 實現的
例如說 part 1 之中的 main.c 變成了這樣
Main file a.c
#include <dlfcn.h>
int main() {
void *handle = dlopen("libtest.so", RTLD_LAZY);
void (*test)() = dlsym(handle, "test");
void (*test2)() = dlsym(handle, "test2");
test();
test2();
return 0;
}
dlopen 雖然會讀取 LD_LIBRARY_PATH
不過卻不像使用 LD_PRELOAD 的可以讀取多個檔案
因此就算我們編譯出來的檔案 hook library 名稱是 libtest.so
還是讀取不到 test2(),造成 segmentation fault
$ LD_LIBRARY_PATH=hook/ ./a.out
hook
[1] 5721 segmentation fault LD_LIBRARY_PATH=hook/ ./a.out
因此我們剩下這個選擇:
「在我們掛上去的 libtest.so 中實作舊有的 libtest.so 的所有界面,要 bypass 的就自己用 dlopen 開啟舊的 libtest.so」
不過這於巨大的 library 來說太麻煩了
我們可不可能把「連結原本的 libtest.so」此一資訊放在「hook 的 libtest.so」裡面呢?
這樣一來 dlopen 開啟的時候便會包還這個資訊
答案是可能的
我們把原本的 libtest.so 改成大寫 libTEST.so
要用來取代的 hook library 叫做 libtest.so
而如果 ldd libtest.so 我們會看到
$ LD_LIBRARY_PATH=hook/ ldd hook/libtest.so
linux-vdso.so.1 => (0x00007fff1dd45000)
libTEST.so => hook/libTEST.so (0x00007f946ec9d000)
...
要到這一個目的
我們先製造一個 hook 資料夾
改名原有 library(沒有修改其中內容)
$ mkdir hook
$ mv libtest.so hook/libTEST.so
接著編譯
$ gcc -Wl,--no-as-needed\
hook/hook.c\
-L./hook -lTEST\
-o hook/libtest.so\
-shared -fPIC
這邊我們看到跟之前相比多了兩個參數- -L./hook -lTEST 如前面所說明是為了要連結到舊的 library 所使用
- -Wl,--no-as-needed 確保 linker 會把沒用到的 library 放進去
$ LD_LIBRARY_PATH=./hook ./a.out
Haha
origin2
沒有留言:
張貼留言