Rootkit技术的主要原理及防护

早期的rootkit主要为应用级rootkit应用级rootkit主要通过替换loginpslsnetstat等系统命令,或修改.rhosts等系统配置文件等实现隐藏及后门硬件级rootkit主要指bios rootkit,可以在系统加载前获得控制权,通过向磁盘中写入文件,再由引导程序加载该文件重新获得控制权,也可以采用虚拟机技术,使整个操作系统运行 rootkit掌握之中;目前最常见的rootkit是内核级rootkit

 

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

 

lkm rootkit要实现对内核的修改,首先需要获得内核空间的内存,因此需要调用kmalloc分配内存,而kmalloc是内核空间的调用,无法在用户空 间直接调用该函数,因此想到了通过int 0x80调用该函数的方法。先选择一个不常见的系统调用号,在sys_call_table中找到该项,通过写/dev/mem直接将其修改为 kmalloc函数的地址,这样当我们在用户空间调用该系统调用时,就能通过int 0x80进入内核空间,执行kmalloc函数分配内存,并将分配好的内存地址由eax寄存器返回,从而我们得到了一块属于内核地址空间的内存,接着将要 hack的函数写入该内存,并再次修改系统调用表,就能实现hook系统调用的功能。

 

rootkit的常见功能:

 

隐藏文件:通过strace ls可以发现ls命令其实是通过sys_getdents64获得文件目录的,因此可以通过修改sys_getdents64系统调用或者更底层的 readdir实现隐藏文件及目录,还有对ext2文件系统直接进行修改的方法,不过实现起来不够方便,也有一些具体的限制。

 

隐藏进程:隐藏进程的方法和隐藏文件类似,ps命令是通过读取/proc文件系统下的进程目录获得进程信息的,只要能够隐藏/proc文件系统下的进程目录就可以达到隐藏进程的效果,即hook sys_getdents64readdir等。

 

隐藏连接netstat命令是通过读取/proc文件系统下的net/tcpnet/udp文件获得当前连接信息,因此可以通过hook sys_read调用实现隐藏连接,也可以修改tcp4_seq_showudp4_seq_show等函数实现。

 

隐藏模块lsmod命令主要是通过sys_query_module系统调用获得模块信息,可以通过hook sys_query_module系统调用隐藏模块,也可以通过将模块从内核模块链表中摘除从而达到隐藏效果。

 

嗅探工具:嗅探工具可以通过libpcap库直接访问链路层,截获数据包,也可以通过linuxnetfilter框架在IP层的hook点上截获数据 包。嗅探器要获得网络上的其他数据包需要将网卡设置为混杂模式,这是通过ioctl系统调用的SIOCSIFFLAGS命令实现的,查看网卡的当前模式是 通过SIOCGIFFLAGS命令,因此可以通过hook sys_ioctl隐藏网卡的混杂模式。

 

密码记录:密码记录可以通过hook sys_read系统调用实现,比如通过判断当前运行的进程名或者当前终端是否关闭回显,可以获取用户的输入密码。hook sys_read还可以实现login后门等其它功能。

 

日志擦除:传统的unix日志主要在/var/log/messages/var/log/lastlog/var/run/utmp/var /log/wtmp下,可以通过编写相应的工具对日志文件进行修改,还可以将HISTFILE等环境变设为/dev/null隐藏用户的一些操作信息。

 

内核后门:可以是本地的提权后门和网络的监听后门,本地的提权可以通过对内核模块发送定制命令实现,网络内核后门可以在IP层对进入主机的数据包进行监听,发现匹配的指定数据包后立刻启动回连进程。

 

rootkit的主要技术:

 

lkm注射、模块摘除、拦截中断(0x800x01)、劫持系统调用、运行时补丁、inline hook、端口反弹……

 

lkm注射:也是一种隐藏内核模块的方法,通过感染系统的lkm,在不影响原有功能的情况下将rootkit模块链接到系统lkm中,在模块运行时获得控制权,初始化后调用系统lkm的初始化函数,lkm注射涉及到elf文件格式与模块加载机制。

 

模块摘除:主要是指将模块从模块链表中摘除从而隐藏模块的方法,最新加载的模块总是在模块链表的表头,因此可以在加载完rootkit模块后再加载一个清 除模块将rootkit模块信息从链表中删除,再退出清除模块,新版本内核中也可以通过判断模块信息后直接list_del

 

拦截中断:主要通过sidt指令获得中断调用表的地址,进而获取中断处理程序的入口地址,修改对应的中断处理程序,如int 0x80int 0x1等。其中拦截int 0x1是较新的技术,主要利用系统的调试机制,通过设置DR寄存器在要拦截的内存地址上下断点,从而在执行到指定指令时转入0x1中断的处理程序,通过修 0x1中断的处理程序即可实现想要的功能。

 

劫持系统调用:和拦截中断类似,但主要是对系统调用表进行修改,可以直接替换原系统调用表,也可以修改系统调用表的入口地址。在2.4内核之前,内核的系 统调用表地址是导出的,因此可以直接对其进行修改。但在2.6内核之后,系统调用表的地址已经不再导出,需要对0x80中断处理程序进行分析从而获取系统 调用表的地址。

 

运行时补丁:字符设备驱动程序和块设备驱动程序在加载时都会向系统注册一个Struct file_operations结构实现指定的readwrite等操作,文件系统也是如此,通过修改文件系统的file_operations结构, 可以实现新的readwrite操作等。

 

inline hook:主要是指对内存中的内核函数直接修改,而不影响原先的功能,可以采用跳转的办法,也可以修改对下层函数的call offset实现。

 

端口反弹:主要是为了更好的突破防火墙的限制,可以在客户端上监听80端口,而在服务器端通过对客户端的80端口进行回连,伪装成一个访问web服务的正常进程从而突破防火墙的限制。

 

简单的解决方法:就是将一些重要的文件作MD5,定期检查MD5是否有改变。

附脚本:

#!/bin/bash

#

#Shell name:md5_cmd_checkfile.sh

#

#as md5_checkfile.sh

#

#Program:

#     check some system files wasn't change by md5sum -c

#

#Author:perofu

#Email:  [email protected]

#

#History:

#     2013/1/27

#

#Usage:

#            sh md5_cmd_checkfile.sh

#

##########################################################

#NOTE:

#add some importan files:

#

#input some files at cmds "ls" or "find" in funtion initmd5()

# and check() in the same time ,

#besides,del two files where created by funtion initmd5()

#

#chattr -i /root/finger.md5

#

#if you change some importan files,please update immediately.

#

#exec funtion initmd5

#

##########################################################

 

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:.

export PATH

 

#file

list_file=/root/important_md5.list

md5_file=/root/finger.md5

report_file=/root/report.md5

 

initmd5 ()

{

       ls /etc/{passwd,group} > ${list_file}

       find /bin /sbin /usr/bin /usr/sbin -perm +6000 >> ${list_file}

 

       flist=$(cat ${list_file})

 

       for fn in $flist

       do

              md5sum $fn >> ${md5_file}

       done

 

       chattr +i ${md5_file}

}

 

check ()

{

       md5sum -c ${md5_file} &> ${report_file}

       md5sum -c ${md5_file} |grep -v "OK" | mail -s "finger error and check file /root/report.md5..." root

}

 

#main

 

if [ ! -e /root/finger.md5 ]

then

       initmd5

else

       check

fi


你可能感兴趣的:(rootkit)