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表示该分区未用(即没有指定);   
                                           06HFAT16基本分区;   
                                           0BHFAT32基本分区;   
                                           05H扩展分区;   
                                           07HNTFS分区;   
                                           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的模块即可实现,网上亦有同类文章可参考学习。