首页
社区
课程
招聘
[分享]WindowsUEFI启动介绍
发表于: 2025-1-26 20:21 8819

[分享]WindowsUEFI启动介绍

2025-1-26 20:21
8819

Windows进行UEFI启动过程

最近在看Windows的UEFI启动过程中发现相关资料较少,且外文资料多为机翻,本帖总结的同时进行了校对,部分译名可能不通用,如有错误,望大佬轻喷。

1.概述

1)UEFI 固件执行UEFI平台初始化,执行CPU和芯片组初始化,并加载UEFI引导驱动程序。
2)UEFI引导管理器枚举外部总线,如PCI总线上的设备,加载UEFI设备驱动程序,然后加载Windows引导应用程序。
3)Windows 引导管理器(bootmgfw.efi) 加载Windows引导加载程序。
4)Windows 引导加载程序(winload.efi) 加载 Windows 操作系统。
如图:

2.讨论UEFI与Windows之间的过渡关系

1.EFI分区

操作系统加载程序由存储在EFI系统分区中的几个文件组成,包括bootmgfw.efi和 winload.efi模块。第一个称为Windows引导管理器,第二个称为Windows引导加载程序。

(EFI分区)
这些程序的位置也由NVRAM变量(类似于ROM)指定。而包含EFI分区的驱动器的UEFI路径存储在引导顺序NVRAM变量BOOT_ORDER中,EFI分区文件系统中的路径存储在另一个变量BOOT 中(通常在\EFIMicrosoft\BOOT\中)

2.UEFI如何访问Windows

UEFI引导管理器会依据上文的NVRAM变量来查找EFI分区,进而查找到bootmgfw.efi(Windows引导管理器)。然后UEFI引导管理器将其加载到内存。bootmgfw.efi加载后,跳转到bootmgfw.efi的入口点EfiEntry。这是Windows引导过程的开始。
EfiEntry的定义原型:

1
2
3
4
EFI_STATUS EfiEntry(
    EFI_HANDLE ImageHandle,        // 应用程序的UEFI映像句柄
    EFI_SYSTEM_TABLE *SystemTable  // UEFI系统表的指针
);

EfiEntry 的第一个参数指向 bootmgfw.efi模块,负责继续引导过程并在后面调用winload.efi。第二个参数包含指向UEFI配置表(EFI_SYSTEM_TABLE)的指针,它是访问大部分EFI数据的关键。

3.从EfiEntry到BmMain

EfiEntry的反汇编结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
EFI_STATUS __stdcall EfiEntry(EFI_HANDLE ImageHandle,
                             EFI_SYSTEM_TABLE *SystouTeble)
push rbx
sub  rsp,20h
call EfiInitCreateInputParametersEx 
xor  ebx.ebx
test rax,rax
jz loc_10014D7D
...跳转略
mov rcx.rax
call BmMain     //注意这里
mov ecx,0c0000088h
...略

EfiInitCreateInputParametersEx
该函数将EfiEntry参数转换为bootmgfw.efi所需要的格式,同时在这个函数中的 EfiInitpCreateApplicationEntry函数会在引导配置数据(BCD)中为bootmgfw.efi创建一个条目。在下文中会介绍。
在 EfInitCreateInputParametersEx返回后,BmMain(在图中突出显示)开始执行。

4.BmMain做了什么

调用BmFwInitializeBootDirectoryPath用于初始化引导程序路径(\EFI\Microsoft\Boot)。
调用BmOpenDataStore用于通过UEFI服务(磁盘I/O)挂载和读取BCD数据库文件(\EFI\Microsoft\Boot\BCD)。
调用BmpLaunchBootEntryImgArchEfiStartBootApplication用于执行引导程序(从winload.efi开始)
可以通过bcdedit和IDA验证:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS C:\Windows\system32> bcdedit
 
Windows 启动管理器
--------------------
标识符                  {bootmgr}
device                  partition=\Device\HarddiskVolume3
path                    \EFI\MICROSOFT\BOOT\BOOTMGFW.EFI
description             Windows Boot Manager
 
Windows 启动加载器
-------------------
标识符                  {current}
device                  partition=C:
path                    \Windows\system32\winload.efi
description             Windows 10

注意:分页在这时才由bootmgw.efi开启

总调用流程

在bootmgfw.efi最后阶段,BmpLaunchBootEntry将加载并执行winload.efi。
BmpLaunchBootEntry函数之前的控制流根据之前提到的BCD存储的值选择正确的引导条目。如果启用了BitLocker,那么引导管理器在将控制转移到引导加载程序之前对系统分区进行解密。

BmpLaunchBootEntry函数接着执行BmpTransferExecution检查引导选项ImgArchEfiStartBootApplication函数负责初始化winload.efi的受保护内存模式。在此之后,Archpx64TransferTo64BitApplicationAsm执行,该函数完成启动winload.efi的准备工作。

5.winload.efi与OslMain函数

winload.efi执行以下操作:
1.如果操作系统在调试模式下引导(包括管理程序的调试模式),则初始化内核调试器。
2.将UEFI引导服务封装到HAL抽象中,以供内核稍后使用调用。
3.检查 CPU的 Hyper-V特性,如果支持,就设置它们。
4.在内核本身和Windows组件上运行完整性检查,然后将控制权转移到内核。
winload.efi从OslMain开始执行

6.OslMain分析

执行OslBuildKernelMemoryMap:配置内核内存。接下来,通过调用OslFwpKernelSetupPhase1函数来加载内核。
OslFwpKernelSetupPhase1函数调用EfiGetMemoryMap函数来获取之前配置的 EFI_BOOT_SERVICE结构的指针,然后将其存储在一个全局变量中,以便通过HAL进行之后的操作。
之后,OslFwpKernelSetupPhase1调用EFI函数ExitBootServices。这个函数通知操作系统它将得到完全的控制。
最后,通过OslArchTransferToKernel到达操作系统内核(ntoskrnl.exe)。

OslArchTransferToKernel函数:

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
text:0000000180123C900 OslArchTransferToKernel proc near
.text:0000000180123C90 xor esi, esi
.text:0000000180123C92 mov I12,Icx
.text:0000000180123C95 mov r13,rdx
.text:0000000180123C98 wbinvd
.text:0000000180123C9A sub rax, rax
.text:0000000180123C9D mov ss, ax
.text:0000000180123CA0 mov rsp,cs:0slArchKernelStack
.text:0000000180123CA7 lea rax,0slArchKernelGdt
.text:0000000180123CAE lea rcx,0slArchKernelIdt
.text:0000000180123CB5 lgdt fword ptr [rax]
.text:0000000180123CB8 lidt fword ptr [rcx]
.text:0000000180123CBB mov rax,cr4
.text:0000000180123CBE xor rax,680h
.text:0000000180123CC4 mov cr4,rax
.text:0000000180123CC7 mov rax,cro
.text:0000000180123CCA xor rax,50020h
.text:0000000180123CD0 mov cro, rax
.text:0000000180123CD3 xor ecx,ecx
.text:0000000180123CD5 mov cr8,rcx
.text:0000000180123CD9 mov ecx,oCo00008oh
.text:0000000180123CDE rdmsr
.text:0000000180123CE0 xor rax,cs:OslArchEferFlags
.text:0000000180123CE7 wrmsr
.text:0000000180123CE9 mov eax, 40h
.text:0000000180123CEE ltr ax
.text:0000000180123CF1 mov ecx,2Bh
.text:0000000180123CF6 mov gs,ecx
.text:0000000180123CF8 assume gs:nothing
.text:0000000180123CF8 mov rcx,r12
.text:0000000180123CFB push rsi
.text:0000000180123CFC.text:0000000180123CFE push push10h r13
.text:0000000180123D00 retfq
.text:0000000180123D000slArchTransferToKernel endp

3.总结

Windows启动过程极为复杂,本贴只为概述,欢迎批评指正

参考

深入解析Windows操作系统---人民邮电出版社
Rootkits and Bootkits: Reversing Mordern Malare and Next Generation Threats------No Starch Press
Intel® 64 and IA-32 Architectures Software Developer Manuals
EDK2:050K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6@1K9h3q4F1L8$3y4G2M7X3g2Q4x3V1k6W2k6r3D9J5
GRUB2:1fcK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2Y4L8Y4g2Q4x3X3g2G2M7X3N6Q4x3V1k6K6L8$3k6@1N6$3q4J5k6g2)9J5c8X3N6J5N6h3u0Q4x3V1k6Y4M7Y4g2T1i4K6u0V1k6r3g2$3k6h3I4G2M7r3#2W2L8Y4c8Q4x3X3g2Z5N6r3#2D9
其余帮助文献,在此一并感谢!


[培训]科锐逆向工程师培训第53期2025年7月8日开班!

最后于 2025-1-26 20:49 被TurkeybraNC编辑 ,原因:
收藏
免费 4
支持
分享
最新回复 (5)
雪    币: 12
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
我搜了说UEFI是跨平台的,但是这个只是规范吧?这个固件是不是不同的平台要发布不同的版本,就像同一个C++要不同平台编译一样?
2025-1-27 12:50
0
雪    币: 1183
活跃值: (876)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
3
UEFI固件是由固件商提供的,UEFI固件因平台而异(和BIOS类似),而它会建立UEFI服务函数供操作系统调用,这些服务是由EDK开发规范规定统一的,所以bootmgfw.efi和winload.efi基本只和Windows版本有关,对不同平台的适配是UEFI服务和hal.dll完成的。
2025-1-27 14:35
0
雪    币: 460
活跃值: (220)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2025-1-30 00:48
0
雪    币: 5205
活跃值: (5430)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
计算机diy爱好者,能自己编写自己的UEFI固件或者BIOS固件程序吗
2025-1-30 13:14
0
雪    币: 1183
活跃值: (876)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
木志本柯 计算机diy爱好者,能自己编写自己的UEFI固件或者BIOS固件程序吗
UEFI固件的开发没有仔细找过,不过UEFI驱动(DXE驱动)有EDK的文档可用来开发,BIOS闭源,架构和逆向可以看BIOS Disassembly Ninjutsu Uncovered,GitHub上都有这些文档。不过UEFI和BIOS都要与操作系统密切配合,建议再看一下GRUB和部分Linux内核源码,总之这个相当难,可以团队开发。
2025-1-30 20:17
0
游客
登录 | 注册 方可回帖
返回