论文部分内容阅读
摘要:随着计算机网络技术的发展,网络安全问题越来越多的受到人们的关注,同时,也出现了各种类型的计算机病毒和木马程序。最近,出现了一种特殊木马程序——Rootkit,该文详细的介绍了Rootkit的隐藏技术和检测方法。
关键词:Rootkit;木马程序;网络安全;隐藏;检测
中图分类号:TP393文献标识码:A文章编号:1009-3044(2008)31-0838-02
Defence and Detection Technology Against RootKit
ZHANG Gui-qiang1,LI Lan-lan2
(Lanzhou Petrochemical College of Vocational Technology, Lanzhou 730060, China; 2.Lanzhou University, Lanzhou 730030, China)
Abstract: With the development of computer network, security of network attracts more and more attention. Meanwhile, all kinds of computer viruses and Trojan programs arised, inluding a special Trojan program: RootKit. A detailed introduction of hidden technology and detection method of RootKit has been put forward in this paper.
Key words: rootkit; trojan program; network security; hidden technology; detection
众所周知,木马病毒是指寄生于用户计算机系统中,盗窃用户信息,并通过网络发送给作者的一类病毒程序。但是随着安全技术的发展和计算机用户安全技术的提高,普通的木马越来越难生存,于是一部分有能力的后门作者把眼光投向了系统底层——ring 0。利用系统驱动模块以驱动形式隐藏木马程序,这就是让人闻之色变的Rootkit。
1 什么是Rootkit
ring 0 层的是系统核心模块和各种驱动程序模块,因此,位于这一层的木马也是以驱动形式生存的,而不是一般的exe。后门作者把后门写成符合wdm规范(windows driver model)的驱动程序模块,把自身添加进注册表的驱动程序加载入口,便实现了“无启动项”运行。一般的进程查看器都只能枚举可执行文件exe的信息,所以通过驱动模块和执行文件结合的后门程序便得以生存下来,由于它运行在 ring 0 级别,拥有与系统核心同等级的权限,因此它可以更轻易的把自己隐藏起来,无论是进程信息还是文件体,甚至通讯的端口和流量也能被隐藏起来,在如此强大的隐藏技术面前,无论是任务管理器还是系统配置实用程序,甚至系统自带的注册表工具都失去了效果,这种木马就是Rootkit。所以,Rootkit是通过加载特殊的驱动,修改系统内核,进而达到隐藏信息的目的。
2 rootkit的隐藏技术
2.1 删除进程双项链表上的进程对象。
现在所有人查看进程一般都是通过任务管理器(taskmgr.exe)来查看。任务管理器枚举进程信息是靠的NtQuerySystemInformation 也就是ZwQuerySystemInformation 函数。其中,Native Api枚举进程是要通过进程活动链表的,如果我们将进程对象从进程双向链表中移除,那么调用NtQuerySystemInformation来枚举进程的任务管理器taskmgr.exe中就不会看到我们的进程了。那么就有人会担心了。如果进程从链表中删除,那还会被运行么?答案是,会。因为windows的ds,也就是线程分派器,也叫任务调度分配器(dispatcher scheduler)使用的是另一个数据结构,也就是说,进线程是否被调度处理与进程双向活动链表无关,不会被CPU忽略。所以,rootkit会将进程双向链表中的相关对象删除,这样使用任务管理器是看不到的。
2.2 修改系统调用表(sst)
系统调用,就是操作系统提供给用户程序调用的一组“特殊”接口。用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置定时器等。在相应寄存器中储存着系统调用号,中断处理程序把该寄存器里的值作为查找表中的索引,去找到最终的目标函数,这个表就是系统服务表SST。rootkit可以通过在系统调用表中添加自己的服务然后运行想要执行的任务。He4HookInv就是这样,He4HookInv也是一个比较有名的windows rootkit。
2.3 端口隐藏
很多人检查自己中没中木马或后门,都会一些方法来查看自己本机所开的端口来判断是否有木马监听,而有些rootkit就开始想如何隐藏端口了。最简单的枚举当前所开放的端口信息是调用iphlpapi.dll中的AllocateAndGetTcpTableFromStack和AllocateAndGetUdpTableFromStack函数,或者AllocateAndGetTcpExTableFromStack和AllocateAndGetUdpExTableFromStack函数。还有另外一种方法。当程序创建了一个套接字并开始监听时,它就会有一个为它和打开端口的打开句柄。我们在系统中枚举所有的打开句柄并通过NtDeviceIoControlFile把它们发送到一个特定的缓冲区中,来找出这个句柄是否是一个打开端口的。这样也能给我们有关端口的信息。因为打开句柄太多了,所以我们只检测类型是File并且名字是DeviceTcp或DeviceUdp的。打开端口只有这种类型和名字。而通过察看iphlpapi.dll的代码。就会发现这些函数同样都是调用NtDeviceIoControlFile并发送到一个特定缓冲区来获得系统中所有打开端口的列表。也就是说,我们挂接NtDeviceIoControlFile函数就可以隐藏端口。
2.4 文件隐藏
在WINNT里在某些目录中寻找某个文件的方法是枚举它里面所有的文件和它的子目录下的所有文件。文件的枚举是使用NtQueryDirectoryFile函数。与隐藏文件相关的重要参数是FileHandle、FileInformation、FileInformationClass。如果我们想要隐藏一个文件,我们需要分别通知FileDirectoryInformation、FileFullDirectoryInformation、FileBothDirectoryInformation 、FileNamesInformation这4种类型,对每种类型的返回记录我们需要和我们打算隐藏的文件比较名字。如果我们打算隐藏第一个记录,我们可以把后面的结构向前移动,移动长度为第一个结构的长度,这样会导致第一个记录被改写。如果我们想要隐藏其它任何一个,只需要很容易的改变上一个记录的NextEntryOffset的值就行。如果我们要隐藏最后一个记录就把它的NextEntryOffset改为0,否则NextEntryOffset的值应为我们想要隐藏的那个记录和前一个的NextEntryOffset值的和。然后修改前一个记录的Unknown变量的值,它是下一次搜索的索引。把要隐藏的记录之前一个记录的Unknown变量的值改为我们要隐藏的那个记录的Unkown变量的值即可。
3 隐藏技术的应对方法
像刚才提到的将进程对象从进程双向链表中删除就有办法突破。虽然NtQuerySystemInformation所需要的链表已经被做了手脚,但windows dispatcher scheduler跟他所用的链表不一样,那么我门可以通过读取windows dispatcher scheduler所用的另一个链表来列出进程。也就是说可以直接通过读取KiWaitInListHead和KiWaitOutListHead来列举进程,这样就突破了修改双向链表隐藏进程的方法,pjf通过读取KiWaitInListHead列出隐藏的进程中给出了代码。不过这种检测方法不久又被突破了,就是替换内核的进程链表。
还有人提出使用HOOK SwapContext方法来检测,只要被处理器调度的线程就逃不掉。
WINDOWS 2K/NT/XP系统中,处理器的调度对象是线程,在非SMP的OS中某时间段内当前 CPU 处理的进程只可能有一个。每个进程分配特定的 CPU 时间片来达到执行目的,而系统的 CPU 时钟中断确定了每个进程分配的时间片。也就是当系统 CPU 时钟中断触发时,产生的进程调度请求。处理器时钟中断发生的时候会调用KiDispatchInterrupt(),比较当前进程分配的时间片,如用完后会调用 KiQuantumEnd() 根据各线程优先级等信息用特定的调度算法选择新的线程(ETHREAD),然后将其返回值,一个 ETHREAD 结构作为参数,来调用 SwapContext() 设置 ETHREAD,EPROCESS 中的各项参数,并替换 KPCR 中的相应结构完成线程切换,调度到另一个进程(EPROCESS)的线程(ETHREAD)继续执行。可以说CPU的线程切换离不开SwapContext函数,当然,rootkit所执行线程的都会通过SwapContext函数来切换使之被CPU处理。
而在这之后有人就提出自己替换线程的调度就可以躲过这种检测。在我看来,这种检测方法会占用很大的资源,毕竟CPU的线程切换非常频繁。如果谁有条件可以自己看看,一秒内会发生多少次的线程切换。
4 rootkit的检测
我们可以借助一些rootkit检测工具,如RootkitRevealer(成名的和令人尊敬的安全专家Mark Russinovich和Bryce Cogswell制作的)、Blacklight(知名安全软件厂商F-Secure公司制作的)、Klister(卑鄙的内核模式rootkitFU的作者制作的)。这些工具都有自己独特的功能和缺陷。但是,恶意软件作者不断地更新他们的工具以便避开最新的检测应用程序,因此,某一种工具也许也不能检测出所有的恶意软件。你也许需要手工执行微软研究院2004年发布的工具软件“Strider GhostBuster”的白皮书中解释的那些程序。简言之,你要在系统启动的时候拍下系统的快照,收集每个硬盘的目录列表等信息。然后,你使用替代的操作系统启动计算机,用你在干净的操作系统中所看到的东西与被攻破的操作系统中的东西进行比较。
计算机网络技术在不断的发展和更新,而一些恶意软件的作者也在不断的更新自己的技术和攻击工具,所以,要达到100%绝对安全的计算机系统是不可能的。但是,计算机用户要不断提高自己的安全意识,在日常的使用过程中随时更新自己的系统,不断加强防范措施。
参考文献:
[1] 崔甲.Rootkit的分类方法和检测技术研究[D].电子科技大学,2007.
[2] 颜仁仲.实时检测Rootkit并自动修复系统的研究与实现[D].中国科学院研究生院(计算技术研究所),2006.
[3] 王松涛,吴灏.Linux下基于可执行路径分析的内核rootkit检测技术研究[J].计算机工程与应用,2005(11):121-123.
[4] 吴昆.Windows Rootkit技术概述[D].湖南大学软件学院,2008(05)
[5] 冯万利.基于内核入侵的木马设计与实现[J].微计算机信息,2006(18):59-60,92.
关键词:Rootkit;木马程序;网络安全;隐藏;检测
中图分类号:TP393文献标识码:A文章编号:1009-3044(2008)31-0838-02
Defence and Detection Technology Against RootKit
ZHANG Gui-qiang1,LI Lan-lan2
(Lanzhou Petrochemical College of Vocational Technology, Lanzhou 730060, China; 2.Lanzhou University, Lanzhou 730030, China)
Abstract: With the development of computer network, security of network attracts more and more attention. Meanwhile, all kinds of computer viruses and Trojan programs arised, inluding a special Trojan program: RootKit. A detailed introduction of hidden technology and detection method of RootKit has been put forward in this paper.
Key words: rootkit; trojan program; network security; hidden technology; detection
众所周知,木马病毒是指寄生于用户计算机系统中,盗窃用户信息,并通过网络发送给作者的一类病毒程序。但是随着安全技术的发展和计算机用户安全技术的提高,普通的木马越来越难生存,于是一部分有能力的后门作者把眼光投向了系统底层——ring 0。利用系统驱动模块以驱动形式隐藏木马程序,这就是让人闻之色变的Rootkit。
1 什么是Rootkit
ring 0 层的是系统核心模块和各种驱动程序模块,因此,位于这一层的木马也是以驱动形式生存的,而不是一般的exe。后门作者把后门写成符合wdm规范(windows driver model)的驱动程序模块,把自身添加进注册表的驱动程序加载入口,便实现了“无启动项”运行。一般的进程查看器都只能枚举可执行文件exe的信息,所以通过驱动模块和执行文件结合的后门程序便得以生存下来,由于它运行在 ring 0 级别,拥有与系统核心同等级的权限,因此它可以更轻易的把自己隐藏起来,无论是进程信息还是文件体,甚至通讯的端口和流量也能被隐藏起来,在如此强大的隐藏技术面前,无论是任务管理器还是系统配置实用程序,甚至系统自带的注册表工具都失去了效果,这种木马就是Rootkit。所以,Rootkit是通过加载特殊的驱动,修改系统内核,进而达到隐藏信息的目的。
2 rootkit的隐藏技术
2.1 删除进程双项链表上的进程对象。
现在所有人查看进程一般都是通过任务管理器(taskmgr.exe)来查看。任务管理器枚举进程信息是靠的NtQuerySystemInformation 也就是ZwQuerySystemInformation 函数。其中,Native Api枚举进程是要通过进程活动链表的,如果我们将进程对象从进程双向链表中移除,那么调用NtQuerySystemInformation来枚举进程的任务管理器taskmgr.exe中就不会看到我们的进程了。那么就有人会担心了。如果进程从链表中删除,那还会被运行么?答案是,会。因为windows的ds,也就是线程分派器,也叫任务调度分配器(dispatcher scheduler)使用的是另一个数据结构,也就是说,进线程是否被调度处理与进程双向活动链表无关,不会被CPU忽略。所以,rootkit会将进程双向链表中的相关对象删除,这样使用任务管理器是看不到的。
2.2 修改系统调用表(sst)
系统调用,就是操作系统提供给用户程序调用的一组“特殊”接口。用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置定时器等。在相应寄存器中储存着系统调用号,中断处理程序把该寄存器里的值作为查找表中的索引,去找到最终的目标函数,这个表就是系统服务表SST。rootkit可以通过在系统调用表中添加自己的服务然后运行想要执行的任务。He4HookInv就是这样,He4HookInv也是一个比较有名的windows rootkit。
2.3 端口隐藏
很多人检查自己中没中木马或后门,都会一些方法来查看自己本机所开的端口来判断是否有木马监听,而有些rootkit就开始想如何隐藏端口了。最简单的枚举当前所开放的端口信息是调用iphlpapi.dll中的AllocateAndGetTcpTableFromStack和AllocateAndGetUdpTableFromStack函数,或者AllocateAndGetTcpExTableFromStack和AllocateAndGetUdpExTableFromStack函数。还有另外一种方法。当程序创建了一个套接字并开始监听时,它就会有一个为它和打开端口的打开句柄。我们在系统中枚举所有的打开句柄并通过NtDeviceIoControlFile把它们发送到一个特定的缓冲区中,来找出这个句柄是否是一个打开端口的。这样也能给我们有关端口的信息。因为打开句柄太多了,所以我们只检测类型是File并且名字是DeviceTcp或DeviceUdp的。打开端口只有这种类型和名字。而通过察看iphlpapi.dll的代码。就会发现这些函数同样都是调用NtDeviceIoControlFile并发送到一个特定缓冲区来获得系统中所有打开端口的列表。也就是说,我们挂接NtDeviceIoControlFile函数就可以隐藏端口。
2.4 文件隐藏
在WINNT里在某些目录中寻找某个文件的方法是枚举它里面所有的文件和它的子目录下的所有文件。文件的枚举是使用NtQueryDirectoryFile函数。与隐藏文件相关的重要参数是FileHandle、FileInformation、FileInformationClass。如果我们想要隐藏一个文件,我们需要分别通知FileDirectoryInformation、FileFullDirectoryInformation、FileBothDirectoryInformation 、FileNamesInformation这4种类型,对每种类型的返回记录我们需要和我们打算隐藏的文件比较名字。如果我们打算隐藏第一个记录,我们可以把后面的结构向前移动,移动长度为第一个结构的长度,这样会导致第一个记录被改写。如果我们想要隐藏其它任何一个,只需要很容易的改变上一个记录的NextEntryOffset的值就行。如果我们要隐藏最后一个记录就把它的NextEntryOffset改为0,否则NextEntryOffset的值应为我们想要隐藏的那个记录和前一个的NextEntryOffset值的和。然后修改前一个记录的Unknown变量的值,它是下一次搜索的索引。把要隐藏的记录之前一个记录的Unknown变量的值改为我们要隐藏的那个记录的Unkown变量的值即可。
3 隐藏技术的应对方法
像刚才提到的将进程对象从进程双向链表中删除就有办法突破。虽然NtQuerySystemInformation所需要的链表已经被做了手脚,但windows dispatcher scheduler跟他所用的链表不一样,那么我门可以通过读取windows dispatcher scheduler所用的另一个链表来列出进程。也就是说可以直接通过读取KiWaitInListHead和KiWaitOutListHead来列举进程,这样就突破了修改双向链表隐藏进程的方法,pjf通过读取KiWaitInListHead列出隐藏的进程中给出了代码。不过这种检测方法不久又被突破了,就是替换内核的进程链表。
还有人提出使用HOOK SwapContext方法来检测,只要被处理器调度的线程就逃不掉。
WINDOWS 2K/NT/XP系统中,处理器的调度对象是线程,在非SMP的OS中某时间段内当前 CPU 处理的进程只可能有一个。每个进程分配特定的 CPU 时间片来达到执行目的,而系统的 CPU 时钟中断确定了每个进程分配的时间片。也就是当系统 CPU 时钟中断触发时,产生的进程调度请求。处理器时钟中断发生的时候会调用KiDispatchInterrupt(),比较当前进程分配的时间片,如用完后会调用 KiQuantumEnd() 根据各线程优先级等信息用特定的调度算法选择新的线程(ETHREAD),然后将其返回值,一个 ETHREAD 结构作为参数,来调用 SwapContext() 设置 ETHREAD,EPROCESS 中的各项参数,并替换 KPCR 中的相应结构完成线程切换,调度到另一个进程(EPROCESS)的线程(ETHREAD)继续执行。可以说CPU的线程切换离不开SwapContext函数,当然,rootkit所执行线程的都会通过SwapContext函数来切换使之被CPU处理。
而在这之后有人就提出自己替换线程的调度就可以躲过这种检测。在我看来,这种检测方法会占用很大的资源,毕竟CPU的线程切换非常频繁。如果谁有条件可以自己看看,一秒内会发生多少次的线程切换。
4 rootkit的检测
我们可以借助一些rootkit检测工具,如RootkitRevealer(成名的和令人尊敬的安全专家Mark Russinovich和Bryce Cogswell制作的)、Blacklight(知名安全软件厂商F-Secure公司制作的)、Klister(卑鄙的内核模式rootkitFU的作者制作的)。这些工具都有自己独特的功能和缺陷。但是,恶意软件作者不断地更新他们的工具以便避开最新的检测应用程序,因此,某一种工具也许也不能检测出所有的恶意软件。你也许需要手工执行微软研究院2004年发布的工具软件“Strider GhostBuster”的白皮书中解释的那些程序。简言之,你要在系统启动的时候拍下系统的快照,收集每个硬盘的目录列表等信息。然后,你使用替代的操作系统启动计算机,用你在干净的操作系统中所看到的东西与被攻破的操作系统中的东西进行比较。
计算机网络技术在不断的发展和更新,而一些恶意软件的作者也在不断的更新自己的技术和攻击工具,所以,要达到100%绝对安全的计算机系统是不可能的。但是,计算机用户要不断提高自己的安全意识,在日常的使用过程中随时更新自己的系统,不断加强防范措施。
参考文献:
[1] 崔甲.Rootkit的分类方法和检测技术研究[D].电子科技大学,2007.
[2] 颜仁仲.实时检测Rootkit并自动修复系统的研究与实现[D].中国科学院研究生院(计算技术研究所),2006.
[3] 王松涛,吴灏.Linux下基于可执行路径分析的内核rootkit检测技术研究[J].计算机工程与应用,2005(11):121-123.
[4] 吴昆.Windows Rootkit技术概述[D].湖南大学软件学院,2008(05)
[5] 冯万利.基于内核入侵的木马设计与实现[J].微计算机信息,2006(18):59-60,92.