文章总结: 本文深入分析Windows内核配置管理器中的CmControlVector变量及其在系统早期启动阶段的作用。作者通过逆向工程发现PspSystemMitigationOptions系统级缓解设置是在内核初始化Phase0阶段通过CmControlVector从注册表读取,并提供了提取分析CmControlVector的IDA脚本工具。研究揭示了Windows漏洞利用缓解措施的初始化机制,为二进制安全研究人员提供了实用的内核分析方法和工具。 综合评分: 86 文章分类: 二进制安全,漏洞分析,安全工具,Windows安全,内核安全
Windows 早期启动配置:CmControlVector 与 PspSystemMitigationOptions
Tillmann Oßwald Tillmann Oßwald
securitainment
2026年4月28日 13:10 中国香港
在小说阅读器读本章
去阅读
| 原文链接 | 作者 | | — | — | | https://insinuator.net/2026/04/windows-early-boot-configuration-the-cmcontrolvector-and-pspsystemmitigationoptions/ | Tillmann Oßwald |
在调查进程缓解设置的初始化流程时,我发现了全局变量 PspSystemMitigationOptions。顺着这个值的赋值路径追溯,最终引出了 CmControlVector。本文将深入探讨 Windows 内核层的配置管理器,重点分析其全局变量 CmControlVector。需要说明的是:此处的内核配置管理器与 Microsoft Intune 的 Configuration Manager 并无关联。概括而言,配置管理器负责管理和实现注册表,同时也承担着系统早期启动阶段的部分初始化工作。
本文结构如下:
- 首先,简要介绍我发现
CmControlVector的背景经过,当然是经由一段迂回的路径。 - 接着,讨论内核配置管理器处理
CmControlVector的时机与方式。 - 最后,深入分析
CmControlVector变量并提取若干洞见。
最近,有一个关于进程 MitigationFlags的问题引起了我的关注。这些标志位编码了内核 (或进程本身) 为进程应用的漏洞利用缓解措施。已启用的缓解措施信息存储于进程的 _EPROCESS结构中。许多漏洞利用缓解措施在进程初始化阶段就已发挥作用。在以往的研究中 (例如我们针对应用程序兼容性基础设施的分析),我们经常需要调试 Windows 的进程创建过程,多次遇到全局变量 PspSystemMitigationOptions。该变量在分配新进程时被 PspAllocateProcess显式引用。
简而言之,全局变量 PspSystemMitigationOptions与注册表中按进程 (更准确地说,按映像) 存储的设置相结合,后者即为Image File Execution Options(IFEO)。两者合并后形成有效的MitigationFlags,再经转换后存入进程的_EPROCESS结构。本文无需深入探讨该设置与合并过程,但大致流程如下:系统级设置与按映像设置合并为有效的缓解配置,随后转换为_EPROCESS结构中的三个MitigationOptions字段。该转换主要包括重排比特位顺序,并执行一些额外的检查和查找操作。在_EPROCESS中,这三个字段分别命名为MitigationOptions、MitigationOptions2和MitigationOptions3。MitigationOptions随时间持续演进,随着 Windows 新版本的发布及新缓解措施的引入,目前已有三个 64 位值来编码这些选项。
按映像设置与系统级设置均存储于注册表中。IFEO选项顾名思义,按映像配置。该注册表键不仅可用于配置缓解选项,其功能已部分记录于文档。我通常利用 IFEO选项在进程启动时附加调试器 (优先选用时间旅行调试器)。每个映像的 MitigationOptions值位于以下路径:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<ImageName.exe>
系统级缓解设置存储于:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\kernel
通过更改所谓的”漏洞防护”设置并使用 Procmon 跟踪注册表访问,可以轻松定位这些存储路径。但这仅能获知设置的存储位置,并通过调用栈确定负责写入这些值的代码,至于哪个组件负责读取这些值,则仍不明确。对于 IFEO的 MitigationOptions,读取操作发生在进程分配阶段的 PspAllocateProcess中,这一点相当清晰。而系统级缓解设置的读取流程则不那么直观。在调查过程中,我也参考了其他研究者对 PspSystemMitigationOptions的分析。浏览文章时,有几点引起了我的注意:这些设置”由启动时的注册表配置填充”,且”运行时对 MitigationOptions 的修改在下次重启前均无效”。事实确实如此——每当系统级”漏洞利用缓解”设置发生变更时,Windows 会通知用户需要重启才能使更改生效。
上述文章也提到了系统级缓解设置从注册表中读取的时机,但我略过了这一部分,选择再次通过 Procmon 自行调查。我配置了一个 Procmon 启动跟踪,重启系统后发现该注册表值从未被读取,重复操作结果相同,这表明该值在 Procmon 启动之前就已被访问。与此同时,我也进行了一些静态逆向分析:初始化过程中并不存在对 PspSystemMitigationOptions的直接引用——交叉引用始终预设其已被赋值,仅作读取使用。然而,我很快发现 PspSystemMitigationOptions被引用于一个更大的结构体 CmControlVector中,该结构体由 nt!CmpGetSystemControlValues使用。为验证静态逆向分析的结论,我在 PspSystemMitigationOptions上设置了数据断点。断点如预期命中,nt!CmpGetSystemControlValues也清晰地出现在调用栈中,如下所示:
kd> k
# Child-SP RetAddr Call Site
00 fffff802`8107b258 fffff802`ef23dacc nt!memcpy+0x32
01 fffff802`8107b260 fffff802`ef239bd2 nt!CmpGetBootValueData+0x210
02 fffff802`8107b2d0 fffff802`ef239184 nt!CmpGetSystemControlValues+0x38a
03 fffff802`8107b590 fffff802`ef1fbef0 nt!CmInitSystem0+0x1c
04 fffff802`8107b5c0 fffff802`ef14a156 nt!InitBootProcessor+0x268
05 fffff802`8107b7d0 fffff802`ef13c623 nt!KiInitializeKernel+0x816
06 fffff802`8107bab0 00000000`00000000 nt!KiSystemStartup+0x283
确认了预期结论后,需要将其置于更宏观的背景中加以理解。我们所处理的是内核内部的配置管理器代码,这意味着执行仍处于内核初始化的第零阶段。通常,Windows 内核初始化分为两个阶段:Phase 0 和 Phase 1。
- Phase 0 在系统单线程运行时执行早期底层设置,以最少的资源初始化核心组件,包括内存管理、中断处理和硬件抽象层 (HAL)。注册表的建立以及
CmControlVector的读取也在此阶段完成。 - Phase 1 继续进行完整的系统初始化,启用多任务处理,并初始化设备驱动程序和系统服务。
这也解释了为何 Procmon 始终未能捕获相关注册表访问:CmControlVector在 Phase 0 期间处理,彼时驱动程序和用户态工具尚不可用。
接下来探讨一个核心问题:CmControlVector是什么,又是如何被处理的?本质上,它是一个 CM_CONTROL_VECTOR类型的数组。以下列表提供了概览,并展示了 PspSystemMitigationOptions对应的字段值:
-
pKeyPath:注册表路径的 Unicode 字符串。此处为
Session Manager\Kernel -
pValueName:值名称的 Unicode 字符串。此处为
MitigationOptions -
pTargetBuffer:指向目标缓冲区的指针,可能包含默认值。此处为
PspSystemMitigationOptions,无默认值。 -
pSizeOptional:指向预期数据大小的指针。此处为
PspSystemMitigationOptionsLength,值为0x18。 -
typeOptional:可选类型字段。此处未设置。
-
flagsOptional:可选标志字段。此处同样未设置。
内核初始化期间,CmControlVector逐条遍历。每个条目用于从注册表读取一个值,结果随后存入对应的目标缓冲区——在本例中即为 PspSystemMitigationOptions。这也证实了该注册表值确实仅在早期启动时读取一次,随后存入全局变量 PspSystemMitigationOptions,此后该全局变量只被读取,不再被修改。然而,PspSystemMitigationOptions仅是 CmControlVector的一小部分——以 Windows 11 LTSC 24H2 为例,CmControlVector共包含 563 个条目。
为深入分析 CmControlVector,我编写了一个小型 IDA 脚本来提取相关信息。部分目标缓冲区 (如 PspSystemMitigationOptions) 有符号名称引用,另一些则是匿名的。为进一步分析,脚本还收集了每个目标缓冲区的交叉引用,以便确定哪个内核组件使用了特定的配置条目。实际上,只有少数条目没有符号名称,且大多与内存管理器相关——从注册表路径以及使用该变量的函数可以清楚地看出这一点。
提取数据的脚本可在此处获取,完整结果列表可在此处查阅。此外,我还整理了一些统计信息,发布于此处。该统计文件列出了各条目是否设置了 size、type 或 flags 选项,以及各变量被哪个内核组件使用,分类依据为函数前缀。需注意,私有前缀与非私有前缀被分开列出,例如 Etw和 Etwp。未对这些前缀进行归一化处理,原因在于某些情况下 (如 PnP) 自动分组会产生歧义。此外,部分组件以私有/内部前缀代替,例如内存管理器使用 Mi前缀。
如有兴趣,以下是 ERNW 近期发布的其他 Windows 内核相关研究成果:
- Windows Hell No for Business @ Black Hat USA 2025
- 相关博文:Windows Hello for Business – Faceplant: Planting Biometric Templates
- 相关博文:Windows Hello for Business – The Face Swap
- 相关博文:Windows Hello for Business – Past and Present Attacks
- WinpMem: Volatility’s driver that lets malware volatilize @ Recon 2025
- 相关白皮书发布
- Jigsaw RDPuzzle: Piecing Attacker Actions Together
免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:securitainment Tillmann Oßwald Tillmann Oßwald《Windows 早期启动配置:CmControlVector 与 PspSystemMitigationOptions》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论