【转】Tophet.a
http://wangwpndc.blog.163.com/blog/static/127919242200981543229909/
摘要:
本文揭示了一种新型的Bootkit技术:Tophet,以及其第一代范本Tophet.a使用的一些新鲜的技术。Tophet.a并非病毒或木马,只用来演示高等的启动、穿透与隐身技术。
Bootkit是更高等的Rootkit,该概念最早于2005年被eEye Digital公司在ta们的“BootRoot"项目中提及,该项目通过感染MBR(磁盘主引记载)的方式,实现绕过内核反省和启动隐身。可以以为,所 有在开机时比Windows内核更早加载,实现内核劫持的技术,都可以称之为Bootkit,例如后来的BIOS Rootkit ,, VBootkit,SMM Rootkit等。
在现在MBR\Boot Sector\Nt OS Loader这些众所周之的地位都被HIPS监督软件、检讨软件严防死守,而BIOS, SMM, ROM firmware 之类的启动地位又存在被锁定或通用性不够好的时候,如何简略、通用,又有效地进行Windows内核启动劫持呢?Tophet.a使用了一种新的方 式:NtBootdd.sys。
同时,Tophet.a揭示了一些磁盘级的穿透、暗藏技术,可以穿透目前所有防御软件,进行安装,,同时在目前任何Rootkit文件检测技术下隐身。
要害字:Bootkit 内核劫持 磁盘穿透与暗藏
第一章:启动
最早的Bootkit使用MBR(主引导记载)感染或Boot Sector(启动引导扇区)沾染手法来实现早于Windows内核启动,一般斟酌MBR或BootSector中的代码负荷有限,会在感染代码中,挂钩 Windows内核,再进一步实现具体功效,常用手腕是挂钩INT 0x13中止,干预nt os loader对内核文件的读取, 实现 Windows内核挂钩。
现在看来,这种手腕不免过于原始,对MBR / BootSector这些要害地位,只要严厉防御或者定时检讨,即使Bootkit在体系启动获得节制权后对MBR或BootSector扇区的沾染进行暗藏,也难逃使用低级磁盘读写的反省恢复方法。
感染ntldr和os loader的方法,存在和上面的沾染方式同样的问题。
至于BIOS Rootkit , SMM Rootkit , VBootkit,由于其过于依赖硬件,除了有通用性的难题,再则硬件厂商也开端逐步注意安全问题,BIOS和SMM的写入锁定,启动时抢占VM root等方式,也限制了这类Rootkit的利用。
如何不感染系统要害文件、位置和硬件,来实现内核劫持呢?
boot.ini是一个很好的突破点。
boot.ini中的很多选项都可以用来实现内核劫持,例如启动条目标/KERNEL,/HAL参数可以用来进行内核文件的替换和劫持,这已经是众所周之的了。另外,DEBUG选项和VGA选项都可以用来做劫持或帮助劫持
Vista操作系统已不再使用boot.ini这个文件作为启动配置,其启动配置保留于SystemPartition\boot\bcd这个HIVE 文件中,而这个HIVE的注册表项中的GUID即是相干的启动选项,与以往的boot.ini并没有实质上的区别,本文将不为Vista操作系统做特殊讨 论,下面的相干细节都以Windows XP 操作系统为准。
比起简略的/KERNEL参数替换内核,这里tophet.a用的是更为隐藏的方法。
wo们知道,Windows NT的启动进程简略来说是这样的:
BIOS进行上电领导自检等操作后,将掌握权交给主引导记载(MBR)的引导代码,领导代码读取硬盘分区表(DPT)后,找到引诱分区,并将节制权移交 启动扇区(Boot Sector)的启动代码,启动代码使用其自带的只读FAT32或NTFS的代码,读出其根目录下的NTLDR文件,并将节制权交给NTLDR中的代 码,NTLDR首先将体系切换到维护模式,并开启分页机制,然后掌握权被交给NTLDR体内的OSLoader.exe,OSLoader读入 boot.ini文件,依据配置的启动条目显示启动菜单,等候用户选择(如果只有一个启动项 , 则直接启动那个启动项, 不显示启动菜单),用户选择指定的启动项目后,便会引诱相应的项目。
下面是一个普通的boot.ini中的一条启动项:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
boot.ini中启动项是符合ARC(Advanced RISC Computing)命名规范的。
请注意前面的multi(0),Windows有三种语法:multi , scsi 和signature。当引诱卷所在的磁盘掌握器支撑BIOS的 INT 0x13中止读写磁盘时,就会使用multi语法,这也是绝大部分系统上使用的语法。而scsi语法则是当磁盘控制器不支撑INT 0x13指令时使用的,此时,NTLDR在肯定了领导项后,会从根目录加载一个名为NtBootdd.sys的文件,将其绑定到OSLoader 上,OSLoader中包括的只读NTFS/FAT32代码会使用该驱动来读写磁盘,实现Windows内核文件(ntoskrnl.exe)、硬件抽象 层文件(hal.dll)和BOOT驱动文件的加载。
那么,wo们只须要将boot.ini中当前体系的启动条目中的multi语法改为scsi语法,系统就会在进行内核加载前,加载wo们放置在根目录下的NtBootdd.sys文件了。
这里介绍一个小技能:如何知道当前系统是由boot.ini中的哪个启动条目引导的呢?
在WindowsXP及以后的操作系统中很简单,注册表的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet \Control键下的SystemBootDevice键值就保留着当前系统引导的启动项目标内容,用该键值的内容同boot.ini的条目对照,不难 发明引导当前的系统的启动条目。
在Windows 2000操作系统上则稍微庞杂点,该系统上并没有这么一个键值,但HKEY_LOCAL_MACHINE\System\Setup键下有个名 为"SystemPartition"的键值,该值指明了当前启动卷的装备名,例如:\Device\HarddiskVolumeX“(X为磁盘分区 号),而在系统对象目录的\ArcName目录下保留了这些磁盘装备名对应的ARC名,形如multi(0)disk(X)rdisk(Y),这些Arc 名实际是一些符号链接(Symbolic Link),在对象目录中匹配取得启动卷的装备名对应的ARC名,再在Boot.ini中匹配ARC名,即可肯定当前的启动条目。
言规正 传,OSLoader在读入boot.ini到其数据段的一块缓存并肯定了启动条目后,首先会检讨该条目标前5个字符是不是:"scsi(",如果是,就 会调用名为AEInitializeIo()的函数,该函数会调用BlLoadImage函数加载根目录下的NtBootdd.sys 到内存中,然后使用BlAllocateDataTableEntry函数为该模块分配一个名为"NTBOOTDD.SYS"的 DataTableEntry(该表相似于Windows内核使用的PsLoadedModuleList,是OSLoader用来管理加载模块使用的, 在引导Windows内核进程中,会被复制到PsLoadedModuleList 中)。
接着它会扫描OSLoader的引入表,将 NtBootdd.sys所引出的ScsiPort读写函数绑定到OSLoader的引入表中,然后会调用 NtBootdd.sys的入口点,以便NtBootdd.sys完成本身的初始化工作,如果初始化返回胜利,则继续进行名为 HardDiskInitialize的函数,让以后的磁盘读写操作都通过NtBootdd.sys来实现,若返回失败,则停止 AEInitializeIo函数,继续正常的引导进程。
那么wo们用来劫持的NtBootdd.sys要完成的工作就是:
1.不导出任何函数,这样就不会影响OSLoader的引入表
2.在初始化函数中完成相干的钩子例程及处置例程,然后返回失败,让系统仍然使用INT 0x13来读写磁盘
3.须要注意的是,wo们需要在初始化例程中将ntldr中已读入的boot.ini进行改动,将scsi语法重新改回multi语法,否则在后面的引 导历程中ntldr会以为wo们使用了过错的引导语法,导致系统无法启动。读入的boot.ini是保存在OSLoader的数据段的一个全局变量中 的,wo们扫描整个OSLoader镜像,即可找到须要修正的数据。
4.为了劫持内核,Tophet.a进行了这样的工作:因为调用 NtBootdd.sys的初始化例程的函数是AEInitializeIo,那么wo们在初始化例程中通过堆栈就可以轻松找到该函数 call DriverEntry的下一条指令位置,然后wo们从这条指令向上搜索,就可以精确稳固地找到BlLoadImage函数的地址,OSLoader正是 通过这个函数来加载包含Windows内核文件、HAL和boot驱动的模块的,wo们挂钩该函数,就可以正确地知道Windows内核文件加载的瞬间, 并对其内存镜像进行改动和劫持。
下面是Tophet.a的NtBootdd.sys的DriverEntry函数
NTSTATUS __declspec(naked) DriverEntry(ULONG xx , ULONG xx1)
{
__asm
{