Rootkit隱藏進程和端口檢測
一、引言
Rootkit是一種特殊的惡意軟件,它的功能是在安裝目標上隱藏自身及指定的文件、進程和網絡鏈接等信息,比較多見到的是Rootkit一般都和木馬、后門等其他惡意程序結合使用。
rootkit檢測也成為主機安全一項重要功能,針對rootkit中最常見隱藏進程、端口檢測,主要分為兩種檢測思路,一種基于內核內存分析,一種基于應用層分析。
基于內存分析Rootkit檢測可參考Rootkit檢測,該方案缺點是需要增加內核模塊,風險高,檢測效果相對較好。
本文介紹第二種方案,unhide在應用層發(fā)現(xiàn)隱藏進程、端口,該方案風險小,可集成到主機安全agent中。
二、應用層隱藏進程檢測
1. 進程隱藏和檢測方式
進程隱藏兩種方式:
- 替換ps命令,在讀取/proc/pid目錄時,過濾掉需隱藏進程信息
- 加載內核模塊,通過攔截proc文件系統(tǒng)的回調函數(shù),過濾掉需隱藏進程信息
檢測核心思想:
通過libc系統(tǒng)函數(shù)盲測進程pid的存活狀態(tài),再根據(jù)ps結果對比差異,判斷該pid是隱藏進程。
unhide提供如下19種檢測方式,大致可分為四類:一類通過procfs下的進程目錄信息,第二類通過系統(tǒng)調用函數(shù), 第三類通過前兩類組合方式,第四類通過爆力破解(不推薦)。
- tab_test[TST_PROC].func = checkproc;
- tab_test[TST_CHDIR].func = checkchdir;
- tab_test[TST_OPENDIR].func = checkopendir;
- tab_test[TST_READDIR].func = checkreaddir;
- tab_test[TST_GETPRIO].func = checkgetpriority;
- tab_test[TST_GETPGID].func = checkgetpgid;
- tab_test[TST_GETSID].func = checkgetsid;
- tab_test[TST_GETAFF].func = checksched_getaffinity;
- tab_test[TST_GETPARM].func = checksched_getparam;
- tab_test[TST_GETSCHED].func = checksched_getscheduler;
- tab_test[TST_RR_INT].func = checksched_rr_get_interval;
- tab_test[TST_KILL].func = checkkill;
- tab_test[TST_NOPROCPS].func = checkallnoprocps;
- tab_test[TST_BRUTE].func = brute;
- tab_test[TST_REVERSE].func = checkallreverse;
- tab_test[TST_QUICKONLY].func = checkallquick;
- tab_test[TST_SYS_INFO].func = checksysinfo;
- tab_test[TST_SYS_INFO2].func = checksysinfo2;
- tab_test[TST_SYS_INFO3].func = checksysinfo3;
從名字上可以看出,unhide使用chdir,opendir,readdir,getpriority,getpgid,getsid,sched_getaffinity,kill,sysinfo等libc函數(shù)。
下面分別從三類中各選擇一種檢測方式分析。
2. procfs檢測
抽取checkreaddir檢測分析:
- 遍歷/proc目錄, 子文件名如果是數(shù)字,代表是一個進程pid
- 讀取進程狀態(tài)task目錄(/proc/pid/task), 獲取各子線程號
- 通過ps命令查找是否存在該線程
- 對比差異,不存在判斷為隱藏進程
- procdir = opendir("/proc");
- dirproc = readdir(procdir));
- taskdir = opendir(task);
- dir = readdir(taskdir)
- checkps(procpids,PS_THREAD)
該類方法能檢測出對第二種無效。
3. syscall檢測
抽取checkgetsid檢測分析:
max_pid通過讀取 /proc/sys/kernel/pid_max獲?。?/p>
- 從1到max_pid遍歷進程, 通過getsid返回值和錯誤碼探測進程存活狀態(tài)
- 通過ps命令查找是否存在該進程
- 再次通過getsid確認進程存活狀態(tài),防止在執(zhí)行ps這時間內,進程退出了
- 對比差異,不存在判斷為隱藏進程
- ret = getsid(syspids)
- checkps(syspids,PS_PROC | PS_THREAD);
- ret = getsid(syspids)
該類方法都能檢測上述兩種隱藏進程方式。
4. compund檢測
抽取checkallquick檢測分析:
- 從1到max_pid遍歷進程
- 通過kill返回值和錯誤碼探測進程存活狀態(tài)
- 通過getpriority返回值和錯誤碼探測進程存活狀態(tài)
- 通過getpgid返回值和錯誤碼探測進程存活狀態(tài)
- 通過getsid返回值和錯誤碼探測進程存活狀態(tài)
- 通過sched_getaffinity返回值和錯誤碼探測進程存活狀態(tài)
- 通過sched_getparam返回值和錯誤碼探測進程存活狀態(tài)
- 通過sched_getscheduler返回值和錯誤碼探測進程存活狀態(tài)
- 通過sched_rr_get_interval返回值和錯誤碼探測進程存活狀態(tài)
- 通過chdir,opendir讀取進程目錄(/proc/pid)
- 通過ps命令查找是否存在該進程
- 再次通過kill確認進程存活狀態(tài),防止在執(zhí)行ps這時間內,進程退出
- 對比差異,只有進程不存在(found=0)或者進程經過11項檢測(found == 11)認為是正常的,其余都判斷為隱藏進程
- ret = kill(syspids, 0);
- ret = getpriority(PRIO_PROCESS, syspids);
- ret = getpgid(syspids);
- ret = getsid(syspids);
- ret = sched_getaffinity(syspids, sizeof(cpu_set_t), &mask);
- ret = sched_getparam(syspids, ¶m);
- ret = sched_getscheduler(syspids);
- statstatusproc = stat(directory, &buffer);
- statusdir = chdir(directory);
- dir_fd = opendir(directory) ;
- checkps(syspids,PS_PROC | PS_THREAD)
- ret = kill(syspids, 0);
- if (found_killbefore == found_killafter) {
- if ( ! ((found_killbefore == 0 && found == 0) ||
- (found_killbefore == 1 && found == 11)) ) {
- printbadpid(syspids);
- }
三、應用層隱藏端口檢測
核心思想:通過libc系統(tǒng)函數(shù)bind,listen盲測端口
1. tcp隱藏端口檢測
- 從1到65535遍歷端口
- 創(chuàng)建一個基于tcp協(xié)議SOCK_STREAM的socket
- 通過bind返回值和錯誤碼探測端口狀態(tài)
- 如果被占用,通過listen 錯誤碼是EADDRINUSE確定端口占用
- 通過ss或netstat命令過濾tcp協(xié)議,查看端口情況
- 對比差異,確認該端口為隱藏端口
- socketsocket_desc=socket(AF_INET,SOCK_STREAM,0);
- bind(socket_desc,(struct sockaddr *)&address,sizeof(address));
- listen(socket_desc,1);
- if(EADDRINUSE == errno) {
- checkoneport(i, tcpcommand, TCP);
- }
2. udp隱藏端口檢測
相比tcp, udp使用SOCK_DGRAM的socket, 缺少listen這步,其余檢測步驟類似
- socketsocket_desc=socket(AF_INET,SOCK_DGRAM,0);
- bind(socket_desc,(struct sockaddr *)&address,sizeof(address));
- if(EADDRINUSE == errno) {
- checkoneport(u, udpcommand, UDP);
- }
四、結論
本文提供的通過應用層方式檢測rootkit中最常見的隱藏進程和端口,風險性小,可無縫集成到主機安全agent中。