MBR病毒分析
一、基础知识
1、 Windows启动过程
系统引导过程主要由以下几个步骤组成(以硬盘启动为例)
1、 开机;
2、 BIOS加电自检(POST---Power On Self Test),内存地址为0fff:0000;
3、 将硬盘第一个扇区(0头0道1扇区,也就是Boot Sector)读入内存地址0000:7c00处;
4、 检查(WORD)0000:7dfe是否等于0xaa55.若不等于则转去尝试其他介质;如果没有其他启动介质,则显示 ”No ROM BASIC” ,然后死机;
5、 跳转到0000:7c00处执行MBR中的程序;
6、 MBR先将自己复制到0000:0600处,然后继续执行;
7、 在主分区表中搜索标志为活动的分区.如果发现没有活动分区或者不止一个活动分区,则停止;
8、 将活动分区的第一个扇区读入内存地址0000:7c00处;
9、 检查(WORD)0000:7dfe是否等于0xaa55,若不等于则显示 “Missing Operating System”,然后停止,或尝试软盘启动;
10、 跳转到0000:7c00处继续执行特定系统的启动程序;
11、 启动系统. 以上步骤中(2),(3),(4),(5)步由BIOS的引导程序完成;(6),(7),(8),(9),(10)步由MBR中的引导程序完成.
Windows启动过程主要由以下几个步骤组成,其中vista和win7可一概而论;
BIOS—>Master Boot Record—>Partition Bootloader—>ntldr/ bootmgr—>OS Loader
—>winload.exe—>NT kernel
关于ntldr文件的介绍请查看 http://bbs.pediy.com/showthread.php?t=121890
Ntldr= 16-bit stub + OS Loader (just binary appended)
Windows Vista splits up ntldr into bootmgr, winload.exe and winresume.exe
WindowsXP Windows Vista Processor Environment
ntldr bootmgr RealMode
OS Loader OS Loader Protected Mode
- winload.exe Protected Mode
NT kernel NTkernel Protected Mode +Paging
2、 硬盘主引导区结构
硬盘的主引导区在0柱面0磁道1扇区,包括硬盘主引导记录MBR(Main Boot Record)、四个分区表DPT(Disk Partition Table)信息和主引导记录有效标志字三部分,如表所示:
0000-0088 Master Boot Record主引导程序 主引导程序
0089-01BD 出错信息数据区 数据区
01BE-01CD 分区项1(16字节) 分区表
01CE-01DD 分区项2(16字节)
01DE-01ED 分区项3(16字节)
01EE-01FD 分区项4(16字节)
01FE 55 结束标志
01FF AA
主引导记录MBR从0000H开始到00D9H结束,共218个字节。MBR的作用就是检查分区表是否正确以及确定哪个分区为引导分区,并在程序结束时把该分区的启动程序(也就是操作系统引导扇区)调入内存加以执行。MBR是由分区程序(例如DOS 的Fdisk.exe)产生的,在不同的操作系统平台下,这个扇区的内容可能不完全相同。主引导记录比较容易编写,例如,我们自己也可以编写一个这样的程序,只要能完成前述的任务就可以了(参见网上资料“主引导扇区代码(MBR)”)。正是因为主引导记录容易编写,所以才出现了很多的引导区病毒(eeye bootroot、 Vbootkit 、Stoned bootkit、Sinowal等)。
我们都知道,任何硬盘最多只能有四个分区。分区表自偏移01BEH处开始,共64个字节,表中可填入四个分区信息,每16个字节为一个分区说明项,这16个字节含义如分区表结构信息表(偏移量)所示。
图:分区表结构信息表(偏移量)
存贮字节位 内容及含义
第1字节 引导标志。若值为80H表示活动分区,若值为00H表示非活动分区。
第2、3、4字节 本分区的起始磁头号、扇区号、柱面号。其中:
磁头号——第2字节;
扇区号——第3字节的低6位;
柱面号——为第3字节高2位+第4字节8位。
第5字节 分区类型符。
00H——表示该分区未用(即没有指定);
06H——FAT16基本分区;
0BH——FAT32基本分区;
05H——扩展分区;
07H——NTFS分区;
0FH——(LBA模式)扩展分区(83H为Linux分区等)。
第6、7、8字节 本分区的结束磁头号、扇区号、柱面号。其中:
磁头号——第6字节;
扇区号——第7字节的低6位;
柱面号——第7字节的高2位+第8字节。
第9、10、11、12字节 本分区之前已用了的扇区数。
第13、14、15、16字节 本分区的总扇区数。
分区表每一项结构简介
BYTE State:分区状态,0=未激活,0x80=激活(注意此项);
BYTE StartHead:分区起始磁头号;
WORD StartSC:分区起始扇区和柱面号,底字节的底6位为扇区号,高2位为柱面号的第9,10位,高字节为柱面号的低8位;
BYTE Type:分区类型,如0x0B=FAT32,0x83=Linux等,00表示此项未用;
BYTE EndHead:分区结束磁头号;
WORD EndSC:分区结束扇区和柱面号,定义同前;
DWORD Relative:在线性寻址方式下的分区相对扇区地址(对于基本分区即为绝对地址);
DWORD Sectors:分区大小(总扇区数).
3、 MBR病毒感染基本思想
MBR病毒感染的基本思想,首先是读取主引导记录和把分区表从主引导记录中复制出来。然后,MBR病毒把自己的包含恶意二进制数据的主引导记录放到主引导扇区,并复制新的分区表到它。但是,并非只有分区表需要保留,还有微软公司原来的主引导记录也需要保存下来。为此,MBR病毒复制原始主引导记录到其它64个未用到的扇区。到MBR病毒执行完自己的操作后在读取原始的主引导记录并跳到0x7c00处执行来引导开机。
二、样本分析
1、 常驻内存
最早设计DOS操作系统时,PC机的硬件系统只支持1M字节的寻址空间,所以DOS只能直接管理最多1M字节的连续内存空间。在这1M内存中,仅有640K被留给应用程序使用,它们被称为常规内存或基本内存(Base Memory)。
在内存0040h:0013h开始处的两个字节描述了内存中未用内存的高端位置,它的值是KB的倍数。病毒程序首先将自身复制到内存的高端,修改内存容量标志单元0:413H,在原有值的基础上减去病毒长度,使得病毒的int 13h能够常驻内存,并将原int 13h磁盘中断服务程序的中断向量保存,然后将该中断向量置成新的int 13h中断程序入口,即加上一段病毒感染程序,每次调用int13时病毒程序就会被执行。
mov ax, ds:[0413h]
and al, NOT 3
sub ax, 4
mov ds:[0413h], ax
shl ax, (10-4)
mov es, ax
以上代码实现为病毒程序预备4KB的常规内存以实现代码常驻内存。
2、 HOOK INT 13
BIOS Int 13H 调用是 BIOS 提供的磁盘基本输入输出中断调用,它可以完成磁盘(包括
硬盘和软盘)的复位,读写,校验,定位,诊断,格式化等功能。所以MBR病毒一般都是通过HOOK int 13h执行恶意代码。
mov eax, ds:[13h*4]
mov es:[INT13HANDLER - @SYSRQCODE16_START], eax
mov word ptr ds:[13h*4], (@Int13Hook)
mov ds:[(13h*4) + 2], es
以上代码实现对INT 13H的HOOK,并将原始int 13h的入口INT13HANDLER保存并使其指向新的入口点@Int13Hook。
3、HOOK NTLDR
在HOOK INT 13H 部分完成后需要对NTLDR进行HOOK,所以在HOOK INT 13H中断操作中需要对NTLDR的特征码进行扫描。
cld
mov cl, al ;LENGHT
mov al,8Bh ;要查找的字符
shl cx, 9 ; (AL * 200h)
mov di, bx ;字符串首地址
@Int13Hook_scan_loop:
; 8B F0 MOV ESI, EAX
; 85 F6 TEST ESI, ESI
; 74 21 JZ $+23h
; 80 3D ... CMP BYTE PTR [ofs32], imm8
; (the first 6 bytes of this signature exist
; in other modules!)
repne scasb
jne short @Int13Hook_scan_done
cmp dword ptr es:[di], 74F685F0h
jne short @Int13Hook_scan_loop
cmp word ptr es:[di+4], 8021h
jne short @Int13Hook_scan_loop
mov word ptr es:[di-1], 15FFh ; FFh/15h: CALL NEAR [ofs32]
以上代码实现对NTLDR OSLoder模块里的6字节进行扫描,并在FFh/15h:使用CALL NEAR [OFS32]指令进行NTLDR HOOK,该指令寻址采用绝对地址,类似指令也可以。HOOK之后置CALL NEAR [OFS32]指令跳转到恶意代码的地址处执行。
3、 HOOK NTOSKRNL
当代码再次运行到NTLDR OSLoder 被HOOK处时,就会执行恶意代码,此时代码运行在保护模式下。在这里通过扫描_BlLoaderData模块基址来获取NTOSKRNL的镜像地址。通过PE搜索NTOSKRNL.EXE的导出函数,并对NTOSKRNL的导出函数KeAddSystemServiceTable进行HOOK。因为进程SMSS.EXE会加载WIN32K.SYS,当WIN32K.SYS初始化时,它必须调用KeAddSystemServiceTable来为用户以及GDI系统程序提供注册。所以通过对这个函数HOOK操作,可以更快更好的把它加载到执行的WIN32K.SYS中,同时我们可以使用免费的系统服务表(_W32pServiceTable)和相应的参数表 (_W32pArgumentTable)。
对KeAddSystemServiceTable的HOOK主要是通过HOOK NtUserRegisterClassExWOW这个系统调用函数来实现的,因为那个函数没有输出,因此需要一点更复杂的操作。针对这个问题,我们的答案是通过对在W32pServiceTable的代码进行逐个函数扫描,直到找到NtUserRegisterHotkey。一旦发现这个函数,就替换掉WIN32K系统表的入口并用一个指针指到我们自己的钩子函数处,最终替换掉原先这个函数的指针,并从已恢复运行的KeAddSystemServiceTable中脱掉钩子。
该NtUserRegisterClassExWOW钩子函数并不复杂,它只用来比较这个类的名称(都2个参数与一个unicode字符串指针)和SAS Windows class来完成匹配,它用我们在用户映射的用户共享数据中的那个更换过的SASWndProc代码来替换掉lpfnWndProc领域中的WNDCLASSEXW结构,替换完后再把在PEB特定位置的原始函数指针进行存储操作。对NtUserRegisterClassExWOW的HOOK操作可以截获所有的应用层程序窗口类,以便再次HOOK窗口类操作,此时代码就运行到NT的应用层模式下了。
经过在开源代码基础之上的试验,成功实现在Winlogon加载之前创建一个CMD实例。
参考文献:
NTFS文件系统启动扇区代码
主引导扇区代码(MBR)
FAT文件系统启动扇区代码
扩展INT 13H调用规范
驻留程序设计TSR(Terminate but Stay Resident)
PE文件格式
NTLDR源代码及分析
Bochs调试
Windbg与VMWare的连接调试
80x86汇编程序设计与保护模式概念
涉及工具:
Masm6.11
Nasm
IDA5.0
Bochs
Windbg
WinHex
参考开源项目:
eeye bootroot、Vbootkit、Stoned Bootkit、Sinowal Bootkit、ROMOS。
Date:2010-5-26
Author:Cryin
Link:http://hi.baidu.com/justear
注:文中多数内容均来自互联网,时间仓促,加上本人菜鸟初学,可能有遗漏、甚至错误的地方。还有在实际编程中对于保护模式下线性寻址的理解并不是很明确,所以未在本文中提及。另外关于CD ROM引导扇区的分析请查看http://bbs.pediy.com/showthread.php?t=121414 , 对于后续的扩展的思考,bios后门的开发只需要前面加一个hook int 19的模块即可实现,网上亦有同类文章可参考学习。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课