论文部分内容阅读
【摘要】Rootkit是恶意软件用于隐藏自身及其它特定资源和活动的程序集合。本文针对windows Rootkit的启动方式,将Rootkit归为先于操作系统启动和伴随操作系统启动两类,详细分析了这两类windows Rootkit的启动方式、实现原理及隐藏技术,并对现有的检测方法的原理进行了深入的分析。
【关键词】Rootkit;宿主进程;BIOS Rootkit;MBR Bootkit
1.介绍
Rootkit[1]最早出现于Unix系统中,随着计算机技术的发展,现在多种操作系统平台中都出现了Rootkit。现在的研究表明恶意代码的Rootkit技术化趋势非常明显,Rootkit越来越多地出现在Windows操作系统中用于获取敏感信息、实现目标控制。Rootkit使用的技术通常比较高深和复杂,常规检测工具和查杀软件一般难以将其检测出,鉴于其日益增强的危害性,有必要对Rootkit实现的原理进行分析,对现有的检测技术进行深入的分析。
本文依据windows Rootkit的启动方式,将windows Rootkit归为先于操作系统启动和伴随操作系统启动两类,详细分析了其启动方式、隐藏技术和实现原理,并对现有的检测技术的原理进行了深入的分析。
本文组织如下:第二部分介绍windows Rootkit的启动方式、实现原理及隐藏技术;第三部分介绍现有的windows Rootkit检测技术的原理;第四部分综合检测方法及总结。
2.windows Rootkit的实现原理
依照windows Rootkit的启动实现方式,我们将windows Rootkit分为先于操作系统启动和伴随操作系统启动两类,在伴随操作系统启动的Rootkit中,深入分析内核劫持、svchost宿主启动、winlogon事件通知、系统文件感染、DLL劫持实现的原理和方法,在先于widnows操作系统启动的Rootkit中,详细分析基于BIOS(Basic Input/Output System)的Rootkit和基于MBR(Master Boot Record)的Rootkit。
2.1 伴随widnows启动的Rootkit
windows操作系统引导过程可以分为预引导阶段、引导和载入内核阶段、内核初始化阶段、以及登录阶段,在这个过程中提供给应用程序启动的扩展接口,包括系统服务、常用注册表启动项、IE的BHO,winsock2的SPI,驱动程序,甚至是普通的启动文件夹都可以作为Rootkit的加载方式,图1显示sysinternals提供的autoruns显示widnows提供的启动项。
2.1.1 NtBootdd.sys内核劫持
利用Boot.ini文件中的特殊选项scsi来实现内核的劫持,当windows通过NRLDR中的OSLoader在读入boot.ini到其数据段的一段缓存并确定了启动条目后,会检查该条目的前5个字符(windows支持mutil,scsi,signature),如果是scsi,就会调用名为AEInitializeIo()的函数,该函数会调用BlLoadImage函数加载根目录下的NtBootdd.sys到内存中,然后使用BlAllocateDataTableEntry函数为该模块分配一个名为“NTBOOTDD.SYS”的Data-TableEntry,接着它会扫描OSLoader的引入表,将NtBootdd.sys所引出的ScsiPort读写函数绑定到OSLoader的引入表中,然后会调用NtBootdd.sys的入口点,以便NtBootdd.sys完成本身的初始化工作,如果初始化返回胜利,则继续进行名为HardDiskInitialize的函数,让以后的磁盘读写操作都通过NtBootdd.sys来实现,若返回失败,则停止AEInitializeIo函数,继续正常的引导进程。因此实现NtBootdd.sys的劫持来启动Rootkit采用如下方法[2]:
(1)不导出任何函数,这样就不会影响OSLoader的引入表。
(2)在初始化函数中完成相干的钩子例程及处置例程,然后返回失败,让系统仍然使用INT 0×13来读写磁盘。
(3)在初始化例程中将ntldr中已读入的boot.ini进行改动,将scsi语法重新改回multi语法,否则在后面的引导历程中ntldr会以为们使用了错误的引导语法,导致系统无法启动。读入的boot.ini是保存在OSLoader的数据段的一个全局变量中,扫描整个OSLoader镜像,即可找到须要修正的数据。
(4)在初始化例程中通过堆栈就可以找到该函数call DriverEntry的下一条指令位置,然后从这条指令向上搜索,就可以精确稳固地找到BlLoadImage函数的地址,OSLoader正是通过这个函数来加载包含Windows内核文件、HAL和boot的驱动模块,挂钩该函数就可以正确地知道Windows内核文件加载的瞬间,并对其内存镜像进行改动和劫持。
2.1.2 Svchost宿主启动
svchost本身只是作为服务宿主,并不实现任何功能,需要svchost启动的服务以动态链接库形式实现,在安装这些服务时,把服务的可执行程序指向svchost,启动这些服务时由svchost调用相应服务的动态链接库来启动服务。svchost获取某一个服务是由哪个动态链接库负责是由注册表services\*\parameters子键的ServiceDll说明,这些动态链接库中必须包含导出函数ServiceMain()函数来处理服务任务。在启动一个svchost.exe负责的服务时,服务管理器如果遇到可执行程序内容的ImagePath已经存在服务管理器的映像库中,就不再启动第二个svchost进程,而直接启动服务,这就实现了多个服务共享一个进程。Svchost.exe属于访问网络的关键进程,因此在网络通讯过程中隐蔽性和穿透性更强。实现svchost作为宿主进程启动Rootkit采用如下方法[3]: (1)关闭svchost共享的netsvc服务,如System Event Notification。
(2)通过服务控制管理器删除该服务。
(3)实现一个DLL,设计Service-Main()的导出函数。
(4)重新创建一个同名服务,把DLL的镜像指向上述设计的DLL。
(5)重新启动System Event Notifi-cation,实现Rootkit通过svchost进行加载。
2.1.3 winlogon事件通知包
winlogon事件通知包是winlogon事件功能扩展提供的接口,这些事件包括锁定、解锁、登录、注销、关机、屏保等,可以通过winlogon事件通知包的规范实现一个DLL来启动Rootkit。实现过程如下[4]:
(1)首先声明一个winlogon事件的数据结构,并将该结构传入所选择的winlogon事件函数,该事件决定何时加载实现Rootkit的DLL。
(2)导出所选择的winlogon事件函数,并将实现Rootkit的DLL释放到 %syst emroot%\system32\下。
(3)在注册表HKEY_LOCAL_MACHINE \SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify\Intrasrv下注册该DLL。
2.2 先于widnows启动的Rootkit
依据windows操作系统的启动方式,先于windows启动的Rootkit主要包括BIOS的Rootkit[5]和基于MBR的Rootkit[6],当然功能的实现还需要操作系统内部的支持。随着Rootkit技术的不断发展,陆续出现了基于PCI的BIOS Rootkit,基于NDIS的Rootkit等,总之这些Rootkit在发生在操作系统的预启动阶段,我们统一称之为先于windows启动的Rootkit。
2.2.1 基于ISA的BIOS Rootkit
Icelord是一个典型的基于ISA的BIOS Rootkit,它利用了BIOS中仍然保留的ISA调用的接口实现了Rootkit的启动,表1显示在BIOS中ISA模块编写的格式。
Icelord将Leaving.bin文件和Windows驱动文件IO_HLPER.SYS一同嵌入到Icelord.exe PE文件的资源节中,这三个文件的作用分别为:Icelord.exe主要负责将资源节中的Leaving.bin和IO_HLPER.SYS文件释放到磁盘中,然后加载并运行IO_HLPER.SYS驱动文件,并将Leaving.bin文件以ISA模块的形式刷入主板的BIOS中;IO—HLPER.SYS驱动文件主要是负责辅助Icelord.exe直接读取物理内存和I/O端口;Leaving.bin文件则属于BIOS Rootkit的启动文件,负责在windows启动过程中绕过内核的安全防御且加载并运行指定的模块程序。用于启动BIOS Rootkit的Leaving.bin启动原理分析如下:
(1)首先Leaving.bin会HOOK BIOS的Int 19h中断,把原来的Int 19h中断地址存入启动代码的一个变量中。然后把控制权交还给BIOS。Int 19h中断主要是用于将启动盘(如;硬盘启动、软盘启动、光驱肩动等)的引导代码装入到内存的0000:7C00的地方,然后把控制权交给引导代码。Int 19h的调用通常是在BIOS启动的最后阶段了。所以Hook这个中断,就能在BIOS执行的末尾阶段获得控制权。
(2)其次在BIOS调用Int 19h中断时,启动模块代码会Hook BIOS的Int 13h中断,由于Int 13H为BIOS的磁盘服务中断,启动模块可以在操作系统读取NTLDR文件时再次获得控制权。这时Leaving.bin文件会搜索读入的NTLDR文件中是否存在下面的特征码:Code={33 cO f3 ab,Of 20 d8 Of,22 d8 al}。
(3)当NTLDR运行到被HOOK的特征码以后,Leaving.bin再次获得了执行的机会,然后它会通过B1LoaderBlock变量去搜索BootDriver驱动,然后选定一个BootDriver驱动对其入口进行Inline Hook,这样便可以让指定的驱动程序得以加载并运行。
(4)当内核加载并运行那个被Hook的BootDriver时,Leaving.bin所指定的驱动程序得以顺利加载并运行。
2.2.2 基于MBR的Rootkit
基于MBR的Rootkit通过感染MBR的方式把Rootkit的代码放在原来MBR的位置,然后在MBR加载到内存的时候获得控制权,并分发了Windows启动过程的NTLDR和NDIS文件,最后在操作系统的启动过程中得以顺利加载并运行,成功的绕过Windows操作系统的安全防御,最后在NDIS驱动中实现功能模块。
(1)篡改MBR后,0磁道0柱面1扇区的MBR已为Rootkit,当BIOS调用Int 19h的时候会读入Rootkit代码到内存的0000:7COOh处,并把控制权交给了Rootkit代码。
(2)Rootkit首先HOOK BIOS的Int 13h磁盘中断服务,由于NTLDR的Osloader文件从磁盘读入内存是通过BIOS的Int 13h中断服务实现,所以HOOK这个中断可以在操作系统的NTLDR文件运行的时候能再次获得控制权。
(3)被HOOK的Int 13h代码会在NTLDR的Osloader文件读入到内存的过程中执行很多次,这时Rootkit代码会搜索读入的内容是否为如下代码:code={8b f0 85 f6,74 21 80},如果搜索到这段特征码,Rootkit会对这段特征码进行分发操作。当上面这段代码运行时,内核和BootDriver都已经加载到内存中,分发这段特征码是为了进一步HOOK内核或者BootDriver。 (4)当被分发的特征码运行时,Root-kit再次获得了控制权,此时Rootkit会在Osloader内存映像文件地址范围内搜索如下的特征码:code={c7 46 34 00,40 00 00,****,al XX XX XX XX},搜索上面的特征码是为了定位到B1LoaderBlock变量,这个变量包含很多有用的信息,其中包括内核和BootDriver信息。当定位到这个变量后Rootkit就可以根据偏移然后找到BootDriver里面的NDIS驱动内存映像地址。接下来Rootkit会HOOK NDIS驱动的ethFilterDprIndicateReceivePacket函数,这个函数主要是用于过滤网络数据包。最后Rootkit会将自己的后门代码挪到NDIS内存映像的基地址偏移为Ox40h位置,这样做的目的是为了让功能代码不受Windows操作系统启动过程的影响。
(5)当功能代码获得控制权的时候,它会通过匹配数据包,然后判断这个进入的数据包是否为所要查找的,如果是的话就会执行数据包所包含的shellcode,如果不是则把控制权交还给操作系统。
3.Rootkit检测技术
基于windows Rootkit日益的复杂性和为危害性,因此安全公司和研究结构在Rookit检测研究方面提出了一系列的方法和成果,目前已有产品中用到的检测方法主要有以下4种[7]:
(1)基于特征码的内核内存扫描检测。该检测方法通过在内核内存中搜索含有特征码的内存块来检测Rootkit,但它通常只能检测出已知特征码的Rootkit。
(2)启发式扫描检测。这是一种通过发现非常规系统行为寻找Rootkit痕迹的检测方法。这种方法的主要缺陷在于通常会挂钩系统频繁调用的处理函数,对操作系统性能有较大影响。
(3)基于内存完整性校验的检测。该检测方法对于采用Hook方式的Rootkit具有较好的检测效果,但一般只能判断Rootkit是否存在,无法判断具体类型。
(4)基于交叉视图的检测。该检测方法通过比较不同途径所枚举到的系统信息,根据其中的差异发现Rootkit的痕迹。
3.1 EPROCESS枚举交叉比较
检测这种方式隐藏进程的Rootkit十分困难,目前尚无单一的有效检测方法,因此需要综合使用多种手段,由于系统对各种进程和线程的管理,因此依赖于各种内核链表数据结构,这些链表数据结构之间有一定联系但又有差异,修改其中某一个链表结构可能不会影响其他链表。基于这个原理,利用各个内核链表结构中的一些进程EPROCESS结构差异对多种方法获得的进程EPROCESS进行交叉对比,就有可能发现Rootkit的迹象。对EPROCESS的枚举操作可采用表2提供的方式。
3.2 基于交叉视图的检测方法
下面以检测修改系统服务描述符表SSDT (System Service Descriptor Table)的Rootkit来说明这种检测方法。所有SSDT中对应的内核函数都在Windows内核ntoskrnl.exe中,当Rootkit加载以后,通过修改SSDT实现对系统内核函数进行Hook,这个hook操作已经破坏了系统内存中SSDT的真实性。因此,如果需要检测出SSDT中哪些项被Hook了,必须构建一个原始的干净SSDT。检测步骤如下:
(1)计算磁盘上ntoskrnl.exe文件的Md5散列值,并与未被感染情况下的散列值比较,判断其是否已经被patch。
(2)如果当前系统的ntoskrnl.exe文件被patch,则将未被patch的相同版本系统中的ntoskrnl.exe载入内存,否则直接载入当前系统的ntoskrnl.exe,分析其导出表,获取KeService DescriptorTable地址。
(3)打开\device\physical memory,将KeServiceDescriptor Table所在物理内存的页映射到虚拟内存。
(4)在物理内存中搜索KeServiceDesc-riptorTable结构中ServiceDescriptor[0]. Service Table的地址,并将该所在地址的物理内存的页映射到虚拟内存,以获取当前SSDT的内容
(5)获取系统中所有已加载模块列表的名称、加载基地址和大小等信息。
(6)分析ntoskrnl.exe文件的PE结构,将其中的导出函数地址作为基准,和步骤4)中所获得的SSDT进行比较,不同的地址即是被Hook的SSDT项,判断修改之后的地址属于系统已加载的哪个模块的地址范围,即可获取挂钩SSDT中该表项地址重定位之后所处的模块信息。
3.3 基于特定函数集合的检测方法
Rootkit要实现特定功能必须使用系统的API函数(包括内核级和用户级的),因此如果某个程序调用了危险的特定函数集合,有理由怀疑其可能是木马或者Rootkit之类的恶意代码,分析Rootkit的API函数调用也可以有效的对Rootkit进行归类。在程序加载之前,对于引入的任何程序文件,扫描其代码获得其系统函数集合(这个过程可能需要代码逆向技术和虚拟机配合),与本文实现根据对多个木马或者Rootkit分析设置好的一系列特征函数集合做交集运算,就可以知道该程序文件使用了哪些危险的函数,并大致估计其功能和属于哪种类型,表3显示Rootkit可能调用的API函数及危险程度。
4.综合检测和总结
windows Rootkit实现的日益复杂性和隐蔽性,使得单一检测技术很难有效的对Rootkit进行检测,因此综合运用多种检测方法是应对Rootkit威胁的有效手段。本文详细分析了多种主流windows Rootkit的启动方式和实现原理,并对现有的检测技术的原理进行了分析,对于新出现的Rootkit及其检测技术还有很多的技术细节需要跟踪和研究以对抗日益负责的Rootkit技术。
参考文献
[1]Hoglund G,Butler J.Rootkits:Subverting the Windows Kernel[M].[S.l.]:Addison Wesley Professional,2005.
[2]郑文彬.高级Rootkit-Tophet安全焦点信息安全峰会,2008,11.
[3]孟宁.windows下Rootkit启动技术的研究与应用[D].同济大学软件学院,2009,9.
[4]http://msdn.microsoft.com/en-us/library/aa380545.aspx.
[5]IceLord.BIOS Rootkit:welcome home,my Loord!.http://www.Xfocus.Net/artices/200705/918.html,2007.
[6]Derek Soeder,Ryan Permeh:eEye BootRoot:A Basis for Bootstrap-Based windows kernel code.BlackHat, 2005.
[7]Butler J.Windows Rootkits of 2005,Part One & Part Three[DB/OL].(2007-12-05).http://www.securitvfocus.com/infocus/1850.
【关键词】Rootkit;宿主进程;BIOS Rootkit;MBR Bootkit
1.介绍
Rootkit[1]最早出现于Unix系统中,随着计算机技术的发展,现在多种操作系统平台中都出现了Rootkit。现在的研究表明恶意代码的Rootkit技术化趋势非常明显,Rootkit越来越多地出现在Windows操作系统中用于获取敏感信息、实现目标控制。Rootkit使用的技术通常比较高深和复杂,常规检测工具和查杀软件一般难以将其检测出,鉴于其日益增强的危害性,有必要对Rootkit实现的原理进行分析,对现有的检测技术进行深入的分析。
本文依据windows Rootkit的启动方式,将windows Rootkit归为先于操作系统启动和伴随操作系统启动两类,详细分析了其启动方式、隐藏技术和实现原理,并对现有的检测技术的原理进行了深入的分析。
本文组织如下:第二部分介绍windows Rootkit的启动方式、实现原理及隐藏技术;第三部分介绍现有的windows Rootkit检测技术的原理;第四部分综合检测方法及总结。
2.windows Rootkit的实现原理
依照windows Rootkit的启动实现方式,我们将windows Rootkit分为先于操作系统启动和伴随操作系统启动两类,在伴随操作系统启动的Rootkit中,深入分析内核劫持、svchost宿主启动、winlogon事件通知、系统文件感染、DLL劫持实现的原理和方法,在先于widnows操作系统启动的Rootkit中,详细分析基于BIOS(Basic Input/Output System)的Rootkit和基于MBR(Master Boot Record)的Rootkit。
2.1 伴随widnows启动的Rootkit
windows操作系统引导过程可以分为预引导阶段、引导和载入内核阶段、内核初始化阶段、以及登录阶段,在这个过程中提供给应用程序启动的扩展接口,包括系统服务、常用注册表启动项、IE的BHO,winsock2的SPI,驱动程序,甚至是普通的启动文件夹都可以作为Rootkit的加载方式,图1显示sysinternals提供的autoruns显示widnows提供的启动项。
2.1.1 NtBootdd.sys内核劫持
利用Boot.ini文件中的特殊选项scsi来实现内核的劫持,当windows通过NRLDR中的OSLoader在读入boot.ini到其数据段的一段缓存并确定了启动条目后,会检查该条目的前5个字符(windows支持mutil,scsi,signature),如果是scsi,就会调用名为AEInitializeIo()的函数,该函数会调用BlLoadImage函数加载根目录下的NtBootdd.sys到内存中,然后使用BlAllocateDataTableEntry函数为该模块分配一个名为“NTBOOTDD.SYS”的Data-TableEntry,接着它会扫描OSLoader的引入表,将NtBootdd.sys所引出的ScsiPort读写函数绑定到OSLoader的引入表中,然后会调用NtBootdd.sys的入口点,以便NtBootdd.sys完成本身的初始化工作,如果初始化返回胜利,则继续进行名为HardDiskInitialize的函数,让以后的磁盘读写操作都通过NtBootdd.sys来实现,若返回失败,则停止AEInitializeIo函数,继续正常的引导进程。因此实现NtBootdd.sys的劫持来启动Rootkit采用如下方法[2]:
(1)不导出任何函数,这样就不会影响OSLoader的引入表。
(2)在初始化函数中完成相干的钩子例程及处置例程,然后返回失败,让系统仍然使用INT 0×13来读写磁盘。
(3)在初始化例程中将ntldr中已读入的boot.ini进行改动,将scsi语法重新改回multi语法,否则在后面的引导历程中ntldr会以为们使用了错误的引导语法,导致系统无法启动。读入的boot.ini是保存在OSLoader的数据段的一个全局变量中,扫描整个OSLoader镜像,即可找到须要修正的数据。
(4)在初始化例程中通过堆栈就可以找到该函数call DriverEntry的下一条指令位置,然后从这条指令向上搜索,就可以精确稳固地找到BlLoadImage函数的地址,OSLoader正是通过这个函数来加载包含Windows内核文件、HAL和boot的驱动模块,挂钩该函数就可以正确地知道Windows内核文件加载的瞬间,并对其内存镜像进行改动和劫持。
2.1.2 Svchost宿主启动
svchost本身只是作为服务宿主,并不实现任何功能,需要svchost启动的服务以动态链接库形式实现,在安装这些服务时,把服务的可执行程序指向svchost,启动这些服务时由svchost调用相应服务的动态链接库来启动服务。svchost获取某一个服务是由哪个动态链接库负责是由注册表services\*\parameters子键的ServiceDll说明,这些动态链接库中必须包含导出函数ServiceMain()函数来处理服务任务。在启动一个svchost.exe负责的服务时,服务管理器如果遇到可执行程序内容的ImagePath已经存在服务管理器的映像库中,就不再启动第二个svchost进程,而直接启动服务,这就实现了多个服务共享一个进程。Svchost.exe属于访问网络的关键进程,因此在网络通讯过程中隐蔽性和穿透性更强。实现svchost作为宿主进程启动Rootkit采用如下方法[3]: (1)关闭svchost共享的netsvc服务,如System Event Notification。
(2)通过服务控制管理器删除该服务。
(3)实现一个DLL,设计Service-Main()的导出函数。
(4)重新创建一个同名服务,把DLL的镜像指向上述设计的DLL。
(5)重新启动System Event Notifi-cation,实现Rootkit通过svchost进行加载。
2.1.3 winlogon事件通知包
winlogon事件通知包是winlogon事件功能扩展提供的接口,这些事件包括锁定、解锁、登录、注销、关机、屏保等,可以通过winlogon事件通知包的规范实现一个DLL来启动Rootkit。实现过程如下[4]:
(1)首先声明一个winlogon事件的数据结构,并将该结构传入所选择的winlogon事件函数,该事件决定何时加载实现Rootkit的DLL。
(2)导出所选择的winlogon事件函数,并将实现Rootkit的DLL释放到 %syst emroot%\system32\下。
(3)在注册表HKEY_LOCAL_MACHINE \SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify\Intrasrv下注册该DLL。
2.2 先于widnows启动的Rootkit
依据windows操作系统的启动方式,先于windows启动的Rootkit主要包括BIOS的Rootkit[5]和基于MBR的Rootkit[6],当然功能的实现还需要操作系统内部的支持。随着Rootkit技术的不断发展,陆续出现了基于PCI的BIOS Rootkit,基于NDIS的Rootkit等,总之这些Rootkit在发生在操作系统的预启动阶段,我们统一称之为先于windows启动的Rootkit。
2.2.1 基于ISA的BIOS Rootkit
Icelord是一个典型的基于ISA的BIOS Rootkit,它利用了BIOS中仍然保留的ISA调用的接口实现了Rootkit的启动,表1显示在BIOS中ISA模块编写的格式。
Icelord将Leaving.bin文件和Windows驱动文件IO_HLPER.SYS一同嵌入到Icelord.exe PE文件的资源节中,这三个文件的作用分别为:Icelord.exe主要负责将资源节中的Leaving.bin和IO_HLPER.SYS文件释放到磁盘中,然后加载并运行IO_HLPER.SYS驱动文件,并将Leaving.bin文件以ISA模块的形式刷入主板的BIOS中;IO—HLPER.SYS驱动文件主要是负责辅助Icelord.exe直接读取物理内存和I/O端口;Leaving.bin文件则属于BIOS Rootkit的启动文件,负责在windows启动过程中绕过内核的安全防御且加载并运行指定的模块程序。用于启动BIOS Rootkit的Leaving.bin启动原理分析如下:
(1)首先Leaving.bin会HOOK BIOS的Int 19h中断,把原来的Int 19h中断地址存入启动代码的一个变量中。然后把控制权交还给BIOS。Int 19h中断主要是用于将启动盘(如;硬盘启动、软盘启动、光驱肩动等)的引导代码装入到内存的0000:7C00的地方,然后把控制权交给引导代码。Int 19h的调用通常是在BIOS启动的最后阶段了。所以Hook这个中断,就能在BIOS执行的末尾阶段获得控制权。
(2)其次在BIOS调用Int 19h中断时,启动模块代码会Hook BIOS的Int 13h中断,由于Int 13H为BIOS的磁盘服务中断,启动模块可以在操作系统读取NTLDR文件时再次获得控制权。这时Leaving.bin文件会搜索读入的NTLDR文件中是否存在下面的特征码:Code={33 cO f3 ab,Of 20 d8 Of,22 d8 al}。
(3)当NTLDR运行到被HOOK的特征码以后,Leaving.bin再次获得了执行的机会,然后它会通过B1LoaderBlock变量去搜索BootDriver驱动,然后选定一个BootDriver驱动对其入口进行Inline Hook,这样便可以让指定的驱动程序得以加载并运行。
(4)当内核加载并运行那个被Hook的BootDriver时,Leaving.bin所指定的驱动程序得以顺利加载并运行。
2.2.2 基于MBR的Rootkit
基于MBR的Rootkit通过感染MBR的方式把Rootkit的代码放在原来MBR的位置,然后在MBR加载到内存的时候获得控制权,并分发了Windows启动过程的NTLDR和NDIS文件,最后在操作系统的启动过程中得以顺利加载并运行,成功的绕过Windows操作系统的安全防御,最后在NDIS驱动中实现功能模块。
(1)篡改MBR后,0磁道0柱面1扇区的MBR已为Rootkit,当BIOS调用Int 19h的时候会读入Rootkit代码到内存的0000:7COOh处,并把控制权交给了Rootkit代码。
(2)Rootkit首先HOOK BIOS的Int 13h磁盘中断服务,由于NTLDR的Osloader文件从磁盘读入内存是通过BIOS的Int 13h中断服务实现,所以HOOK这个中断可以在操作系统的NTLDR文件运行的时候能再次获得控制权。
(3)被HOOK的Int 13h代码会在NTLDR的Osloader文件读入到内存的过程中执行很多次,这时Rootkit代码会搜索读入的内容是否为如下代码:code={8b f0 85 f6,74 21 80},如果搜索到这段特征码,Rootkit会对这段特征码进行分发操作。当上面这段代码运行时,内核和BootDriver都已经加载到内存中,分发这段特征码是为了进一步HOOK内核或者BootDriver。 (4)当被分发的特征码运行时,Root-kit再次获得了控制权,此时Rootkit会在Osloader内存映像文件地址范围内搜索如下的特征码:code={c7 46 34 00,40 00 00,****,al XX XX XX XX},搜索上面的特征码是为了定位到B1LoaderBlock变量,这个变量包含很多有用的信息,其中包括内核和BootDriver信息。当定位到这个变量后Rootkit就可以根据偏移然后找到BootDriver里面的NDIS驱动内存映像地址。接下来Rootkit会HOOK NDIS驱动的ethFilterDprIndicateReceivePacket函数,这个函数主要是用于过滤网络数据包。最后Rootkit会将自己的后门代码挪到NDIS内存映像的基地址偏移为Ox40h位置,这样做的目的是为了让功能代码不受Windows操作系统启动过程的影响。
(5)当功能代码获得控制权的时候,它会通过匹配数据包,然后判断这个进入的数据包是否为所要查找的,如果是的话就会执行数据包所包含的shellcode,如果不是则把控制权交还给操作系统。
3.Rootkit检测技术
基于windows Rootkit日益的复杂性和为危害性,因此安全公司和研究结构在Rookit检测研究方面提出了一系列的方法和成果,目前已有产品中用到的检测方法主要有以下4种[7]:
(1)基于特征码的内核内存扫描检测。该检测方法通过在内核内存中搜索含有特征码的内存块来检测Rootkit,但它通常只能检测出已知特征码的Rootkit。
(2)启发式扫描检测。这是一种通过发现非常规系统行为寻找Rootkit痕迹的检测方法。这种方法的主要缺陷在于通常会挂钩系统频繁调用的处理函数,对操作系统性能有较大影响。
(3)基于内存完整性校验的检测。该检测方法对于采用Hook方式的Rootkit具有较好的检测效果,但一般只能判断Rootkit是否存在,无法判断具体类型。
(4)基于交叉视图的检测。该检测方法通过比较不同途径所枚举到的系统信息,根据其中的差异发现Rootkit的痕迹。
3.1 EPROCESS枚举交叉比较
检测这种方式隐藏进程的Rootkit十分困难,目前尚无单一的有效检测方法,因此需要综合使用多种手段,由于系统对各种进程和线程的管理,因此依赖于各种内核链表数据结构,这些链表数据结构之间有一定联系但又有差异,修改其中某一个链表结构可能不会影响其他链表。基于这个原理,利用各个内核链表结构中的一些进程EPROCESS结构差异对多种方法获得的进程EPROCESS进行交叉对比,就有可能发现Rootkit的迹象。对EPROCESS的枚举操作可采用表2提供的方式。
3.2 基于交叉视图的检测方法
下面以检测修改系统服务描述符表SSDT (System Service Descriptor Table)的Rootkit来说明这种检测方法。所有SSDT中对应的内核函数都在Windows内核ntoskrnl.exe中,当Rootkit加载以后,通过修改SSDT实现对系统内核函数进行Hook,这个hook操作已经破坏了系统内存中SSDT的真实性。因此,如果需要检测出SSDT中哪些项被Hook了,必须构建一个原始的干净SSDT。检测步骤如下:
(1)计算磁盘上ntoskrnl.exe文件的Md5散列值,并与未被感染情况下的散列值比较,判断其是否已经被patch。
(2)如果当前系统的ntoskrnl.exe文件被patch,则将未被patch的相同版本系统中的ntoskrnl.exe载入内存,否则直接载入当前系统的ntoskrnl.exe,分析其导出表,获取KeService DescriptorTable地址。
(3)打开\device\physical memory,将KeServiceDescriptor Table所在物理内存的页映射到虚拟内存。
(4)在物理内存中搜索KeServiceDesc-riptorTable结构中ServiceDescriptor[0]. Service Table的地址,并将该所在地址的物理内存的页映射到虚拟内存,以获取当前SSDT的内容
(5)获取系统中所有已加载模块列表的名称、加载基地址和大小等信息。
(6)分析ntoskrnl.exe文件的PE结构,将其中的导出函数地址作为基准,和步骤4)中所获得的SSDT进行比较,不同的地址即是被Hook的SSDT项,判断修改之后的地址属于系统已加载的哪个模块的地址范围,即可获取挂钩SSDT中该表项地址重定位之后所处的模块信息。
3.3 基于特定函数集合的检测方法
Rootkit要实现特定功能必须使用系统的API函数(包括内核级和用户级的),因此如果某个程序调用了危险的特定函数集合,有理由怀疑其可能是木马或者Rootkit之类的恶意代码,分析Rootkit的API函数调用也可以有效的对Rootkit进行归类。在程序加载之前,对于引入的任何程序文件,扫描其代码获得其系统函数集合(这个过程可能需要代码逆向技术和虚拟机配合),与本文实现根据对多个木马或者Rootkit分析设置好的一系列特征函数集合做交集运算,就可以知道该程序文件使用了哪些危险的函数,并大致估计其功能和属于哪种类型,表3显示Rootkit可能调用的API函数及危险程度。
4.综合检测和总结
windows Rootkit实现的日益复杂性和隐蔽性,使得单一检测技术很难有效的对Rootkit进行检测,因此综合运用多种检测方法是应对Rootkit威胁的有效手段。本文详细分析了多种主流windows Rootkit的启动方式和实现原理,并对现有的检测技术的原理进行了分析,对于新出现的Rootkit及其检测技术还有很多的技术细节需要跟踪和研究以对抗日益负责的Rootkit技术。
参考文献
[1]Hoglund G,Butler J.Rootkits:Subverting the Windows Kernel[M].[S.l.]:Addison Wesley Professional,2005.
[2]郑文彬.高级Rootkit-Tophet安全焦点信息安全峰会,2008,11.
[3]孟宁.windows下Rootkit启动技术的研究与应用[D].同济大学软件学院,2009,9.
[4]http://msdn.microsoft.com/en-us/library/aa380545.aspx.
[5]IceLord.BIOS Rootkit:welcome home,my Loord!.http://www.Xfocus.Net/artices/200705/918.html,2007.
[6]Derek Soeder,Ryan Permeh:eEye BootRoot:A Basis for Bootstrap-Based windows kernel code.BlackHat, 2005.
[7]Butler J.Windows Rootkits of 2005,Part One & Part Three[DB/OL].(2007-12-05).http://www.securitvfocus.com/infocus/1850.