GlobalSign 新闻 & 分享

HVCI 与 Secure Boot 双重拦截下,为什么你的内核驱动必须通过 WHQL 认证才能正常加载?

分类:代码签名

时间:2026-08-14

前阵子帮一个做安全软件的团队排查问题。他们的过滤驱动在自家测试机上一切正常,发给客户后设备管理器直接黄叹号,事件查看器 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 管的是跑起来之后内核里的代码干不干净。SecureBoot 给HVCI 提供了一个内核改不了的执行环境,HVCI才在最后一刻对驱动做裁决。两头一卡,结论就一句:驱动既得是微软签的,又得HVCI 兼容。


二、先从签名说起:DSE 早就不认你自己的签名了

先说签名这道。早年的64 位 Windows 允许驱动拿 CA 交叉证书(cross-certificate)签了就加载,这条路在 Windows 10 1607(2016 年)被微软堵死:从那以后,新的内核模式驱动必须走 Windows 硬件开发者中心(WHCP),由微软对你的目录文件 .cat 签名,才能链到 Microsoft Trusted Root。老的交叉证书慢慢到期,到 2021 年前后基本就没人管用了。

所以你拿 EV 代码证书亲手给 .sys 签了名也没用,信任链根本到不了微软根,DSE 二话不说拦下来。真正能让 DSE 放行的,是带 MicrosoftWindows Hardware Compatibility Publisher 签名的那个 .cat,也就是过完 WHQL / HLK 之后微软发给你的那张。

开发阶段可以用 bcdedit /set testsigning on 临时放行测试签名,但那是带水印、自降安全等级的调试模式,上生产想都别想。而且 Secure Boot 一旦严格开着,这条后门也未必好使。


三、再是 HVCI:它压根不看你签名对不对

不少团队签名这关过了,到了开了 HVCI 的客户机器上还是挂,因为 HVCI 看的不是签名。

HVCI(Hypervisor-ProtectedCode Integrity)靠hypervisor 兜着,对内核模式代码立了条死规矩:任何内存页不能又写又执行(W^X),内核代码必须是静态的、签过名的。驱动映射进内核的时候它会挨个查节(section)的属性,下面几种情况直接拦:

运行时申请一块 RWX 内存塞代码进去,比如自解密壳、JIT 那类;

把数据页改成可执行页,某些HS 防护、热补丁、inline hook 框架常干这种事;

用了不兼容 HVCI 的分配/ 映射接口,或者依赖写完还能执行的节。

这种失败在 Microsoft-Windows-CodeIntegrity/Operational 日志里会记一条"驱动因不兼容 HVCI 被阻止",病因不是签名,是内存完整性。一句话:签了名不等于能加载,HVCI 认才算数。


四、为什么 WHQL 是绕不过去的那个口子

把这两关放一块就清楚了。DSE 要的是签名链到微软根,只有交 WHCP 拿到微软签的 .cat 才满足;HVCI要的是代码内存兼容,而 HLK 的测试项里本来就带 HVCI 兼容性检查,能过测基本等于代码层面达标。

所以"过WHQL"本质上就是同时满足这两点的唯一正规路子:微软的签名解决信任链,HLK 的兼容性测试解决 HVCI。那些"自己签了再关掉校验"的野路子,要么只在测试模式里混得下去,要么直接撞上客户的安全基线。


五、正经走一遍 WHCPHLK 路径)

最常见的是 HLK 全测这条路,步骤大概这样:

1. 身份和 EV 证书

先在 Windows 硬件开发者中心注册组织,手里得有一张有效的 EV 代码签名证书,后面给测试结果包签名、向微软证明你是你,都靠它。

2. HLK 环境

把 HLK控制器(Studio / Controller)和目标测试机部署好,要覆盖的 Windows 版本尽量都覆盖,至少 Win10 / 11 主流版本别漏。

3. 跑测试,出 .hlkx

对驱动跑 WHCP 相关测试家族,HVCI 兼容性那几项别跳过,跑完导出 .hlkx。

4. 交仪表板

用 EV 代码签名证书给 .hlkx 签上名,传上硬件开发者中心等微软审。

5. 拿回签名 .cat

微软签完你下回来,跟 .sys、INF一起打包发。安装时 INF 里引用这个.cat,DSE 就放行了。

早些年纯软件驱动还能走attestation 签名,现在那个口子基本关了,都往 HLK 收。新项目别纠结,直接 HLK


六、代码里真正要改的几处

HVCI 拦得最多的其实不是签名,是老写法。提交之前先把自己代码过一遍:

先把 RWX 内存清掉:代码页标 NX(不可写),数据页可写但不可执行;要可执行的内存池用带 NX 语义的标志去分配。

运行时改可执行代码的事别干了:inline hook、热补丁、自修改代码在 HVCI 下基本活不成,换微软给的回调 / 过滤框架(WFP、minifilter、ETW 这些)。

分配接口用对:涉及可执行内存优先走带 NX 语义的接口,别再抱着老 ExAllocatePool的写法不放。

节属性别搞野的:节表老老实实按标准来,可执行节不要顺手叠个可写标志。

早点把 HVCI 测试接进 CI:别等到了客户机器上才暴露。


七、翻车了怎么定位

你看到的现象

实际是什么

往哪使劲

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 版本为准。

相关推荐

  • 最新
  • TLS/SSL
  • 代码签名
  • eIDAS
  • ACME
  • 数字证书
  • 自动化