Rootkit隐藏进程和端口检测

admin 2024年3月26日08:50:31评论25 views字数 6133阅读20分26秒阅读模式

简介

Rootkit是一种特殊的恶意软件,它的功能是在安装目标上隐藏自身以及指定的文件,进程和网络链接等信息,比较多见的是Rootkit一般都和木马,后门等其它恶意程序结合使用。Rootkit的三要素就是:隐藏、操纵、收集数据。

Rootkit的主要分类

Rootkit主要分为三类:应用级,内核级,硬件级

应用级:主要通过替换login、ps、ls、netstat等系统工具,或修改.rhosts等系统配置文件等实现隐藏及后门

硬件级:要指bios rootkit,可以在系统加载前获得控制权,通过向磁盘中写入文件,再由引导程序加载该文件重新获得控制权,也可以采用虚拟机技术,使整个操作系统运行在rootkit掌握之中;

内核级:目前最常见的,内核级rootkit又可分为lkm rootkit、非lkm rootkit。lkm rootkit主要基于lkm技术,通过系统提供的接口加载到内核空间,成为内核的一部分,进而通过hook系统调用等技术实现隐藏、后门功能。非lkm rootkit主要是指在系统不支持lkm机制时修改内核的一种方法,主要通过/dev/mem、/dev/kmem设备直接操作内存,从而对内核进行修改。

Rootkit的检测思路

Rootkit检测也成为主机安全一项重要功能,针对rootkit中最常见隐藏进程,端口,主要分为两种检测思路:

1)基于内核内存分析:缺点是需要增加内核模块,风险高;优点是检测效果最好

2)基于应用层分析:缺点是检测效果可能不如上一个;优点是在应用层发现隐藏进程,端口,风险小,可集成到主机安全agent中。

基于应用级的进程隐藏和检测方式

进程隐藏的方式上面已经说过一些,这边再说一下,主要是以下两种方式:

1)替换ps命令,在读取/proc/pid目录时,过滤掉需隐藏进程信息。

2)加载内核模块,通过拦截proc文件系统的回调函数,过滤掉需隐藏进程信息。

进程隐藏的检测方式,大致可分为四类:

通过libc系统函数盲测进程pid的存活状态,再根据ps结果对比差异,判断该pid是隐藏进程。

1)通过procfs下的进程目录信息

2)通过系统调用函数

3)通过前两类组合方式

4)通过暴力破解(不推荐)

下面分别从三类中各选择一种检测方式分析:

1)procfs检测:

基本检测流程:

1.遍历/proc目录,子文件名如果是数字,代表一个进程

2.读取进程状态task目录(/proc/pid/task),获取各子线程号

3.通过ps命令查找是否存在该线程

4.对比差异,不存在的判断为隐藏进程

1)procdir = opendir("/proc");2)dirproc = readdir(procdir));3)taskdir = opendir(task);4) dir = readdir(taskdir)5) checkps(procpids,PS_THREAD)

该类方法能检测出第一种隐藏进程方式,对第二种无效。

2)syscall检测(OSSEC检测流程)

基本检测流程:

1)从1到max_pid遍历进程, 通过getsid返回值和错误码探测进程存活状态(python中,os.getsid这个命令调用不成功)

2)通过ps命令查找是否存在该进程

3)再次通过getsid确认进程存活状态,防止在执行ps这时间内,进程退出了

4)对比差异,不存在判断为隐藏进程

1)ret = getsid(syspids)

2)checkps(syspids,PS_PROC | PS_THREAD);

3)ret = getsid(syspids)

该类方法都能检测上述两种隐藏进程方式。

3)compund检测

基本检测流程:

1)从1到max_pid遍历进程

2) 通过kill返回值和错误码探测进程存活状态

3) 通过getpriority返回值和错误码探测进程存活状态

4) 通过getpgid返回值和错误码探测进程存活状态

5) 通过getsid返回值和错误码探测进程存活状态

6) 通过sched_getaffinity返回值和错误码探测进程存活状态

7) 通过sched_getparam返回值和错误码探测进程存活状态

8) 通过sched_getscheduler返回值和错误码探测进程存活状态

9) 通过sched_rr_get_interval返回值和错误码探测进程存活状态

10) 通过chdir,opendir读取进程目录(/proc/pid)

11) 通过ps命令查找是否存在该进程

12)再次通过kill确认进程存活状态,防止在执行ps这时间内,进程退出

13)对比差异,只有进程不存在(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);statusproc = 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盲测端口(65535个端口每个尝试去连接,消耗机器性能而且有点疯狂)

TCP隐藏端口检测:

1)从1到65535遍历端口

2) 创建一个基于tcp协议SOCK_STREAM的socket

3) 通过bind返回值和错误码探测端口状态

4) 如果被占用,通过listen 错误码是EADDRINUSE确定端口占用

5) 通过ss或netstat命令过滤tcp协议,查看端口情况

6)对比差异,确认该端口为隐藏端口

socket_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);}

UDP隐藏端口检测:

相比tcp, udp使用SOCK_DGRAM的socket, 缺少listen这步,其余检测步骤类似

socket_desc=socket(AF_INET,SOCK_DGRAM,0);bind(socket_desc,(struct sockaddr *)&address,sizeof(address));if(EADDRINUSE == errno) {checkoneport(u, udpcommand, UDP);}

基于内核内存的检测方式

基于内存分析:这种方式需要增加内核模块,实现起来比较困难,而且要考虑稳定性问题,参考了其它文章的一些内容,如下:

Linux系统中存在用户态与内核态,当用户态的进程需要申请某些系统资源时便会发起系统调用。而内核态如何将系统的相关信息实时反馈给用户态呢,便是通过proc文件系统。如此便营造了一个相对隔离的环境。

么proc文件系统是如何呈现我们平时最关心的进程/网络连接信息的呢?在/proc目录下存在着一些以数字命名的目录,这些数字便对应了系统中正在运行的进程的pid。自然,对应进程的一些相关信息便保存在/proc/{pid}目录下。比如/proc/{pid}/fd目录中就保存了进程打开的文件描述符。

系统会将tcp协议的连接信息保存在/proc/net/tcp文件中。其他网络协议的连接信息也均保存在/proc/net对应协议的文件中。需要特别指出的是,上图中socket文件名中括号里的数字与下图中inode列是存在对应关系的。

Rootkit隐藏进程和端口检测

综上所述,像ps和netstat这类命令便是读取了proc文件系统中提供的数据,然后将数据格式化输出给用户的。出于隐藏指定进程/网络连接的目的,大部分Rootkit对写proc文件的回调函数做了些手脚,造成黑客指定的一些进程/网络连接的信息不会出现在proc文件系统中。于是,也就实现了进程/网络连接的隐藏。

### 探索

那么,如何发现那些被隐藏的进程/网络连接呢?首先是进程,这个其实并不复杂。系统给我们提供了一个方便的全局变量current。current永远指向当前正在运行的进程的task_struct数据结构,而进程的主要信息都包含在这个名为task_struct的巨大结构体中。当我们遍历到系统中所有进程task_struct结构体中的pid值,然后再去/proc目录下去寻找是否有对应的值。一但我们得到的pid未出现在ps的返回结果中,那么说明该进程被隐藏了。

如何发现被隐藏的网络连接呢?其实还是基于上一步进一步挖掘,因为网络IO请求都是由进程发起的,那么理论上来说我们肯定可以从进程一步步“捋”到socket。Linux一切皆文件的准则告诉我们,所谓网络IO其实就是读写socket文件,而每个socket结构体中都会有一个对应的inet_sock结构体,来记录IP协议下网络连接的四元组信息。那么我们把这些四元组再和netstat命令的返回结果比对一下便可知是否存在隐藏的网络信道了

总结出来在Kernel2.6.32中,进程-文件-网络三者之间大致的关系如下图所示。

Rootkit隐藏进程和端口检测

fdtable结构体的成员fd字符数组中存储的是file结构体,每当进程开启了一个文件描述符之后会自动在fd数组中新增一个对应的file结构体。通过获取file结构体中的f_path成员,我们可以获得对应的path结构体。系统内置的d_path函数可以返回path结构体对应文件的绝对路径信息。当d_path返回了一个“socket:[xxx]”的信息时,就说明这是个socket文件,该进程在试图进行网络IO。我们引用这个file结构体的private_data成员就可以获得这个socket文件对应的socket结构体了。最后通过内置的inet_sk()函数我们就可以找到对应socket文件的inet_sock结构体,我们需要的四元组便存在这个结构体中。

检测rootkit的两种工具(chkrootkit和rookit hunter)

1.chkrootkit:

已经停止更新,下面是他的检测方式:

搜索通用的ROOTKIT特征的字符串

对某种特定的rootkits,或者命令的特殊的感染特征进行检测

对某种特定的rootkits的生成的特定文件的检测

对程序的SUID位的设置进行检测

对ldsopreload的检测

查找可疑的log文件

查找可疑的php文件

检测.history文件

检测有无程序监听了一些可疑的端口

检测Linux可加载内核模块

检测有无隐藏进程

检测目录的软链接异常

检测网络接口的异常

检测用户的登录日志

检测上一次登录

检测可疑的没有tty记录的进程

2.rkhunter

1.下载:http://downloads.sourceforge.net/rkhunter/rkhunter-1.3.4.tar.gz?use_mirror=jaist

2.解压,使用

tar -zxvf rkhunter-1.3.4

cd rkhunter-1.3.4

./rkhunter -h

安装命令:./installer.sh --layout default --install

使用:rkhunter -C 检测

功能特性:

1. 基于指纹库思想的rootkit检测

1.1 建立了一个已知rootkit的默认目录名、文件名列表,通过默认文件名、目录名特征这个维度对rootkit进行检测

1.2 通过检查某个文件或目录是否存在来判断对应的rootkit病毒是否存在(FILESCAN)

1.3 在文件系统中搜索rootkit常用的文件名(SUSP_FILES_INFO)

1.4 检测是否有已知的sniffer(嗅探器)的日志文件存在(SNIFFER_FILES)

1.5 检测是否有已知的LKM Rootkit对应的.so文件存在(LKM_BADNAMES)

1.6 检查自从上次运行rkhunter以来,/etc/passwd的内容文件有没有变化

1.7 检查是否存在"逻辑rootkit",即通过减低指定系统配置或软件的安全配置来构建逻辑后门rootkit

2. 基于可疑字符串的指令劫持检测

 2.1 检查某个"二进制系统命令"是否否存在某个字符串,如存在则有危险(STRINGSCAN)

2.2 依次用一些rootkit病毒的文件名或路径做参数调用strings命令,看其是否能正常输出

2.3 检查和动态链接库预加载相关的环境变量

1) LD_PRELOAD

2) LD_AOUT_PRELOAD

3) LD_ELF_PRELOAD

4) /etc/ld.so.preload

5) LD_LIBRARY_PATH

3. 基于可疑字符串的Linux启动文件恶意修改、劫持检测

3.1 检查某个"二进制启动文件"是否存在某个字符串,如存在则有危险(STRINGSCAN、RCLOCATIONS)

3.2 在系统启动文件中搜索特定的字符串,如果搜到,则说明有危险(RCLOCAL_STRINGS)

4. 基于异常文件目录属性特征的rootkit检测

1) 检查系统命令程序文件的ACL属性

1.1) 异常-s标志位

1.2) 权限开放过大(任意用户可执行)

1.3) 异常的隐藏标志位

1.4) 可疑文件修改时间

2) 检查敏感文件的HASH值是否和标准的一致(需要建立一个标准黄金基准列表),以确定这些系统命令是否被篡改过

5. 基于网络异常状态监控的rootkit检查

1) 检查指定端口上监听的程序是否在白名单中(正常的程序只会listen在指定的端口上)

2) 检查是否有白名单之外的程序在进行流程sniffer

6. 基于系统账户、组异常权限检查的rootkit监控

1) 检查/etc/passwd中是否有白名单之外的"超级用户(uid)",这是一种异常现象

2) 检查是否存在无密码账户

总结

Rootkit是一种特殊的恶意软件,常被用来隐藏端口,进程,文件等。

Rootkit检测可以从Rootkit特征以及行为等方面进行检测。

例如:

1.通过检测是否有隐藏的进程,端口等(分为两种方式:应用层分析以及内核层分析)

2.检测有无程序监听了一些可疑的端口

3.搜索通用的Rootkit特征的字符串

等等。

原文始发于微信公众号(信安路漫漫):Rootkit隐藏进程和端口检测

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月26日08:50:31
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Rootkit隐藏进程和端口检测https://cn-sec.com/archives/2603560.html

发表评论

匿名网友 填写信息