演示 CVE-2022-34302,一种通过 New Horizon Datasys 签名的引导加载程序实现的 Secure Boot 绕过,该引导加载程序内置的自定义 PE/COFF 加载器可执行未签名的 UEFI 应用程序。
New Horizon Datasys Reboot Restore 引导加载程序 - 自带易受攻击的 UEFI 应用程序 (BYOVUA) - 通过签名的引导加载程序绕过安全启动,该引导加载程序内置自定义 PE/COFF 加载器,可加载未签名的 UEFI 应用程序。
本仓库演示了 BYOVUA(自带易受攻击的 UEFI 应用程序) 技术,通过利用 CVE-2022-34302 实现,这是 New Horizon Datasys 引导加载程序中的一个安全启动绕过漏洞。
与基于 UEFI Shell 的漏洞(CVE-2022-34301 和 CVE-2022-34303)不同,此引导加载程序不暴露 UEFI Shell。相反,shdloader.efi 实现了自己的自定义 PE/COFF 加载器,该加载器加载第二阶段二进制文件(shdmgr.ef_),不使用固件的 LoadImage() 函数,也不执行任何签名验证。攻击者只需将 shdmgr.ef_ 替换为任何兼容的 UEFI 应用程序,即可在启用安全启动的情况下实现任意代码执行。
这是“一个引导加载程序加载所有内容”研究中披露的三个漏洞中最危险的一个。正如 Eclypsium 所指出的:该绕过是内置的、完全静默的,并且在屏幕上没有任何视觉指示——即使在有显示器的系统上也不可见,在服务器或工业设备等无头系统上更是无法检测。
BYOVUA 是内核级使用的 BYOVD(自带易受攻击的驱动程序)技术在 UEFI 层面的等价物。攻击者不是携带一个存在漏洞的已签名内核驱动程序,而是携带一个已签名的 UEFI 应用程序,该应用程序包含能够破坏安全启动的功能。
由于 shdloader.efi 使用 Microsoft 受信任的证书签名,安全启动会毫无疑问地接受它,使其在任何将此证书包含在其安全启动数据库(db)中的系统上都被信任——这几乎是过去十年中出货的每一台支持 UEFI 的 PC。一旦运行,其内置的自定义 PE 加载器就为攻击者提供了在操作系统加载之前加载并执行任意未签名代码的能力,而且是在现代安全控制(ASLR、DEP、内核保护)根本不存在的环境中。
shdloader.efi 是 New Horizon Datasys 系统还原和恢复产品(Reboot Restore Rx、RollBack Rx)中分发的 UEFI 引导加载程序。它在合法启动链中的角色是加载一个预操作系统管理组件(shdmgr.ef_),该组件在操作系统启动之前处理快照和还原操作。
| 属性 | 值 |
|---|
| 文件 | shdloader.efi = EFI/Boot/bootx64.efi |
| 厂商 | New Horizon Datasys Inc |
| 产品 | Reboot Restore Rx / RollBack Rx |
| CVE | CVE-2022-34302 |
| 签名 | Microsoft Windows UEFI Driver Publisher → Microsoft Corporation UEFI CA 2011 |
| 发现者 | Eclypsium(Mickey Shkatov、Jesse Michael)- 2022 年 8 月 |
| 演讲 | DEF CON 30 - "One Bootloader to Load Them All" |
| 撤销 | 通过 Microsoft KB5012170 添加到 DBX(2022 年 8 月) |
该漏洞是引导加载程序架构中的一个设计缺陷。shdloader.efi 没有使用固件的 LoadImage() 和 StartImage() 启动服务——这些服务会强制执行安全启动签名验证——而是实现了自己的自定义 PE/COFF 加载器,直接从原始磁盘字节读取、重定位并执行 shdmgr.ef_,完全绕过了固件的安全检查。
核心问题在于:一个被安全启动信任的已签名二进制文件包含了自己的映像加载器,而该加载器不验证签名。固件将 shdloader.efi 验证为已签名,但一旦它运行起来,它就在没有任何验证的情况下加载 shdmgr.ef_。将 shdmgr.ef_ 替换为任意 UEFI 应用程序,就会导致该应用程序在拥有完整硬件访问权限的情况下运行,而安全启动却报告为已启用。
这与 CVE-2022-34301 和 CVE-2022-34303 有本质区别,后者需要攻击者与 UEFI Shell 交互并手动破坏 gSecurity2 以禁用验证。而在这里,绕过是自动且静默的——无需用户交互,没有可见输出,没有 shell 提示符。
已签名的 shdloader.efi 包含了自己的 PE/COFF 映像加载器实现。它没有调用固件的 LoadImage() 启动服务(该服务会调用安全架构协议并根据安全启动数据库验证映像的签名),而是:
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL 打开 \EFI\Boot\shdmgr.ef_.reloc 节并应用基址重定位在此过程中的任何时刻,加载器都不会验证映像的 Authenticode 签名、检查安全启动数据库(db/dbx)或调用 EFI_SECURITY2_ARCH_PROTOCOL。映像完全基于其 PE/COFF 结构有效性进行加载。```c
// Pseudocode of what shdloader.efi does internally
//
// NOTE: This is a simplified representation. The actual
// implementation was derived from reverse engineering.
EFI_STATUS LoadShdmgr(VOID) { // Step 1: Open the file File = OpenFile(L"\EFI\Boot\shdmgr.ef_");
// Step 2: Read raw bytes (no signature check)
ReadFile(File, &Buffer, &Size);
// Step 3: Parse PE/COFF headers
DosHeader = (EFI_IMAGE_DOS_HEADER *)Buffer;
PeHeader = (EFI_IMAGE_NT_HEADERS *)(Buffer + DosHeader->e_lfanew);
// Step 4: Allocate memory and copy sections
ImageBase = AllocatePages(...);
CopySections(ImageBase, Buffer, PeHeader);
// Step 5: Apply base relocations from .reloc
Delta = ImageBase - PeHeader->OptionalHeader.ImageBase;
ApplyRelocations(ImageBase, PeHeader, Delta);
// Step 6: Jump to entry point
// NO SIGNATURE VERIFICATION ANYWHERE
EntryPoint = ImageBase + PeHeader->OptionalHeader.AddressOfEntryPoint;
((EFI_IMAGE_ENTRY_POINT)EntryPoint)(ImageHandle, SystemTable);
}
---
<div id='LoadImageVsCustomLoader'/>
### ***LoadImage 与自定义加载器***
固件的 `LoadImage()` 与自定义加载器之间的差异,正是关键的安全缺口:```
┌─────────────────────────────────────────────────────────────────────────┐
│ Firmware LoadImage() - How legitimate boot chains work │
│ │
│ bootx64.efi ──> LoadImage("shdmgr.ef_") │
│ │ │
│ ├── Parse PE/COFF headers │
│ ├── Verify Authenticode signature │
│ ├── Check signature against db (allowed) │
│ ├── Check hash against dbx (revoked) │
│ ├── Call gSecurity2->FileAuthenticationState() │
│ │ │ │
│ │ ├── Signature valid? ── YES ──> Load image │
│ │ └── Signature invalid? ── NO ──> REJECT │
│ └── StartImage() │
│ │
├─────────────────────────────────────────────────────────────────────────┤
│ Custom PE Loader - What shdloader.efi does │
│ │
│ shdloader.efi ──> OpenFile("shdmgr.ef_") │
│ │ │
│ ├── ReadFile() into buffer │
│ ├── Parse PE/COFF headers │
│ ├── Allocate memory │
│ ├── Copy sections │
│ ├── Apply .reloc relocations │
│ ├── *** NO SIGNATURE CHECK *** │
│ └── Jump to EntryPoint │
│ │
│ Result: ANY valid PE/COFF EFI application runs, signed or not │
└─────────────────────────────────────────────────────────────────────────┘
自定义 PE 加载器是一个简化实现,期望特定的 PE/COFF 布局。不符合规范的二进制文件将被拒绝并报错:``` Reloc table overflows binary Relocation failed Invalid entry point
缺少其中任何一项的二进制文件都会被自定义加载器拒绝。
| 字段 | 必需值 | 原因 |
|-------|---------------|--------|
| *Machine* | `0x8664` (x64) | 加载器仅支持 x86-64 映像 |
| *Subsystem* | `10` (EFI Application) | 必须是 EFI 应用程序 |
| *.reloc 节* | `.reloc` 必须存在且包含有效的基址重定位条目 | 加载器执行自己的映像重定位。没有 .reloc,它会失败并报错 "Reloc table overflows binary" |
| *重定位目录* | `VirtualAddress` != 0, Size != 0 (DATA_DIRECTORY[5]) | 目录项必须指向有效的重定位数据 |
提供了一个验证脚本 (Scripts/VerifyPE.py),用于在部署前检查兼容性。
---
<div id='BYOVD'/>
### ***与内核 BYOVD 的平行关系***
UEFI BYOVUA 与内核 BYOVD 之间的结构平行关系是完全一致的,尽管 CVE-2022-34302 代表了最直接的形式——已签名的组件**自身**加载未签名代码,而不是提供一个禁用验证的原语:```
┌──────────────────────────────────────────────────────────────┐
│ UEFI BYOVUA - CVE-2022-34302 (Custom PE Loader) │
│ │
│ Signed Bootloader ──> Custom PE Loader ──> Load unsigned │
│ (trusted by (no sig check) UEFI apps │
│ Secure Boot) │
├──────────────────────────────────────────────────────────────┤
│ UEFI BYOVUA - CVE-2022-34301/34303 (Shell + gSecurity2) │
│ │
│ Signed Shell ─ mm ─> gSecurity2 = NULL ─> Load unsigned │
│ (trusted by (Security2 Protocol) UEFI apps │
│ Secure Boot) │
├──────────────────────────────────────────────────────────────┤
│ Kernel BYOVD (DSE Bypass) │
│ │
│ Signed Driver ─ IOCTL ─> g_CiOptions = 0 ─> Load unsigned │
│ (trusted by (CI.dll) kernel drivers │
│ DSE / CI) │
└──────────────────────────────────────────────────────────────┘
CVE-2022-34302 是最危险的变体,因为该绕过源于引导加载程序的设计本身——不存在攻击者需要破坏安全机制的中间步骤。已签名的组件直接加载未签名代码,这正是其正常操作。
已签名的 shdloader.efi 被放置在 EFI 系统分区(ESP)上作为默认引导加载程序。由于它由 Microsoft 的 UEFI 驱动程序发布者证书签名,Secure Boot 会验证并顺利加载它。```
EFI System Partition (ESP)
└── EFI/
└── Boot/
└── bootx64.efi (shdloader.efi) ← Signed by Microsoft Windows UEFI Driver Publisher
└── shdmgr.ef_ (PAYLOAD) ← Unsigned, loaded by shdloader's custom PE loader
当系统启动时,固件会:
1. 从 ESP 读取 `bootx64.efi`
2. 调用 `LoadImage()`,该函数会根据 Secure Boot 数据库验证 Authenticode 签名
3. 签名与 `db` 中的 Microsoft UEFI CA 2011 证书匹配 → 映像被接受
4. 调用 `StartImage()` 将执行权转移给 `shdloader.efi`
---
<div id='Phase2'/>
### ***阶段 2 - 自定义 PE 加载器激活***
一旦 `shdloader.efi` 获得控制权,它会打印一条诊断消息,并立即激活其自定义 PE/COFF 加载器:```
Booting in insecure mode
引导加载程序随后:
\EFI\Boot\shdmgr.ef_.text、.data、.reloc 等)复制到已分配的内存中LoadAddress - ImageBase)并应用 .reloc 节区中的所有基址重定位LoadAddress + AddressOfEntryPoint 解析为执行目标在此过程中的任何时刻都不会进行签名验证。 加载器不会调用 LoadImage(),不会调用 gSecurity2->FileAuthenticationState(),也不会检查 db 或 dbx 数据库。该文件完全基于结构有效性进行加载。
如果未找到该文件,引导加载程序会报告:``` Failed to open \EFI\Boot\shdmgr.ef_ - 800000000000000E Failed to load image
---
<div id='Phase3'/>
### ***阶段 3 - 未签名代码执行***
自定义加载器跳转到 `shdmgr.ef_` 的入口点。这个未签名的 UEFI 应用程序现在以以下条件运行:
- 完全硬件访问权限(直接内存、I/O 端口、PCI、MMIO)
- 尚未加载操作系统
- 无 ASLR、DEP 或内核保护
- 无 EDR 或端点安全监控
- 对任何后续操作系统查询均报告 Secure Boot 为**已启用**
该攻击完全静默。与 CVE-2022-34301 和 CVE-2022-34303 不同(它们会显示可见的 UEFI Shell 提示符),此漏洞利用除了 "Booting in insecure mode" 消息外不产生任何视觉输出(在合法系统上,该消息会短暂出现并很快被操作系统启动画面取代)。在无头系统(服务器、IoT、工业设备)上,则完全没有迹象。
---
<div id='Phase4'/>
### ***阶段 4 - 持久化***
该攻击默认具有持久性。只要 `shdloader.efi` 保留在 ESP 上的 `\EFI\Boot\bootx64.efi`,且攻击者的载荷保留在 `\EFI\Boot\shdmgr.ef_`,未签名的载荷就会在每次启动时执行。
不需要 `startup.nsh` 脚本。不需要在固件更新后重新计算 gSecurity2 地址。自定义 PE 加载器会无条件加载它找到的任何 `shdmgr.ef_`。
系统继续报告 Secure Boot 为 "已启用"——只有信任链在引导加载程序层面被破坏。这使得该攻击对操作系统级别的 Secure Boot 状态查询以及任何依赖 Secure Boot 认证的安全软件都不可见。
> **重要:** 只有当 DBX 更新了 `shdloader.efi` 的吊销条目(KB5012170)时,持久化才会被破坏,这会导致固件在自定义加载器激活之前就拒绝 `shdloader.efi` 本身。
---
---
---
<div id='Exploit'/>
## ***漏洞利用***
`Exploit/` 目录包含构建兼容 `shdmgr.ef_` 所需的一切:```
Exploit/
|
├── README.md ← Build guide and PE/COFF requirements
|
├── PayloadShdmgr/
| |
│ ├── ForceReloc.nasm ← Force .reloc section generation
│ ├── shdmgr.ef_.c ← UEFI application source (EDK2)
│ ├── shdmgr.ef_.inf ← EDK2 module definition
│ ├── shdmgr.ef_.dsc ← EDK2 platform build configuration
│ └── shdmgr.ef_.dec ← EDK2 package declaration
|
└── Scripts/
└── VerifyPE.py ← PE/COFF compatibility verifier
已签名的引导加载程序已通过 KB5012170(2022 年 8 月)被添加到 Microsoft 的 DBX 撤销列表中。在已更新的系统上,引导加载程序将在自定义 PE 加载器激活之前就被 Secure Boot 拒绝。
对于实验环境,你需要一个满足以下条件的系统:
QEMU UEFI 研究环境为此提供了自动化搭建方案。
CVE-2022-34302 比 CVE-2022-34301 和 CVE-2022-34303 更容易利用:
| 方面 | CVE-2022-34302(自定义加载器) | CVE-2022-34301/34303(Shell) |
|---|
| 技术 | 用 payload 替换 shdmgr.ef_ | 通过 mm 命令破坏 gSecurity2 |
| 交互 | 无(全自动) | 手动 shell 命令或 startup.nsh |
| 可见性 | 静默("Booting in insecure mode") | 可见的 UEFI Shell 提示符 |
| 固件依赖 | 无(payload 自包含) | gSecurity2 地址随固件版本变化 |
| 复杂度 | 低(文件替换) | 中(内存扫描和修补) |
| 隐蔽性 | 高(无头环境下无视觉输出) | 低(屏幕上可见 shell) |