| 
                        副标题[/!--empirenews.page--]
                         一、引言 
Rootkit是一种特殊的恶意软件,它的功能是在安装目标上隐藏自身及指定的文件、进程和网络链接等信息,比较多见到的是Rootkit一般都和木马、后门等其他恶意程序结合使用。 
例如:inetd或者login,为攻击者提供后门;隐藏攻击者的目录和进程的程序,ps、netstat等常见命令。 
rootkit检测也成为主机安全一项重要功能,针对rootkit中最常见隐藏进程、端口检测,主要分为两种检测思路,一种基于内核内存分析,一种基于应用层分析。 
基于内存分析Rootkit检测可参考Rootkit检测,该方案缺点是需要增加内核模块,风险高,检测效果最好。 
本文介绍第二种方案,unhide在应用层发现隐藏进程、端口,该方案风险小,可集成到主机安全agent中。 
  
二、应用层隐藏进程检测 
1. 进程隐藏和检测方式 
进程隐藏两种方式: 
    - 替换ps命令,在读取/proc/pid目录时,过滤掉需隐藏进程信息
 
    - 加载内核模块,通过拦截proc文件系统的回调函数,过滤掉需隐藏进程信息
 
 
检测核心思想: 
通过libc系统函数盲测进程pid的存活状态,再根据ps结果对比差异,,判断该pid是隐藏进程。 
unhide提供如下19种检测方式,大致可分为四类:一类通过procfs下的进程目录信息,第二类通过系统调用函数,  第三类通过前两类组合方式,第四类通过爆力破解(不推荐)。 
- 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函数。 
下面分别从三类中各选择一种检测方式分析。 
2. procfs检测 
抽取checkreaddir检测分析: 
    - 遍历/proc目录, 子文件名如果是数字,代表是一个进程pid
 
    - 读取进程状态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获取: 
    - 从1到max_pid遍历进程, 通过getsid返回值和错误码探测进程存活状态
 
    - 通过ps命令查找是否存在该进程
 
    - 再次通过getsid确认进程存活状态,防止在执行ps这时间内,进程退出了
 
    - 对比差异,不存在判断为隐藏进程
 
     - ret = getsid(syspids) 
 - checkps(syspids,PS_PROC | PS_THREAD); 
 - ret = getsid(syspids) 
 
  
该类方法都能检测上述两种隐藏进程方式。 
4. compund检测 
抽取checkallquick检测分析: 
    - 从1到max_pid遍历进程
 
    - 通过kill返回值和错误码探测进程存活状态
 
    - 通过getpriority返回值和错误码探测进程存活状态
 
    - 通过getpgid返回值和错误码探测进程存活状态
 
    - 通过getsid返回值和错误码探测进程存活状态
 
    - 通过sched_getaffinity返回值和错误码探测进程存活状态
 
    - 通过sched_getparam返回值和错误码探测进程存活状态
 
    - 通过sched_getscheduler返回值和错误码探测进程存活状态
 
    - 通过sched_rr_get_interval返回值和错误码探测进程存活状态
 
    - 通过chdir,opendir读取进程目录(/proc/pid)
 
    - 通过ps命令查找是否存在该进程
 
    - 再次通过kill确认进程存活状态,防止在执行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系统函数bind,listen盲测端口 
                                                (编辑:91站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |