
前阵子帮一个做安全软件的团队排查问题。他们的过滤驱动在自家测试机上一切正常,发给客户后设备管理器直接黄叹号,事件查看器 System 日志刷出 Event ID 219,应用层拿到的错误是 0xC0000428(STATUS_INVALID_IMAGE_HASH)。客户那台机器开着 Secure Boot,组策略又把 VBS / HVCI 打开了。团队负责人第一句话是"可我都用 EV 代码签名证书签过了啊"。问题就在这儿:在 64 位 Windows 上,内核驱动真不是你签了名就能跑,得微软签过、还得 HVCI 认,缺一样都白搭。
这事得从按下电源说起。驱动不是凭空进内核的,系统从开机到把你的 .sys 映射进去,中间有四道关,一道比一道硬:
阶段 | 守门者 | 校验什么 | 失败表现 |
|---|---|---|---|
UEFI 启动 | Secure Boot | Bootloader / OS Loader 是否由微软(或白名单密钥)签名 | 直接拒绝启动,进入恢复 |
内核初始化 | VBS / 虚拟化层 | 把 Code Integrity 策略搬进 hypervisor 保护的内存 | CI 策略不可被内核篡改 |
驱动映射 | DSE(驱动签名强制) | 驱动与 .cat 是否链到 Microsoft Trusted Root | 0xC0000428 , Event 219 |
页属性落地 | HVCI(内存完整性) | 内核代码页是否满足 W^X 等兼容性 | Code Integrity 事件拦截,驱动不加载 |
说白了,Secure Boot 管的是启动这条链可不可信,HVCI 管的是跑起来之后内核里的代码干不干净。Secure Boot 给 HVCI 提供了一个内核改不了的执行环境,HVCI 才在最后一刻对驱动做裁决。两头一卡,结论就一句:驱动既得是微软签的,又得 HVCI 兼容。
先说签名这道。早年的 64 位 Windows 允许驱动拿 CA 交叉证书(cross-certificate)签了就加载,这条路在 Windows 10 1607(2016 年)被微软堵死:从那以后,新的内核模式驱动必须走 Windows 硬件开发者中心(WHCP),由微软对你的目录文件 .cat 签名,才能链到 Microsoft Trusted Root。老的交叉证书慢慢到期,到 2021 年前后基本就没人管用了。
所以你拿 EV 代码证书亲手给 .sys 签了名也没用,信任链根本到不了微软根,DSE 二话不说拦下来。真正能让 DSE 放行的,是带 Microsoft Windows Hardware Compatibility Publisher 签名的那个 .cat,也就是过完 WHQL / HLK 之后微软发给你的那张。
开发阶段可以用 bcdedit /set testsigning on 临时放行测试签名,但那是带水印、自降安全等级的调试模式,上生产想都别想。而且 Secure Boot 一旦严格开着,这条后门也未必好使。
不少团队签名这关过了,到了开了 HVCI 的客户机器上还是挂,因为 HVCI 看的不是签名。
HVCI(Hypervisor-Protected Code Integrity)靠 hypervisor 兜着,对内核模式代码立了条死规矩:任何内存页不能又写又执行(W^X),内核代码必须是静态的、签过名的。驱动映射进内核的时候它会挨个查节(section)的属性,下面几种情况直接拦:
这种失败在 Microsoft-Windows-CodeIntegrity/Operational 日志里会记一条"驱动因不兼容 HVCI 被阻止",病因不是签名,是内存完整性。一句话:签了名不等于能加载,HVCI 认才算数。
把这两关放一块就清楚了。DSE 要的是签名链到微软根,只有交 WHCP 拿到微软签的 .cat 才满足;HVCI 要的是代码内存兼容,而 HLK 的测试项里本来就带 HVCI 兼容性检查,能过测基本等于代码层面达标。
所以"过 WHQL"本质上就是同时满足这两点的唯一正规路子:微软的签名解决信任链,HLK 的兼容性测试解决 HVCI。那些"自己签了再关掉校验"的野路子,要么只在测试模式里混得下去,要么直接撞上客户的安全基线。
最常见的是 HLK 全测这条路,步骤大概这样:
先在 Windows 硬件开发者中心注册组织,手里得有一张有效的 EV 代码签名证书,后面给测试结果包签名、向微软证明你是你,都靠它。
把 HLK 控制器(Studio / Controller)和目标测试机部署好,要覆盖的 Windows 版本尽量都覆盖,至少 Win10 / 11 主流版本别漏。
对驱动跑 WHCP 相关测试家族,HVCI 兼容性那几项别跳过,跑完导出 .hlkx。
用 EV 代码签名证书给 .hlkx 签上名,传上硬件开发者中心等微软审。
微软签完你下回来,跟 .sys、INF 一起打包发。安装时 INF 里引用这个 .cat,DSE 就放行了。
早些年纯软件驱动还能走 attestation 签名,现在那个口子基本关了,都往 HLK 收。新项目别纠结,直接 HLK。
HVCI 拦得最多的其实不是签名,是老写法。提交之前先把自己代码过一遍:
你看到的现象 | 实际是什么 | 往哪使劲 |
|---|---|---|
Event ID 219 + 0xC0000428 | 镜像哈希无效,签名链不到微软根 | 走 WHCP 拿微软签名 .cat |
CodeIntegrity/Operational 里写 " 不兼容 HVCI" | 驱动内存不满足 W^X | 清掉 RWX / 自修改代码,过 HLK 的 HVCI 项 |
测试机正常、客户机挂 | 客户开了 Secure Boot + VBS / HVCI | 按生产安全基线重新测 |
testsigning 下能加载 | 只是测试签名被放行 | 调试态而已,必须换成微软签名 |
关了 Secure Boot 还是被拦 | DSE 跟 Secure Boot 开不开没关系 | 还是签名的问题 |
Secure Boot 和 HVCI 不是两个互不搭界的安全开关,是从固件一路到内核的一条信任链:前者把启动链焊死、给后者一个内核改不动的底座,后者在驱动进内核那一刻做最后的内存完整性裁决。在这条链下面,"驱动必须过 WHQL"真不是走形式,而是技术上唯一能让 DSE 和 HVCI 同时放你过的口子。把 HLK(连同 HVCI 兼容性)提前塞进构建流水线,比在客户现场救火便宜太多。以上是我们团队在驱动合规上踩过的一些坑的整理,具体测试项和签名政策以微软 WHCP 文档和你目标 Windows 版本为准。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。