4. 操作系统加载器:Windows Boot Manager、Linux(shim+GRUB)的签名验证流程

好,咱们接着往下走。前面几章我们把固件层面的验证链路理清了,从 Boot Guard 到 Secure Boot 的 DBX 吊销,基本上把硬件和 UEFI 驱动阶段的坑都踩了一遍。但说实话,真正让安全启动工程师头疼的,往往是操作系统加载器这一层。

为什么?因为这里涉及两个完全不同的生态——Windows 和 Linux。它们的签名验证逻辑、证书链、甚至失败后的行为都截然不同。我这些年排查过的 Secure Boot 故障,至少有一半是卡在这一步。要么是 Windows Boot Manager 被篡改,要么是 GRUB 的 shim 版本不对。

今天我们就来拆开看看,这两个加载器到底是怎么做签名验证的。

4.1 Windows Boot Manager 的签名验证流程

Windows 的启动加载器叫 bootmgfw.efi,它位于 ESP 分区的 \EFI\Microsoft\Boot\ 目录下。很多人以为它只是一个简单的 PE 文件,其实它的签名验证机制相当复杂。

我个人的习惯是,把 Windows Boot Manager 的验证流程分成三个阶段来看:

  1. 固件验证阶段:UEFI Secure Boot 在加载 bootmgfw.efi 时,会检查它的数字签名是否在 DB 或 DBX 中。
  2. 自身完整性校验:bootmgfw.efi 加载后,会立即校验自己的代码段和关键数据段。
  3. 后续加载器验证:它负责加载 winload.efi,并对这个内核加载器做签名检查。

这里有个关键点——Windows Boot Manager 的签名证书是 Microsoft Windows Production PCA 2011。这个证书默认就在 UEFI DB 里。所以理论上,只要你的 Secure Boot 没被乱改,bootmgfw.efi 应该能顺利通过固件验证。

核心验证逻辑:Windows Boot Manager 使用 Authenticode 签名格式,并且支持嵌套签名。也就是说,一个 PE 文件可以同时包含 SHA-1 和 SHA-256 签名。UEFI 固件会优先使用 SHA-256 签名进行验证。

但我在项目中遇到过一个问题:某款国产主板在加载 bootmgfw.efi 时总是报 Security Violation。查了半天,发现是固件只支持 SHA-1 签名验证,而 Windows 10 21H2 之后的 bootmgfw.efi 默认只带 SHA-256 签名。最后给 BIOS 打了一个补丁才解决。

4.2 Linux 的 shim + GRUB 验证机制

Linux 这边的情况就更有意思了。因为 GRUB 本身不是微软签名的,所以不能直接通过 Secure Boot 的固件验证。那怎么办?Linux 社区想了一个办法——加一层 shim。

shim 是一个极简的 EFI 程序,它只做一件事:验证 GRUB 的签名。shim 本身由微软签名(使用 Microsoft Windows UEFI Driver Signing 证书),所以它能通过固件验证。然后 shim 再去加载 GRUB,GRUB 再去加载内核。

整个链路是这样的:

UEFI Secure Boot 验证 shim.efi → shim 验证 GRUB → GRUB 验证 Linux 内核

嗯,这里要注意,shim 验证 GRUB 时,用的不是微软的证书,而是 Linux 基金会自己的证书。这个证书的公钥被编译进了 shim 的二进制文件里。所以如果你自己编译了一个 GRUB,想用 shim 加载,就必须用 Linux 基金会的私钥签名,或者把你自己证书的哈希加到 shim 的允许列表里。

个人经验:我建议你在调试 shim 问题时,先检查一下 shim 的版本。不同版本的 shim 支持的签名算法不一样。比如 shim 15 只支持 SHA-256,而 shim 14 还兼容 SHA-1。如果你用的 GRUB 是 SHA-1 签名的,但 shim 版本太高,就会验证失败。

4.3 两种验证流程的对比

为了让你看得更清楚,我整理了一个对比表:

对比项 Windows Boot Manager Linux (shim + GRUB)
签名主体 微软直接签名 shim 由微软签名,GRUB 由 Linux 基金会签名
验证层级 固件 → bootmgfw.efi → winload.efi 固件 → shim.efi → GRUB → 内核
证书链 Microsoft Windows Production PCA 2011 Microsoft UEFI Driver Signing → Linux Foundation
失败行为 直接黑屏,显示 "Secure Boot violation" shim 会进入 MOK 管理界面,允许用户手动添加密钥
自定义密钥 需要替换 DB 中的微软证书 通过 MOK (Machine Owner Key) 机制添加

你看,最大的区别在于失败后的行为。Windows 那边一旦验证失败,直接罢工,没有任何商量余地。而 Linux 的 shim 会给你一个 MOK 管理界面,让你手动导入密钥。说白了,Linux 的设计更灵活,但也更容易被攻击者利用。

4.4 签名验证的完整流程图

下面这张图是我用 SVG 画的,把整个流程串起来了。你可以看到,从 UEFI 固件开始,到最终加载操作系统内核,中间经过了哪些验证节点。

操作系统加载器签名验证流程图 操作系统加载器签名验证流程 UEFI 固件 (Secure Boot) Windows Boot Manager (bootmgfw.efi) shim.efi (微软签名) 验证自身完整性 (Authenticode) 加载 winload.efi (签名检查) shim 验证 GRUB (Linux 基金会证书) GRUB 验证 Linux 内核 操作系统内核加载 注意:任何一步验证失败,都会导致启动中断。Windows 直接黑屏,Linux 进入 MOK 管理界面。

4.5 常见故障与排查方法

讲完了理论,咱们来点实际的。我这些年遇到过的加载器签名验证故障,归纳起来就三类:

  • bootmgfw.efi 被篡改或损坏:最常见的情况是 ESP 分区被误格式化,或者病毒修改了 bootmgfw.efi。排查方法很简单——用 Windows PE 启动,检查 bootmgfw.efi 的数字签名是否有效。
  • shim 版本不匹配:Linux 内核升级后,shim 版本太旧,导致 GRUB 验证失败。我建议你每次升级内核时,顺便检查一下 shim 的版本号。
  • MOK 密钥丢失:如果你自己编译了内核,并且通过 MOK 导入了密钥,但密钥被误删了,GRUB 就会拒绝加载。这时候只能进 shim 的 MOK 管理界面重新导入。

避坑指南:我曾经遇到过一台服务器,每次重启都报 "shim: error loading GRUB"。查了三天,最后发现是 GRUB 的签名文件被备份脚本覆盖了。所以,我强烈建议你在修改 ESP 分区之前,先备份整个 /boot/efi 目录。

4.6 调试工具与命令

最后,分享几个我常用的调试命令。Windows 下用 sigcheck 检查 bootmgfw.efi 的签名:

sigcheck -i C:\EFI\Microsoft\Boot\bootmgfw.efi

Linux 下用 sbverify 检查 GRUB 的签名:

sbverify --list /boot/efi/EFI/ubuntu/grubx64.efi

如果 sbverify 报错,说明 GRUB 没有签名,或者签名格式不对。这时候你可以用 sbsign 重新签名:

sbsign --key my.key --cert my.crt --output grubx64.efi.signed grubx64.efi

嗯,这些命令看起来简单,但实际排查时能帮你省不少时间。你想想看,如果每次都要重启进 UEFI 界面看日志,那效率得多低。