Windows启动过程原理:叙Windows平台下基于MBR和UEFI的bootkit

一:基于MBR的bootkit

1.1:windowsXP的系统加载流程

  运行流程如下图:

  BIOS:BIOS代码存在于主板上的EEPROM(Electronically Erased Programmable Read Only Memory)芯片中。大多数PC都会执行一些称为“Shadow”的操作,它们从RAM复制并运行BIOS代码(地址为0x000F0000),RAM比ROM快,因此可以加快启动速度。BIOS将MBR从引导设备的第一个扇区读入地址0x7C00。并提供一系列低级功能,称为BIOS中断,可通过“int”指令访问实模式代码。

  MBR(Master Boot Record):MBR是引导设备的绝对第一扇区,大小为1扇区(512字节),此代码由BIOS加载到0x7C00,然后在实模式下执行。然而,MBR的大部分是代码; MBR内部是一个表(实际主引导记录),该表由4 x 16字节条目组成,并从偏移量0x1BE开始进入MBR。一旦执行,代码将查看分区表,找到活动分区,然后将分区的第一个扇区(VBR)读入0x7C00然后执行它。 由于MBR将VBR读入0x7C00,因此它将在事先重新定位,以避免覆盖自身。 MBR的最后2个字节是引导签名(0x55,0xAA)。读写MBR的代码很简单,如下:

  VBR(Volume Boot Record):VBR是可引导分区的第一个扇区,就像MBR一样,它的大小为1扇区(512字节)。它由MBR在地址0x7C00(实模式)下加载并执行。 VBR的前两个字节是跳转指令,跳过Bios参数块(BPB)并进入主代码。在VBR的前2个字节之后是BPB,此块包含有关驱动程序和分区的一些信息(主文件表的位置,驱动器的磁盘/磁头/扇区设置,卷序列 等)。除了从BPB收集一些信息之外,VBR没有做太多其他事情,然后将分区的前16个扇区读入内存(通常从地址0xD000开始)。 ?分区的前16个扇区称为$BOOT,尽管所有16个扇区都被加载到内存中,但只使用了7个扇区(1个用于VBR,6个用于IPL)。

  IPL(Inital Program Loader):IPL最大可达15个扇区(7680字节),位于磁盘上的VBR(分区的扇区1-15)之后,此代码从地址0xD000开始,然后在实模式下运行。 Windows XP IPL仅使用15个已分配扇区中的6个。 IPL的工作是在磁盘上定位NTDLR,然后将其读入内存。 IPL将始终读取并执行地址0x20000处的NTLDR。

  NTLDR(New Technology Loader):NTLDR是一个“实际”文件,驻留在C:NTLDR并具有属性FILE_ATTRIBUTE_HIDDEN和FILE_ATTRIBUTE_SYSTEM(MBR,VBR和IPL无法从文件系统访问),它在地址0x20000处执行。TLDR由2个主要部分组成:1.NTLDR – 16位实模式和保护模式代码的混合,可在两种模式之间切换,以便使用BIOS中断。 2.OSLOADER.exe – 一个PE文件(编译为驱动程序),由32位代码组成,在保护模式下执行。NTLDR将设置GDT和IDT,然后进入保护模式(分页仍未设置)。OSLOADER.exe从NTLDR中提取并加载其入口点0x401000,这是因为OSLOADER是PE文件,如果位于0x401000,则不需要重定位表。NTLDR调用0x401000(OSLOADER入口点)。

  OSLoader.exe:OSLOADER是一个PE文件,它被编译为内核驱动程序,但它有点像普通文件而不是驱动程序,因为内核尚未加载。 虽然OSLOADER是PE文件,但PE头不会加载到内存中,只会加载到代码中。OSLOADER中的代码做了很多,所以我只强调主要内容:

i:启用分页并设置页表。

ii:使用NTDETECT检测是否存在运行Windows所需的硬件。

iii:解析boot.ini以获取启动设置,如果是双启动,请询问用户他们希望加载哪个操作系统。 

iV:加载启动驱动程序。

V:在调用KiSystemStartup(ntoskrnl入口点)之前,找到ntoskrnl.exe并将其加载到内存中。

  ntoskrnl.exe:Ntoskrnl是位于C:WindowsSystem32ntoskrnl.exe的PE文件,它将由OSLoader.exe加载(加载地址将在 service pack地址中变化),而ntoskrnl.exe的入口点是KiSystemStartUp,它负责初始化内核并启动操作系统,然后执行由OSLoader.exe架子啊的启动驱动程序。当内核初始化完成后,操作系统将准备好登陆。

  以上便是整个系统启动的调用流程。

1.2 :根据 tinyPXB讲解基于MBR的bootkit的运行机理

1.2.1 MBR代码流程

  bootkit MBR最初将在0x7C00加载并执行;一旦执行它就会将自身复制到地址0x80000并从那里执行。代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

 

 

 

   一旦到达0x8000,MBR将解析软盘的12位文件分配表(FAT),寻找LOADER16BIN,LOADER32BIN和DRIVER32SYS。 MBR将使用INT 0x13,AH = 2(标准磁盘读取)BIOS中断将磁盘中的文件读入内存。我们不能在软盘上使用扩展读取,因此MBR还会将逻辑块地址转换为Cylinder-Head-Sector值。 Loader16将加载到地址0x80200,Loader32将加载到地址0x80400,driver32将加载到地址0x8100。一旦MBR完成加载bootkit组件,它将执行转移到0x80200(Loader16)。

1.2.2 Loader16

  Loader16将从地址0x80200执行,并将完全在实模式下执行。

  代码将负责挂钩INT 0x13(磁盘读取中断)和处理调用,以及挂钩NTLDR中的代码和OSLOADER.exe的入口点。

  INT 0x13是BIOS提供的磁盘服务中断。 MBR,VBR,IPL和NTLDR将使用它来读取磁盘中的扇区以及其他内容。挂钩int 0x13代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

 

 

 

 

 

  通过挂钩磁盘中断,我们可以扫描MBR,VBR,IPL或NTLDR读取的每个扇区。我们通过搜索特征码(FC F3 67 66 A5 66 8B 4E 0C 66 83 E1 03,此代码 NTLDR使用它将OSLOADER加载到内存中),当IPL使用INT 0x13将NTLDR读入内存时,将找到特征码并在“rep movsw”之后进行HOOK。(在OSLOADER加载到0x401000之后)。Hook OSloader代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

  所有代码都是从我们的软盘运行的。 Loader16会将真正的Windows MBR从硬盘驱动器读入0x7C00(就像BIOS一样),挂起INT 0x13,然后执行windows MBR。

1.2.3 Loader32

  Loader16中,我们在NTLDR中进行了HOOK,当运行到这个HOOk的时候,我们将删除HOOK,然后扫描OSLoder对其进行挂钩,扫描一下特征码( 51 6A 01 52 50 6A 05 E8),这段代码后面跟随的是BlAllocateDescriptor的地址,这个函数用于分配内存,当Loader尝试调用BlAllocateDescriptor时,它将运行Hook代码,现在让系统继续运行。一旦NTLDR完成并且OSLOADER开始执行,它将调用被我们Hook住的BlAllocateDescriptor。由于BlAllocateDescriptor已经可以使用了,删除钩子并对BlAllocateDescriptor进行3次调用。

  i:第一个调用是分配一些内存来移动Loader32,这是因为当启用分页时,我们当前执行的内存将被分页。

  ii:第二个调用是为我们的驱动程序分配一些内存来运行,因为存储驱动程序PE文件的地址也将被分页,我们现在也可以将驱动程序的PE文件映射到内存中,准备执行。

  iii:最后一次调用调用没有被Hook情况下调用分配的内存。就在我们的BlAllocateDescriptor将执行转移回OSLOADER之前,我们将把loader32重新定位到分配的内存.

  然后在OSLOADER中执行另一个字节扫描。?这次我们扫描以下字节:8B F0 85 F6 74 11 68 4C 23这些对应于指令:

mov esi,eax

test esi,esi

jz 0x11

push 234Ch

OSLOADER使用这些指令之后的代码直接调用在ntoskrnl中的KiSystemStartup,就在“mov esi,eax”之前是一个push,然后是一个调用,push将把“LOADER_PARAMETER_BLOCK”推送到堆栈,我们将把调用的地址改为指向我们的代码。 ?KiSystemStartup挂钩将指向我们复制到已分配内存的loader32中的代码(0x80000000范围内的某处)。

   现在我们将控制权返回给OSLOADER,以便继续加载操作系统。加载操作系统之后,由于之前已经对系统做了挂钩。所以我们可以你在加载系统的第一时间获取控制流,从而可以对系统为所欲为。

 1.3:windows7的系统加载流程

  1:首先,MBR加载NT Boot Sector,NT boot Sector可以读取FAT32和NTFS,它将读取在 system32或者system32/boot目录下的BOOTMGR.exe函数。

  2:bootmgr.exe有一个16字节的校验头,当检验成功后,将将其映射到0x40000的位置,并以BmMain函数开始。

  3:然后BootMgr.exe检查休眠状态。一但发现休眠,则加载winresume.exe并继续运行。

  4:BootMgr.exe加载BCD数据库,并且遍历boot入口。

  5:选择了Boot入口后,使用BmLanuchBootEntry函数进行加载。然后CPU进入64位模式并跳转到winload.exe。

  6:winload.exe首先加载system的hive文件,然后加载ntoskrnl.exe,HAL.dll,依赖和关键驱动

  7:创建PSLoadModuleList和LOADER_PARAMETER_BLOCK结构,其中包含了内核映射和选项列表等信息

  8:然后使用OslArchTranslateToKernel函数进行内核(ntoskrnol.exe)的初始化流程。

  总体流程如图所示:

  其中内核初始化一共分为两步,这于本篇内容没有太大关系,略过。

 二:vbookit2.0原理

  windows7 x64上,我们需要在不被Patch Guard和驱动签名检测的前提下,过掉所有的安全功能。所以我们只能在内存中打补丁。和tinyXp一样,文件加载的时候打补丁,一步步前进,直到到达内核为止。原理基本同tinyXP,所以不多解释,具体可参考源码。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年5月15日
下一篇 2020年5月15日

相关推荐