<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parag Mali - tag: windows-kernel</title><description>Posts tagged windows-kernel.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 07 Jun 2026 04:13:16 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/windows-kernel/rss.xml" rel="self" type="application/rss+xml"/><item><title>The Registry Adventure: How One Researcher Read 100,000 Lines of Windows Kernel C and Found 50 Bugs</title><link>https://paragmali.com/blog/the-registry-adventure-how-one-researcher-read-100000-lines-/</link><guid isPermaLink="true">https://paragmali.com/blog/the-registry-adventure-how-one-researcher-read-100000-lines-/</guid><description>Between May 2022 and December 2023, Mateusz Jurczyk audited the Windows registry parser and produced 50 CVEs. The methodology is the story.</description><pubDate>Sun, 24 May 2026 00:00:00 GMT</pubDate><content:encoded>
Between May 2022 and December 2023, Mateusz Jurczyk of Google Project Zero manually audited the Windows kernel registry parser and filed 39 bug reports under Project Zero&apos;s 90-day disclosure deadline plus 20 low-severity reports without deadline, which Microsoft serviced as 50 CVEs total (44 from the 90-day cohort and 6 more in a March 2024 bulletin). The bugs share a root cause: a thirty-year-old hybrid on-disk-and-in-memory format with a deterministic, unrandomized cell allocator that Microsoft cannot redesign without breaking backward compatibility to Windows NT 4.0. The methodology pivot is the story. Jurczyk started with a coverage-guided fuzzer, found one bug, then put the fuzzer down and read 100,000 lines of kernel C for twenty months. What the audit implies for the rest of the Windows kernel is the open question the article ends on.
&lt;h2&gt;1. I Loaded a Registry Hive From a Network Share and the Kernel Crashed&lt;/h2&gt;
&lt;p&gt;In May 2022, Mateusz Jurczyk pointed a coverage-guided fuzzer at the Windows registry. Within days the fuzzer crashed the kernel and produced CVE-2022-35768. Twenty months later, when he stopped, Jurczyk had filed thirty-nine bug reports against the same subsystem, Microsoft had assigned fifty CVEs to his name, and the fuzzer was sitting unused. Somewhere in those first few days, Jurczyk had realised that the bugs he actually wanted were ones a fuzzer could not see [@pz1-registry-adventure-1].&lt;/p&gt;
&lt;p&gt;The threat model is almost too small to fit on a slide. An unprivileged process running at Medium Integrity Level calls &lt;code&gt;RegLoadAppKey&lt;/code&gt; with the path of a file the attacker controls. The kernel opens the file, runs its in-house binary parser on the bytes, and exposes the resulting tree of keys back to the caller through a private handle. Microsoft&apos;s own documentation describes the surface this way: the hive becomes a private namespace reachable only through that handle, but &quot;the registry will prevent an application from accessing keys in this hive using an absolute path&quot; [@ms-regloadappkey]. The handle is sandboxed. The parser, which is the interesting part, is not. It runs in the kernel with attacker-supplied input, and it has been doing so since Windows Vista.&lt;/p&gt;

A file-and-in-memory tree of registry keys and values, encoded in Microsoft&apos;s regf binary format and operated on by the Windows kernel&apos;s Configuration Manager. Hives live on disk as `*.dat` files (plus `.log` and `.alt` companions) and are loaded into the kernel&apos;s address space when an application or the operating system opens them [@ms-registry-hives].

Medium Integrity Level: the integrity label an ordinary logged-in Windows user runs at. Crossing from Medium IL to SYSTEM is what a kernel local privilege escalation does. The class of bug this article is about reliably accomplishes that crossing from an attacker-supplied file.
&lt;p&gt;The fifty CVEs that Jurczyk&apos;s audit produced are not a uniform pile. Most of them are kernel local privilege escalations (LPEs); a handful are information disclosures; one is a denial of service [@pz1-registry-adventure-1]. The seventeen that matter for this article are the cohort Jurczyk later catalogued in his Project Zero post on practical exploitation: a tight set of memory-corruption bugs that share a single root cause and a single exploitation primitive, which he named &lt;strong&gt;hive-based memory corruption&lt;/strong&gt; [@pz8-registry-adventure-8].&lt;/p&gt;

flowchart TD
    A[&quot;Medium-IL user process&quot;] --&amp;gt; B[&quot;RegLoadAppKey API&quot;]
    B --&amp;gt; C[&quot;NtLoadKeyEx system call&quot;]
    C --&amp;gt; D[&quot;Configuration Manager dispatch&quot;]
    D --&amp;gt; E[&quot;Hv* hive parser&quot;]
    E --&amp;gt; F[&quot;Cell allocator and KCB tree&quot;]
    F --&amp;gt; G[&quot;Mapped section pages -- kernel address space&quot;]
&lt;p&gt;Two questions are doing all the work in this article. Why is a thirty-year-old binary parser running in the Windows kernel willing to accept arbitrary input from unprivileged users? And why did it take a single researcher twenty months to map the consequences? The first question is about Microsoft and design. The second is about Jurczyk and method. To take either one seriously, we have to start at the very beginning -- with Windows 3.1.&lt;/p&gt;
&lt;h2&gt;2. Why There Is a Hive Parser in the Kernel&lt;/h2&gt;
&lt;p&gt;In 1992 the registry was 64 kilobytes. Windows 3.1 shipped with a single file at &lt;code&gt;C:\WINDOWS\REG.DAT&lt;/code&gt;, encoded in a small custom format whose magic bytes spelled &lt;code&gt;SHCC3.10&lt;/code&gt;. It held one top-level key, no named values, and existed solely to register OLE objects and shell file-type associations [@pz2-registry-adventure-2]. The first &lt;code&gt;regedit.exe&lt;/code&gt; shipped alongside it. There was no security descriptor, no recovery story, and no kernel involvement. You could fit the whole thing in the L2 cache of a 2026 laptop.&lt;/p&gt;
&lt;p&gt;Windows NT 3.1, released in July 1993, swept that design away and introduced something different. The new format was called &lt;strong&gt;regf&lt;/strong&gt;, and the design decision that has determined the next thirty-three years of Windows kernel security was made here: &lt;em&gt;the on-disk format and the in-memory format are the same format&lt;/em&gt;. Jurczyk&apos;s blog post on the regf file format states this plainly: &quot;the regf format aims to bypass the reparsing step -- likely to optimize the memory/disk synchronization process -- and reconcile the two types of data encodings into a single one... This unique approach comes with its own set of challenges, and has been a contributing factor in a number of historical vulnerabilities&quot; [@pz5-registry-adventure-5].&lt;/p&gt;

Microsoft&apos;s binary registry file format, introduced in Windows NT 3.1 (1993) and stabilized at v1.3 in NT 4.0 (1996). Later versions (v1.4 Whistler beta, v1.5 XP, v1.6 Win10 AU) layer features on top but all remain cross-compatible with the v1.3 baseline. The same format encodes a hive on disk and in kernel memory; there is no separate &quot;loaded&quot; representation [@pz5-registry-adventure-5]. Microsoft has never published an official regf specification [@pz5-registry-adventure-5].
&lt;p&gt;The motivation was reasonable. NT was a multi-user, securable, network-capable operating system targeting servers; its configuration store needed access control, transactional recovery, and the ability to grow well past 64 KiB. Reusing the same byte layout for disk and memory meant a hive could be loaded by mapping or copying its file image, modified in place, and flushed back without a serialization step.&lt;/p&gt;
&lt;p&gt;Pre-release builds used regf v1.0; the first shipping NT used v1.1; NT 3.5 and 3.51 used v1.2 [@pz2-registry-adventure-2]. The Win9x consumer line went a different direction entirely, with an incompatible format called CREG that never made it into the NT lineage and quietly died with Windows Me.Windows 95, 98, and Me used a completely incompatible CREG format that did not survive into NT. The modern registry inherits nothing from the Win9x line; every memory corruption bug Jurczyk found descends from the NT 3.1 decision.&lt;/p&gt;
&lt;p&gt;The next stabilization happened on July 29, 1996. Windows NT 4.0 (whose pre-RTM development builds had introduced v1.3 in 1995) froze the &lt;em&gt;backward-compatibility baseline&lt;/em&gt; at regf v1.3, added a &quot;fast leaves&quot; optimization for subkey lookups, and locked in the binary layout that the modern Windows kernel still reads thirty years later. Later versions layered features on top -- v1.4 (Whistler beta, big values), v1.5 (Windows XP, 2001, hash leaves), and v1.6 (Windows 10 Anniversary Update, 2016, layered keys) -- but every one of them remains cross-compatible with v1.3-aware parsers, and v1.3 itself still encodes a number of Windows 11 hives [@pz5-registry-adventure-5].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s own documentation for &lt;code&gt;RegSaveKeyExA&lt;/code&gt; describes &lt;code&gt;REG_STANDARD_FORMAT&lt;/code&gt; as &quot;the only format supported by Windows 2000,&quot; meaning that hives written by Windows 2000 and later, in the default format, are interchangeable with hives produced by Windows NT 4.0 [@ms-regsavekeyex]. A hive file authored on NT 4.0 in 1996 will still mount on Windows 11 in 2026. That backward compatibility is not an accident; it is a load-bearing requirement of system-image management, forensics, and third-party installers.&lt;/p&gt;

gantt
    title Registry format evolution
    dateFormat YYYY
    axisFormat %Y
    section Win 3.x
    reg.dat (SHCC3.10) :1992, 1993
    section NT 3.x
    regf v1.0 to v1.2  :1992, 1996
    section NT 4.0+
    regf v1.3 (standard) :1996, 2026
    section XP
    regf v1.5 (hash leaves) :2001, 2026
    section Vista
    RegLoadAppKey + KTM  :2006, 2026
    section Win 8.1
    LOG1 and LOG2 logging :2013, 2026
    section Win 10 RS4
    Section-backed hives  :2018, 2026
    section Win 10 AU
    regf v1.6 (layered keys) :2016, 2026
&lt;p&gt;Ten years later, in November 2006, Windows Vista added the second design decision that completes the threat model. &lt;code&gt;RegLoadAppKey&lt;/code&gt; shipped as a public Win32 API, allowing an unprivileged application to load an arbitrary hive file as a private &quot;application hive&quot; reachable only through the returned handle [@ms-regloadappkey]. The motivation was legitimate; per-application configuration sidecars are a reasonable feature.&lt;/p&gt;
&lt;p&gt;The consequence was that the kernel-mode regf parser, frozen at v1.3 a decade earlier and unchanged in any of its load-bearing routines, was now reachable from Medium IL with no special privileges. Jurczyk&apos;s introduction to the series says it plainly: &quot;arbitrary registry hives can be loaded from disk without any special privileges via the &lt;code&gt;RegLoadAppKey&lt;/code&gt; API (since Windows Vista)&quot; [@pz1-registry-adventure-1].&lt;/p&gt;

A Win32 API introduced in Windows Vista (2006) that lets an unprivileged process load an arbitrary hive file as a private &quot;app hive,&quot; running the full kernel-mode regf parser on attacker-supplied bytes. Microsoft documents the API as one that &quot;loads the specified registry hive as an application hive&quot; reachable only through a private handle; the parser itself is not sandboxed [@ms-regloadappkey].
&lt;p&gt;With the parser reachable from low privilege and the format frozen for thirty years, the only question left was who would notice.&lt;/p&gt;
&lt;h2&gt;3. Prior Attempts: The &quot;Fuzzed Precisely Once&quot; Misconception&lt;/h2&gt;
&lt;p&gt;Before we go further, a fact you may have heard in a conference Q&amp;amp;A: the Windows registry is &quot;the most-fuzzed subsystem in Windows,&quot; &quot;fuzzed precisely once,&quot; by one person. It is not true. The registry has been poked at, in one form or another, since 1996. None of those efforts found the bug class that Jurczyk would eventually name -- but that is a different statement, and the difference is the point of this section.&lt;/p&gt;
&lt;p&gt;The first instrument to touch the registry from outside Microsoft was Mark Russinovich and Bryce Cogswell&apos;s &lt;strong&gt;RegMon&lt;/strong&gt;, released in 1996 as a Sysinternals utility. RegMon was a kernel driver that intercepted every registry call and surfaced the path, type, process identifier, and result to a user-mode console. It was operational tooling, not a bug-finding tool. Microsoft&apos;s own page on the modern successor, Process Monitor, attributes the lineage to Russinovich and notes that Procmon &quot;combines the features of two legacy Sysinternals utilities, Filemon and Regmon&quot; [@ms-procmon]. RegMon made the registry observable from outside the kernel. It could not see corruption inside a hive.&lt;/p&gt;
&lt;p&gt;The next wave came from forensics. Microsoft never published a regf specification, so the digital-forensics community reverse-engineered one. Timothy D. Morgan&apos;s regfi paper appeared at DFRWS in 2009. Joachim Metz&apos;s libregf project published its first format-spec document in July 2009 and has been updated continuously through 2026 [@libregf-spec]. Maxim Suhanov&apos;s regf specification covers, among other things, the old single-&lt;code&gt;.log&lt;/code&gt; dirty-vector recovery format and the new two-file LOG1/LOG2 layout introduced in Windows 8.1 [@msuhanov-spec]. These were user-space parsers built to mount hive files for evidence extraction. They exercised the format from the outside. They never touched the kernel parser.&lt;/p&gt;
&lt;p&gt;A separate research line, in parallel, pursued the layer &lt;em&gt;above&lt;/em&gt; the parser. James Forshaw of Project Zero spent years hunting capability and access-control bugs in the registry&apos;s name-resolution and permission logic -- registry symbolic links, virtualization quirks, sandbox-escape paths that ride on registry redirection. Jurczyk&apos;s PZ #4 covers some of this surface in passing, noting that the registry has at least four distinct ways in which &quot;access to a registry key can be transparently redirected to another path&quot; [@pz4-registry-adventure-4]. These were logic bugs, not memory-corruption bugs. The parser was not the target.&lt;/p&gt;
&lt;p&gt;Then, in 2016, Jurczyk and Forshaw collaborated on a black-box bitflipping fuzzing pass against &lt;code&gt;RegLoadKey&lt;/code&gt; and &lt;code&gt;RegLoadAppKey&lt;/code&gt;. Jurczyk acknowledges the collaboration directly in his retrospective: &quot;I was also somewhat familiar with basic harnessing of the registry, having fuzzed it in 2016 together with James Forshaw&quot; [@pz1-registry-adventure-1]. The cohort produced a handful of registry bug reports filed as Project Zero issues #873, #874, #876, and #993.&lt;/p&gt;
&lt;p&gt;It did not find the hive-memory-corruption class. The reason is the same one that would defeat the 2022 fuzzer: random byte flips on a hive file produce a malformed-but-rejected hive far more often than they produce one that passes base-block validation, enters the parser proper, and exercises an interesting bug.Per-issue contents of the 2016 cohort are not anonymously fetchable; the Project Zero tracker now lives at &lt;code&gt;project-zero.issues.chromium.org&lt;/code&gt; and redirects unauthenticated requests to a Google sign-in page [@pz-tracker-root]. The cohort&apos;s existence is primary-source-confirmed by Jurczyk&apos;s reference in PZ #1.&lt;/p&gt;

The hive binary format is not very well suited for trivial bitflipping-style fuzzing, because it is structurally simple, and random mutations are much more likely to render (parts of) the hive unusable than to trigger any interesting memory safety violations. -- Mateusz Jurczyk, *The Windows Registry Adventure #1* [@pz1-registry-adventure-1]
&lt;p&gt;In early 2022, Jurczyk made a more serious attempt. He built a &lt;strong&gt;coverage-guided Bochs-based kernel fuzzer&lt;/strong&gt;, the same lineage as his earlier Bochspwn work, and pointed it at the kernel&apos;s hive-loading path. Within days the harness produced its first registry kernel bug, filed as Project Zero issue #2299 and assigned CVE-2022-35768 by Microsoft. The fuzzer worked. It just did not scale to the bug class Jurczyk actually wanted, which is the part of the story that matters.&lt;/p&gt;
&lt;p&gt;A frequent third-party confusion is worth naming and dispatching here. &lt;strong&gt;Bochspwn Reloaded is not the registry-research tool.&lt;/strong&gt; The repository&apos;s own README describes the goal as detecting &quot;the disclosure of uninitialized kernel stack/heap memory,&quot; not memory corruption, and reports &quot;over 70 bugs in the Windows kernel&quot; found by the tool in 2017 and early 2018 [@bochspwn-reloaded-repo]. The 2018 white paper makes the same scope clear; the project&apos;s technical content is about shadow-memory representation and tainting stack frames and pool allocations to catch infoleaks [@bochspwn-reloaded-paper]. The 2022 Bochs-based registry harness is a separate, unreleased instrument sharing the lineage but not the codebase.&lt;/p&gt;

A 2018 Bochs-based Project Zero tool by Mateusz Jurczyk for detecting uninitialized kernel memory disclosures via taint tracking [@bochspwn-reloaded-repo]. *Not* the registry-audit instrument. The 2022 coverage-guided Bochs registry harness is a separate, unreleased tool that shares Bochspwn&apos;s general design but is not the public Bochspwn Reloaded repository.

flowchart LR
    A[&quot;RegMon (1996)&lt;br /&gt;Operational visibility&quot;] --&amp;gt; B[&quot;Forensic parsers&lt;br /&gt;regfi, libregf, msuhanov&lt;br /&gt;2008 to present&quot;]
    B --&amp;gt; C[&quot;Forshaw logic bugs&lt;br /&gt;Sym-links, virtualization&lt;br /&gt;2014 to present&quot;]
    C --&amp;gt; D[&quot;Jurczyk-Forshaw fuzz&lt;br /&gt;Bitflipping RegLoadKey&lt;br /&gt;2016&quot;]
    D --&amp;gt; E[&quot;Bochs coverage fuzz&lt;br /&gt;One good bug&lt;br /&gt;2022&quot;]
    E --&amp;gt; F[&quot;Jurczyk manual audit&lt;br /&gt;50 CVEs&lt;br /&gt;2022 to 2023&quot;]
&lt;p&gt;Every prior attempt had hit the same ceiling. The bug class lived in the code, not in the file. And the code had not yet been read.&lt;/p&gt;
&lt;h2&gt;4. Six Generations of Hardening Without Redesign&lt;/h2&gt;
&lt;p&gt;Between 1992 and 2018, Microsoft shipped six generations of registry changes. Not one of them redesigned the parser. Every generation added a feature, hardened a recovery path, lifted a scale limit, or shifted a memory model. Each of those changes also created new surface for the next decade&apos;s attackers. The cell allocator at the heart of the format has been substantively the same routine for twenty-five years.&lt;/p&gt;
&lt;p&gt;The table below collapses Stage 2&apos;s defensive arc into one view. Each row is a generation; the &quot;Surface effect&quot; column captures the bug class that became reachable as a side effect of the improvement.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Gen&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;What was added&lt;/th&gt;
&lt;th&gt;Surface effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;A-1&lt;/td&gt;
&lt;td&gt;1992&lt;/td&gt;
&lt;td&gt;&lt;code&gt;reg.dat&lt;/code&gt; / SHCC3.10, 64 KiB OLE database&lt;/td&gt;
&lt;td&gt;None in the kernel; user-mode only [@pz2-registry-adventure-2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A-2&lt;/td&gt;
&lt;td&gt;1993&lt;/td&gt;
&lt;td&gt;regf v1.0/v1.1, hybrid on-disk and in-memory&lt;/td&gt;
&lt;td&gt;Every memory-corruption bug class to follow [@pz5-registry-adventure-5]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A-3&lt;/td&gt;
&lt;td&gt;1996&lt;/td&gt;
&lt;td&gt;regf v1.3 lock-in, fast-leaves optimization&lt;/td&gt;
&lt;td&gt;30-year backward compatibility freezes the parser [@ms-regsavekeyex]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A-3b&lt;/td&gt;
&lt;td&gt;2001 / 2016&lt;/td&gt;
&lt;td&gt;regf v1.5 (XP, hash leaves), v1.6 (Win10 AU, layered keys)&lt;/td&gt;
&lt;td&gt;New features, same v1.3-cross-compatible parser core [@pz5-registry-adventure-5]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A-4&lt;/td&gt;
&lt;td&gt;2006&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RegLoadAppKey&lt;/code&gt;, KTM transactions&lt;/td&gt;
&lt;td&gt;Parser becomes reachable from Medium IL with no privileges [@ms-regloadappkey]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A-5&lt;/td&gt;
&lt;td&gt;2013&lt;/td&gt;
&lt;td&gt;LOG1/LOG2 incremental write-ahead logging&lt;/td&gt;
&lt;td&gt;New log-replay path becomes attacker-influenceable [@pz5-registry-adventure-5]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A-6&lt;/td&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;Section-backed hive mapping&lt;/td&gt;
&lt;td&gt;Pages become pageable; double-fetch class enabled [@pz5-registry-adventure-5]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Each row deserves a sentence. &lt;strong&gt;A-1&lt;/strong&gt; is the registry&apos;s prehistory; nothing here lives in the kernel, but the hierarchical key/value mental model is established. &lt;strong&gt;A-2&lt;/strong&gt; is the load-bearing decision: hybrid on-disk and in-memory format, modified in place [@pz5-registry-adventure-5]. &lt;strong&gt;A-3&lt;/strong&gt; is the moment Microsoft signed a thirty-year contract; the format defined by &lt;code&gt;REG_STANDARD_FORMAT&lt;/code&gt; is binary-compatible with NT 4.0 [@ms-regsavekeyex].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A-3b&lt;/strong&gt; is the format-level feature layering done since: v1.5 (Windows XP, 2001) added hash leaves to speed up large subkey lookups, and v1.6 (Windows 10 Anniversary Update, 2016) added layered keys for differencing hives; both stay cross-compatible with v1.3-aware parsers, and v1.3 still encodes a number of Windows 11 hives [@pz5-registry-adventure-5]. &lt;strong&gt;A-4&lt;/strong&gt; is the entry-point change: &lt;code&gt;RegLoadAppKey&lt;/code&gt; and the Kernel Transaction Manager arrive together in Vista, and both are now attacker-reachable [@ms-regloadappkey].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A-5&lt;/strong&gt; introduces the new log format; PZ #5 describes &quot;incremental logging added in Windows 8.1&quot; as one of the two big runtime-recovery overhauls of the modern era [@pz5-registry-adventure-5]. &lt;strong&gt;A-6&lt;/strong&gt; is the section-backed mapping shipped in Windows 10 RS4 (April 2018), and is the change that makes a hive on an SMB share into a moving target -- hive pages become pageable, and a page that was validated on load can be evicted and re-read with different contents [@pz5-registry-adventure-5].Some Windows 11 system hives, such as &lt;code&gt;UsrClass.dat&lt;/code&gt; under &lt;code&gt;HKU\&amp;lt;SID&amp;gt;_Classes&lt;/code&gt;, are still written in regf v1.3 -- a format frozen in 1996. The backward-compatibility freeze is not a hypothetical concern [@pz5-registry-adventure-5].&lt;/p&gt;

The unit of allocation inside a hive. A length-prefixed chunk of bytes; positive prefix means the cell is free, negative prefix means it is allocated, and the absolute value of the prefix is the size in bytes (multiples of eight). Cells are the building blocks of keys, values, security descriptors, and index nodes [@msuhanov-spec].

Key Control Block: the in-memory kernel object that represents an open registry key. It holds the cell index of the on-disk key node, a parent pointer, a refcount, and a per-key synchronization primitive [@pz6-registry-adventure-6]. The KCB tree is the live representation of every currently-open registry key.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Each generation added new mitigation, new performance, or new functionality. None redesigned the cell allocator, the cell-index-to-virtual-address translation, or the hybrid on-disk-and-in-memory layout. Six generations of mitigation; one unmoved load-bearing routine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mapping the result is helpful before we get to the audit. Here is what a hive looks like in the 2025-era kernel from the bytes on disk up to the kernel-object tree that user-mode code touches.&lt;/p&gt;

flowchart TD
    A[&quot;Hive file on disk&lt;br /&gt;REGF base block + HBINs&quot;] --&amp;gt; B[&quot;Memory-mapped section&lt;br /&gt;pageable pages&quot;]
    B --&amp;gt; C[&quot;_HHIVE structure&lt;br /&gt;0x600 bytes, hive descriptor&quot;]
    C --&amp;gt; D[&quot;_CMHIVE structure&lt;br /&gt;0x12F8 bytes, kernel state&quot;]
    D --&amp;gt; E[&quot;Cell map&lt;br /&gt;cell-index translation&quot;]
    E --&amp;gt; F[&quot;Hv* allocator&lt;br /&gt;HvAllocateCell, HvFreeCell&quot;]
    F --&amp;gt; G[&quot;KCB tree&lt;br /&gt;open keys in kernel memory&quot;]
    G --&amp;gt; H[&quot;User-mode handles via NtCreateKey&quot;]
&lt;p&gt;The diagram is not a model; it is the structure. PZ #6 documents the exact sizes: &lt;code&gt;_CMHIVE&lt;/code&gt; is 0x12F8 bytes and contains an embedded &lt;code&gt;_HHIVE&lt;/code&gt; of 0x600 bytes at offset zero [@pz6-registry-adventure-6]. None of these objects existed in NT 3.1; what existed was the bottom three layers and a simpler kernel-side wrapper. The architecture grew. The cell allocator did not.&lt;/p&gt;
&lt;p&gt;By 2018 the parser had been substantively unchanged for twenty-five years, and nobody had read all of it.&lt;/p&gt;
&lt;h2&gt;5. The Pivot: Audit, Not Fuzz&lt;/h2&gt;
&lt;p&gt;Return to May 2022, but now with the full context loaded. Six generations of hardening have created a thirty-year-old attack surface. Forty years of forensic and security research have not penetrated the parser. Jurczyk is sitting at his desk with a working coverage-guided Bochs harness and one good registry bug, and instead of letting the fuzzer run for another six months, he stops.&lt;/p&gt;
&lt;p&gt;The detective work that produced the stop is documented in the introduction to the series. Jurczyk noticed two facts that together amount to a methodology critique.&lt;/p&gt;
&lt;p&gt;First, the regf format is &quot;structurally simple&quot; in the sense that bitflipping a random byte usually produces an invalid base-block checksum, an out-of-range cell offset, or some other condition that the kernel rejects long before it reaches anything interesting [@pz1-registry-adventure-1]. The base-block validator is doing a lot of work.&lt;/p&gt;
&lt;p&gt;Second, the bug class he was chasing -- one that produces kernel memory corruption from an attacker-controlled hive -- requires &lt;em&gt;legal-on-disk&lt;/em&gt; hives that exercise particular &lt;em&gt;combinations&lt;/em&gt; of features. The interesting bugs live in interactions: transactions plus virtualization plus predefined keys plus log replay, all in the same legal hive image. No byte-level mutator is going to synthesize that.&lt;/p&gt;
&lt;p&gt;So Jurczyk did something almost retro. He pulled &lt;code&gt;ntoskrnl.exe&lt;/code&gt; with public PDB symbols into the kind of static-and-dynamic analysis toolchain PZ #3 enumerates -- IDA Pro for cross-referencing, WinDbg attached to a kernel target, Ghidra alongside [@pz3-registry-adventure-3] -- and started reading the Configuration Manager. He cross-referenced every entry point against &lt;code&gt;libregf&lt;/code&gt;, against Suhanov&apos;s spec, and against &lt;em&gt;Windows Internals, Part 2, 7th edition&lt;/em&gt; by Allievi, Russinovich, Ionescu, and Solomon [@winint7-part2; @libregf-spec; @msuhanov-spec]. Every attacker-reachable function got traced to every cell read, write, free, and allocation on every path. PZ #3 lists the bibliography he assembled along the way and marks the Russinovich book with the equivalent of a gold star [@pz3-registry-adventure-3]. The methodology is twentieth-century. The yield is not.&lt;/p&gt;
&lt;p&gt;The numbers came in twenty months later. Per PZ #1, the audit produced 39 bug reports, which Microsoft serviced as 44 CVEs in the 90-day cohort plus 6 more in a March 2024 low-severity batch, for 50 CVEs total; the average time from report to fix was 81 days [@pz1-registry-adventure-1]. By December 2024, with more Microsoft CVE assignments rolling in, PZ #5 was reporting 52 CVEs [@pz5-registry-adventure-5]. By May 2025, PZ #7 was at 53 [@pz7-registry-adventure-7]. The growth across the publication arc reflects CVE assignment, not new discoveries. &quot;50+&quot; is the safe headline figure.&lt;/p&gt;
&lt;p&gt;Inside those 50 CVEs, a tight subset of 17 share a single root cause and a single exploitation primitive [@pz8-registry-adventure-8]. Jurczyk&apos;s PZ #8 gives them a name -- &lt;strong&gt;hive-based memory corruption&lt;/strong&gt; -- and divides them into two subclasses. &lt;em&gt;Spatial&lt;/em&gt; violations are cell-boundary overflows: writes that cross the boundary of a legitimately-allocated cell into an adjacent cell whose type, owner, or pointer the attacker now controls. &lt;em&gt;Temporal&lt;/em&gt; violations are cell-reuse use-after-frees: writes through a cell-index reference whose backing storage has been freed and reallocated to attacker-influenced content. Spatial and temporal together; everything else is detail.&lt;/p&gt;

Mateusz Jurczyk&apos;s coinage for the bug class that corrupts the in-memory representation of an active hive via the deterministic cell allocator [@pz8-registry-adventure-8]. The spatial subclass is cell-boundary overflows. The temporal subclass is cell-reuse use-after-frees. The class is named in PZ #8 and demonstrated on Windows 11 with all modern kernel mitigations enabled.
&lt;p&gt;The exploitation primitive is the deliberate engineering of the cell allocator, and PZ #8 is unsentimental about it.&lt;/p&gt;

The registry cell allocator... completely lacks any safeguards against memory corruption, and... has no element of randomness, making its behavior entirely predictable. -- Mateusz Jurczyk, *The Windows Registry Adventure #8* [@pz8-registry-adventure-8]
&lt;p&gt;A deterministic, unrandomized allocator with no integrity checks on its cell metadata is what you would design if you wanted recovery from a torn write to produce the same byte image every time. It is also, identically, what you would design if you wanted an exploit primitive that places a controlled object at a predictable cell index. The property that makes the parser correct under crash recovery and the property that makes it exploitable are the same property.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The bug class was semantic. The fuzzer was syntactic. That mismatch is the audit&apos;s entire reason for existing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;How does an attacker-controlled hive actually become a corruption primitive? The sequence is shorter than you might expect.&lt;/p&gt;

sequenceDiagram
    participant U as Medium-IL process
    participant K as Configuration Manager
    participant V as Base-block validator
    participant P as Bin and cell parser
    participant A as Cell allocator
    U-&amp;gt;&amp;gt;K: RegLoadAppKey(hive_path)
    K-&amp;gt;&amp;gt;V: Validate REGF header
    V-&amp;gt;&amp;gt;P: Walk HBINs, accept legal cells
    P-&amp;gt;&amp;gt;A: Reserve cell indices for keys, values, security
    A-&amp;gt;&amp;gt;P: Hand back deterministic indices
    P-&amp;gt;&amp;gt;K: Build cell map, expose KCB
    Note over A,P: Attacker-shaped cells now live at predictable kernel addresses
    K-&amp;gt;&amp;gt;U: Return private handle
    U-&amp;gt;&amp;gt;K: Trigger second-stage operation (e.g., transaction abort)
    K-&amp;gt;&amp;gt;A: Spatial or temporal violation fires
&lt;p&gt;The diagram makes the loss of generality clear. The base-block validator does its job; the bin and cell parser accept a &lt;em&gt;legal&lt;/em&gt; hive; the cell allocator places attacker-shaped cells at &lt;em&gt;deterministic&lt;/em&gt; indices; and then a second-stage operation -- a transaction abort, a log replay, a predefined-key dereference -- reuses a cell index whose backing storage no longer means what the kernel assumes. There is no point in the lifecycle where a fuzzer&apos;s mutator could have engineered the legal-on-disk-but-semantically-explosive hive that the audit&apos;s reader engineered by hand.&lt;/p&gt;
&lt;p&gt;Coverage-guided fuzzing and manual audit are not equivalent tools on this target. The empirical numbers from the same researcher, on the same target, are instructive.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Researcher-months&lt;/th&gt;
&lt;th&gt;Good registry kernel bugs&lt;/th&gt;
&lt;th&gt;Empirical rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Bitflipping fuzz of &lt;code&gt;RegLoadKey&lt;/code&gt; / &lt;code&gt;RegLoadAppKey&lt;/code&gt; (2016)&lt;/td&gt;
&lt;td&gt;~few [@pz1-registry-adventure-1]&lt;/td&gt;
&lt;td&gt;4 (PZ #873, #874, #876, #993)&lt;/td&gt;
&lt;td&gt;~1 per month or worse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bochs coverage-guided harness (early 2022)&lt;/td&gt;
&lt;td&gt;~1 to 2&lt;/td&gt;
&lt;td&gt;1 (CVE-2022-35768)&lt;/td&gt;
&lt;td&gt;~0.5 to 1 per month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manual audit (May 2022 -- December 2023)&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;50 CVEs across 39 reports [@pz1-registry-adventure-1]&lt;/td&gt;
&lt;td&gt;~2.5 CVEs per month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;To understand why hive-based memory corruption works as a primitive, we have to look at what the parser actually is.&lt;/p&gt;
&lt;h2&gt;6. Anatomy of the Configuration Manager&lt;/h2&gt;
&lt;p&gt;If you want to find bugs in the registry, you have to know exactly what a hive is. Here is what one looks like on disk and in memory.&lt;/p&gt;
&lt;p&gt;A hive begins with a &lt;strong&gt;base block&lt;/strong&gt;: a 4 KiB header that contains the magic string &lt;code&gt;regf&lt;/code&gt;, the format version (v1.3 in modern hives), a sequence-number pair for crash recovery, a checksum, the root cell index, the hive length, the boot type and recovery information [@pz5-registry-adventure-5; @libregf-spec]. The validator that runs at hive load time vets this block first. If the checksum does not match, if the version is unrecognized, if the lengths do not add up, the parser refuses the file and no further code runs. This is the line of defense that ate 99% of the bitflipping fuzzer&apos;s effort in 2016 and again in 2022.&lt;/p&gt;
&lt;p&gt;After the base block come one or more &lt;strong&gt;HBIN&lt;/strong&gt; blocks. Each HBIN is a 4-KiB-multiple chunk of the hive carved into cells. Microsoft&apos;s documentation on registry hives describes the on-disk supporting files alongside the main hive: an &lt;code&gt;.alt&lt;/code&gt; backup of the critical &lt;code&gt;HKLM\System&lt;/code&gt; hive, a &lt;code&gt;.log&lt;/code&gt; transaction log, and a &lt;code&gt;.sav&lt;/code&gt; backup [@ms-registry-hives]. The HBIN is the layer the cells live in.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;cell&lt;/strong&gt; is a length-prefixed chunk of bytes whose first 32-bit field is a signed integer. Positive means free, negative means allocated, and the absolute value is the cell size in bytes (cells are 8-byte aligned). The Suhanov spec documents the convention plainly, alongside the cell types we are about to walk through [@msuhanov-spec]. The signed-size convention is not just a curiosity; it is the load-bearing invariant that the cell allocator must protect, and it is the convention an attacker exploits when they convince the kernel to walk one allocated cell into the next.&lt;/p&gt;
&lt;p&gt;{`
// Demonstrates the regf signed-size cell convention from Suhanov&apos;s spec.
// A cell whose first 32-bit field is positive is FREE.
// A cell whose first 32-bit field is negative is ALLOCATED; |size| is bytes.&lt;/p&gt;
&lt;p&gt;function readCellHeader(buf, offset) {
  const raw = new DataView(buf).getInt32(offset, true); // little-endian
  const allocated = raw &amp;lt; 0;
  const sizeBytes = Math.abs(raw);
  return { allocated, sizeBytes, raw };
}&lt;/p&gt;
&lt;p&gt;// Build a 16-byte buffer: cell #1 allocated, 16 bytes, then a sentinel.
const buf = new ArrayBuffer(20);
new DataView(buf).setInt32(0, -16, true); // header: -16 -&amp;gt; allocated, 16 B
new DataView(buf).setInt32(16, 1234, true); // sentinel &quot;next cell&quot; prefix&lt;/p&gt;
&lt;p&gt;console.log(&quot;Cell 1:&quot;, readCellHeader(buf, 0));
console.log(&quot;Cell 2 sentinel:&quot;, readCellHeader(buf, 16));&lt;/p&gt;
&lt;p&gt;// A trivial validator that only checks &quot;is the size positive after abs()&quot;
// will accept a maliciously flipped header that overlaps into the next cell.
const tampered = buf.slice();
new DataView(tampered).setInt32(0, -24, true); // size now spans into cell 2
console.log(&quot;Tampered cell 1:&quot;, readCellHeader(tampered, 0));
`}&lt;/p&gt;
&lt;p&gt;A hive holds a small number of cell types. The five that matter for security analysis are catalogued below. Each describes a different on-disk concept, and each can be malformed in ways the parser must catch.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cell type&lt;/th&gt;
&lt;th&gt;Signature&lt;/th&gt;
&lt;th&gt;What it stores&lt;/th&gt;
&lt;th&gt;Failure mode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Key node&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A registry key: name, parent index, child-list index, value-list index, security index, timestamp [@libregf-spec]&lt;/td&gt;
&lt;td&gt;Dangling indices; malformed name length; recursive parenting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A registry value: name, type tag, length, inline data or data-block index [@libregf-spec]&lt;/td&gt;
&lt;td&gt;Length-versus-buffer mismatch; type-tag confusion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security descriptor&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A security descriptor for one or more keys; reference-counted [@libregf-spec]&lt;/td&gt;
&lt;td&gt;Refcount underflow on shared SDs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Index node&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lf&lt;/code&gt; / &lt;code&gt;lh&lt;/code&gt; / &lt;code&gt;li&lt;/code&gt; / &lt;code&gt;ri&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A subkey list: leaves with hash hints, intermediate ri lists [@msuhanov-spec]&lt;/td&gt;
&lt;td&gt;Out-of-order entries; phantom subkeys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Big-data block&lt;/td&gt;
&lt;td&gt;&lt;code&gt;db&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A continuation cell for values larger than 16,344 bytes (just under 16 KiB) [@libregf-spec]&lt;/td&gt;
&lt;td&gt;Length math overflow; truncated continuation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Between the cells and the parser sits a layer most people do not know about: the &lt;strong&gt;cell map&lt;/strong&gt;. Bins are not guaranteed to be contiguously mapped in kernel virtual address space, so the Configuration Manager maintains a page-table-like indirection that translates a 32-bit cell index into a virtual address. PZ #6 documents this in detail in its discussion of &lt;code&gt;_HHIVE&lt;/code&gt; and &lt;code&gt;_CMHIVE&lt;/code&gt;, with the latter spanning 0x12F8 bytes and the former 0x600 bytes at offset zero [@pz6-registry-adventure-6].Per PZ #6: &lt;code&gt;_CMHIVE&lt;/code&gt; is 0x12F8 bytes and contains an embedded &lt;code&gt;_HHIVE&lt;/code&gt; of 0x600 bytes at offset 0. The depth of Jurczyk&apos;s reverse-engineering is reflected in these exact offsets, which are not in any Microsoft-published documentation.&lt;/p&gt;

A page-table-like indirection layer that translates a 32-bit cell index into a kernel virtual address [@pz6-registry-adventure-6]. The cell map exists because the bins making up a hive are not guaranteed to be contiguously mapped. Most cell-boundary exploitation primitives walk through the cell map.

flowchart LR
    A[&quot;32-bit cell index&quot;] --&amp;gt; B[&quot;Directory index&quot;]
    A --&amp;gt; C[&quot;Table index&quot;]
    A --&amp;gt; D[&quot;Cell offset within bin&quot;]
    B --&amp;gt; E[&quot;Cell map directory&quot;]
    E --&amp;gt; F[&quot;Cell map table&quot;]
    C --&amp;gt; F
    F --&amp;gt; G[&quot;Bin base address&quot;]
    D --&amp;gt; G
    G --&amp;gt; H[&quot;Kernel virtual address of cell&quot;]
&lt;p&gt;The cell allocator itself -- &lt;code&gt;HvAllocateCell&lt;/code&gt;, &lt;code&gt;HvReallocateCell&lt;/code&gt;, &lt;code&gt;HvFreeCell&lt;/code&gt; [@pz8-registry-adventure-8] -- is small, deterministic, and unrandomized. There is no allocator metadata integrity check; freed cells are eagerly reused; cell placement is a function of the bins&apos; free lists, which the attacker can influence by shaping the input hive. Combined with the cell map, the result is that the attacker can place a chosen byte pattern at a chosen cell index with reasonable predictability, and -- because the same allocator services both attacker-influenced and kernel-managed cells -- the attacker can place that pattern &lt;em&gt;adjacent&lt;/em&gt; to a kernel-managed object whose corruption hands them an elevation primitive [@pz8-registry-adventure-8].&lt;/p&gt;
&lt;p&gt;Since Windows 10 RS4, hive pages are not copied into the paged kernel pool; they are backed by &lt;strong&gt;memory-mapped sections&lt;/strong&gt; that can be paged in from the underlying file [@pz5-registry-adventure-5]. The performance and footprint benefits are real. The security side effect is a new bug class: the kernel can read a hive byte at validation time, then read the same byte again at use time, and the underlying page can have been re-fetched in between. This is the &lt;strong&gt;double-fetch&lt;/strong&gt; pattern, and CVE-2024-43452 -- a double-fetch while loading hives from remote network shares -- is the canonical example Jurczyk cites in PZ #5 [@pz5-registry-adventure-5].&lt;/p&gt;

A vulnerability pattern where the kernel reads the same attacker-influenced memory location twice and treats both reads as authoritative. The section-backed registry (Windows 10 RS4) made hive pages pageable, which enables this on hive files served from remote SMB shares: between the kernel&apos;s two reads, the attacker swaps the byte under the kernel&apos;s feet. CVE-2024-43452 is the canonical example [@pz5-registry-adventure-5].
&lt;p&gt;A small but stubborn misconception about the registry deserves a callout before we move on. The registry is not lock-free. The Configuration Manager uses &lt;strong&gt;pushlocks&lt;/strong&gt; -- a Windows kernel synchronization primitive supporting shared and exclusive modes -- on a per-Key-Control-Block basis, plus a hive-wide pushlock for operations that touch the hive globally [@pz6-registry-adventure-6]. PZ #6&apos;s discussion of &lt;code&gt;_CMHIVE&lt;/code&gt; and &lt;code&gt;_HHIVE&lt;/code&gt; documents the pushlock placements directly. The design is fine-grained pushlock synchronization, not lock-free concurrency, and the difference matters because temporal hive-memory-corruption bugs frequently exploit the &lt;em&gt;gap between unlocking a parent and re-locking it&lt;/em&gt;, which exists in pushlock designs and would not exist in a true lock-free one.&lt;/p&gt;

A Windows kernel synchronization primitive supporting shared and exclusive modes [@pz6-registry-adventure-6]. The registry uses per-KCB pushlocks and a hive-wide pushlock. The implementation is *not* lock-free; that is a third-party misconception, and several of Jurczyk&apos;s temporal hive-memory-corruption bugs exploit the moment a pushlock is released and re-acquired.
&lt;p&gt;Two other runtime subsystems sit on top of the parser. The Kernel Transaction Manager (KTM) lets registry writes be grouped into atomic, rollbackable transactions; KTM rides on the Common Log File System (CLFS).KTM&apos;s CLFS backing is interesting in its own right: CLFS has had its own significant CVE history, and a transactional registry write whose KTM log can be tampered with reaches a separate kernel subsystem with its own attack surface. The transactional layer is one of the &quot;semantic combinators&quot; Jurczyk explicitly lists as outside the syntactic-fuzzer reach.&lt;/p&gt;
&lt;p&gt;Incremental write-ahead logging via LOG1 and LOG2 provides crash-recoverable durability for individual writes that have not yet been flushed to the main hive [@pz5-registry-adventure-5]. Both layers add features. Both layers add cell-lifetime states the parser must reason about. Both layers contributed bugs to the audit.&lt;/p&gt;
&lt;p&gt;The PZ #1 summary breakdown of the 50-CVE cohort is the clearest single statistic in the entire series.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Elevation of privilege&lt;/td&gt;
&lt;td&gt;39 [@pz1-registry-adventure-1]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Information disclosure&lt;/td&gt;
&lt;td&gt;9 [@pz1-registry-adventure-1]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory information disclosure&lt;/td&gt;
&lt;td&gt;1 [@pz1-registry-adventure-1]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Denial of service&lt;/td&gt;
&lt;td&gt;1 [@pz1-registry-adventure-1]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Of those 50, the subset PZ #8 picks out as exploitable via the hive-memory-corruption primitive numbers seventeen: CVE-2022-34707, CVE-2022-34708, CVE-2022-37956, CVE-2022-37988, CVE-2022-38037, CVE-2023-21675, CVE-2023-21748, CVE-2023-23420, CVE-2023-23421, CVE-2023-23422, CVE-2023-23423, CVE-2023-28248, CVE-2023-35382, CVE-2023-38139, CVE-2024-26182, CVE-2024-43641, and CVE-2024-49114 [@pz8-registry-adventure-8]. Seventeen kernel LPEs from one researcher, one subsystem, one bug class, one exploitation primitive.&lt;/p&gt;
&lt;p&gt;Microsoft has known about every one of these issues since the day they were reported. Why has the parser not been rewritten?&lt;/p&gt;
&lt;h2&gt;7. Why Doesn&apos;t Microsoft Just Rewrite It?&lt;/h2&gt;
&lt;p&gt;The first thing anyone asks after seeing the architecture is the obvious question. Why doesn&apos;t Microsoft rewrite this thing? The answer is, roughly, &quot;because they cannot.&quot;&lt;/p&gt;
&lt;p&gt;Backward compatibility is the dominant constraint. A hive file from NT 4.0 in 1996 still mounts on Windows 11 in 2026; that is the published behaviour of &lt;code&gt;REG_STANDARD_FORMAT&lt;/code&gt; in &lt;code&gt;RegSaveKeyExA&lt;/code&gt; [@ms-regsavekeyex]. Three decades of system images, third-party installers, forensic tooling, configuration-management products, and group-policy templates depend on the regf v1.3 format being readable. A new on-disk format with a hardened in-memory representation would not be a parser change; it would be the kind of compatibility break Microsoft has not made since the move from Win9x to NT.&lt;/p&gt;
&lt;p&gt;There are databases inside Windows that look like reasonable alternatives at a glance. None of them is a drop-in replacement, for reasons that have less to do with their internals than with what the registry is asked to do.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;Used for&lt;/th&gt;
&lt;th&gt;Why it is not a drop-in&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Registry&lt;/td&gt;
&lt;td&gt;regf, kernel parser&lt;/td&gt;
&lt;td&gt;All Windows configuration, COM, security, policy [@ms-structure-registry]&lt;/td&gt;
&lt;td&gt;The thing we are auditing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;esent.dll&lt;/code&gt;, full ACID DB&lt;/td&gt;
&lt;td&gt;Active Directory, Windows Search, Mail, Exchange [@winint7-part2]&lt;/td&gt;
&lt;td&gt;Different access model; userland; not designed for boot-path config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LSA Secrets / &lt;code&gt;SECURITY&lt;/code&gt; hive&lt;/td&gt;
&lt;td&gt;regf substrate, restricted access&lt;/td&gt;
&lt;td&gt;Cached credentials, Kerberos keys [@winint7-part2]&lt;/td&gt;
&lt;td&gt;Same parser, same bug class -- moving the lock does not move the bug&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://paragmali.com/blog/the-object-manager-namespace/&quot; rel=&quot;noopener&quot;&gt;Object Manager Namespace&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Kernel object directory&lt;/td&gt;
&lt;td&gt;Named kernel objects (events, mutexes, sections)&lt;/td&gt;
&lt;td&gt;Different threat model; not a config store&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MSIX / AppX state&lt;/td&gt;
&lt;td&gt;Per-package JSON/XML in app container&lt;/td&gt;
&lt;td&gt;UWP/Store-app configuration&lt;/td&gt;
&lt;td&gt;New apps only; cannot host legacy registry consumers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;ESE&lt;/strong&gt; -- the Extensible Storage Engine -- is the closest existing internal candidate. It is a full ACID embedded database, used by Active Directory and Windows Search, and it is much better-engineered as a storage layer than regf is. It is also userland, designed for very different consumers, and not on the kernel boot path. Reusing it would require porting every kernel-mode registry caller across the kernel-user boundary, which has performance implications that nobody has signed off on publicly.&lt;/p&gt;

Microsoft&apos;s Extensible Storage Engine, an embedded ACID database implemented in `esent.dll`. Active Directory, Windows Search, Exchange, and Windows Mail all use it as their internal data store [@winint7-part2]. It is a much more modern design than the registry&apos;s regf, but it is userland, not boot-path, and its access model is different enough that it is not a drop-in replacement for the kernel-mode configuration store.
&lt;p&gt;The &lt;strong&gt;LSA Secrets&lt;/strong&gt; and &lt;code&gt;SECURITY&lt;/code&gt; hive are even more instructive. They are regf-format hives with stricter access controls. They inherit the entire hive-memory-corruption bug class verbatim; restricting &lt;em&gt;who&lt;/em&gt; can talk to the parser does not change &lt;em&gt;what&lt;/em&gt; the parser does with the bytes it receives.&lt;/p&gt;

The Windows kernel has another old, hierarchical, semantically-rich subsystem that has not been audited at this scale: the Object Manager Namespace, which exposes named kernel objects (events, sections, mutexes, devices, symbolic links) through a path-like API. It is the same era as the registry, the same kind of in-kernel data structure with a path-resolution layer, the same authorization model that has been hardened incrementally over thirty years. James Forshaw&apos;s work has touched it in places; no one has yet read it the way Jurczyk read the Configuration Manager. The Object Manager Namespace is the most plausible next target for a Jurczyk-style audit by anyone who wants to repeat the result on a different subsystem.
&lt;p&gt;The structural argument is the one to remember. The registry&apos;s on-disk format and its in-memory format are the same format, and its recovery semantics depend on deterministic cell placement; the attack surface and the recovery semantics are therefore literally the same code [@pz5-registry-adventure-5; @pz8-registry-adventure-8]. You cannot harden one without weakening the other unless you give up the hybrid-format premise entirely -- in which case, you are not hardening the parser; you are rewriting it. And rewriting it is what backward compatibility forbids.&lt;/p&gt;
&lt;p&gt;If a wholesale redesign is off the table, can the existing parser be hardened in place?&lt;/p&gt;
&lt;h2&gt;8. The Theoretical Limits of In-Place Hardening&lt;/h2&gt;
&lt;p&gt;If Microsoft cannot rewrite the parser, can they at least harden it? Four levers are theoretically available. Each one trades against a different property the existing design depends on.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lever&lt;/th&gt;
&lt;th&gt;What it would achieve&lt;/th&gt;
&lt;th&gt;Backward-compat cost&lt;/th&gt;
&lt;th&gt;Effectiveness against hive-memory-corruption&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Allocator randomization&lt;/td&gt;
&lt;td&gt;Break the placement predictability the exploitation primitive relies on&lt;/td&gt;
&lt;td&gt;Breaks log-replay recovery semantics that depend on deterministic cell placement [@pz8-registry-adventure-8]&lt;/td&gt;
&lt;td&gt;High in principle; incompatible in practice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cell-metadata integrity checks&lt;/td&gt;
&lt;td&gt;Catch naive corruption at allocator boundaries&lt;/td&gt;
&lt;td&gt;Modest format change for in-memory layout; on-disk format unaffected&lt;/td&gt;
&lt;td&gt;Low; catches accidental corruption, not crafted-input semantic violations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structured deserialization at load time&lt;/td&gt;
&lt;td&gt;Validate the entire hive into a separate in-memory structure&lt;/td&gt;
&lt;td&gt;Abandons the hybrid-format premise; effectively rewrites the parser&lt;/td&gt;
&lt;td&gt;High but indistinguishable from rewriting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Move the parser to user mode&lt;/td&gt;
&lt;td&gt;Reduce blast radius of a parser bug to one process&lt;/td&gt;
&lt;td&gt;Performance and correctness implications for boot-path config&lt;/td&gt;
&lt;td&gt;Mitigation only; the bug class survives in userland&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Allocator randomization&lt;/strong&gt; is the obvious idea. ASLR-like randomization of cell placement would defeat the &quot;place attacker-controlled bytes at predictable index&quot; half of the primitive, but it would also break recovery semantics: log replay assumes that after a crash, the cells in the recovered hive end up at the same indices the log expected, because the on-disk-equals-in-memory format encodes the cell index in the hive itself. PZ #8&apos;s framing of the allocator&apos;s lack of randomness as a &lt;em&gt;design property&lt;/em&gt; rather than an oversight is precisely about this trade-off [@pz8-registry-adventure-8].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cell-metadata integrity checks&lt;/strong&gt; are cheap to add and have an obvious limit. The cell allocator currently has no metadata integrity at all; adding a checksum or a canary would catch a corrupted size header, a stale free-list pointer, or a write that accidentally overran a cell boundary. It would not catch an attacker who shapes a &lt;em&gt;legal&lt;/em&gt; hive that exercises the parser&apos;s combinatorial logic. The semantic bugs Jurczyk hunted do not write garbage cells; they trick the parser into reusing valid cells for purposes the parser does not realize it is being asked to.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Structured deserialization at hive-load time&lt;/strong&gt; is the option computer-science textbooks recommend. Validate the entire input file against a formal grammar, deserialize into a separate in-memory representation that is unrelated to the on-disk byte layout, and let the kernel operate on that. This is what the LangSec discipline calls for, and what structure-aware fuzzing surveys treat as the right shape for parser hardening [@manes-fuzz-survey]. It is also identical to &quot;rewrite the parser.&quot; The hybrid-format premise that has been load-bearing since 1993 has to die for this option to exist.&lt;/p&gt;

Language-theoretic security: a discipline that treats parsers as recognizers for a formal grammar, rejecting inputs outside the grammar instead of recovering from malformed input. The registry parser does the opposite by design: it accepts inputs that the recognizer would call &quot;marginal&quot; (a slightly-malformed log, an off-by-one bin) because recovery from a torn write requires acceptance, not rejection.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; LangSec&apos;s central recommendation is that a parser should be a &lt;em&gt;recognizer&lt;/em&gt; for a formal language: an input either belongs to the language or it is rejected outright, with no recovery and no partial acceptance. The registry&apos;s regf parser is not a recognizer in this sense, and cannot be retrofitted into one without abandoning the hybrid on-disk-and-in-memory premise.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Moving the parser to user mode&lt;/strong&gt; -- running the parser inside an isolated process and exposing only sanitized handles to kernel callers -- is what the academic literature recommends for other kernel parsers. There is no public Microsoft work on doing this for the registry specifically, and the performance cost of a kernel/user boundary on the boot-path configuration store is, charitably, &quot;unstudied.&quot; The bug class would still exist; the blast radius would shrink.&lt;/p&gt;

Static analysis cannot save us in general. Rice&apos;s theorem says, informally, that any non-trivial semantic property of an arbitrary program is undecidable: there is no algorithm that takes a program and tells you whether it has property $P$, for any interesting $P$. Memory safety is interesting. Therefore, any static-analysis approach to &quot;find every memory-safety bug in the Configuration Manager&quot; must be either unsound (it misses bugs) or incomplete (it flags false positives), and in practice usually both. Formal verification of a *specific* parser against a *specific* specification can sidestep this -- the EverParse project at `github.com/project-everest/everparse` does exactly that for TLS and QUIC message parsers in Microsoft research -- but it requires a formal specification of the input language, and the regf format has none.
&lt;p&gt;The honest answer is the one Jurczyk gives in PZ #7 and PZ #8: the parser can be incrementally hardened, and is being, in response to each individual CVE [@pz7-registry-adventure-7; @pz8-registry-adventure-8]. The deeper design choices that make the parser exploitable are the same choices that make it work at all. We have a thirty-year-old parser that cannot be redesigned, cannot easily be replaced, and can only be hardened in ways that trade safety for compatibility. So what does that tell us about the rest of the Windows kernel?&lt;/p&gt;
&lt;h2&gt;9. Open Problems and What the Audit Implies&lt;/h2&gt;
&lt;p&gt;Jurczyk read one Windows kernel subsystem for twenty months and produced fifty CVEs. Windows has dozens of kernel subsystems. None of them has been read this way.&lt;/p&gt;
&lt;p&gt;That sentence is the article. The rest of this section is bookkeeping.&lt;/p&gt;
&lt;p&gt;First, the open business inside the audit itself. Microsoft chose not to fix some of Jurczyk&apos;s low-severity reports; PZ tracker issue #2508 is the canonical example of a WontFix close, and the broader &quot;low severity in isolation&quot; category is not &quot;not exploitable in combination&quot; -- modern kernel exploitation is bug-chaining, and a benign-looking primitive plus a benign-looking infoleak often compose into something less benign [@pz7-registry-adventure-7]. PZ #1 also explicitly flags higher-level wrapper logic (path translation in &lt;code&gt;CmpDoOpen&lt;/code&gt;, predefined-key abuses, virtualization layers) as parts of the surface that the 20-month audit did not exhaust [@pz1-registry-adventure-1]. There are more registry bugs to find.&lt;/p&gt;
&lt;p&gt;Second, the cross-subsystem implication. Microsoft&apos;s Windows Insider Preview bounty program pays &quot;from $500 to $100,000 USD&quot; for qualifying critical kernel bugs [@msrc-bounty-windows-insider]. The 50-CVE cohort, valued at the upper bound of the Insider Preview range, is somewhere in the neighbourhood of $5M in latent bounty value, all produced by one person reading code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; At Microsoft&apos;s published $100,000 ceiling for critical Windows kernel bugs under the Windows Insider Preview program [@msrc-bounty-windows-insider], the 50-CVE cohort represents roughly $5M in latent bounty value. That is one person, twenty months, one subsystem. The question is not how to fix the registry; it is how many other subsystems would yield similar numbers under similar treatment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What does that imply for the Object Manager Namespace, the I/O Manager, the print stack, the transactional file system, the Common Log File System, or the WinUSB stack? No public audit of any of those subsystems at the depth of Jurczyk&apos;s registry work exists. Some of them have had targeted fuzzing campaigns; none has had a 100,000-line code review by a single expert reader. The expected yield is, charitably, unknown.&lt;/p&gt;

flowchart TD
    A[&quot;Windows kernel subsystems&quot;] --&amp;gt; B[&quot;Registry / Configuration Manager&quot;]
    A --&amp;gt; C[&quot;Object Manager Namespace&quot;]
    A --&amp;gt; D[&quot;I/O Manager&quot;]
    A --&amp;gt; E[&quot;KTM and CLFS&quot;]
    A --&amp;gt; F[&quot;Print spooler stack&quot;]
    A --&amp;gt; G[&quot;Transactional NTFS&quot;]
    A --&amp;gt; H[&quot;GDI and Win32k&quot;]
    B --&amp;gt; B1[&quot;Jurczyk 2022-2023, 50 CVEs&quot;]
    C --&amp;gt; C1[&quot;Partial Forshaw 2014+, logic bugs&quot;]
    D --&amp;gt; D1[&quot;Episodic fuzzing, no public deep audit&quot;]
    E --&amp;gt; E1[&quot;Episodic CLFS exploitation, no full audit&quot;]
    F --&amp;gt; F1[&quot;PrintNightmare-era patches, no full audit&quot;]
    G --&amp;gt; G1[&quot;No public deep audit&quot;]
    H --&amp;gt; H1[&quot;Years of TYPESAFE_CAST + targeted fuzzing&quot;]
&lt;p&gt;Third, Microsoft&apos;s own internal posture. The MSRC SDL pipeline includes OneFuzz-lineage tooling internally, though the public OneFuzz repository was archived in September 2023 [@onefuzz-repo]. No public Microsoft statement confirms or denies whether the registry was systematically fuzzed or audited inside Microsoft before Jurczyk&apos;s 2022 audit. The absence of such a statement is itself information: if Microsoft had a parallel internal effort that found these bugs first, they would normally publish that.&lt;/p&gt;
&lt;p&gt;Fourth, the methodological question that the article cannot answer because nobody has the data. Does manual code audit scale? One researcher, twenty months, one subsystem, fifty CVEs. Two researchers do not produce twice the bugs because of overlap and coordination cost; the typical second-researcher contribution on the same target is sublinear. There is no obvious path to ten Jurczyks reading ten subsystems in parallel and producing five hundred CVEs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The registry is not interesting because it had bugs. The registry is interesting because someone read it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jurczyk did not break new ground by finding a bug. He broke new ground by reading the code -- and the implication for everything else nobody has read is left, as Jurczyk himself might say, as an exercise for the reader.&lt;/p&gt;
&lt;h2&gt;10. A Practical Guide&lt;/h2&gt;
&lt;p&gt;Up to here, this article has been about the research. The rest is for practitioners.&lt;/p&gt;
&lt;h3&gt;For vulnerability researchers&lt;/h3&gt;
&lt;p&gt;If you want to understand Jurczyk&apos;s audit at the level required to repeat it, the Project Zero series is the primary text and the reading order is not the publication order. PZ #4 (hives and the registry layout) and PZ #5 (the regf file format) are the canonical references for the &lt;em&gt;substrate&lt;/em&gt;; PZ #6 (kernel-mode objects) is the reverse-engineering of the in-memory structures; PZ #7 (attack surface analysis) is the bug-class taxonomy; PZ #8 (practical exploitation) is the exploitation primitive on Windows 11 with modern mitigations [@pz4-registry-adventure-4; @pz5-registry-adventure-5; @pz6-registry-adventure-6; @pz7-registry-adventure-7; @pz8-registry-adventure-8]. PZ #1 and #2 are the framing and the history; PZ #3 is the bibliography. Read 4 -- 5 -- 6 -- 7 -- 8, in that order, with PZ #1 alongside as a CVE-index lookup.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Audience&lt;/th&gt;
&lt;th&gt;Where to start&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Researcher learning the surface&lt;/td&gt;
&lt;td&gt;PZ #4 then PZ #5 [@pz4-registry-adventure-4; @pz5-registry-adventure-5]&lt;/td&gt;
&lt;td&gt;Substrate first; specifics later&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defender / SOC engineer&lt;/td&gt;
&lt;td&gt;PZ #7 attack-surface taxonomy [@pz7-registry-adventure-7]&lt;/td&gt;
&lt;td&gt;Detection patterns map to bug classes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kernel engineer (defensive)&lt;/td&gt;
&lt;td&gt;PZ #4--6 collectively&lt;/td&gt;
&lt;td&gt;Best non-Microsoft technical reference on the Configuration Manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Patch manager&lt;/td&gt;
&lt;td&gt;PZ #8&apos;s 17-CVE list + PZ #1 full table [@pz8-registry-adventure-8; @pz1-registry-adventure-1]&lt;/td&gt;
&lt;td&gt;Prioritize the hive-memory-corruption cohort&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

The Jurczyk pattern is reproducible. Pick a closed-source Windows kernel subsystem with a structurally rigid input format. Get the public PDB symbols for `ntoskrnl.exe` (or the relevant driver). Find the equivalent of `RegLoadAppKey` for the surface in question -- the unprivileged user-mode entry point that runs the most kernel code on the most attacker-influenced input. Then read every reachable function. The unglamorous methodology and the long-form Project Zero blog series are the same artifact.Jurczyk&apos;s 2022 registry-specific coverage-guided Bochs harness has never been publicly released. The lineage -- Bochspwn (2013), Bochspwn Reloaded (2018) -- is well-documented in Jurczyk&apos;s public papers and repositories [@bochspwn-reloaded-paper; @bochspwn-reloaded-repo]. The registry-specific configuration is not.
&lt;h3&gt;For defenders&lt;/h3&gt;
&lt;p&gt;The detection story for hive-memory-corruption attempts is unusual. Most real-world exploitation chains will load an attacker-controlled hive via &lt;code&gt;RegLoadAppKey&lt;/code&gt; (or its close relatives &lt;code&gt;RegLoadKey&lt;/code&gt;, &lt;code&gt;RegLoadKeyEx&lt;/code&gt;, &lt;code&gt;RegRestoreKey&lt;/code&gt;) from an unusual path -- typically a temporary directory under the calling user&apos;s profile or an SMB share. The hive file itself can be analyzed offline by mounting it with a forensic parser such as libregf [@libregf-repo] or Suhanov&apos;s regf tools [@msuhanov-repo].&lt;/p&gt;
&lt;p&gt;The kernel exposes the operation via the &lt;code&gt;Microsoft-Windows-Kernel-Registry&lt;/code&gt; &lt;a href=&quot;https://paragmali.com/blog/etw-how-windows-2000s-performance-hack-became-the-edr-substr/&quot; rel=&quot;noopener&quot;&gt;ETW&lt;/a&gt; provider, and &lt;a href=&quot;https://paragmali.com/blog/from-cmdexe-to-a-kusto-row-in-90-seconds-how-sysmon-and-defe/&quot; rel=&quot;noopener&quot;&gt;Sysmon&lt;/a&gt; surfaces registry operations under event IDs 12 (key create/delete), 13 (value set), and 14 (key/value rename) [@ms-sysmon]. A simple detection heuristic is &quot;Medium-IL process performs an unusual rate of hive-load operations on attacker-shaped paths.&quot; Detection logic looks like the following.&lt;/p&gt;
&lt;p&gt;{`
// Toy detection: Medium-IL process loads multiple app hives from
// non-standard paths within a short window. Inspired by Sysmon event IDs
// 12 (registry create/delete) and 13 (registry value set).&lt;/p&gt;
&lt;p&gt;function suspiciousHiveLoad(event, profileWindowMs) {
  const isLoad = event.operation === &apos;CreateKey&apos; || event.operation === &apos;LoadAppKey&apos;;
  if (!isLoad) return false;&lt;/p&gt;
&lt;p&gt;  const path = event.targetPath || &apos;&apos;;
  const fromTempOrShare =
    path.match(/AppData\\Local\\Temp/i) ||
    path.match(/^\\\\[^\\]+\\/) ||
    path.match(/Users\\Public/i);&lt;/p&gt;
&lt;p&gt;  const lowIntegrity = event.integrityLabel === &apos;Medium&apos; || event.integrityLabel === &apos;Low&apos;;&lt;/p&gt;
&lt;p&gt;  const recentCount = countRecentEventsFromPid(event.pid, profileWindowMs);
  const burst = recentCount &amp;gt; 5;&lt;/p&gt;
&lt;p&gt;  return lowIntegrity &amp;amp;&amp;amp; fromTempOrShare &amp;amp;&amp;amp; burst;
}&lt;/p&gt;
&lt;p&gt;function alert(event) {
  if (suspiciousHiveLoad(event, 60000)) {
    console.log(&apos;ALERT: anomalous hive load from PID &apos; + event.pid +
                &apos; path=&apos; + event.targetPath);
  }
}
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The 17 CVEs in Jurczyk&apos;s PZ #8 cohort all share the same exploitation primitive. If you are triaging a backlog of Windows security updates, prioritize fixes for these CVE IDs over the broader 50-CVE list: CVE-2022-34707, -34708, -37956, -37988, -38037; CVE-2023-21675, -21748, -23420, -23421, -23422, -23423, -28248, -35382, -38139; CVE-2024-26182, -43641, -49114 [@pz8-registry-adventure-8].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;For engineers maintaining adjacent code&lt;/h3&gt;
&lt;p&gt;PZ #4, #5, and #6 collectively are the most accessible non-Microsoft technical reference on the Configuration Manager [@pz4-registry-adventure-4; @pz5-registry-adventure-5; @pz6-registry-adventure-6]. If you are doing security review of a subsystem that interacts with the registry -- ETW, KTM, AppX state, group policy -- those three posts plus PZ #7 give you the model of the in-kernel data structures you are talking to.&lt;/p&gt;
&lt;h3&gt;For everyone else&lt;/h3&gt;
&lt;p&gt;The 50 CVE IDs spanning CVE-2022-34707 through CVE-2024-49114 are a checklist for &quot;have these been rolled across our fleet?&quot; [@pz1-registry-adventure-1]. The 17-CVE hive-memory-corruption subset is the priority order [@pz8-registry-adventure-8]. The fixes are in Microsoft&apos;s monthly servicing channel; there are no out-of-band patches required, but the cohort is large enough that a fleet that fell behind on Patch Tuesday in 2022 -- 2024 may have several of these still outstanding.&lt;/p&gt;
&lt;p&gt;The research is published. The detection is uncomplicated. The next twenty months of Windows kernel research will not be about the registry, which makes the question this article ends on -- what about everything else nobody has read -- the only question left.&lt;/p&gt;
&lt;h2&gt;11. FAQ&lt;/h2&gt;
&lt;p&gt;A handful of questions worth correcting before they propagate. These are the misconceptions inherited from secondary summaries of the research, including the prompt for this article.&lt;/p&gt;

No. **Bochspwn Reloaded** is a separate 2017--2018 Project Zero tool, also by Jurczyk, that detects uninitialized kernel memory disclosures via x86 taint tracking [@bochspwn-reloaded-repo; @bochspwn-reloaded-paper]. The 2022--2023 registry research is **The Windows Registry Adventure**, an eight-part Project Zero blog series [@pz1-registry-adventure-1]. The 2022 coverage-guided Bochs harness Jurczyk briefly used on the registry was a separate, unreleased tool sharing the same general lineage, but it is not the public Bochspwn Reloaded repository. Conflating the two is the most common third-party error about this research.

No. At a minimum, Jurczyk and Forshaw fuzzed it in 2016 -- the bug reports filed as Project Zero issues #873, #874, #876, and #993 are the surviving artifacts of that effort [@pz1-registry-adventure-1] -- and Jurczyk built a coverage-guided Bochs harness against it in early 2022 that produced CVE-2022-35768 within days. The 2022--2023 work that produced 50 CVEs was a manual code audit, not a fuzzing campaign. The &quot;fuzzed precisely once&quot; claim mixes up &quot;no published fuzzing campaign at scale&quot; with &quot;no one ever pointed a fuzzer at this,&quot; and the latter is just not true.

No. The Configuration Manager uses **pushlocks** (shared and exclusive modes) on a per-Key-Control-Block basis, plus a hive-wide pushlock for global hive operations [@pz6-registry-adventure-6]. &quot;Lock-free&quot; is a misconception that appears in some secondary summaries -- including the prompt for this article. The actual design is fine-grained pushlock-synchronized, and several of Jurczyk&apos;s temporal hive-memory-corruption bugs exploit the moment a pushlock is released and re-acquired.

All of those are correct at different points in the publication arc. PZ #1 (April 2024) counts 44 from the 90-day cohort plus 6 from the March 2024 low-severity batch = 50 [@pz1-registry-adventure-1]. PZ #5 (December 2024) reports 52 [@pz5-registry-adventure-5]. PZ #7 (May 2025) reports 53 [@pz7-registry-adventure-7]. The growth reflects Microsoft assigning more CVE IDs to Jurczyk&apos;s existing bug reports over time, not new discoveries. &quot;50+&quot; is the safe shorthand; &quot;50 in the original cohort, 53 by mid-2025&quot; is the precise version.

**OffensiveCon 2024**, in Berlin. The talk was &quot;Practical Exploitation of Registry Vulnerabilities in the Windows Kernel&quot;; slides and recording are public [@offcon24-jurczyk-speaker; @offcon24-slides; @offcon24-video]. The earlier **BlueHat Redmond 2023** talk (titled &quot;Exploring the Windows Registry as a powerful LPE attack surface&quot;) was the first public disclosure of the research [@bluehat23-slides; @bluehat23-video]. &quot;OffensiveCon 2025&quot; is wrong; that talk has not happened.

No. Microsoft has never published a regf specification; PZ #5 states this directly: &quot;Throughout the 30 years of the format&apos;s existence, Microsoft has never released its official specification&quot; [@pz5-registry-adventure-5]. Unofficially, two community-maintained specs cover almost all of it: Joachim Metz&apos;s libregf, updated continuously since July 2009 [@libregf-spec], and Maxim Suhanov&apos;s regf project [@msuhanov-spec]. The Microsoft-blessed reference book is *Windows Internals, Part 2, 7th Edition* by Allievi, Russinovich, Ionescu, and Solomon [@winint7-part2]. Everything else is forensics-community reverse engineering.
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;windows-registry-adventure&quot; keyTerms={[
  { term: &quot;regf&quot;, definition: &quot;Microsoft&apos;s binary registry file format, introduced in NT 3.1 (1993) and frozen at v1.3 in NT 4.0 (1996). The on-disk format and the in-memory format are the same format.&quot; },
  { term: &quot;Hive&quot;, definition: &quot;A file-and-in-memory tree of registry keys and values, encoded in regf and parsed by the Windows kernel&apos;s Configuration Manager.&quot; },
  { term: &quot;Cell&quot;, definition: &quot;The unit of allocation inside a hive: length-prefixed bytes whose signed prefix marks free (positive) or allocated (negative), with size in multiples of eight bytes.&quot; },
  { term: &quot;Cell map&quot;, definition: &quot;A page-table-like indirection layer that translates a 32-bit cell index into a kernel virtual address.&quot; },
  { term: &quot;RegLoadAppKey&quot;, definition: &quot;Win32 API since Vista that lets an unprivileged process load an arbitrary hive file. The kernel parser runs on attacker-supplied bytes.&quot; },
  { term: &quot;Hive-based memory corruption&quot;, definition: &quot;Jurczyk&apos;s bug class: spatial (cell-boundary overflows) and temporal (cell-reuse use-after-frees) memory corruption via the deterministic cell allocator.&quot; },
  { term: &quot;Pushlock&quot;, definition: &quot;Windows kernel synchronization primitive (shared/exclusive). The registry uses per-KCB and hive-wide pushlocks; it is not lock-free.&quot; },
  { term: &quot;Double-fetch&quot;, definition: &quot;Pattern where the kernel reads the same attacker-influenced memory twice; section-backed hives since Windows 10 RS4 made this exploitable on hive files from SMB shares.&quot; },
  { term: &quot;Bochspwn Reloaded&quot;, definition: &quot;A 2018 Project Zero tool for detecting kernel infoleaks via Bochs-based taint tracking. NOT the registry-research instrument.&quot; },
  { term: &quot;LangSec&quot;, definition: &quot;Language-theoretic security: parsers as recognizers for a formal grammar. The regf parser is not a LangSec recognizer by design.&quot; }
]} questions={[
  { q: &quot;Why does the Windows kernel run a binary parser on attacker-supplied bytes at Medium IL?&quot;, a: &quot;&lt;code&gt;RegLoadAppKey&lt;/code&gt;, introduced in Vista (2006), explicitly allows an unprivileged process to load an arbitrary hive file as a private app hive. The kernel-mode regf parser runs on those bytes; only the resulting handle is sandboxed.&quot; },
  { q: &quot;Why was bitflipping fuzzing ineffective against regf?&quot;, a: &quot;The base-block validator rejects most random mutations before the parser proper sees them; the interesting bugs are semantic, requiring legal hive images that exercise multi-feature combinations (transactions, virtualization, log replay).&quot; },
  { q: &quot;Why is the cell allocator unrandomized?&quot;, a: &quot;Recovery semantics require deterministic cell placement after log replay; cells encode their indices in the on-disk format. Randomization would break crash recovery.&quot; },
  { q: &quot;Distinguish spatial from temporal hive-memory-corruption violations.&quot;, a: &quot;Spatial: a write crosses a cell boundary into an adjacent cell. Temporal: a write uses a cell-index reference whose backing storage has been freed and reallocated to attacker-influenced content.&quot; },
  { q: &quot;Why is the section-backed hive design in Windows 10 RS4 a double-fetch enabler?&quot;, a: &quot;Hive pages became pageable. The kernel can read a hive byte at validation time and again at use time, and the underlying page can be re-fetched in between -- especially over SMB. CVE-2024-43452 is the canonical example.&quot; }
]} /&amp;gt;&lt;/p&gt;
&lt;p&gt;The eight Project Zero posts run roughly 120,000 words across April 2024 -- May 2025. Microsoft has serviced 53 CVEs from them so far. The registry&apos;s parser remains substantively the same routine it has been since Windows NT 4.0. There is no public roadmap for a redesign. The question that follows -- what is the expected yield of similar audits of every other Windows kernel subsystem that no one has read end-to-end -- is the one a research community could answer in another twenty months, if it chose to.&lt;/p&gt;
</content:encoded><category>windows-kernel</category><category>security-research</category><category>fuzzing</category><category>manual-audit</category><category>project-zero</category><category>registry</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Rust in the Windows Kernel: A Field Guide to the 2024-2026 Memory-Safety Refit</title><link>https://paragmali.com/blog/rust-in-the-windows-kernel-a-field-guide-to-the-2024-2026-me/</link><guid isPermaLink="true">https://paragmali.com/blog/rust-in-the-windows-kernel-a-field-guide-to-the-2024-2026-me/</guid><description>Rust ships in the Windows 11 kernel today. A primary-sourced field guide to what actually shipped from BlueHat IL 2019 through 24H2 in 2026, and what did not.</description><pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Rust ships in the Windows kernel today.** The binary is `%SystemRoot%\System32\win32kbase_rs.sys`, first surfaced in Insider Preview Build 25905 on 12 July 2023 and most recently in the news through Check Point Research&apos;s May 2025 &quot;Denial of Fuzzing&quot; disclosure. The realistic ten-year trajectory is **not** a Windows rewrite. It is &quot;memory-safe by default for newly written code&quot; plus targeted rewrites of high-blast-radius modules, with the unsafe-FFI boundary as the irreducible audit frontier. This article is a primary-sourced field guide to what actually shipped from BlueHat IL 2019 through Windows 11 24H2 in 2026, what did not, and what the next decade looks like.
&lt;h2&gt;1. The Blue Screen That Wasn&apos;t a Bug&lt;/h2&gt;
&lt;p&gt;On 28 May 2025, Microsoft shipped KB5058499 to patch a kernel bug in Windows 11 24H2 [@kb5058499]. The bug was an out-of-bounds array access in a Rust function called &lt;code&gt;region_from_path_mut()&lt;/code&gt; inside the binary &lt;code&gt;%SystemRoot%\System32\win32kbase_rs.sys&lt;/code&gt; [@cybersecuritynews]. Rust correctly detected the access. Because the detection fired at high IRQL inside a kernel binary compiled with &lt;code&gt;panic = &quot;abort&quot;&lt;/code&gt;, the response was a system-wide blue screen [@checkpoint-dof].&lt;/p&gt;
&lt;p&gt;Read that again. &lt;em&gt;Rust&lt;/em&gt;. In &lt;code&gt;ntoskrnl&lt;/code&gt;&apos;s neighbourhood. In production. Detecting a memory-safety violation. Panicking. Bugchecking the box.&lt;/p&gt;

The class of programming error -- buffer overflow, use-after-free, type confusion, integer overflow, double-free, uninitialised read -- where unsafe memory access leads to undefined behaviour. For two decades the Microsoft Security Response Center has reported that roughly seventy percent of Microsoft&apos;s CVE-assigned vulnerabilities come from this class.

The first Windows kernel binary written in Rust. It contains the Win32k GDI region and shape engine, and after 2025 includes portions of the EMF and EMF+ metafile parsing path. The `_rs` suffix is Microsoft&apos;s internal convention for Rust-implemented kernel binaries. You can verify the file exists on any modern Windows 11 install by checking `%SystemRoot%\System32\win32kbase_rs.sys`.The first public ship was Windows 11 Canary-channel Insider Preview Build 25905 on 12 July 2023. The Windows Insider blog called out the change explicitly: &quot;This preview shipped with an early implementation of critical kernel features in safe Rust&quot; [@insider-25905].
&lt;p&gt;The Check Point Research write-up tells the story tightly [@checkpoint-dof]. A handcrafted Enhanced Metafile Format Plus (EMF+) record -- specifically an &lt;code&gt;EmfPlusDrawBeziers&lt;/code&gt; shape with a mismatched point count -- arrives at the kernel by way of a normal-looking &lt;code&gt;NtGdiSelectClipPath&lt;/code&gt; syscall. The metafile parser hands the malformed point array to &lt;code&gt;region_from_path_mut()&lt;/code&gt;, the Rust function that converts a Bezier path into a clipping region. Indexing into the array, Rust observes the index is out of bounds. Safe Rust&apos;s bounds check fires. &lt;code&gt;core::panicking::panic_bounds_check&lt;/code&gt; runs. And because the binary lives in kernel mode, the panic does not unwind: it aborts [@esecurityplanet]. The bugcheck code is &lt;code&gt;SYSTEM_SERVICE_EXCEPTION&lt;/code&gt; [@cybersecuritynews].&lt;/p&gt;

The Windows kernel&apos;s per-CPU priority level, ranging from PASSIVE_LEVEL up through DIRQL. At IRQL ≥ DISPATCH_LEVEL the scheduler cannot run, paged memory cannot be touched, and almost no recovery path is available. A panic at high IRQL has nowhere to go except the system-wide bugcheck.

The Rust compilation profile setting that converts any runtime panic into an immediate process abort rather than stack unwinding. It is mandatory for `no_std` kernel binaries because there is no unwinder, no `std::panic::catch_unwind`, and no way to clean up locks, allocations, or interrupt state held at the point of panic.
&lt;p&gt;Microsoft classified the issue as a moderate-severity denial of service. The patch tightened the bounds check upstream, kept the Rust panic as the last-resort backstop, and shipped on. There is no CVE-2025 RCE here, no privilege escalation, no infoleak: this Rust panic was the security boundary doing exactly what it was designed to do, and the price was a controlled BSOD rather than a memory-corruption primitive in attacker hands [@checkpoint-dof].&lt;/p&gt;
&lt;p&gt;That single bug carries two non-obvious claims that the rest of the article will unpack. First, this is the largest &lt;em&gt;language-level&lt;/em&gt; memory-safety refit in NT&apos;s roughly thirty-three-year history, distinct in kind from &lt;code&gt;/GS&lt;/code&gt; stack cookies, Address Space Layout Randomization (ASLR), Control Flow Guard (CFG), Hypervisor-protected Code Integrity (HVCI), or Intel Control-flow Enforcement Technology (CET). All of those are mitigations that raise the &lt;em&gt;cost&lt;/em&gt; of exploiting a memory-safety bug. Rust eliminates the bug &lt;em&gt;class&lt;/em&gt; in the modules it covers. That is a different kind of fix.&lt;/p&gt;
&lt;p&gt;Second, the realistic ten-year shape is &quot;memory-safe by default for new code,&quot; not &quot;rewrite Windows.&quot; Microsoft&apos;s distinguished engineer Galen Hunt got in trouble in December 2025 for a LinkedIn post about an internal &quot;1 engineer, 1 month, 1 million lines of code&quot; research target [@register-2025-12-24]. Frank X. Shaw, head of Microsoft&apos;s communications, confirmed within days that the company has no plan to rewrite Windows 11 using AI [@windowslatest-galen; @infoworld-not-rewriting]. The trajectory is policy, not project.&lt;/p&gt;
&lt;p&gt;So: Rust in the Windows kernel. Real binary, real BSOD, real patch, real timeline. &lt;em&gt;How did we get here, and why is a Rust-detected memory-safety violation still a system-wide crash?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;2. The 70-Percent Number and Why Mitigations Plateaued&lt;/h2&gt;
&lt;p&gt;In early February 2019, in Tel Aviv, Matt Miller stood up at BlueHat IL and asked the question that anchored the next seven years of Microsoft&apos;s security strategy. After two decades of Microsoft Security Response Center (MSRC) triage, what fraction of vulnerabilities are still memory-safety bugs? His answer, drawn from a decade of CVE data: about seventy percent [@miller-bluehat-2019; @infoq-mitigating].&lt;/p&gt;
&lt;p&gt;The number was not new in 2019. The MSRC&apos;s own July 2019 essay re-stated it in plain prose: &quot;approximately 70% of the vulnerabilities Microsoft assigns a CVE each year continue to be memory safety issues&quot; [@msrc-proactive-2019]. It had not moved in a decade despite &lt;code&gt;/GS&lt;/code&gt; stack cookies, Data Execution Prevention (DEP), ASLR, CFG, &lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;Hypervisor-protected Code Integrity&lt;/a&gt;, and Intel CET [@msrc-safer-2019]. Mark Russinovich repeated the number at RustConf 2025 in Seattle: &quot;about 70% over the past two decades&quot; [@newstack-russinovich].&lt;/p&gt;
&lt;p&gt;A note on attribution. The originating talk was Miller&apos;s, not David Weston&apos;s. The press cycle following Weston&apos;s 2023 BlueHat IL announcement often credited him with the 70% figure. Weston and Russinovich operationalised it; Miller and the MSRC published it. The deck is in the &lt;code&gt;microsoft/MSRC-Security-Research&lt;/code&gt; repository on GitHub under the &lt;code&gt;2019_02_BlueHatIL&lt;/code&gt; directory; you can read it today [@miller-bluehat-2019].Miller was MSRC&apos;s Partner Security Software Engineer at the time of the talk. He has since moved on, but Microsoft kept the BlueHat IL 2019 deck in the public security-research repo as a primary artefact for the figure.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The 70% figure was roughly the same in 2009 as in 2019. The mitigations stack had absorbed two decades of compiler, OS, and hardware investment without moving the curve. That is why the question shifted from &quot;how do we make exploitation harder&quot; to &quot;how do we eliminate the bug class itself.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To see why the curve stayed flat, walk the supersession history. Each generation of mitigation closed a specific exploitation primitive. None closed a bug class.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/GS&lt;/code&gt; (Visual Studio .NET 2002/2003) inserted a per-function stack canary to detect linear stack-buffer overruns that overwrote a saved return address [@learn-gs]. It defended only the prologue-epilogue window of stack frames. Heap overflows, non-adjacent stack writes, type confusion, and info-leak-then-corrupt all walked around it.&lt;/p&gt;
&lt;p&gt;DEP / NX (Windows XP Service Pack 2, 2004) marked data pages non-executable so attackers could not jump into a buffer they had written [@learn-dep]. Hovav Shacham&apos;s 2007 paper on Return-Oriented Programming showed how to compose Turing-complete payloads from existing executable code without ever introducing a new instruction [@shacham-rop-2007]. DEP raised exploit cost. It did not close the bug class.&lt;/p&gt;
&lt;p&gt;ASLR (Windows Vista, 2006) randomised module, heap, and stack base addresses so attackers could not pre-compute jump targets [@learn-aslr]. The defeat was a single information-disclosure primitive away. Every modern Windows exploit chain begins with an infoleak.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://paragmali.com/blog/control-flow-integrity-on-windows-cfg-xfg-and-the-cet-shadow/&quot; rel=&quot;noopener&quot;&gt;CFG (Windows 8.1, 2014)&lt;/a&gt; restricted indirect calls to a per-binary set of valid call targets [@learn-cfg]. XFG (announced at BlueHat Shanghai 2019, &lt;code&gt;/guard:xfg&lt;/code&gt; compiler support shipped in MSVC in 2020, available in Windows 11 from 2021 as an opt-in compile-time flag, not enabled by default for third-party binaries) tightened that to type-signed indirect call sites [@quarkslab-xfg; @mcgarr-examining-xfg]. CET shadow stack (broadly shipping in Windows 11 in 2021) sealed the return-address half of the same family on hardware that supports it [@msft-cet-shadow]. All three are forms of Control-Flow Integrity, and all three by construction defend the &lt;em&gt;control-flow graph&lt;/em&gt; only.&lt;/p&gt;

The family of compile-time and hardware mitigations -- including CFG, XFG, and CET shadow stack -- that restricts indirect control transfers (jumps, calls, returns) to a per-binary set of valid targets. CFI is, by construction, blind to attacks that corrupt program data without changing the control-flow graph.

A class of exploitation in which an attacker corrupts program *data* without changing the control-flow graph. Hu et al. proved at IEEE Symposium on Security and Privacy 2016 that DOP is Turing-complete -- meaning an attacker who can corrupt the right pieces of data can compute arbitrary functions while the protected program faithfully follows its original control flow [@hu-dop-2016].
&lt;p&gt;That theorem is the structural ceiling. If DOP can express arbitrary computation while the program&apos;s control-flow graph remains unviolated, then no amount of CFI can close the bug class. Every CFI variant could be implemented perfectly tomorrow and the 70% figure would still not move. The MSRC&apos;s July 2019 &quot;We need a safer systems programming language&quot; essay said the quiet part aloud: &quot;no matter the amount of mitigations put in place, it is near impossible to write memory-safe code using traditional systems-level programming languages at scale&quot; [@msrc-safer-2019].&lt;/p&gt;

The MSRC essay -- written by Matt Miller&apos;s team in the same July 2019 cycle as the BlueHat IL talk -- ends with a striking concession: &quot;rather than providing guidance and tools for addressing flaws, we should strive to prevent the developer from introducing the flaws in the first place&quot; [@msrc-safer-2019]. That sentence is the strategic pivot. After two decades of *mitigation* investment, Microsoft publicly accepted that mitigations could not solve the problem alone. The only structural fixes are at the language layer (eliminate the unsafe primitives) or the hardware layer (enforce safety at every dereference). Hu et al.&apos;s DOP theorem was the formal moment &quot;mitigations are necessary but not sufficient&quot; stopped being a slogan and became math.
&lt;p&gt;The supersession trace is compact enough to fit in one table.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;Mitigation&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Closes&lt;/th&gt;
&lt;th&gt;Defeated by&lt;/th&gt;
&lt;th&gt;Residual bug class&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;G1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/GS&lt;/code&gt; stack canary&lt;/td&gt;
&lt;td&gt;2002/2003&lt;/td&gt;
&lt;td&gt;Linear stack overruns past return address&lt;/td&gt;
&lt;td&gt;Heap overflows, non-adjacent writes, infoleaks&lt;/td&gt;
&lt;td&gt;Memory corruption (all classes except narrow stack)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G2&lt;/td&gt;
&lt;td&gt;DEP / NX&lt;/td&gt;
&lt;td&gt;2004&lt;/td&gt;
&lt;td&gt;Code injection into data pages&lt;/td&gt;
&lt;td&gt;ROP (Shacham 2007)&lt;/td&gt;
&lt;td&gt;Memory corruption (control transferred to existing code)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G3&lt;/td&gt;
&lt;td&gt;ASLR&lt;/td&gt;
&lt;td&gt;2006&lt;/td&gt;
&lt;td&gt;Pre-computed gadget addresses&lt;/td&gt;
&lt;td&gt;Information-disclosure primitives&lt;/td&gt;
&lt;td&gt;Memory corruption (after infoleak)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G4&lt;/td&gt;
&lt;td&gt;CFG (default) / XFG (opt-in)&lt;/td&gt;
&lt;td&gt;2014 / 2021&lt;/td&gt;
&lt;td&gt;Arbitrary indirect call targets&lt;/td&gt;
&lt;td&gt;Data-oriented programming (Hu 2016)&lt;/td&gt;
&lt;td&gt;Data-only memory corruption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G4&lt;/td&gt;
&lt;td&gt;CET shadow stack&lt;/td&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;Return-address rewrites&lt;/td&gt;
&lt;td&gt;DOP, non-return CFI bypass&lt;/td&gt;
&lt;td&gt;Data-only memory corruption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G5&lt;/td&gt;
&lt;td&gt;HVCI, Driver Verifier, WDAC&lt;/td&gt;
&lt;td&gt;2015+&lt;/td&gt;
&lt;td&gt;Unsigned/unverified driver code&lt;/td&gt;
&lt;td&gt;Memory corruption in signed drivers&lt;/td&gt;
&lt;td&gt;Memory corruption in trusted code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G6&lt;/td&gt;
&lt;td&gt;Rust in the Windows kernel&lt;/td&gt;
&lt;td&gt;2023+&lt;/td&gt;
&lt;td&gt;The bug class itself, in covered modules&lt;/td&gt;
&lt;td&gt;Bugs in &lt;code&gt;unsafe&lt;/code&gt; blocks; panic-as-BSOD&lt;/td&gt;
&lt;td&gt;Logic bugs, FFI invariant violations, DoS via panic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The cross-vendor data agrees. Chromium&apos;s own engineering reports peg roughly 70% of high-severity browser bugs as memory safety. Google&apos;s Android security team published in September 2024 that memory-safety vulnerabilities in Android dropped from 76% of total in 2019 to 24% in 2024 -- not by rewriting existing C and C++, but by writing &lt;em&gt;new&lt;/em&gt; code in Rust [@google-android-2024]. The structural fix shows up in the data when it ships.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Mitigations bound the &lt;em&gt;cost&lt;/em&gt; of exploitation. Only a memory-safe language or capability hardware bounds the &lt;em&gt;size of the bug class itself&lt;/em&gt;. After two decades, the 70% figure had not moved. The structural answer was no longer optional.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the structural fix had to come from the language layer, why did Microsoft choose Rust -- and not the safer-systems-language it had been researching since 2006?&lt;/p&gt;

flowchart LR
  GS[&quot;/GS stack cookie&lt;br /&gt;2002 / 2003&quot;] --&amp;gt; DEP[&quot;DEP / NX&lt;br /&gt;2004&quot;]
  DEP --&amp;gt; ASLR[&quot;ASLR&lt;br /&gt;2006&quot;]
  ASLR --&amp;gt; CFG[&quot;CFG / XFG&lt;br /&gt;2014 / 2021&quot;]
  CFG --&amp;gt; CET[&quot;CET shadow stack&lt;br /&gt;2021&quot;]
  CFG --&amp;gt; HVCI[&quot;HVCI + WDAC&lt;br /&gt;2015+&quot;]
  CET --&amp;gt; Rust[&quot;win32kbase_rs.sys&lt;br /&gt;Rust in kernel&lt;br /&gt;2023&quot;]
  HVCI --&amp;gt; Rust
  ASLR -.-&amp;gt;|&quot;defeated by infoleaks&quot;| Bypass1[&quot;arbitrary primitives&quot;]
  CFG -.-&amp;gt;|&quot;defeated by DOP, Hu 2016&quot;| Bypass2[&quot;data-only attacks&quot;]
  Rust ==&amp;gt;|&quot;closes the bug class&lt;br /&gt;in covered modules&quot;| Win[&quot;memory-safe by default&lt;br /&gt;for new code&quot;]
&lt;h2&gt;3. Verona, windows-rs, and the Long Approach&lt;/h2&gt;
&lt;p&gt;Microsoft&apos;s first publicly-named safer-systems-language experiment was not Rust. It was Singularity, the Microsoft Research operating system Galen Hunt and Jim Larus described in &lt;em&gt;ACM SIGOPS Operating Systems Review&lt;/em&gt; in April 2007 [@singularity]. Singularity was built in Sing#, a dialect of C# extended with software-isolated processes, contract-based channels, and manifest-based programs that the OS verified at install time. The idea was the same as Rust&apos;s: prove memory safety at the language level so the runtime cost of process isolation becomes negligible. Singularity worked. It also stayed in the lab.&lt;/p&gt;
&lt;p&gt;A decade later, in 2019, Microsoft Research open-sourced &lt;em&gt;Project Verona&lt;/em&gt; at &lt;code&gt;github.com/microsoft/verona&lt;/code&gt;, a collaboration with Imperial College London and Uppsala University [@verona-github; @verona-msr]. Verona explores &lt;em&gt;concurrent ownership&lt;/em&gt; in regions: where Rust&apos;s borrow checker tracks one owner per object, Verona lets multiple objects share a single region-level ownership lifetime, simplifying some concurrent patterns at the cost of additional runtime structure.Verona&apos;s region-based concurrent ownership lets multiple objects share a single ownership lifetime. The academic publications appear at OOPSLA and PLDI. The repository README is explicit that the project is &quot;not ready to be used outside of research.&quot; Verona remains alive as research. It has not been productised.&lt;/p&gt;
&lt;p&gt;So why did Rust win against two memory-safe languages of Microsoft&apos;s own design?&lt;/p&gt;
&lt;p&gt;The answer is &lt;em&gt;adoption&lt;/em&gt;. Singularity and Verona were technically interesting; the community around them was Microsoft Research. Rust came with crates.io, a stable compiler, a community of working programmers, a foreign-function-interface story, and -- as of January 2020 -- official Microsoft-maintained bindings. Microsoft Research kept its own safe-systems-language line for the questions Rust does not answer, and Microsoft the platform vendor met developers where they already were.&lt;/p&gt;
&lt;p&gt;The pivot to Rust shows up in three threads.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread A -- the user-mode bindings.&lt;/strong&gt; In January 2020, Microsoft published &lt;code&gt;microsoft/windows-rs&lt;/code&gt; on GitHub, a set of idiomatic Rust bindings to the entire Win32, Windows Runtime, and Component Object Model surface generated on the fly from Windows-metadata projections. The README is exact: &quot;the windows and windows-sys crates let you call any Windows API past, present, and future using code generated on the fly directly from the metadata describing the API&quot; [@windows-rs-github]. The crate is strictly user-mode. The kernel bindings come later, in a different repository.The premise paragraph that originally framed this article conflated &lt;code&gt;windows-rs&lt;/code&gt; with the kernel bindings. They are different repositories: &lt;code&gt;microsoft/windows-rs&lt;/code&gt; is user-mode (Win32, WinRT, COM); &lt;code&gt;microsoft/windows-drivers-rs&lt;/code&gt; is the kernel and driver bindings. We will look at the latter in section 4.3.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread B -- the institutional commitment.&lt;/strong&gt; On 8 February 2021, Microsoft joined the Rust Foundation as a founding (Platinum) member, and announced it was forming an in-house Rust team to contribute compiler and tooling work [@msft-rust-foundation]. The same year, Microsoft began funding Ralf Jung&apos;s verification line at the Max Planck Institute for Software Systems -- the MIRI interpreter, the RustBelt proofs -- both of which give the formal teeth that distinguish &quot;Rust is safer&quot; from &quot;Rust is provably safe in a specific sense.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread C -- the academic foundation.&lt;/strong&gt; In April 2021, Jung, Jourdan, Krebbers, and Dreyer published &quot;Safe Systems Programming in Rust&quot; in &lt;em&gt;Communications of the ACM&lt;/em&gt; [@cacm-jung-2021]. The paper builds on their RustBelt result at POPL 2018, which constructed the first formal, machine-checked safety proof for a realistic subset of Rust [@rustbelt-popl-2018; @rustbelt-popl-page]. The RustBelt theorem has a property no informal language design has: it is &lt;em&gt;extensible&lt;/em&gt;. The project page states the result precisely: &quot;for each new Rust library that uses unsafe features, we can say what verification condition it must satisfy&quot; [@rustbelt-popl-page]. In plain language: safe Rust is type-sound by construction, and every &lt;code&gt;unsafe&lt;/code&gt; block can be discharged separately by a per-library proof obligation.&lt;/p&gt;
&lt;p&gt;That property -- a discharged proof obligation per &lt;code&gt;unsafe&lt;/code&gt; block -- is the engineering hook that makes Rust-in-kernel tractable. The kernel is full of &lt;code&gt;unsafe&lt;/code&gt;. There is no way around that fact; the kernel &lt;em&gt;is&lt;/em&gt; the trusted base, the layer that touches raw pointers and hardware. But if every &lt;code&gt;unsafe&lt;/code&gt; block has a local, statable proof obligation, then the engineering question shrinks from &quot;is the language safe?&quot; to &quot;is the audit of these specific blocks correct?&quot; That is a question reviewers can answer.&lt;/p&gt;

Singularity / Sing# and Verona are not the only Microsoft-adjacent safer-systems-language threads. The Cyclone project (AT&amp;amp;T / Cornell, mid-2000s) added region-based memory management to C; the Spec# / Code Contracts line (Microsoft Research, late 2000s) attached pre- and post-conditions to .NET methods. All three were technically attractive. None achieved industrial-scale adoption. The lesson Microsoft drew from those efforts -- visible in the windows-rs investment -- is that the surrounding toolchain and community trump language design. Rust came with crates.io and a working community; the Microsoft Research languages did not.
&lt;p&gt;By early 2023 the four ingredients were in place: a user-mode-scale Rust footprint at Microsoft, executive commitment via the Foundation, a verification story with RustBelt-grade formal teeth, and a working &lt;code&gt;windows-rs&lt;/code&gt; for the user-mode call sites. The pieces existed.&lt;/p&gt;
&lt;p&gt;What did it take to put Rust inside the kernel itself?&lt;/p&gt;
&lt;h2&gt;4. Three Generations of Microsoft&apos;s Rust-in-Windows Effort&lt;/h2&gt;
&lt;p&gt;The 2019-to-2026 story falls naturally into three generations. Each one solves the problem the previous one identified.&lt;/p&gt;

flowchart TD
  subgraph G1[&quot;Generation 1 -- 2019 to early 2023: Prerequisites&quot;]
    A1[&quot;Miller BlueHat IL 2019&lt;br /&gt;(70 percent figure)&quot;]
    A2[&quot;MSRC safer-systems essay&lt;br /&gt;(July 2019)&quot;]
    A3[&quot;windows-rs&lt;br /&gt;(January 2020)&quot;]
    A4[&quot;Rust Foundation founding&lt;br /&gt;(February 2021)&quot;]
    A5[&quot;Secure Future Initiative&lt;br /&gt;(November 2023)&quot;]
  end
  subgraph G2[&quot;Generation 2 -- March to July 2023: First ship&quot;]
    B1[&quot;Weston BlueHat IL 2023&lt;br /&gt;(March 29 to 30)&quot;]
    B2[&quot;DWriteCore in user-mode Rust&lt;br /&gt;(152K LOC)&quot;]
    B3[&quot;win32kbase_rs.sys in kernel Rust&lt;br /&gt;(36K LOC, behind flag)&quot;]
    B4[&quot;Insider Build 25905&lt;br /&gt;(July 12, 2023)&quot;]
  end
  subgraph G3[&quot;Generation 3 -- 2024 to 2026: Expansion and toolchain&quot;]
    C1[&quot;windows-drivers-rs public&lt;br /&gt;(2024)&quot;]
    C2[&quot;EMF parser in win32kbase_rs&lt;br /&gt;(by May 2025)&quot;]
    C3[&quot;Surface Rust drivers ship&lt;br /&gt;(July 2025)&quot;]
    C4[&quot;Russinovich RustConf 2025&lt;br /&gt;(September 2 to 5, Seattle)&quot;]
    C5[&quot;cargo-wdk on crates.io&lt;br /&gt;(November 2025)&quot;]
  end
  G1 --&amp;gt; G2
  G2 --&amp;gt; G3
&lt;h3&gt;4.1 Generation 1 (2019 to early 2023): the prerequisites&lt;/h3&gt;
&lt;p&gt;Generation 1 was &lt;em&gt;preparation&lt;/em&gt;. Four things had to land before Rust could ship in the kernel itself: Microsoft running Rust at user-mode scale internally; a working &lt;code&gt;no_std&lt;/code&gt; kernel target (the Rust compilation profile that strips the standard library&apos;s OS-services assumptions so a binary can run in kernel context); a verification story credible enough for executive sign-off; and that sign-off itself.&lt;/p&gt;
&lt;p&gt;The chronology is clean. January 2020: &lt;code&gt;windows-rs&lt;/code&gt; ships [@windows-rs-github]. February 2021: Microsoft joins the Rust Foundation as a founding member [@msft-rust-foundation]. 2019 through 2022: Project Verona and Singularity supply the academic foundations and the in-house safer-systems-language credibility [@verona-github; @singularity]. April 2021: the Jung et al. &lt;em&gt;Safe Systems Programming in Rust&lt;/em&gt; paper in &lt;em&gt;CACM&lt;/em&gt; gives the public-facing formal warrant [@cacm-jung-2021]. November 2, 2023: Brad Smith and Charlie Bell launch the Secure Future Initiative (SFI), a company-wide commitment that explicitly names memory-safety-language adoption as a software-engineering pillar [@sfi-onissues; @sfi-secblog]. The March 6, 2024 update on SFI confirms the engineering follow-through after the Storm-0558 and Midnight Blizzard incidents [@sfi-march24].&lt;/p&gt;
&lt;p&gt;The limitation of Generation 1 is in the name. &lt;em&gt;Prerequisites.&lt;/em&gt; No Rust had shipped &lt;em&gt;in&lt;/em&gt; the Windows kernel yet. DWriteCore was in user mode. windows-rs was in user mode. Verona was research. The next generation had to fire the actual gun.&lt;/p&gt;
&lt;h3&gt;4.2 Generation 2 (March to July 2023): the first ship&lt;/h3&gt;
&lt;p&gt;On 29 and 30 March 2023 in Tel Aviv, David &quot;dwizzle&quot; Weston, then Vice President of Enterprise and OS Security at Microsoft, took the BlueHat IL stage and announced two distinct Rust ports.BlueHat IL 2023 was held in Tel Aviv on 29 to 30 March 2023; the dominant English-language press coverage broke same-day on 27 April 2023 when an embargo lifted. The article uses 27 April 2023 throughout when the date in question is the public record rather than the talk itself. The Register&apos;s same-day write-up has the canonical quote set and used Weston&apos;s earlier &quot;Director&quot; title [@register-2023-04-27]. The article keeps the two ports strictly separate because conflating them is the most common error in the secondary coverage.&lt;/p&gt;
&lt;p&gt;The first port was &lt;em&gt;DWriteCore&lt;/em&gt;, the text-rendering and shaping engine that ships through the Windows App SDK. The Register&apos;s same-day coverage carried the line-of-code and performance numbers from Weston&apos;s deck -- we return to the exact counts in §6.2 -- but the load-bearing point at BlueHat IL 2023 was that DWriteCore is strictly user-mode code, not in the kernel [@register-2023-04-27].&lt;/p&gt;
&lt;p&gt;The second port was the one that the article you are reading is mostly about: &lt;strong&gt;&lt;code&gt;win32kbase_rs.sys&lt;/code&gt;&lt;/strong&gt;, a kernel binary containing the Win32k GDI region and shape engine -- about 36,000 lines of Rust, behind a feature flag, with at least one syscall in the Windows kernel implemented in Rust [@register-2023-04-27]. Weston&apos;s verbatim line is the moment that mattered.&lt;/p&gt;

There&apos;s actually a SysCall in the Windows kernel now that is implemented in Rust. -- David Weston, BlueHat IL 2023 [@register-2023-04-27].
&lt;p&gt;The first reader-verifiable artefact of that ship came on 12 July 2023. Windows 11 Canary-channel Insider Preview Build 25905 dropped, and the Windows Insider blog called out the change: &quot;Rust in the Windows Kernel ... win32kbase_rs.sys contains a new implementation of GDI region&quot; [@insider-25905]. From that moment forward, any reader with a recent Windows 11 Insider build could open Explorer at &lt;code&gt;C:\Windows\System32&lt;/code&gt;, sort by name, and find &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; on disk. Generation 2 was a proof of existence. The binary was real. The syscall path it implemented was real. Some pieces ran behind a feature flag, but the cement had set.&lt;/p&gt;
&lt;p&gt;The limitation of Generation 2 was that the toolchain was Microsoft-internal. External driver authors could not reproduce the build pipeline; the &lt;code&gt;no_std&lt;/code&gt; kernel target had not been upstreamed to &lt;code&gt;rust-lang/rust&lt;/code&gt;; the allocator shim that adapted &lt;code&gt;GlobalAlloc&lt;/code&gt; onto &lt;code&gt;ExAllocatePool2&lt;/code&gt; lived in a private repository. Generation 3 had to address the third-party adoption question.&lt;/p&gt;
&lt;h3&gt;4.3 Generation 3 (2024 to mid-2026): expansion and toolchain rollout&lt;/h3&gt;
&lt;p&gt;Generation 3 has four threads running in parallel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread 1: the public driver-development crate suite.&lt;/strong&gt; Microsoft published &lt;code&gt;microsoft/windows-drivers-rs&lt;/code&gt; -- the public repository of Rust crates for Windows driver development [@windows-drivers-rs; @heise-rust]. The repository contains six crates (&lt;code&gt;wdk&lt;/code&gt;, &lt;code&gt;wdk-sys&lt;/code&gt;, &lt;code&gt;wdk-alloc&lt;/code&gt;, &lt;code&gt;wdk-build&lt;/code&gt;, &lt;code&gt;wdk-panic&lt;/code&gt;, &lt;code&gt;wdk-macros&lt;/code&gt;) plus the &lt;code&gt;cargo-wdk&lt;/code&gt; Cargo subcommand that wraps &lt;code&gt;link.exe&lt;/code&gt;, &lt;code&gt;inf2cat&lt;/code&gt;, &lt;code&gt;signtool&lt;/code&gt;, and friends into a coherent Rust build. A companion sample repository &lt;code&gt;microsoft/Windows-rust-driver-samples&lt;/code&gt; provides Rust ports of the canonical Windows Driver Samples [@windows-rust-samples]. The README of &lt;code&gt;windows-drivers-rs&lt;/code&gt; is candid: the project is &quot;still in early stages of development and is not yet recommended for production use&quot; [@windows-drivers-rs]. It also pins LLVM 17 explicitly, because LLVM 18 introduced an ARM64 bindgen bug that breaks WDK header binding generation [@windows-drivers-rs].The &lt;code&gt;windows-drivers-rs&lt;/code&gt; README specifically pins LLVM 17 because LLVM 18 has a bug that causes bindings to fail to generate for ARM64. The fix is expected in LLVM 19. This is the kind of detail that distinguishes a developer-preview toolchain from a production one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread 2: the 2025 in-kernel Rust expansion.&lt;/strong&gt; Between the 2023 ship and the May 2025 Check Point disclosure, the Rust footprint inside &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; grew. The growth surface that became publicly known is the Enhanced Metafile Format (EMF / EMF+) parsing path -- the code that converts a path of Bezier curves into a clipping region [@checkpoint-dof; @cybersecuritynews]. The Check Point disclosure documents &lt;code&gt;region_from_path_mut()&lt;/code&gt; as Rust; the KB5058499 patch hardened the call site upstream of the Rust panic [@kb5058499; @esecurityplanet].The original article-focus paragraph speculated that the 2025 in-kernel expansion was the Win32k DirectDraw stack. No first-party Microsoft material identifies a DirectDraw Rust port. The publicly documented 2025 expansion is in the EMF / EMF+ metafile parser inside &lt;code&gt;win32kbase_rs.sys&lt;/code&gt;. We follow the public record.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread 3: the first in-box Rust drivers.&lt;/strong&gt; In July 2025, Microsoft&apos;s Surface team confirmed that several new Copilot+ Surface PCs ship with drivers written in Rust [@winbuzzer-surface; @thurrott-rust]. Microsoft&apos;s Melvin Wang wrote on the Windows Driver Development blog that &quot;the Surface team has contributed further to the open-source &lt;code&gt;windows-drivers-rs&lt;/code&gt; repository for driver development and shipped Surface drivers written in Rust&quot; [@thurrott-rust]. By September 2025, &lt;em&gt;The Register&lt;/em&gt; reported that no production third-party Rust driver had yet shipped through Windows Hardware Compatibility Program (WHCP) certification: CodeQL supports Rust in public preview at version 2.22.1, but only version 2.21.4 is &quot;validated for use with WHCP&quot; [@register-2025-09-04]. The certification path is being assembled in public.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread 4: the executive narrative.&lt;/strong&gt; On 2 to 5 September 2025, Mark Russinovich -- Azure CTO, Deputy CISO, and Technical Fellow -- delivered the RustConf 2025 keynote in Seattle, titled &quot;From Blue Screens to Orange Crabs: Microsoft&apos;s Rusty Revolution&quot; [@rustconf-2025-prog; @newstack-russinovich; @itpro-rust]. The keynote made three claims that matter for this article. First, Rust is &quot;mandated for new Azure components that handle untrusted input.&quot; Second, Microsoft is using Rust across &quot;kernel components, a cryptography library (&lt;code&gt;rustls-symcrypt&lt;/code&gt;), and ancillary components (&lt;code&gt;DirectWrite&lt;/code&gt;)&quot; plus Project Mu firmware, &lt;a href=&quot;https://paragmali.com/blog/pluton-a-tpm-on-silicon-microsoft-can-patch/&quot; rel=&quot;noopener&quot;&gt;Caliptra&lt;/a&gt;, the Azure Integrated HSM, OpenVMM, and Hyperlight [@infoq-russinovich]. Third, the Check Point bug is success, not failure: a Rust panic that crashes the box is operationally better than a memory-corruption primitive that escalates privilege [@newstack-russinovich].The InfoQ piece that covers Russinovich&apos;s named-project list is dated May 2025 and is actually about his Rust Nation UK talk earlier that year, not RustConf 2025. The substantive content overlaps, but the venue is not the same. For RustConf 2025 itself, the primary references are the Rust Foundation program page and The New Stack&apos;s same-week summary [@rustconf-2025-prog; @newstack-russinovich].&lt;/p&gt;
&lt;p&gt;One more thread to acknowledge: on 24 December 2025, a LinkedIn post by Microsoft distinguished engineer Galen Hunt triggered a press cycle around an internal &quot;1 engineer, 1 month, 1 million lines of code&quot; research target [@register-2025-12-24]. The picture was corrected within days by Hunt&apos;s own clarification and Frank X. Shaw&apos;s denial that Microsoft has any plan to rewrite Windows 11 using AI [@infoworld-not-rewriting; @windowslatest-galen]. The §9 Aside walks the story in full.&lt;/p&gt;
&lt;p&gt;Three generations in, the toolchain is public, the binaries ship, the executive commitment is on the record, the certification path is being assembled, and the press has been corrected twice on the difference between research and roadmap. The pieces are in place. What is the &lt;em&gt;insight&lt;/em&gt; that makes Rust-in-kernel tractable as an engineering policy?&lt;/p&gt;
&lt;h2&gt;5. Memory-Safe by Default for New Code + the Unsafe-FFI Boundary&lt;/h2&gt;
&lt;p&gt;The structural insight that emerged from Generations 2 and 3 is one Russinovich named explicitly at RustConf 2025: Rust adoption inside an existing C / C++ kernel of roughly thirty million lines -- a widely-cited engineering estimate; Microsoft has not published an exact figure -- is a &lt;em&gt;policy decision&lt;/em&gt;, not a rewrite project [@newstack-russinovich]. The policy has two clauses. For &lt;em&gt;new&lt;/em&gt; code, default to Rust. For existing code, rewrite the high-blast-radius surfaces -- the GDI region engine, the EMF parser -- but not the rest. Russinovich&apos;s framing at the keynote: Rust is &quot;mandated for new Azure components that handle untrusted input&quot; [@infoq-russinovich].&lt;/p&gt;
&lt;p&gt;The new-code policy is empirically validated. The Android security team&apos;s September 2024 publication tracks the share of memory-safety vulnerabilities in Android over five years [@google-android-2024]. The headline curve looks like this.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Memory-safety share of vulnerabilities&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;~76%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;~24%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The drop did not come from rewriting existing C and C++. It came from writing &lt;em&gt;new&lt;/em&gt; code in Rust while letting the older code stop being modified. Vulnerabilities in any specific code module decay exponentially as that module stops changing, because (a) bugs that were going to be discovered get patched, and (b) new bugs are introduced primarily by new code [@google-android-2024]. Stop adding C, and the long-run share of memory-safety CVEs falls without anybody rewriting anything. That is the empirical anchor for the &quot;memory-safe by default for new code&quot; policy.&lt;/p&gt;
&lt;p&gt;The policy alone is not enough. The &lt;em&gt;mechanism&lt;/em&gt; that makes it executable is the unsafe-FFI boundary: a narrow, typed, auditable seam where safe Rust meets the C kernel it has to talk to.&lt;/p&gt;

A Rust crate attribute (`#![no_std]`) that opts out of linking the Rust standard library. The crate keeps `core` (and optionally `alloc`), and gets nothing else for free. Required for kernel binaries because the standard library assumes OS services -- file descriptors, threads, dynamic memory through libc -- that the kernel itself is in the business of providing.

The Rust standard-library trait that defines the global memory allocator. In kernel Rust, the trait is implemented by `wdk-alloc` to call `ExAllocatePool2` (allocate) and `ExFreePoolWithTag` (free) -- the NT pool allocator entry points that drivers have used since the late 1990s.

The mechanism a programming language uses to call functions written in another language across an Application Binary Interface (ABI). In kernel Rust, FFI to C kernel headers is generated mechanically by `bindgen` from WDK headers; every call site that crosses the boundary is wrapped in `unsafe`.

A region of Rust code where the compiler relaxes its safety invariants and the programmer accepts responsibility for upholding them. Inside `unsafe`, raw pointers may be dereferenced, mutable static state may be touched, and FFI calls may be made. The safety guarantee of any Rust system is exactly as strong as the human audit of these blocks.
&lt;p&gt;Every Rust kernel module has three &lt;code&gt;unsafe&lt;/code&gt; layers, and the audit of those three layers &lt;em&gt;is&lt;/em&gt; the safety story.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 1: the allocator shim.&lt;/strong&gt; The kernel has no malloc. It has &lt;code&gt;ExAllocatePool2&lt;/code&gt;, which takes a pool type, a size, and a four-character tag, and returns memory from one of the NT pool managers. Rust&apos;s &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, and &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt; all expect a &lt;code&gt;GlobalAlloc&lt;/code&gt; implementation underneath. &lt;code&gt;wdk-alloc&lt;/code&gt; is the bridge: it implements &lt;code&gt;GlobalAlloc&lt;/code&gt; over &lt;code&gt;ExAllocatePool2&lt;/code&gt; / &lt;code&gt;ExFreePoolWithTag&lt;/code&gt;, with &lt;code&gt;unsafe&lt;/code&gt; blocks at every FFI call [@windows-drivers-rs]. If the allocator shim is wrong -- if it forgets to zero memory, mismatches a tag, or returns a misaligned pointer -- every safe Rust collection above it is suddenly &lt;em&gt;not&lt;/em&gt; safe.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 2: the FFI surface.&lt;/strong&gt; Bindgen generates &lt;code&gt;extern &quot;system&quot;&lt;/code&gt; declarations from the WDK headers, turning each C function signature into a Rust prototype with &lt;code&gt;unsafe&lt;/code&gt; semantics [@windows-drivers-rs]. Every cross-language call is an &lt;code&gt;unsafe&lt;/code&gt; block in the Rust caller. The audit obligation here is: did bindgen translate the C signature faithfully? Is the calling convention right? Are pointer ownership and lifetime invariants in the C function&apos;s documentation actually upheld in the Rust caller? Bindgen is mechanical; the audit is not.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 3: the pointer-arithmetic wrappers.&lt;/strong&gt; Where Rust must observe raw C structs -- &lt;code&gt;IRP&lt;/code&gt;, &lt;code&gt;KAPC&lt;/code&gt;, &lt;code&gt;FAST_IO_DISPATCH&lt;/code&gt;, and the various &lt;code&gt;Win32k&lt;/code&gt;-internal layouts -- the boundary code wraps each struct in a typed Rust newtype that asserts the invariants the C code expects, before any non-&lt;code&gt;unsafe&lt;/code&gt; Rust code touches it. A common pattern is the &lt;code&gt;RegionImpl&amp;lt;&apos;a&amp;gt;&lt;/code&gt; family of wrappers: a Rust struct that holds a raw pointer plus a lifetime parameter, with all public methods written in safe Rust and a small number of private &lt;code&gt;unsafe&lt;/code&gt; methods that do the actual dereferencing.&lt;/p&gt;

flowchart TD
  subgraph Safe[&quot;Safe Rust&quot;]
    SR[&quot;Rust kernel module&lt;br /&gt;(safe code, ~90% of LOC)&quot;]
  end
  subgraph Unsafe[&quot;Three unsafe layers&quot;]
    U1[&quot;Allocator shim&lt;br /&gt;wdk-alloc on ExAllocatePool2&quot;]
    U2[&quot;FFI surface&lt;br /&gt;bindgen extern system decls&quot;]
    U3[&quot;Pointer-arithmetic wrappers&lt;br /&gt;IRP, KAPC, FAST_IO_DISPATCH&quot;]
  end
  subgraph C[&quot;C kernel&quot;]
    NT[&quot;ntoskrnl, win32k, hal&quot;]
  end
  SR --&amp;gt; U1
  SR --&amp;gt; U2
  SR --&amp;gt; U3
  U1 --&amp;gt; NT
  U2 --&amp;gt; NT
  U3 --&amp;gt; NT
&lt;p&gt;The picture is small. A typical Rust kernel module has a few hundred FFI call sites, all typed, all auditable, with the conventional Rust community discipline that every &lt;code&gt;unsafe&lt;/code&gt; block carries a &lt;code&gt;SAFETY:&lt;/code&gt; comment justifying the invariants the human author claims to uphold.The Rust community convention is that every &lt;code&gt;unsafe&lt;/code&gt; block carries a &lt;code&gt;SAFETY:&lt;/code&gt; comment justifying the invariants the human author guarantees. Microsoft&apos;s internal review guidance reinforces this for kernel code, and the &lt;code&gt;windows-drivers-rs&lt;/code&gt; samples follow the pattern consistently. The safety guarantee of the whole module is exactly as strong as the audit of those few hundred sites. Not magic. Not a free lunch. A finite, reviewable boundary.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;windows-drivers-rs&lt;/code&gt; README acknowledges this without euphemism. Microsoft&apos;s Nate Deisinger captured the position in the November 2025 Windows Driver Development blog post:&lt;/p&gt;

Drivers using these crates still need to make use of unsafe blocks for interacting with the Windows operating system, removing some of the benefits of Rust. -- Nate Deisinger, *Towards Rust in Windows Drivers* [@techcommunity-rust-drivers].
&lt;p&gt;That is the load-bearing acknowledgement. Rust does not magically make the C kernel disappear. It pushes the audit frontier &lt;em&gt;to a narrow, typed, fuzz-able boundary&lt;/em&gt;. The wins compound there: type checking catches whole bug families before they ever reach review, fuzzing concentrates on a few hundred sites rather than a million, and the rest of the Rust code -- the other 90% -- gets the full benefit of the safety guarantee with no per-call-site audit burden.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Rust in the Windows kernel is not magic. It is a finite, typed, fuzzable, reviewable boundary between safe Rust and &lt;code&gt;unsafe&lt;/code&gt; C interop. The safety guarantee of any module is exactly as strong as the audit of that boundary -- which is exactly what makes it engineering policy rather than a wishful slogan.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is the strategy in the abstract. What does it actually look like on disk in Windows 11 24H2 in May 2026?&lt;/p&gt;
&lt;h2&gt;6. What Actually Ships in Windows 11 24H2 in 2026&lt;/h2&gt;
&lt;p&gt;This section is an inventory of artefacts you can verify yourself: files on disk, GitHub repositories, KB articles, conference keynotes. Six subsections, each with receipts.&lt;/p&gt;
&lt;h3&gt;6.1 &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; -- the in-kernel GDI region and shape engine&lt;/h3&gt;
&lt;p&gt;File location: &lt;code&gt;%SystemRoot%\System32\win32kbase_rs.sys&lt;/code&gt;. Reader-verifiable on any Windows 11 24H2 install. This is the binary the article opened on.&lt;/p&gt;
&lt;p&gt;Original scope at the April 2023 announcement: the Win32k GDI region and shape engine, about 36,000 lines of Rust, behind a feature flag, with at least one syscall in the Windows kernel implemented in Rust [@register-2023-04-27]. By July 2023 the binary was visible in Canary Insider Preview Build 25905 with the GDI region implementation called out by name in the Windows Insider blog [@insider-25905].&lt;/p&gt;
&lt;p&gt;The 2025 expansion surface is the Enhanced Metafile Format / EMF+ metafile-parsing path. The Check Point Research disclosure -- whose call flow §1 walks through in prose and the diagram below replays -- documents the bug; KB5058499, dated 28 May 2025, hardens the bounds check upstream and ships as a preview update for OS Build 26100.4202 [@checkpoint-dof; @kb5058499].&lt;/p&gt;

sequenceDiagram
  participant App as Untrusted process
  participant K as Win32k C dispatcher
  participant R as win32kbase_rs.sys (Rust)
  participant Panic as core::panicking
  App-&amp;gt;&amp;gt;K: NtGdiSelectClipPath (malformed EMF+ metafile)
  K-&amp;gt;&amp;gt;R: parse EmfPlusDrawBeziers record
  R-&amp;gt;&amp;gt;R: build path with mismatched point count
  R-&amp;gt;&amp;gt;R: region_from_path_mut() indexes out of bounds
  R-&amp;gt;&amp;gt;Panic: panic_bounds_check (safe Rust detects OOB)
  Panic-&amp;gt;&amp;gt;Panic: panic = abort (no unwinder in no_std)
  Panic--&amp;gt;&amp;gt;K: bugcheck SYSTEM_SERVICE_EXCEPTION
  K--&amp;gt;&amp;gt;App: machine bluescreens (DoS, not RCE)
  Note over R,K: Microsoft fixed in KB5058499 on May 28, 2025
&lt;p&gt;The article does not claim a 2026 line-of-code figure for &lt;code&gt;win32kbase_rs.sys&lt;/code&gt;. The most recent first-party number is the April 2023 ~36,000 figure quoted to The Register; no first-party Microsoft source has published a refresh. Open Problem P1 in section 9 keeps that an honest open question.Earlier drafts of articles like this one have asserted &quot;over 100,000 lines of in-kernel Rust by 2026.&quot; That number is not in the primary record. The empirical claim we can make is that the binary exists, the GDI region engine is in Rust, the EMF parser is partly in Rust, and the binary is observably larger and more functional in 2026 than the 2023 ship -- but the actual line count is unpublished.&lt;/p&gt;
&lt;h3&gt;6.2 DWriteCore -- user-mode Rust in the Windows App SDK&lt;/h3&gt;
&lt;p&gt;DWriteCore is the standalone, distributable text-rendering and OpenType-shaping engine that ships through the Windows App SDK. At the April 2023 BlueHat IL announcement Weston quoted about 152,000 lines of Rust plus about 96,000 lines of C++, with a 5 to 15% performance improvement on selected OpenType shaping paths [@register-2023-04-27]. Russinovich at RustConf 2025 framed the team size and timeline: &quot;Two Microsoft developers did it in six months -- 154,000 lines of code&quot; [@newstack-russinovich]. DWriteCore is &lt;em&gt;strictly user mode&lt;/em&gt;. The distribution channel is Windows App SDK 1.2 and above, not Windows 11 22H2/23H2 system updates. It is the user-mode counterpart to the kernel-mode &lt;code&gt;win32kbase_rs.sys&lt;/code&gt;, not the same thing.&lt;/p&gt;
&lt;h3&gt;6.3 The &lt;code&gt;windows-drivers-rs&lt;/code&gt; crate suite&lt;/h3&gt;
&lt;p&gt;The driver-development face of Microsoft&apos;s Rust effort is &lt;code&gt;microsoft/windows-drivers-rs&lt;/code&gt; [@windows-drivers-rs]. The repository contains six crates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wdk&lt;/code&gt; -- safe wrappers over the Windows Driver Kit&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-sys&lt;/code&gt; -- bindgen-generated raw FFI bindings&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-alloc&lt;/code&gt; -- the &lt;code&gt;GlobalAlloc&lt;/code&gt; shim onto &lt;code&gt;ExAllocatePool2&lt;/code&gt; / &lt;code&gt;ExFreePoolWithTag&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-build&lt;/code&gt; -- build script infrastructure for &lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-panic&lt;/code&gt; -- the &lt;code&gt;panic_handler&lt;/code&gt; implementation with &lt;code&gt;panic = &quot;abort&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-macros&lt;/code&gt; -- procedural macros (driver entry-point, IOCTL routing, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;cargo-wdk&lt;/code&gt; subcommand wraps &lt;code&gt;link.exe&lt;/code&gt;, &lt;code&gt;inf2cat&lt;/code&gt;, and &lt;code&gt;signtool&lt;/code&gt; so &lt;code&gt;cargo build&lt;/code&gt; does the right thing in a developer-mode signed driver workflow. November 2025: &lt;code&gt;cargo-wdk&lt;/code&gt; became publishable on crates.io [@techcommunity-rust-drivers]. The companion samples repository &lt;code&gt;microsoft/Windows-rust-driver-samples&lt;/code&gt; provides Rust ports of the canonical Windows Driver Samples for KMDF and UMDF [@windows-rust-samples].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;windows-drivers-rs&lt;/code&gt; README is explicit: &quot;still in early stages of development and is not yet recommended for production use&quot; [@windows-drivers-rs]. Treat the crate suite as a developer-preview toolchain. KMDF 1.33-era bindings are on crates.io; WDM and UMDF are possible with &lt;code&gt;wdk-build&lt;/code&gt; modification. LLVM 17 is pinned because LLVM 18 has an ARM64 bindgen bug.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.4 OpenVMM, OpenHCL, and Hyperlight -- the virtualization-side Rust&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;microsoft/openvmm&lt;/code&gt; is a modular, cross-platform Virtual Machine Monitor written in Rust. The README is candid about scope: OpenVMM &quot;can function as a traditional VMM, [but] OpenVMM&apos;s development is currently focused on its role in the OpenHCL paravisor&quot; [@openvmm-github; @openvmm-guide]. OpenHCL is the Rust paravisor for &lt;a href=&quot;https://paragmali.com/blog/inside-azure-confidential-vms-sev-snp-intel-tdx-and-the-para/&quot; rel=&quot;noopener&quot;&gt;AMD SEV-SNP and Intel TDX confidential virtual machines&lt;/a&gt; -- a guest-side software component that sits between the hardware-isolated VM and the host, mediating the small set of operations that have to round-trip [@phoronix-openhcl]. Hyperlight is Microsoft&apos;s Azure-side micro-VMM for very-low-latency function execution, with cold-start times in the low millisecond range [@newstack-russinovich].&lt;/p&gt;

A common confusion: OpenVMM is *not* the production [Hyper-V VSP (Virtualisation Service Provider) front-end](/blog/hyper-v-enlightenments-vmbus-and-the-synthetic-device-model/) that ships inside Windows 11 24H2. OpenVMM is a separate Rust VMM whose primary production deployment in 2026 is as the OpenHCL paravisor for confidential VMs in Azure [@openvmm-github]. The Rust status of the in-Windows Hyper-V VSP front-end has not been publicly announced; we treat it as Open Problem P6 in section 9.
&lt;h3&gt;6.5 The first in-box Rust drivers (Surface)&lt;/h3&gt;
&lt;p&gt;In July 2025, Microsoft&apos;s Surface team confirmed that several new Copilot+ Surface PCs ship with drivers written in Rust [@winbuzzer-surface; @thurrott-rust]. The drivers are &lt;em&gt;Microsoft-internal&lt;/em&gt; -- shipped under the Surface OEM identity, signed through Microsoft&apos;s own driver-signing keys, exempted from the WHCP path that third parties must traverse. &lt;em&gt;The Register&lt;/em&gt;, reporting in September 2025, summarised the third-party status: &quot;There is also work underway to use Rust in the Windows kernel itself, some of which shipped in Windows 11 24H2&quot; but no production third-party Rust driver has yet shipped under WHCP, because CodeQL&apos;s Rust support is in public preview at version 2.22.1 and the WHCP-validated version is still 2.21.4 [@register-2025-09-04].&lt;/p&gt;
&lt;h3&gt;6.6 The toolchain itself&lt;/h3&gt;
&lt;p&gt;The toolchain is the boring foundation that makes everything above possible. The shape, as of mid-2026:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compiler:&lt;/strong&gt; a recent stable &lt;code&gt;rustc&lt;/code&gt; plus the MSVC linker. No specific minimum version is pinned by the public README; the LLVM dependency through &lt;code&gt;bindgen&lt;/code&gt; is what determines the version floor [@windows-drivers-rs].Earlier coverage has speculated about a &quot;rustc 1.72+&quot; minimum version pin for the Microsoft kernel target. We have not found a first-party Microsoft source that pins this exact number. The README pins LLVM 17 (the bindgen LLVM, not the rustc LLVM) and is silent on the rustc minimum version.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Target:&lt;/strong&gt; a custom &lt;code&gt;no_std&lt;/code&gt; kernel target, not upstreamed to &lt;code&gt;rust-lang/rust&lt;/code&gt;. Third-party reproducibility is therefore limited.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bindings:&lt;/strong&gt; bindgen-generated &lt;code&gt;extern &quot;system&quot;&lt;/code&gt; declarations from WDK headers; LLVM 17 pinned because of the LLVM 18 ARM64 bug.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Allocator:&lt;/strong&gt; &lt;code&gt;wdk-alloc&lt;/code&gt; implementing &lt;code&gt;GlobalAlloc&lt;/code&gt; over &lt;code&gt;ExAllocatePool2&lt;/code&gt; / &lt;code&gt;ExFreePoolWithTag&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Panic handler:&lt;/strong&gt; &lt;code&gt;wdk-panic&lt;/code&gt; with &lt;code&gt;panic = &quot;abort&quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build orchestration:&lt;/strong&gt; &lt;code&gt;cargo-wdk&lt;/code&gt; plus &lt;code&gt;cargo-make&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verification:&lt;/strong&gt; MIRI (where the code is portable enough to interpret), Driver Verifier (always-on inside the kernel test loop), OneFuzz and WinAFL for fuzzing, CodeQL with Rust support in public preview.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Russinovich announced at RustConf 2025 that Microsoft is also working on a &quot;Cargo plugin for MSBuild,&quot; which would let MSBuild-driven internal builds invoke &lt;code&gt;cargo&lt;/code&gt; cleanly [@newstack-russinovich]. Across Microsoft, Rust shows up in many places beyond Windows: SymCrypt-in-Rust, the Project Mu firmware effort, Azure Caliptra, the Azure Integrated HSM, and components of Azure Data Explorer all use Rust today [@infoq-russinovich]. The cross-context Microsoft Rust footprint is much larger than the in-Windows-kernel footprint alone, which gives the kernel effort upstream pressure to keep evolving.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s posture is articulated and shipping. Is this a Microsoft idiosyncrasy or a cross-vendor convergence?&lt;/p&gt;
&lt;h2&gt;7. Linux, Android, Apple, CHERI: The Cross-Vendor Picture&lt;/h2&gt;
&lt;p&gt;Microsoft is not alone. The convergence is industry-wide -- with structurally different details per vendor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rust for Linux.&lt;/strong&gt; Under maintainer Miguel Ojeda, Rust support landed in mainline Linux 6.1 in December 2022 [@rust-for-linux]. The &quot;experimental&quot; label was removed in late 2025. In-tree Rust drivers today include the AMCC QT2025 PHY, Android Binder, the ASIX PHY, DRM Panic QR, the Nova GPU driver (a long-term NVIDIA-replacement effort), Null Block, and the Tyr GPU; out-of-mainline-tree work includes the Apple AGX driver shipping on Asahi Linux, NVMe, and PuzzleFS [@rust-for-linux]. The structural difference from Microsoft&apos;s path is upstream: Linux &lt;em&gt;forbids&lt;/em&gt; bindgen for in-tree drivers. Every Rust binding to a kernel C struct or function must be hand-reviewed and accepted onto LKML. The acceptance criteria are public; the upstream community has been contested -- Wedson Almeida Filho resigned in September 2024 citing non-technical conflicts -- but the project continues under Ojeda and the kernel maintainers&apos; summit has reaffirmed it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Android.&lt;/strong&gt; Google&apos;s September 2024 &quot;Eliminating Memory Safety Vulnerabilities at the Source&quot; post is the empirical anchor for this article&apos;s policy claim [@google-android-2024]. The numbers we summarised in section 5 (76% in 2019 to 24% in 2024) come from this post. The strategy is identical to Microsoft&apos;s: write new code in Rust, leave most existing C and C++ alone, observe the long-run share of memory-safety bugs drop as the old code stops being modified. Android is the proof of concept that the new-code policy works at scale.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Apple.&lt;/strong&gt; No public kernel-Rust commitment. XNU, Darwin, and IOKit remain C, C++, and Swift. The Asahi GPU project -- which lets Apple Silicon Macs boot Linux with full GPU acceleration -- is written in Rust and runs Apple hardware. But that is Rust running on Linux on Apple silicon, not Rust in Apple&apos;s own operating system. As of mid-2026, Apple has not publicly announced a Rust-in-kernel program.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CHERI and CHERIoT.&lt;/strong&gt; The structural alternative to &quot;Rust for new code&quot; is &quot;capability hardware that enforces memory safety on every dereference, including for legacy C and C++.&quot; CHERI is the Cambridge and SRI International project that extends conventional instruction set architectures with capability pointers -- tagged, bounded, monotonic references that the hardware checks at every load and store [@cheri-cambridge]. Arm&apos;s Morello prototype processor, released in January 2022, is the first commercial-class implementation. CHERIoT is Microsoft&apos;s microcontroller adaptation, a CHERI-extended RISC-V profile aimed at embedded and IoT workloads [@cheriot-org]. The CHERIoT RTOS lives at &lt;code&gt;microsoft/cheriot-rtos&lt;/code&gt; [@cheriot-rtos-ms]. Structurally CHERI is different from Rust: it does not require a language rewrite, because the hardware enforces spatial and temporal safety on whatever language emits the pointers. Microsoft maintains both lines in parallel -- Rust for general-purpose Windows code, CHERIoT for embedded silicon -- and the two paths are complementary at the platform level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Project Verona.&lt;/strong&gt; Still alive as Microsoft Research [@verona-github; @verona-msr]. Publications at OOPSLA and PLDI. Not productising. Region-based concurrent ownership answers a different question from Rust&apos;s per-object model. Verona&apos;s value to the kernel-Rust effort was the academic credibility it lent the safer-systems-language thread; as a productisation candidate it remains unpursued.&lt;/p&gt;

flowchart LR
  subgraph Windows
    W1[&quot;win32kbase_rs.sys&lt;br /&gt;Rust GDI/EMF&quot;]
    W2[&quot;windows-drivers-rs&lt;br /&gt;preview&quot;]
    W3[&quot;CHERIoT for IoT&lt;br /&gt;MSR plus partners&quot;]
    W4[&quot;HVCI, CFG, CET&lt;br /&gt;mitigations stack&quot;]
  end
  subgraph Linux
    L1[&quot;Rust for Linux&lt;br /&gt;mainline since 6.1&quot;]
    L2[&quot;Hand-reviewed bindings&lt;br /&gt;no bindgen in-tree&quot;]
  end
  subgraph Android
    A1[&quot;New code in Rust&lt;br /&gt;76 percent to 24 percent&quot;]
    A2[&quot;Existing C / C++&lt;br /&gt;left in place&quot;]
  end
  subgraph Apple
    AP1[&quot;XNU in C and C plus plus&lt;br /&gt;no public Rust commitment&quot;]
    AP2[&quot;Asahi GPU in Rust&lt;br /&gt;on Linux&quot;]
  end
  subgraph Hardware
    H1[&quot;Arm Morello&lt;br /&gt;CHERI prototype 2022&quot;]
    H2[&quot;CHERIoT silicon&quot;]
  end
  W1 --&amp;gt; Common[&quot;memory-safe by default&lt;br /&gt;for new code&lt;br /&gt;plus targeted rewrites&quot;]
  W2 --&amp;gt; Common
  L1 --&amp;gt; Common
  A1 --&amp;gt; Common
  Common --&amp;gt; Defense[&quot;defence in depth&lt;br /&gt;with mitigations stack&lt;br /&gt;plus CHERI hardware where available&quot;]
  W3 --&amp;gt; Defense
  W4 --&amp;gt; Defense
  H1 --&amp;gt; Defense
  H2 --&amp;gt; Defense
&lt;p&gt;The pattern across the table is consistent. Every major operating-system vendor&apos;s safest forward path is some combination of (Rust for new code) + (CHERI-class hardware capabilities where the silicon supports them) + (the existing mitigations stack as defence-in-depth). No vendor is rewriting wholesale. The vendors differ on bindgen-versus-hand-written bindings, on in-tree process discipline, on capability-hardware availability, and on the relative weight of the three threads. They agree on the shape.&lt;/p&gt;
&lt;p&gt;A compact decision matrix may help architects compare the seven approaches that were considered in the source survey.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Closes bug class&lt;/th&gt;
&lt;th&gt;Worst-case crash&lt;/th&gt;
&lt;th&gt;Hardware requirement&lt;/th&gt;
&lt;th&gt;Production in Win 11 24H2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Legacy C/C++ with &lt;code&gt;/GS&lt;/code&gt;, DEP, ASLR, CFG, CET&lt;/td&gt;
&lt;td&gt;No (raises cost)&lt;/td&gt;
&lt;td&gt;Memory corruption to exploitation&lt;/td&gt;
&lt;td&gt;None (CET on Tiger Lake+)&lt;/td&gt;
&lt;td&gt;Yes (default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust in-kernel modules&lt;/td&gt;
&lt;td&gt;Yes (covered modules)&lt;/td&gt;
&lt;td&gt;Rust panic to kernel BSOD&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes (&lt;code&gt;win32kbase_rs.sys&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;windows-drivers-rs&lt;/code&gt; for third-party drivers&lt;/td&gt;
&lt;td&gt;Yes (per module)&lt;/td&gt;
&lt;td&gt;Driver panic to bugcheck&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Preview only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CHERI / Arm Morello capability hardware&lt;/td&gt;
&lt;td&gt;Yes (all pointers, all languages)&lt;/td&gt;
&lt;td&gt;Capability fault, process aborted&lt;/td&gt;
&lt;td&gt;Yes (Morello, CHERIoT)&lt;/td&gt;
&lt;td&gt;No (embedded only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verification (MIRI, RustBelt, formal proofs)&lt;/td&gt;
&lt;td&gt;Yes (where proofs cover)&lt;/td&gt;
&lt;td&gt;Caught at build time&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Tooling only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenVMM / OpenHCL (Rust paravisor)&lt;/td&gt;
&lt;td&gt;Yes (paravisor surface)&lt;/td&gt;
&lt;td&gt;Paravisor panic in confidential VM&lt;/td&gt;
&lt;td&gt;TDX or SEV-SNP CPU&lt;/td&gt;
&lt;td&gt;Yes (Azure confidential VMs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI-assisted C-to-Rust migration&lt;/td&gt;
&lt;td&gt;Aspirational&lt;/td&gt;
&lt;td&gt;Per migrated module&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Research only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The convergence is real. The strategy is articulated. So what &lt;em&gt;cannot&lt;/em&gt; Rust-in-kernel do, even when everything goes right?&lt;/p&gt;
&lt;h2&gt;8. Four Theoretical Limits Rust-in-Kernel Cannot Escape&lt;/h2&gt;
&lt;p&gt;This section is the corrective. Even when everything goes right, Rust-in-kernel runs into four principled limits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limit 1: the &lt;code&gt;unsafe&lt;/code&gt; boundary is irreducible.&lt;/strong&gt; Any Rust module that interoperates with the C kernel must call into it; the FFI is &lt;code&gt;unsafe&lt;/code&gt; by construction. The safety guarantee is exactly as strong as the audit of the &lt;code&gt;unsafe&lt;/code&gt; blocks. This is not a flaw in Rust; it is a property of &lt;em&gt;any&lt;/em&gt; safe-language-in-an-unsafe-substrate adoption. Inside &lt;code&gt;unsafe&lt;/code&gt;, Rust does not check what you do; it trusts the human review. The audit therefore has to be load-bearing. The &lt;code&gt;windows-drivers-rs&lt;/code&gt; README&apos;s statement that &quot;drivers ... still need to make use of unsafe blocks for interacting with the Windows operating system&quot; is the candid admission of this limit [@windows-drivers-rs; @register-2025-09-04].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limit 2: a Rust panic at high IRQL is a kernel bugcheck.&lt;/strong&gt; Because &lt;code&gt;panic = &quot;abort&quot;&lt;/code&gt; is the only sound policy for &lt;code&gt;no_std&lt;/code&gt; kernel binaries, and because at IRQL ≥ DISPATCH_LEVEL the kernel has nowhere to send a panic except the system-wide bugcheck, a correctly-fired Rust safety check in kernel context becomes a BSOD. Check Point&apos;s &quot;Denial of Fuzzing&quot; disclosure is dispositive: Rust correctly &lt;em&gt;detected&lt;/em&gt; the out-of-bounds access, but the operational response was &lt;code&gt;SYSTEM_SERVICE_EXCEPTION&lt;/code&gt; [@checkpoint-dof; @cybersecuritynews]. Rust transforms memory-corruption CVEs into denial-of-service CVEs in the kernel context. It does &lt;em&gt;not&lt;/em&gt; eliminate the CVE class.&lt;/p&gt;
&lt;p&gt;Russinovich framed this limit as a feature, not a bug, at RustConf 2025:&lt;/p&gt;

This we view as a success ... a bug that would have actually resulted in a potential elevation of privilege, as opposed to a blue screen crash. -- Mark Russinovich, RustConf 2025 [@newstack-russinovich].
&lt;p&gt;He is right operationally. A BSOD is far cheaper than a remote code execution. But the &lt;em&gt;CVE class&lt;/em&gt; did not vanish; it shifted. The new class is &quot;panic-in-kernel-context, denial of service.&quot; That is the bug class that any future Rust-in-kernel security architect has to plan for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limit 3: the legacy C and C++ kernel -- roughly thirty million lines on common engineering estimates -- will not be rewritten on any plausible timeline.&lt;/strong&gt; Even Galen Hunt&apos;s &quot;1 engineer, 1 month, 1 million lines of code&quot; research aspiration -- explicitly clarified by Hunt himself as research, not a corporate mandate -- would require sustained multi-decade effort to clear the whole kernel [@register-2025-12-24; @infoworld-not-rewriting; @windowslatest-galen]. Realistically the kernel will keep most of its existing C and C++ for the foreseeable future. The wins come from partial rewrites of high-blast-radius modules plus the new-code policy. &lt;em&gt;Existing modules that do not change do not need to be rewritten to benefit from the new-code policy&lt;/em&gt; -- that is the Android empirical observation [@google-android-2024] -- but they remain potential bug-class carriers nonetheless.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limit 4: Rust + &lt;code&gt;unsafe&lt;/code&gt; cannot beat hardware capabilities on every bug class.&lt;/strong&gt; CHERI and CHERIoT detect spatial and temporal memory-safety violations at every pointer dereference, including across the C and C++ legacy substrate that language-level approaches cannot rewrite [@cheri-cambridge; @cheriot-org].Spatial safety means accesses stay within an object&apos;s bounds; temporal safety means accesses do not touch freed objects. CHERI capabilities enforce both at the hardware ISA level for every load and store. The most defensible posture combines Rust for new code with CHERI-class hardware where the silicon supports it. Rust is necessary; on legacy code, it is not sufficient. The CHERIoT line at Microsoft (the &lt;code&gt;microsoft/cheriot-rtos&lt;/code&gt; repository [@cheriot-rtos-ms]) is the explicit acknowledgement that Microsoft is investing in both layers because neither alone closes the question.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Rust transforms memory-corruption CVEs into denial-of-service CVEs in the kernel context. It does not eliminate the CVE class -- and that is still a major win, but it is the actual win, not the marketing one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the policy is sound but the limits are real, what does the next decade actually look like in numbers and named open problems?&lt;/p&gt;
&lt;h2&gt;9. The 2026 Frontier and the Ten-Year Trajectory&lt;/h2&gt;
&lt;p&gt;Open problems matter when they are named. The state-of-the-art survey identified eight; each gets a paragraph here.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P1. The public corpus size of in-kernel Rust.&lt;/strong&gt; The most recent first-party Microsoft figure remains the April 2023 number quoted to &lt;em&gt;The Register&lt;/em&gt;: about 36,000 lines of Rust in &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; [@register-2023-04-27]. There has been no first-party refresh since. Any 2026 line-of-code claim greater than this -- including the &quot;over 100,000 lines&quot; framing that has circulated in secondary press -- is unsourced. We treat it as an open question.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P2. Upstreaming the &lt;code&gt;no_std&lt;/code&gt; kernel target.&lt;/strong&gt; Microsoft&apos;s Rust kernel target is not in &lt;code&gt;rust-lang/rust&lt;/code&gt;. Third-party driver developers cannot reproduce the toolchain exactly without internal Microsoft assets. The &lt;code&gt;windows-drivers-rs&lt;/code&gt; repository contains the public-facing crates and the &lt;code&gt;cargo-wdk&lt;/code&gt; build orchestration, but the underlying compilation target is private [@windows-drivers-rs]. Upstreaming it would let external WHCP-bound driver authors build against the same toolchain as Microsoft&apos;s in-box drivers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P3. WHCP and driver certification.&lt;/strong&gt; As of September 2025, CodeQL supports Rust at version 2.22.1 (public preview), while only version 2.21.4 is &quot;validated for use with WHCP&quot; [@register-2025-09-04]. No production third-party Rust driver has yet shipped through WHCP. The certification path is being assembled in public; it is not yet open for production third-party submissions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P4. Panic-as-BSOD mitigation.&lt;/strong&gt; This is the Check Point bug class -- a correct Rust safety check in kernel context becomes a system-wide bugcheck [@checkpoint-dof]. The options are imperfect. Unwinding instead of aborting is unsound at high IRQL because the unwinder needs to run code that may itself page-fault. IRQL-aware fallbacks (degrade gracefully when at high IRQL, panic when at PASSIVE_LEVEL) are doable but add complexity. More conservative bounds-checking patterns in hot paths can reduce the panic surface but cannot eliminate it. This is an active research and engineering frontier.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P5. Mechanised formal verification of kernel &lt;code&gt;unsafe&lt;/code&gt; blocks.&lt;/strong&gt; RustBelt-grade proofs exist for specific libraries [@rustbelt-popl-page]. Production-scale verification of arbitrary kernel &lt;code&gt;unsafe&lt;/code&gt; is open. The proof obligations are statable thanks to the RustBelt framework; discharging them at production scale across an entire driver&apos;s worth of &lt;code&gt;unsafe&lt;/code&gt; blocks is not yet routine.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P6. The Hyper-V VSP migration.&lt;/strong&gt; OpenVMM is in flight as the modular cross-platform Rust VMM whose primary deployment in 2026 is the OpenHCL paravisor [@openvmm-github; @phoronix-openhcl]. The in-Windows Hyper-V VSP front-end&apos;s Rust status is unannounced. This is the Stage-3 P6 open problem; the article does not assert that the production Hyper-V VSP has been migrated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P7. AI-assisted migration.&lt;/strong&gt; Galen Hunt&apos;s &quot;1 engineer, 1 month, 1 million lines of code&quot; target is the headline aspiration [@register-2025-12-24]. The methodological dependencies are non-trivial. Code-graph construction has to be accurate. AI translation quality has to be high. Semantic-equivalence preservation has to be checkable. Manual-intervention burden at the unsafe-FFI boundary will be significant. Recent academic work on type-directed C-to-safe-Rust translation -- &lt;em&gt;Compiling C to Safe Rust, Formalized&lt;/em&gt; (Fromherz and Protzenko, OOPSLA 2026) -- shows what mechanical, proof-grade translation looks like for restricted subsets [@arxiv-c-to-rust], and that is the direction Russinovich has framed as preferred over LLM-only approaches.&lt;/p&gt;

On 24 December 2025, Galen Hunt&apos;s LinkedIn post -- *&quot;My goal is to eliminate every line of C and C++ from Microsoft by 2030 ... Our North Star is 1 engineer, 1 month, 1 million lines of code&quot;* -- was reported by *The Register* under the headline &quot;Microsoft wants to replace its entire C and C++ codebase&quot; [@register-2025-12-24]. The press cycle briefly suggested Microsoft was rewriting Windows in Rust. Within days, the picture was corrected. Hunt&apos;s own clarification: &quot;My team&apos;s project is a research project. We are building tech to make migration from language to language possible. ... [The intent was] to find like-minded engineers, not to set a new strategy for Windows 11+ or to imply that Rust is an endpoint&quot; [@infoworld-not-rewriting]. Microsoft&apos;s communications head Frank X. Shaw confirmed to Windows Latest that the company has no plans to rewrite Windows 11 using AI [@windowslatest-galen]. The &quot;1 / 1 / 1M&quot; project is a research aspiration inside the CoreAI group, not a Windows roadmap. Several outlets republished without that correction; the *InfoWorld* and *Windows Latest* pieces are the load-bearing references for the accurate framing.
&lt;p&gt;&lt;strong&gt;P8. Ten-year trajectory.&lt;/strong&gt; Three independent dynamics will determine the shape: Microsoft&apos;s conversion rate of existing high-blast-radius modules, the rate at which &lt;em&gt;new&lt;/em&gt; code is written in Rust by default, and the empirical Android curve as a reference point [@google-android-2024]. The conclusion is not that the legacy kernel will be rewritten. The conclusion is that the &lt;em&gt;share&lt;/em&gt; of memory-safety CVEs in Windows is likely to follow a trajectory shaped like Android&apos;s -- a multi-year decline driven by new-code-in-Rust plus targeted rewrites, with the absolute floor set by the residual &lt;code&gt;unsafe&lt;/code&gt; audit surface at the FFI boundary and the not-rewritten C and C++ that retains some level of new development.&lt;/p&gt;
&lt;p&gt;Quick reference for the questions almost everyone asks comes next. First, what you can do on Monday.&lt;/p&gt;
&lt;h2&gt;10. Practical Guide&lt;/h2&gt;
&lt;p&gt;Four audiences. Each gets a subsection.&lt;/p&gt;
&lt;h3&gt;10.1 For Windows-internals and security researchers&lt;/h3&gt;
&lt;p&gt;Identifying Rust-implemented kernel binaries is the first step. The Microsoft internal convention is the &lt;code&gt;_rs&lt;/code&gt; suffix; the canonical example is &lt;code&gt;%SystemRoot%\System32\win32kbase_rs.sys&lt;/code&gt;. The fastest verification:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Open PowerShell on any Windows 11 24H2 machine and run: &lt;code&gt;Get-Item C:\Windows\System32\win32kbase_rs.sys&lt;/code&gt;. If the file is present, you are running a Windows with kernel-mode Rust code today.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;{&lt;code&gt;// Demonstrates the logic of:  Test-Path &quot;\$env:SystemRoot\\System32\\win32kbase_rs.sys&quot; const knownRustKernelBinaries = [&quot;win32kbase_rs.sys&quot;]; // Insider Preview 25905 (July 12, 2023) and later const systemRoot = &quot;C:\\\\Windows&quot;; const found = knownRustKernelBinaries.map(b =&amp;gt; systemRoot + &quot;\\\\System32\\\\&quot; + b); for (const path of found) {   console.log(&quot;Expected: &quot; + path); } console.log(&quot;On a real Windows 11 24H2 install, this file is present.&quot;);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;Reverse engineering: dumping strings against &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; will surface Rust panic markers like &lt;code&gt;panic_bounds_check&lt;/code&gt;, &lt;code&gt;core::panicking::panic&lt;/code&gt;, and &lt;code&gt;core::result::unwrap_failed&lt;/code&gt; -- the names the Rust standard library inserts when bounds checks or &lt;code&gt;Option::unwrap&lt;/code&gt; calls misfire [@cybersecuritynews]. The Rust v0 name mangling scheme starts with &lt;code&gt;_R&lt;/code&gt; and uses a Punycode-derived encoding for non-ASCII characters [@rust-rfc-2603]; tools that understand the scheme (recent IDA, recent Ghidra, &lt;code&gt;rustfilt&lt;/code&gt;) demangle it. Functions like &lt;code&gt;region_from_path_mut&lt;/code&gt; will appear in the binary as mangled &lt;code&gt;_R...&lt;/code&gt; symbols.&lt;/p&gt;
&lt;p&gt;For reproducing Check Point&apos;s &quot;Denial of Fuzzing&quot; methodology: the public write-up names WinAFL plus WinAFL-Pet as the orchestration tier, with crafted EMF and EMF+ metafile corpora driving &lt;code&gt;NtGdiSelectClipPath&lt;/code&gt; and other Win32k entry points; BugId handles crash triage; MemProcFS handles memory-dump forensics [@checkpoint-dof]. The toolchain is reproducible on a research VM.&lt;/p&gt;

The Check Point harness suggests four productive bug-class targets when fuzzing the Rust kernel surface: (1) `panic_bounds_check` firings at array-indexing sites in geometry pipelines; (2) integer-overflow-checked-arithmetic divergences from C++ behaviour (Rust panics on overflow in debug builds, wraps in release -- check your build profile); (3) allocator-out-of-memory at the `wdk-alloc` boundary, where `ExAllocatePool2` can return `NULL` under pressure; (4) mismatches at `unsafe`-block invariants where a Rust safe wrapper trusts an assertion the C kernel does not actually guarantee.
&lt;h3&gt;10.2 For Windows driver developers evaluating Rust&lt;/h3&gt;
&lt;p&gt;The setup recipe for &lt;code&gt;windows-drivers-rs&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Clone &lt;code&gt;microsoft/windows-drivers-rs&lt;/code&gt; and &lt;code&gt;microsoft/Windows-rust-driver-samples&lt;/code&gt; [@windows-drivers-rs; @windows-rust-samples].&lt;/li&gt;
&lt;li&gt;Install a recent stable &lt;code&gt;rustc&lt;/code&gt; with the &lt;code&gt;x86_64-pc-windows-msvc&lt;/code&gt; toolchain.&lt;/li&gt;
&lt;li&gt;Install the Windows Driver Kit (WDK) from Microsoft Learn.&lt;/li&gt;
&lt;li&gt;Install LLVM 17. &lt;em&gt;Not&lt;/em&gt; LLVM 18 (ARM64 bindgen bug); LLVM 19 is the awaited fix [@windows-drivers-rs].&lt;/li&gt;
&lt;li&gt;Install &lt;code&gt;cargo-make&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Enter an eWDK developer prompt so MSBuild and the WDK environment variables are present.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cargo install cargo-wdk&lt;/code&gt; (or take the version published on crates.io as of November 2025) [@techcommunity-rust-drivers].&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;{&lt;code&gt;// The shape of the manifest documented in microsoft/windows-drivers-rs README. const cargoToml = [   &quot;[package]&quot;,   &quot;name = \\&quot;example-driver\\&quot;&quot;,   &quot;version = \\&quot;0.1.0\\&quot;&quot;,   &quot;edition = \\&quot;2021\\&quot;&quot;,   &quot;&quot;,   &quot;[lib]&quot;,   &quot;crate-type = [\\&quot;cdylib\\&quot;]&quot;,   &quot;&quot;,   &quot;[profile.dev]&quot;,   &quot;panic = \\&quot;abort\\&quot;&quot;,   &quot;lto = true&quot;,   &quot;&quot;,   &quot;[profile.release]&quot;,   &quot;panic = \\&quot;abort\\&quot;&quot;,   &quot;lto = true&quot;,   &quot;&quot;,   &quot;[dependencies]&quot;,   &quot;wdk = \\&quot;*\\&quot;&quot;,   &quot;wdk-sys = \\&quot;*\\&quot;&quot;,   &quot;wdk-alloc = \\&quot;*\\&quot;&quot;,   &quot;wdk-panic = \\&quot;*\\&quot;&quot;,   &quot;&quot;,   &quot;[build-dependencies]&quot;,   &quot;wdk-build = \\&quot;*\\&quot;&quot;,   &quot;&quot;,   &quot;[package.metadata.wdk.driver-model]&quot;,   &quot;driver-type = \\&quot;KMDF\\&quot;&quot;,   &quot;kmdf-version-major = 1&quot;,   &quot;target-kmdf-version-minor = 33&quot; ].join(&quot;\\n&quot;); console.log(cargoToml);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;KMDF 1.33-era bindings are on crates.io. WDM and UMDF are possible with &lt;code&gt;wdk-build&lt;/code&gt; modification but are not the documented happy path [@windows-drivers-rs]. The WHCP certification path is not yet greenlit for production third-party Rust drivers [@register-2025-09-04]. When &lt;em&gt;not&lt;/em&gt; to choose Rust: driver classes with mature, well-fuzzed C and C++ equivalents, small attack surfaces, and broad cross-vendor deployments where churn cost outweighs Rust&apos;s safety benefits. The first generation of production third-party Rust drivers will likely be filter drivers, virtual-device drivers, and parsers for untrusted formats -- exactly the surfaces where Microsoft&apos;s own first-party Surface drivers have shipped [@winbuzzer-surface; @thurrott-rust].&lt;/p&gt;
&lt;h3&gt;10.3 For security architects&lt;/h3&gt;
&lt;p&gt;Strategic frame: treat Rust adoption as a long-term policy lever, not a near-term mitigation. For the next five years, assume the kernel is still 95%+ C and C++. Treat in-kernel Rust as incremental risk reduction at the modules where it lands -- the GDI region engine, the EMF parser, future surfaces around metafile and graphics parsing, possibly virtualization plumbing. Treat the unsafe-FFI boundary as the audit frontier; concentrate fuzzing, code review, and CodeQL-Rust analysis there. Rely on the existing mitigations stack -- HVCI, CFG, XFG, CET, Driver Verifier, WDAC -- as defence-in-depth that Rust does &lt;em&gt;not&lt;/em&gt; replace [@learn-cfg; @learn-gs; @learn-dep]. Plan for the panic-as-BSOD class as the new DoS surface, and architect monitoring (event-log mining for &lt;code&gt;SYSTEM_SERVICE_EXCEPTION&lt;/code&gt; rates, fleet telemetry for Rust-panic markers) accordingly.&lt;/p&gt;
&lt;h3&gt;10.4 For security researchers fuzzing the Rust kernel surface&lt;/h3&gt;
&lt;p&gt;Check Point&apos;s methodology is the public reference [@checkpoint-dof]; the productive bug classes and the WinAFL + WinAFL-Pet + BugId + MemProcFS pipeline are described in §10.1 above. Two items are specific to the Rust kernel surface and worth adding here. First, integrate CodeQL&apos;s Rust query pack once 2.22.1+ ships in your build pipeline -- only 2.21.4 is WHCP-validated today [@register-2025-09-04]. Second, the empirical companion-CVE pattern: the same Check Point campaign that surfaced &quot;Denial of Fuzzing&quot; also produced several C/C++ GDI vulnerabilities (CVE-2025-30388, CVE-2025-53766, CVE-2025-47984), which suggests there is more to find in the GDI region of Win32k regardless of language [@checkpoint-drawn].&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions&lt;/h2&gt;

No. Microsoft&apos;s stated policy is &quot;memory-safe by default for newly written code&quot; plus targeted rewrites of high-blast-radius modules. The legacy C and C++ kernel is not being rewritten on any announced timeline. Galen Hunt&apos;s &quot;1 engineer, 1 month, 1 million lines of code&quot; framing is a research target inside Microsoft&apos;s CoreAI group; Frank X. Shaw, head of Microsoft&apos;s communications, confirmed within days of the December 2025 LinkedIn post that the company has no plan to rewrite Windows 11 using AI [@windowslatest-galen; @infoworld-not-rewriting; @register-2025-12-24].

No. Rust eliminates the memory-corruption CVE class *in the modules it covers*. It does not eliminate logic bugs, race conditions, or denial-of-service vulnerabilities. Check Point Research&apos;s &quot;Denial of Fuzzing&quot; disclosure -- patched in KB5058499 on 28 May 2025 -- is the dispositive case. Rust correctly detected an out-of-bounds access in `region_from_path_mut()` inside `win32kbase_rs.sys`; because `panic = &quot;abort&quot;` is mandatory in `no_std` kernel binaries, the response was a system-wide BSOD rather than a remote code execution [@checkpoint-dof; @kb5058499].

No. DWriteCore is user-mode code distributed through the Windows App SDK 1.2 and above. The kernel-mode Rust binary is `win32kbase_rs.sys`. The two are often conflated in secondary coverage because David Weston announced both at BlueHat IL 2023 on the same slide deck. DWriteCore is roughly 152,000 lines of Rust plus 96,000 lines of C++; `win32kbase_rs.sys` is the in-kernel piece, originally about 36,000 lines [@register-2023-04-27].

No. The public Microsoft GitHub repository is `microsoft/windows-drivers-rs`. The crate suite contains six crates named `wdk`, `wdk-sys`, `wdk-alloc`, `wdk-build`, `wdk-panic`, and `wdk-macros`. The Cargo subcommand is `cargo-wdk`. There is no &quot;WDR&quot; abbreviation in the official Microsoft naming. The companion samples repository is `microsoft/Windows-rust-driver-samples` [@windows-drivers-rs; @windows-rust-samples].

No. The originating talk was Matt Miller&apos;s at BlueHat IL in early February 2019, titled *Trends, Challenges, and Shifts in Software Vulnerability Mitigation*. The deck is in the `microsoft/MSRC-Security-Research` GitHub repository. Weston and Mark Russinovich later operationalised the figure in their own talks. The Microsoft Security Response Center re-stated it in plain prose in two essays in July 2019 [@miller-bluehat-2019; @msrc-proactive-2019; @msrc-safer-2019; @infoq-mitigating].

No. OpenVMM is a separate modular Rust VMM whose primary 2026 production deployment is as the OpenHCL paravisor for AMD SEV-SNP and Intel TDX confidential virtual machines [@openvmm-github; @phoronix-openhcl]. Hyperlight is the Azure-side production Rust micro-VMM with sub-2-millisecond cold-start times. The in-Windows Hyper-V Virtualisation Service Provider (VSP) front-end&apos;s Rust status has not been publicly announced; that is Open Problem P6 in the article&apos;s frontier section [@newstack-russinovich].
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;rust-in-the-windows-kernel-2026-field-guide&quot; keyTerms={[
  { term: &quot;win32kbase_rs.sys&quot;, definition: &quot;The first Rust-implemented Windows kernel binary; contains the Win32k GDI region/shape engine and, by 2025, parts of the EMF/EMF+ metafile parser.&quot; },
  { term: &quot;panic = abort&quot;, definition: &quot;The Rust compilation profile that converts a panic into an immediate abort rather than stack unwinding; mandatory for no_std kernel binaries.&quot; },
  { term: &quot;no_std&quot;, definition: &quot;Rust crate attribute opting out of the standard library; required for kernel binaries because std assumes OS services the kernel itself provides.&quot; },
  { term: &quot;GlobalAlloc&quot;, definition: &quot;The Rust trait for the global memory allocator; in kernel Rust it is implemented by wdk-alloc over ExAllocatePool2/ExFreePoolWithTag.&quot; },
  { term: &quot;FFI&quot;, definition: &quot;Foreign Function Interface; the ABI-crossing mechanism by which Rust calls C kernel functions. Every FFI call in kernel Rust is an unsafe block.&quot; },
  { term: &quot;CFI&quot;, definition: &quot;Control-Flow Integrity; the mitigation family (CFG, XFG, CET) that defends the control-flow graph; by construction blind to data-only attacks.&quot; },
  { term: &quot;DOP&quot;, definition: &quot;Data-Oriented Programming; Hu et al. (IEEE S&amp;amp;P 2016) proved data-only attacks are Turing-complete and invisible to every CFI variant.&quot; },
  { term: &quot;IRQL&quot;, definition: &quot;Interrupt Request Level; the Windows kernel per-CPU priority. At IRQL &amp;gt;= DISPATCH_LEVEL a panic has nowhere to go except the system bugcheck.&quot; }
]} /&amp;gt;&lt;/p&gt;
&lt;p&gt;The article&apos;s smallest claim is also its largest. Rust is in the Windows kernel today, in production, with a real binary you can list at a real path. The article&apos;s largest claim is its smallest. The realistic ten-year shape is not a Windows rewrite; it is a policy that compounds, over decades, across modules whose authors choose Rust on first contact. The most defended forward posture combines Rust for new code, targeted rewrites of high-blast-radius modules, CHERI-class hardware capabilities where silicon supports them, and the existing mitigations stack as the patient defence-in-depth backstop. Each piece is partial. The combination is the answer to the 70-percent figure that Matt Miller stood up and named in Tel Aviv in early February 2019.&lt;/p&gt;
&lt;p&gt;Now go check &lt;code&gt;C:\Windows\System32\win32kbase_rs.sys&lt;/code&gt;. It is there.&lt;/p&gt;
</content:encoded><category>rust</category><category>windows-kernel</category><category>memory-safety</category><category>win32k</category><category>msrc</category><category>cve-mitigations</category><category>secure-future-initiative</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>The Driver That Was Signed and the Driver That Won&apos;t Load: Windows Kernel Code Integrity, 2006-2026</title><link>https://paragmali.com/blog/windows-kernel-code-integrity-2006-2026/</link><guid isPermaLink="true">https://paragmali.com/blog/windows-kernel-code-integrity-2006-2026/</guid><description>A history of Windows kernel code-signing -- KMCS, BYOVD, HVCI, the Vulnerable Driver Block List, and why a 2026 Windows kernel uses five gates to decide what loads.</description><pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Windows ships a list of Microsoft-signed drivers it refuses to load.** That list -- `DriverSiPolicy.p7b` -- exists because every previous generation of kernel-driver trust assumed a signed driver was a safe driver, and a twenty-year run of Bring-Your-Own-Vulnerable-Driver attacks (Stuxnet, Capcom.sys, RTCore64.sys, gdrv.sys) proved that assumption wrong. The 2026 default-on stack -- KMCS, the block list, HVCI in VTL1, Smart App Control, and Defender ASR coverage -- is five gates doing what one ideal gate cannot do: name the specific weakness, not just the publisher. The architectural gap that motivates the stack is undecidable in principle and will not close.
&lt;h2&gt;1. The Driver That Loaded&lt;/h2&gt;
&lt;p&gt;On 13 September 2016, the researcher Matt Nelson posted on his &lt;em&gt;enigma0x3&lt;/em&gt; blog that a Capcom-published kernel driver, &lt;code&gt;Capcom.sys&lt;/code&gt;, exposed IOCTL &lt;code&gt;0xAA013044&lt;/code&gt; and used it to execute a user-supplied function pointer in kernel mode, with SMEP disabled along the way [@gh-tandasat-capcom] [@gh-tandasat-capcom]. Within two weeks the technique was operational in Metasploit. Later in September 2016, Capcom pushed the same driver to Street Fighter V&apos;s entire installed base as part of an anti-cheat update; in October 2016, Satoshi Tanda published the canonical standalone exploit on GitHub. Capcom withdrew the SFV driver shortly after, but the bytes were already in the wild.The often-told version of this story compresses three distinct events into one. Matt Nelson&apos;s &lt;em&gt;Let&apos;s Be Bad Guys&lt;/em&gt; post on 13 September 2016 disclosed the IOCTL number and the function-pointer-execution primitive. OJ Reeves opened the canonical Metasploit pull request, rapid7/metasploit-framework#7363 [@gh-msf-pr-7363], shortly after; the PR was created on 27 September 2016 and merged the following day [@gh-msf-pr-7363]. Satoshi Tanda&apos;s &lt;code&gt;tandasat/ExploitCapcom&lt;/code&gt; repository was first published in October 2016 and is the canonical standalone PoC, and the artefact this article cites for the IOCTL number and SHA-1 hash.&lt;/p&gt;
&lt;p&gt;The driver was properly Authenticode-signed. It chained to a Microsoft-recognised root. It loaded cleanly on every default-configured Windows 7, 8.1, and 10 machine in the world.&lt;/p&gt;
&lt;p&gt;That is the puzzle this article exists to answer. How does an operating system whose entire kernel-loading policy is &lt;em&gt;was this binary signed?&lt;/em&gt; answer a vulnerability whose only failure mode is &lt;em&gt;yes, by a real publisher, doing exactly what the signature says it does&lt;/em&gt;?&lt;/p&gt;
&lt;h3&gt;A class, not an incident&lt;/h3&gt;
&lt;p&gt;Capcom.sys was not the first signed kernel driver with a primitive IOCTL, and it would not be the last. The pattern recurs across two decades and is the through-line of this article. The catalogue includes Micro-Star&apos;s &lt;code&gt;RTCore64.sys&lt;/code&gt; (the kernel component of MSI Afterburner), Gigabyte&apos;s &lt;code&gt;gdrv.sys&lt;/code&gt;, and the &lt;code&gt;KProcessHacker&lt;/code&gt; driver shipped with Process Hacker. Section 4 walks through each one with its primary disclosure record.&lt;/p&gt;
&lt;p&gt;The attack class has a name. &lt;em&gt;Bring Your Own Vulnerable Driver&lt;/em&gt;, or BYOVD. The adversary does not need to find a kernel zero-day. They need to find one signed driver, anywhere, whose interface is unsafe by design, and to ship it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Windows in 2026 ships a curated list of Microsoft-signed drivers it refuses to load. Understanding that list is understanding why every previous attempt to make kernel-mode trust mean &lt;em&gt;safety&lt;/em&gt; instead of just &lt;em&gt;identity&lt;/em&gt; eventually broke.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The current Windows 11 22H2 client honours &lt;code&gt;%windir%\system32\CodeIntegrity\DriverSiPolicy.p7b&lt;/code&gt;, a Microsoft-signed deny list enforced by a hypervisor-isolated code-integrity engine sitting in Virtual Trust Level 1. The same engine refuses to map any kernel page that is simultaneously writable and executable. Both behaviours are documented on Microsoft Learn&apos;s Memory Integrity page [@ms-hvci-vbs] and the Microsoft-recommended driver block rules page [@ms-driver-block-rules] [@ms-hvci-vbs] [@ms-driver-block-rules]. Neither existed in 2006.&lt;/p&gt;
&lt;p&gt;To understand why Windows now refuses to load drivers it once asked Microsoft to sign, we need to go back thirty years to the moment Windows first asked a publisher to sign anything at all.&lt;/p&gt;
&lt;h2&gt;2. Advisory Trust: 1996 to 2005&lt;/h2&gt;
&lt;p&gt;For its first decade, the Windows driver signing policy was a polite recommendation.&lt;/p&gt;
&lt;p&gt;Microsoft shipped its first user-mode code-signing primitive, &lt;a href=&quot;https://paragmali.com/blog/authenticode-and-catalog-files-the-crypto-foundation-under-w/&quot; rel=&quot;noopener&quot;&gt;Authenticode&lt;/a&gt;, in 1996, packaged for developers in the same tool kit that gave us &lt;code&gt;SignTool&lt;/code&gt;, &lt;code&gt;MakeCat&lt;/code&gt;, and &lt;code&gt;Inf2Cat&lt;/code&gt; -- the suite Microsoft Learn still documents under &quot;Cryptography tools&quot; [@ms-crypto-tools] [@ms-crypto-tools]. Authenticode wrapped a PKCS#7 signature around the SHA-1 (and later SHA-256) hash of a PE image and let a recipient walk the signer&apos;s certificate chain to a trusted root. It was the first answer to the question &lt;em&gt;who shipped this binary?&lt;/em&gt; It was, deliberately, never an answer to &lt;em&gt;is this binary safe?&lt;/em&gt;&lt;/p&gt;

Microsoft&apos;s PKCS#7-based code-signing format for Windows binaries. Authenticode attests to the publisher&apos;s identity by binding the binary&apos;s hash to a certificate chain anchored at a trusted root. It does not analyse the program&apos;s behaviour.
&lt;p&gt;For drivers, the user-mode signing primitive was paired with a separate quality program. The Windows Hardware Quality Labs programme, documented today via the Hardware Lab Kit [@ms-hlk], tested third-party drivers against a Microsoft-curated compatibility suite and rewarded passing drivers with a counter-signature, eventually surfaced as the &quot;Designed for Windows&quot; or &quot;Certified for Windows&quot; mark [@ms-hlk]. The badge was operationally meaningful for OEM badging and Windows Update distribution. It was not a load-time gate. An unsigned &lt;code&gt;.sys&lt;/code&gt; file dropped on disk by a setup script still loaded.&lt;/p&gt;

Microsoft&apos;s compatibility-test programme for third-party drivers. A driver that passes the HLK test suite receives a Microsoft counter-signature and is eligible for OEM and Windows Update distribution. The programme produces a quality signal, not a load-time enforcement decision.
&lt;h3&gt;The SetupAPI prompt&lt;/h3&gt;
&lt;p&gt;On 32-bit Windows, the gate the user actually saw was the SetupAPI driver-installation prompt. The administrator could set the system to &lt;em&gt;Ignore&lt;/em&gt;, &lt;em&gt;Warn&lt;/em&gt;, or &lt;em&gt;Block&lt;/em&gt; unsigned drivers; the default was &lt;em&gt;Warn&lt;/em&gt;. &lt;em&gt;Warn&lt;/em&gt; meant a click-through dialog at install time. An administrator who clicked &lt;em&gt;Install this driver anyway&lt;/em&gt; loaded the unsigned driver, no further questions asked. The structural truth is the one Microsoft&apos;s modern KMCS policy page [@ms-kmcs-policy] acknowledges by contrast: under advisory policy, the prompt is the policy, and a prompt is exactly as strong as the user clicking past it [@ms-kmcs-policy].&lt;/p&gt;
&lt;p&gt;The Sony BMG XCP incident in October 2005 made the structural weakness concrete. The XCP copy-protection software, shipped on retail audio CDs, autorun-installed an unsigned kernel-mode filter driver. The driver hid any file, registry key, or process whose name began with the string &lt;code&gt;$sys$&lt;/code&gt; -- a textbook rootkit by capability if not by intent. The driver loaded after an administrator clicked through the warning prompt, exactly as advisory policy allowed. The pattern is described well in Wikipedia&apos;s code-signing article [@wp-code-signing] [@wp-code-signing].The Sony BMG XCP rootkit triggered class-action lawsuits, FTC settlements, and an industry-wide reconsideration of what &quot;the user clicked OK&quot; actually authorises. From a kernel-trust perspective, the lesson is narrower: any policy that ends in a dismissible dialog has the same threat model as no policy at all, against an attacker who can show the user a dialog.&lt;/p&gt;
&lt;p&gt;The structural takeaway from 1996 through 2005 is the one the next decade tried to repair. When the signing policy is advisory, an attacker who has -- or can socially engineer -- administrator privilege only needs to dismiss a prompt to load a kernel driver. The signing primitive worked. The policy around the primitive did not.&lt;/p&gt;
&lt;p&gt;If the prompt is the only thing between an attacker and ring zero, the kernel itself has to take over. And on a brand-new x64 architecture, Microsoft could break backward compatibility to make that happen.&lt;/p&gt;
&lt;h2&gt;3. KMCS: The Vista x64 Revolution (2006-2016)&lt;/h2&gt;
&lt;p&gt;In November 2006, Vista x64 made a decision that x86 never could: it refused to load any unsigned kernel driver, full stop.&lt;/p&gt;
&lt;p&gt;The mechanism was Kernel-Mode Code Signing, or KMCS. The previous-versions Microsoft Learn page on Vista-era driver signing [@learn-microsoft-com-design-dn653567vvs85]) records the policy [@ms-dn653567]. At the point where the I/O manager called &lt;code&gt;IoLoadDriver&lt;/code&gt;, the Code Integrity module (&lt;code&gt;ci.dll&lt;/code&gt;) intercepted the load, extracted the Authenticode signature embedded in the PE image or attached via a published catalogue, walked the certificate chain, and refused to map the image if the chain did not terminate at a Microsoft-trusted root. There was no SetupAPI prompt to dismiss. If the kernel refused, the kernel refused. The decision lived below the user&apos;s reach.&lt;/p&gt;

The Vista-era mandatory load-time signature policy on 64-bit Windows. Before mapping a kernel driver&apos;s PE image, the Code Integrity module verifies that the image&apos;s Authenticode signature chains to a Microsoft-trusted root. Drivers that fail the check are refused at load time, not at install time.
&lt;p&gt;x86 kept the advisory policy. Microsoft could not break compatibility with two decades of unsigned drivers on the dominant platform. But x64 was a young architecture with a few hundred drivers in the field, and Microsoft used that moment to flip the default. The structural shift was real: kernel-driver trust on x64 became a property of the binary, decided in the kernel, against a fixed set of trusted roots.&lt;/p&gt;
&lt;h3&gt;Cross-certificates: opening the gate to the world&lt;/h3&gt;
&lt;p&gt;A Microsoft-trusted root alone would have meant Microsoft signs every driver, which Microsoft did not want. Instead Microsoft cross-certified a small set of commercial code-signing certificate authorities -- including VeriSign, DigiCert, Entrust, GlobalSign, GoDaddy, and several smaller successors enumerated on the historical cross-certificate list (2020 archive) [@ms-cross-cert-archive] -- so that a publisher could buy a code-signing certificate from a commercial CA, sign their driver, and have the chain still terminate at a Microsoft-recognised root [@ms-cross-cert-archive]. The architecture is documented on the cross-certificates for kernel-mode code signing page [@ms-cross-cert], which now opens with a sentence that did not exist in 2006: &quot;Cross-signing is no longer accepted for driver signing&quot; [@ms-cross-cert]. We will come back to that.&lt;/p&gt;

sequenceDiagram
    participant IO as I/O Manager
    participant CI as Code Integrity (ci.dll)
    participant CA as Cross-certified CA chain
    participant Root as Microsoft trusted root&lt;pre&gt;&lt;code&gt;IO-&amp;gt;&amp;gt;CI: Map PE for kernel driver
CI-&amp;gt;&amp;gt;CI: Extract Authenticode signature (PKCS#7)
CI-&amp;gt;&amp;gt;CA: Walk certificate chain
CA-&amp;gt;&amp;gt;Root: Anchor at Microsoft cross-cert
alt Chain valid and not revoked
    CI-&amp;gt;&amp;gt;IO: Allow section creation
    IO-&amp;gt;&amp;gt;IO: Load driver into kernel address space
else Chain invalid or unsigned
    CI-&amp;gt;&amp;gt;IO: STATUS_INVALID_IMAGE_HASH
    IO-&amp;gt;&amp;gt;IO: Abort load
end
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Documented escape hatches&lt;/h3&gt;
&lt;p&gt;KMCS shipped with three documented bypasses for developers and special cases, all enumerated on the KMCS policy page [@ms-kmcs-policy] [@ms-kmcs-policy]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bcdedit /set TESTSIGNING ON&lt;/code&gt; enables test-signing mode. The kernel will load drivers signed with self-issued test certificates. The cost is a desktop watermark.&lt;/li&gt;
&lt;li&gt;The F8 advanced-boot option &lt;em&gt;Disable Driver Signature Enforcement&lt;/em&gt; turns off KMCS for one boot.&lt;/li&gt;
&lt;li&gt;The legacy &lt;code&gt;nointegritychecks&lt;/code&gt; BCD flag disables enforcement entirely, but is rejected on systems where &lt;a href=&quot;https://paragmali.com/blog/secure-boot-in-windows-the-chain-from-sector-zero-to-userini/&quot; rel=&quot;noopener&quot;&gt;Secure Boot&lt;/a&gt; is on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these was a development workflow concession. Each of them, with admin privileges and a willingness to reboot, also serves as a kernel-driver loading path for an attacker who has already escalated. The policy holds against unprivileged adversaries. Against an attacker who already runs as administrator, the policy was already, by 2010, defending against a different threat than the one people thought it was defending against.Microsoft has been formally clear about this since at least 2016: the administrator-to-kernel transition is not a security boundary in the MSRC servicing-criteria sense. Elastic Security Labs writes the position out explicitly in their analysis of vulnerable-driver mitigations [@elastic-admin] [@elastic-admin]. The historical irony is that Vista x64 KMCS was widely read at the time as a defence against admin-level adversaries; it was actually a defence against unprivileged or pre-admin ones.&lt;/p&gt;
&lt;h3&gt;PatchGuard: the parallel runtime defence&lt;/h3&gt;
&lt;p&gt;KMCS was a load-time check. The runtime parallel arrived in 2005 with Kernel Patch Protection, informally PatchGuard or KPP, which the Wikipedia entry on Kernel Patch Protection [@wp-kpp] describes as a feature of 64-bit Windows that prevents patching of critical kernel structures [@wp-kpp]. KPP polls a set of integrity-critical kernel objects -- the System Service Descriptor Table, IDT, GDT, certain function prologues -- and triggers a bug check if it detects tampering. It is the watchdog against runtime modification of the kernel by code that has already loaded; KMCS gates what loads in the first place.&lt;/p&gt;
&lt;p&gt;What this fixed: the unsigned-driver-loading path closed on 64-bit Windows in production mode. Kernel rootkits of the early 2000s -- FU, Mailbot, Rustock, and their contemporaries, widely documented in the security-research literature of the era -- could no longer ship as bare &lt;code&gt;.sys&lt;/code&gt; files an admin script dropped on disk. The structural class of &quot;unsigned kernel rootkit&quot; effectively died on x64.&lt;/p&gt;
&lt;p&gt;But the day Vista x64 shipped, two new attack surfaces opened up. The first one Stuxnet found four years later. The second one nobody had a name for yet.&lt;/p&gt;
&lt;h2&gt;4. Stuxnet, BYOVD, and the Two Things Vista Did Not Fix&lt;/h2&gt;
&lt;p&gt;On 17 June 2010, researchers in Belarus and Iran identified Stuxnet, a worm targeting supervisory control and data acquisition systems [@wp-stuxnet] used in industrial-control environments [@wp-stuxnet]. Two of its drivers carried perfectly valid Authenticode signatures.&lt;/p&gt;
&lt;p&gt;The signatures were genuine. The certificates were not. Stuxnet had been signed with private keys stolen from semiconductor vendors whose code-signing certs chained to legitimate cross-certified roots. KMCS verified the chain, found it good, and let the drivers load.Stuxnet is widely reported to have used stolen signing keys from two real semiconductor vendors. The malware-analysis literature is consistent on the pattern; specific cert-holder attributions are reproduced in many places but the primary advisory record we cite here is the Wikipedia Stuxnet article [@wp-stuxnet] and the general framing in the Wikipedia code-signing article [@wp-code-signing] [@wp-stuxnet] [@wp-code-signing]. The reactive answer was certificate revocation, but revocation propagates through Windows on a schedule, not instantly, and the cached chain on millions of machines remained valid for days.&lt;/p&gt;
&lt;p&gt;That was the first failure mode KMCS could not block by design. The signature primitive answers &lt;em&gt;was this signed by a key that chains to a trusted root?&lt;/em&gt; It cannot answer &lt;em&gt;was the key still in the publisher&apos;s control when it signed this?&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;The Capcom.sys reframe&lt;/h3&gt;
&lt;p&gt;The second failure mode arrived publicly in 2016. A Capcom driver shipped via a Street Fighter V update exposed an IOCTL, numbered &lt;code&gt;0xAA013044&lt;/code&gt;, that took a user-supplied function pointer and executed it in kernel mode -- with Supervisor Mode Execution Prevention (SMEP) disabled while it did so. The driver was signed and chained correctly. Satoshi Tanda&apos;s standalone proof of concept at &lt;code&gt;tandasat/ExploitCapcom&lt;/code&gt; [@gh-tandasat-capcom] remains the canonical reference, including the SHA-1 of the binary (&lt;code&gt;c1d5cf8c43e7679b782630e93f5e6420ca1749a7&lt;/code&gt;) [@gh-tandasat-capcom].&lt;/p&gt;
&lt;p&gt;There was nothing for KMCS to catch. The driver did exactly what the signature said it did: ship bytes from a publisher Microsoft could identify. The signature has no opinion about the IOCTL surface.&lt;/p&gt;

A signed driver means only that someone Microsoft can identify shipped this binary. It does not mean the driver lacks a function-pointer IOCTL.
&lt;p&gt;That observation is the first of three reframes in this article and the easiest to underestimate. Up to 2010 the conventional security reading of a Microsoft-rooted Authenticode signature was that the driver had passed a review. After Stuxnet, the reading narrowed to &lt;em&gt;the publisher is identifiable&lt;/em&gt;. After Capcom.sys, it narrowed again to &lt;em&gt;the binary&apos;s identity is verifiable&lt;/em&gt;. None of these readings includes &lt;em&gt;the binary does not have a kernel-write primitive in its IOCTL handler&lt;/em&gt;.&lt;/p&gt;

An attack pattern in which an adversary, having obtained or already holding administrator privileges, installs a signed but design-vulnerable third-party kernel driver and uses its exposed primitives -- arbitrary memory read/write, port I/O, MSR access, or function-pointer dispatch -- to gain ring-zero capability. The signature primitive does not refuse the load because the driver is, on signature alone, legitimate.
&lt;h3&gt;The catalogue grows&lt;/h3&gt;
&lt;p&gt;The BYOVD catalogue accumulated through the 2010s.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RTCore64.sys&lt;/code&gt;, the kernel component of MSI&apos;s Afterburner overclocking utility, exposed read/write access to arbitrary kernel memory, I/O ports, and Model-Specific Registers from user mode. The NVD entry for CVE-2019-16098 [@nvd-cve-2019-16098] is unusually direct: &quot;These signed drivers can also be used to bypass the Microsoft driver-signing policy to deploy malicious code.&quot; [@nvd-cve-2019-16098] The driver became a workhorse for ransomware crews. Sophos&apos;s October 2022 incident analysis of BlackByte&apos;s new variant [@sophos-blackbyte] documents the abuse: BlackByte &quot;abus[ed] a known vulnerability in the legitimate vulnerable driver RTCore64.sys&quot; to disable &quot;a whopping list of over 1,000 drivers on which security products rely to provide protection&quot; [@sophos-blackbyte].&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gdrv.sys&lt;/code&gt;, the Gigabyte APP Center driver, exposed a ring-zero memcpy-equivalent that a local attacker could use to overwrite arbitrary kernel addresses. CVE-2018-19320 [@nvd-cve-2018-19320] is on CISA&apos;s Known Exploited Vulnerabilities catalogue [@nvd-cve-2018-19320]. The RobinHood ransomware abused it during the 2019 Baltimore municipal-government attack -- a connection widely documented by Sophos and CrowdStrike incident-response teams, though absent from the bare NVD record.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;KProcessHacker&lt;/code&gt;, the kernel companion to the Process Hacker administration tool, exposed a process-termination primitive that bypassed even the Protected Process Light (PPL) shielding around antivirus and EDR processes. CrowdStrike&apos;s DoppelPaymer write-up [@cs-doppelpaymer] documents the abuse explicitly: &quot;the hijacking technique ... leverages ProcessHacker&apos;s kernel driver, KProcessHacker, that has been registered under the service name KProcessHacker3 ... terminate processes, including those protected by Protected Process Light (PPL).&quot; [@cs-doppelpaymer]&lt;/p&gt;

sequenceDiagram
    participant Adv as Adversary (admin user mode)
    participant SCM as Service Control Manager
    participant CI as Code Integrity (ci.dll)
    participant Drv as Signed vulnerable driver
    participant K as Kernel state&lt;pre&gt;&lt;code&gt;Adv-&amp;gt;&amp;gt;SCM: Install signed driver as kernel service
SCM-&amp;gt;&amp;gt;CI: Request load
CI-&amp;gt;&amp;gt;CI: Authenticode check passes
CI-&amp;gt;&amp;gt;SCM: Allow
SCM-&amp;gt;&amp;gt;Drv: Load into kernel
Adv-&amp;gt;&amp;gt;Drv: IOCTL with attacker-supplied pointers
Drv-&amp;gt;&amp;gt;K: Write attacker bytes at arbitrary kernel address
K-&amp;gt;&amp;gt;K: Clear EDR notify routine / escalate token
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;The third bypass: patching the policy from kernel mode&lt;/h3&gt;
&lt;p&gt;There is a third failure mode that closes the loop. Once an attacker has a signed driver with an arbitrary kernel-write primitive, they can write directly into the in-kernel Code Integrity state. The variable of interest is &lt;code&gt;g_CiOptions&lt;/code&gt;, an integer inside &lt;code&gt;ci.dll&lt;/code&gt; whose bits gate Driver Signature Enforcement. TrustedSec describes the technique cleanly: &quot;this configuration variable has a number of flags that can be set, but typically for bypassing DSE this value is set to 0, completely disabled DSE and allows the attacker to load unsigned drivers just fine.&quot; [@trustedsec-gcioptions] Set &lt;code&gt;g_CiOptions&lt;/code&gt; to zero and the subsequent driver loads do not need signatures at all. The signed driver, in effect, is a one-shot key that opens the gate for any unsigned driver behind it. The pattern recurs through the early 2020s; specific malware-family attributions remain research-folklore, but the technique class is well attested in TrustedSec&apos;s account.&lt;/p&gt;
&lt;p&gt;The structural takeaway: KMCS verifies &lt;em&gt;who signed&lt;/em&gt;, never &lt;em&gt;what was signed&lt;/em&gt;. Once an attacker has a signed driver with a write primitive, they have ring zero. Stricter signing closes the front door for new malicious drivers. Every commercial-CA cert that was ever issued is still loadable. The policy decision has to move out of the attacker&apos;s reach. And the kernel itself has to stop being the thing that decides.&lt;/p&gt;
&lt;h2&gt;5. Microsoft as the Only Signer (2016-2024)&lt;/h2&gt;
&lt;p&gt;In August 2016, Microsoft did something the WHQL programme had refused to do for twenty years: it became the only entity that could counter-sign a new Windows kernel driver.&lt;/p&gt;
&lt;p&gt;The transition shipped with Windows 10 version 1607. The KMCS policy page [@ms-kmcs-policy] records the cut precisely: for end-entity certificates issued after 29 July 2015, the chain had to terminate at one of three Microsoft-owned roots -- &lt;em&gt;Microsoft Root Authority 2010&lt;/em&gt;, &lt;em&gt;Microsoft Root Certificate Authority&lt;/em&gt;, or &lt;em&gt;Microsoft Root Authority&lt;/em&gt; -- and the binary had to be counter-signed via the Windows Hardware Dev Center submission portal [@ms-kmcs-policy]. The commercial CAs were out. Microsoft was in, as the single point through which any new third-party kernel driver had to pass.&lt;/p&gt;
&lt;h3&gt;Two pipelines&lt;/h3&gt;
&lt;p&gt;Behind the portal sat two submission paths. The HLK/WHQL path required a full Hardware Lab Kit compatibility test pass on the publisher&apos;s hardware -- the lab kit is the modern incarnation of the WHQL programme, documented on Microsoft Learn [@ms-hlk] [@ms-hlk]. A passing run produced a &quot;Certified for Windows&quot; mark and made the driver eligible for OEM badging and Windows Update distribution. The lighter-friction path, called attestation signing [@ms-attestation], did not require an HLK run [@ms-attestation]. The publisher submitted a CAB containing the driver and supporting metadata. Microsoft&apos;s backend ran a malware scan and an automated policy check; if both passed, Microsoft applied a counter-signature. Attestation-signed drivers, the page notes, ship only to client SKUs.&lt;/p&gt;

The lower-friction post-2016 Microsoft signing path for Windows kernel drivers. The publisher uploads a CAB to the Hardware Dev Center; Microsoft runs malware scanning and an automated policy check; on pass, Microsoft applies its counter-signature. The path replaces full HLK testing for client-only drivers.
&lt;h3&gt;EV certificates as the account-binding primitive&lt;/h3&gt;
&lt;p&gt;Both paths required the publisher to hold an Extended Validation code-signing certificate. The EV cert does not sign the driver image itself; it signs and binds the Hardware Dev Center submission. That gives Microsoft a real-name handle on every kernel-driver publisher. EV certificates ride a strong identity check, cost meaningfully more than commercial OV certs, and live on a hardware token in the publisher&apos;s possession. The 2021 Microsoft Security blog announcing the Vulnerable &amp;amp; Malicious Driver Reporting Center spells the requirement out: &quot;Kernel-mode driver publishers must pass the Hardware Lab Kit (HLK) compatibility tests, malware scanning, and prove their identity through extended validation (EV) certificates.&quot; [@ms-vdrc-blog]&lt;/p&gt;

flowchart LR
    A[Publisher EV cert + driver CAB] --&amp;gt; B[Hardware Dev Center upload]
    B --&amp;gt; C[Malware scan]
    C --&amp;gt; D{HLK required?}
    D -- &quot;Yes&quot; --&amp;gt; E[HLK compatibility test pass]
    D -- &quot;No&quot; --&amp;gt; F[Attestation policy check]
    E --&amp;gt; G[Microsoft counter-sign]
    F --&amp;gt; G
    G --&amp;gt; H[Optional Windows Update distribution]
&lt;h3&gt;The legacy long tail&lt;/h3&gt;
&lt;p&gt;The pivot to Microsoft-only signing closed the door for new drivers. It did not close the door for old ones.&lt;/p&gt;

The KMCS policy page [@ms-kmcs-policy] is candid about the carve-outs: &quot;Cross-signed drivers are still permitted if any of the following are true: The PC was upgraded from an earlier release of Windows to Windows 10, version 1607. Secure Boot is off in the BIOS. Drivers was signed with an end-entity certificate issued prior to July 29th 2015 that chains to a supported cross-signed CA.&quot; [@ms-kmcs-policy]&lt;p&gt;Operationally, every signed-but-vulnerable driver from the 2006-2015 era remains loadable on a meaningful population of Windows machines: upgraded installs, devices with Secure Boot disabled in firmware, and drivers with pre-cutoff end-entity certs whose chains are still valid. &lt;code&gt;Capcom.sys&lt;/code&gt;, &lt;code&gt;RTCore64.sys&lt;/code&gt;, &lt;code&gt;gdrv.sys&lt;/code&gt;, &lt;code&gt;KProcessHacker&lt;/code&gt; -- the entire 2010s BYOVD catalogue -- continues to chain to roots Windows still accepts.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;What attestation signing catches and what it does not&lt;/h3&gt;
&lt;p&gt;The malware scan inside attestation signing looks for known dangerous behaviour. The Microsoft Security blog post on the Vulnerable &amp;amp; Malicious Driver Reporting Center enumerates the categories the backend flags: &quot;Drivers with the ability to read or write arbitrary kernel, physical, or device memory, including Port I/O and central processing unit (CPU) registers from user mode.&quot; [@ms-vdrc-blog] In other words, the scanner already understands the BYOVD pattern.&lt;/p&gt;
&lt;p&gt;What it does not catch are &lt;em&gt;novel&lt;/em&gt; design flaws. A driver whose IOCTL surface is structurally unsafe in a way the scanner does not have a signature for passes the scan and ships with a Microsoft counter-signature. The Capcom.sys pattern is in the scanner&apos;s repertoire today; the pattern in the next driver to ship is, by definition, not.&lt;/p&gt;
&lt;p&gt;A second weakness sits on the publisher side. EV-key compromise -- whether through the LAPSUS$ supply-chain leaks of 2022 or other vendor incidents -- gives the attacker the Microsoft-only-signing flavour of the Stuxnet problem. The signed-by-Microsoft chain is exactly as strong as the EV key&apos;s safekeeping at the publisher.&lt;/p&gt;
&lt;p&gt;One bottleneck for signing is an improvement. But the bottleneck still trusts the kernel that asks the question. As long as the policy engine runs in the same memory the attacker can write, the policy engine loses.&lt;/p&gt;
&lt;h2&gt;6. HVCI: Moving the Policy Out of Reach (2015-present)&lt;/h2&gt;
&lt;p&gt;In July 2015, Microsoft shipped a feature so structurally important that it took six years to become a consumer default, and so misunderstood that it still travels under three different names.&lt;/p&gt;
&lt;p&gt;The names are the easiest place to start. &lt;em&gt;Virtualization-Based Security&lt;/em&gt; (VBS) is the platform: a Hyper-V-rooted virtualisation layer that exists on every modern Windows installation that meets the hardware requirements. &lt;em&gt;Hypervisor-protected Code Integrity&lt;/em&gt; (HVCI) is the kernel-code-integrity consumer of VBS. &lt;em&gt;Memory Integrity&lt;/em&gt; is the label the Windows Security UI uses today. The Microsoft Learn page on Memory Integrity [@ms-hvci-vbs] is the canonical primary source [@ms-hvci-vbs]. TrustedSec called out the conflation explicitly in their &lt;code&gt;g_CiOptions in a virtualized world&lt;/code&gt; post [@trustedsec-gcioptions] [@trustedsec-gcioptions].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; A security check that shares a trust domain with what it is checking has, by definition, already lost. HVCI moves the check out of the attacker&apos;s trust domain. It is the answer to &lt;em&gt;who decides&lt;/em&gt;. It is not the answer to &lt;em&gt;what gets decided&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That sentence is the second of this article&apos;s three reframes, and the one that makes everything that follows make sense.&lt;/p&gt;
&lt;h3&gt;VBS and the Virtual Trust Levels&lt;/h3&gt;
&lt;p&gt;On a VBS-on Windows machine, &lt;a href=&quot;https://paragmali.com/blog/above-ring-zero-how-the-windows-hypervisor-became-a-security/&quot; rel=&quot;noopener&quot;&gt;Hyper-V&lt;/a&gt; is the Type-1 hypervisor. The bootloader brings the hypervisor up first, the hypervisor brings up two execution environments side by side, and the normal Windows kernel runs in one of them while a much smaller &lt;a href=&quot;https://paragmali.com/blog/the-windows-secure-kernel/&quot; rel=&quot;noopener&quot;&gt;Secure Kernel&lt;/a&gt; runs in the other.&lt;/p&gt;

The VBS abstraction that partitions a Windows installation into two execution environments. VTL0 is the normal Windows kernel and its drivers. VTL1 is a much smaller Secure Kernel and a curated set of &quot;trustlets&quot; -- isolated user-mode processes that hold the most sensitive secrets. VTL1 can read and write VTL0 memory; VTL0 cannot read or write VTL1 memory. Code-integrity policy lives in VTL1.
&lt;p&gt;The Code Integrity engine on an HVCI-on machine -- signature verification and policy-file consultation -- runs inside VTL1&apos;s Secure Kernel as the &lt;em&gt;Secure Kernel Code Integrity&lt;/em&gt; component, SKCI. The VTL0 kernel cannot read or write VTL1 memory by hardware construction: the hypervisor&apos;s second-level address translation tables, programmed before VTL0 ever runs, mark VTL1 pages as unreachable from VTL0. The in-memory &lt;code&gt;g_CiOptions&lt;/code&gt; state continues to reside in &lt;code&gt;ci.dll&lt;/code&gt;&apos;s VTL0 data section -- it does not relocate into VTL1 -- but on an HVCI-on machine Kernel Data Protection (KDP), exposed to VTL0 drivers as &lt;code&gt;MmProtectDriverSection&lt;/code&gt;, asks the Secure Kernel to mark the containing page read-only at the SLAT level. A fully compromised VTL0 kernel -- with kernel debugging attached, with all of ring zero&apos;s privileges -- cannot rewrite &lt;code&gt;g_CiOptions&lt;/code&gt; to zero, because the SLAT mapping refuses the write.&lt;/p&gt;

flowchart TD
    subgraph VTL1 [VTL1 -- Secure Kernel]
        SK[Secure Kernel]
        SKCI[SKCI -- Code Integrity]
        Policy[&quot;Code Integrity policy&lt;br /&gt;(DriverSiPolicy.p7b)&quot;]
        SK --&amp;gt; SKCI
        SKCI --&amp;gt; Policy
    end
    subgraph VTL0 [VTL0 -- Normal Windows]
        Kern[NT Kernel]
        Drv[Driver attempting load]
        CI[ci.dll user-side]
        Kern --&amp;gt; CI
        CI --&amp;gt; Drv
    end
    Hypervisor{&quot;Hyper-V SLAT&quot;}
    Kern --&amp;gt;|&quot;Section create&quot;| Hypervisor
    Hypervisor --&amp;gt;|&quot;Forward&quot;| SKCI
    SKCI --&amp;gt;|&quot;Allow or deny&quot;| Hypervisor
    Hypervisor --&amp;gt;|&quot;Result&quot;| Kern
&lt;h3&gt;W^X on kernel memory&lt;/h3&gt;
&lt;p&gt;There is a second, equally structural property HVCI enforces. When the VTL0 kernel tries to map an executable section -- to create a kernel-executable page from a PE image -- the hypervisor forces the request through SKCI. SKCI verifies the Authenticode signature &lt;em&gt;at section creation time&lt;/em&gt;, not only at the &lt;code&gt;IoLoadDriver&lt;/code&gt; entry point a load goes through later [@ms-hvci-vbs]. And SKCI refuses any page that is simultaneously writable and executable. The classic exploitation technique of allocating a writable kernel buffer, writing shellcode into it, and then jumping to it stops working: the page either is writable, in which case it is not executable, or is executable, in which case it is not writable.&lt;/p&gt;
&lt;p&gt;The hardware acceleration matters. The Memory Integrity page [@ms-hvci-vbs] is unusually direct about the requirement: &quot;Memory integrity works better with Intel Kabylake and higher processors with Mode-Based Execution Control, and AMD Zen 2 and higher processors with Guest Mode Execute Trap capabilities. Older processors rely on an emulation of these features, called Restricted User Mode, and will have a bigger impact on performance.&quot; [@ms-hvci-vbs]Mode-Based Execute Control (MBEC) is the Intel feature that lets the hypervisor distinguish &quot;executable in supervisor mode&quot; from &quot;executable in user mode&quot; at the page-table-entry level. AMD&apos;s Guest Mode Execute Trap (GMET) is the structurally equivalent feature. Older silicon falls back to Restricted User Mode emulation, which works correctly but pays a meaningfully larger performance tax. The hardware cutoff is a major reason HVCI defaulted off on pre-2017 OEM hardware for years.&lt;/p&gt;
&lt;h3&gt;What HVCI fixed&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;g_CiOptions&lt;/code&gt; patching family, the third bypass we met in section 4, closes on HVCI-on systems. TrustedSec&apos;s post [@trustedsec-gcioptions] gives a clean account: &lt;code&gt;g_CiOptions&lt;/code&gt; still lives in &lt;code&gt;ci.dll&lt;/code&gt;&apos;s VTL0 data section, but Kernel Data Protection -- exposed to VTL0 drivers as &lt;code&gt;MmProtectDriverSection&lt;/code&gt; -- asks the Secure Kernel in VTL1 to mark its containing page read-only at the SLAT level, so a VTL0 ring-zero write to it faults; the VTL0 kernel cannot rewrite the variable; live-kernel debuggers attached to VTL0 cannot rewrite it either [@trustedsec-gcioptions]. The arbitrary-write-to-disable-DSE pattern that worked on Windows 7 through pre-HVCI Windows 10 is, on an HVCI-on Windows 11, no longer a primitive that exists in the attacker&apos;s threat model. The trust domain that decides the policy is not the trust domain the attacker can reach.&lt;/p&gt;
&lt;h3&gt;What HVCI did not fix&lt;/h3&gt;
&lt;p&gt;It is essential to be clear about what HVCI does not catch, because misreading this is how the BYOVD class survives.&lt;/p&gt;
&lt;p&gt;HVCI verifies the &lt;em&gt;signature&lt;/em&gt; and enforces W^X. It does not analyse the driver&apos;s &lt;em&gt;behaviour&lt;/em&gt;. The 2019 &lt;code&gt;RTCore64.sys&lt;/code&gt; driver passes SKCI section-mapping unchanged: it is signed by MSI through a Microsoft-recognised chain, it has no writable-and-executable pages, and the Authenticode hash on disk matches the binary in memory. After it loads, an attacker in user mode sends an IOCTL; the driver, executing legitimately in ring zero, writes attacker-controlled bytes to an attacker-chosen kernel address; the EDR notify routine table is patched; the BYOVD attack proceeds. Everything that happens inside the IOCTL handler happens with kernel privilege, on properly-signed code paths, inside HVCI&apos;s W^X policy. The structural BYOVD class is unaffected.&lt;/p&gt;
&lt;p&gt;That is the gap the next two sections close.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Memory Integrity page [@ms-hvci-vbs] is explicit that &quot;some applications and hardware device drivers may be incompatible with memory integrity. This incompatibility can cause devices or software to malfunction and in rare cases may result in a boot failure (blue screen).&quot; [@ms-hvci-vbs] For years OEM and gaming-system vendors shipped with HVCI off because legacy ISV drivers, anti-cheat kernel components, or older virtualisation tools could not coexist with it. On an HVCI-off system the &lt;code&gt;g_CiOptions&lt;/code&gt; patching family is back in play, the kernel-CI engine and the kernel it polices are in the same trust domain, and the analysis of section 4 applies unchanged. The 2026 default-on baseline is real, but it is not yet universal.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;HVCI is the answer to &lt;em&gt;who decides&lt;/em&gt;. It is not the answer to &lt;em&gt;what gets decided&lt;/em&gt;. We still need a way to say: this specific signed binary is one we do not trust.&lt;/p&gt;
&lt;h2&gt;7. The Block List: Naming the Weakness (2020-present)&lt;/h2&gt;
&lt;p&gt;In October 2020, Microsoft started shipping something it had spent twenty-five years avoiding: a list of specific drivers it would refuse to load by name.&lt;/p&gt;
&lt;p&gt;The artefact lives at &lt;code&gt;%windir%\system32\CodeIntegrity\DriverSiPolicy.p7b&lt;/code&gt;. The file is a PKCS#7-signed &lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;App Control for Business&lt;/a&gt; policy -- &quot;WDAC&quot; by its former name -- whose body consists of deny rules expressed at the granularity of file hash, file name, or publisher. The canonical Microsoft-recommended driver block rules page [@ms-driver-block-rules] is the primary source, and is unusually rich for a Microsoft Learn page [@ms-driver-block-rules].&lt;/p&gt;

Microsoft&apos;s policy-driven application-control engine. An App Control policy is a signed XML or binary file that lists allow rules, deny rules, and signer-level rules; at load time, the policy engine consults the rules and either allows or refuses the image. `DriverSiPolicy.p7b` is itself an App Control policy whose body is all deny rules.
&lt;h3&gt;Cadence and the published-vs-shipped gap&lt;/h3&gt;
&lt;p&gt;The block list is refreshed on two cadences. Microsoft publishes the source XML on the block-rules page [@ms-driver-block-rules] on a quarterly schedule and pushes the binary &lt;code&gt;DriverSiPolicy.p7b&lt;/code&gt; to client devices through monthly Windows servicing [@ms-driver-block-rules]. Microsoft&apos;s Security Baselines team also publishes a running update post [@ms-tc-blocklist-baselines] cataloguing the changes [@ms-tc-blocklist-baselines].&lt;/p&gt;
&lt;p&gt;The candid admission on the block-rules page [@ms-driver-block-rules] is the part of the story that is most worth understanding.&lt;/p&gt;

The blocklist included in this article and in the associated downloadable files usually contains a more complete set of known vulnerable drivers than the version in the OS and delivered by Windows Update. It&apos;s often necessary for us to hold back some blocks to avoid breaking existing functionality. -- Microsoft Learn, *Microsoft-recommended driver block rules* [@ms-driver-block-rules]
&lt;p&gt;The published list is, on purpose, more inclusive than the shipped list. The reason is operational: every entry in the shipped list is a driver that would refuse to load on millions of devices, some of which have legitimate dependencies. Microsoft holds entries back when the compatibility cost is too high, even when the security signal is strong. We will come back to whether that gap is closeable in section 9.&lt;/p&gt;
&lt;h3&gt;The 22H2 cut and the Server 2016 carve-out&lt;/h3&gt;
&lt;p&gt;Two dates anchor the deployment story.&lt;/p&gt;
&lt;p&gt;The block list was an &lt;em&gt;optional&lt;/em&gt; feature in Windows 10 1809, enabled by default only on systems that ran Hypervisor-protected Code Integrity, Smart App Control, or Windows in S-mode [@ms-kb5020779] [@ms-kb5020779]. With the Windows 11 2022 Update, also known as 22H2 [@ms-blogs-win11-2022], released on 20 September 2022, default-on coverage extended to every client device, not just the HVCI-on subset [@ms-blogs-win11-2022]. The 22H2 release is the moment the block list became universal Windows client behaviour, six years after the first BYOVD primitive that motivated it.&lt;/p&gt;
&lt;p&gt;The block-rules page [@ms-driver-block-rules] notes a single explicit carve-out worth flagging.&quot;Except on Windows Server 2016, the vulnerable driver blocklist is also enforced when either memory integrity (also known as hypervisor-protected code integrity or HVCI), Smart App Control, or S mode is active.&quot; [@ms-driver-block-rules] Windows Server 2016 does not get the default-on block list even when HVCI is on. An enterprise admin managing Server 2016 has to deploy an explicit App Control policy to get the same coverage. The October 2022 preview cycle saw a documented quirk -- KB5020779 [@ms-kb5020779] explains that a preview release shipped without an actual blocklist refresh, addressed by a subsequent servicing update [@ms-kb5020779].The KB5020779 episode is a useful reminder that the in-box block list ships through the same Windows Update cycle as everything else. Preview releases do not always carry a fresh policy, and the cadence on the block-rules page [@ms-driver-block-rules] describes the intended steady state rather than every individual update [@ms-driver-block-rules].&lt;/p&gt;
&lt;h3&gt;Naming the weakness, not the publisher&lt;/h3&gt;
&lt;p&gt;For the first time in the story, the question Windows asks at load time is not only &lt;em&gt;who signed this binary?&lt;/em&gt; but also &lt;em&gt;is this specific signed binary one we have learned is unsafe?&lt;/em&gt; The block list is a step the previous generations could not have taken with the primitives they had: it requires a deny list that can be authored after the fact, distributed quickly, and enforced inside a trust domain the attacker cannot reach. KMCS supplied the load-time enforcement primitive; HVCI supplied the immune-from-VTL0 enforcement context; only with both in place could &lt;code&gt;DriverSiPolicy.p7b&lt;/code&gt; actually do its job.&lt;/p&gt;

flowchart TD
    A[Driver image requested for load] --&amp;gt; B[Hypervisor mediates section create]
    B --&amp;gt; C[SKCI verifies Authenticode chain]
    C --&amp;gt; D{&quot;Chain OK?&quot;}
    D -- &quot;No&quot; --&amp;gt; X[Refuse]
    D -- &quot;Yes&quot; --&amp;gt; E[Consult DriverSiPolicy.p7b deny rules]
    E --&amp;gt; F{&quot;Hash, name, or signer on deny list?&quot;}
    F -- &quot;Yes&quot; --&amp;gt; X
    F -- &quot;No&quot; --&amp;gt; G[Allow section creation]
    G --&amp;gt; H[Driver maps into kernel address space]
&lt;h3&gt;The Vulnerable &amp;amp; Malicious Driver Reporting Center&lt;/h3&gt;
&lt;p&gt;The block list grew faster after Microsoft built a structured channel to feed it. The December 2021 Microsoft Security blog post [@ms-vdrc-blog] announced the Vulnerable &amp;amp; Malicious Driver Reporting Center: a portal where researchers and vendors can submit kernel drivers for evaluation, backed by an automated analysis pipeline that looks for the BYOVD primitives -- &quot;the ability to read or write arbitrary kernel, physical, or device memory, including Port I/O and central processing unit (CPU) registers from user mode.&quot; [@ms-vdrc-blog] The post explicitly lists the historical CVE backdrop that motivated the centre, naming RobinHood, Uroburos, Derusbi, GrayFish, and Sauron as families that leveraged driver vulnerabilities such as CVE-2008-3431, CVE-2013-3956, CVE-2009-0824, and CVE-2010-1592 [@ms-vdrc-blog].&lt;/p&gt;
&lt;p&gt;The same post anchors the EV-certificate publisher requirement and the HLK or attestation gating that produces the block list&apos;s inputs in the first place. The reporting centre is the path by which a flagged driver moves from &quot;spotted in research&quot; to &quot;deny rule in the next quarterly XML push&quot;.&lt;/p&gt;
&lt;h3&gt;Defender ASR as the HVCI-off coverage path&lt;/h3&gt;
&lt;p&gt;There is a third surface worth knowing about. Microsoft&apos;s Attack Surface Reduction rules [@ms-asr-rules] include &quot;Block abuse of exploited vulnerable signed drivers&quot; (&lt;code&gt;56a863a9-875e-4185-98a7-b882c64b5ce5&lt;/code&gt;) as part of the standard ASR protection set [@ms-asr-rules]. For Microsoft Defender for Endpoint customers on Windows 10 E3 or E5, the rule covers machines where HVCI is not on. Microsoft notes that &quot;the same blocklist is also used by Microsoft Defender Antivirus customers&quot; via the ASR rule [@ms-vdrc-blog]. The path is narrower than HVCI-rooted enforcement -- Defender has to be running, the rule has to be enabled -- but it extends the block list to enterprise environments that have not yet flipped HVCI on.&lt;/p&gt;
&lt;h3&gt;LOLDrivers and the dual-use externality&lt;/h3&gt;
&lt;p&gt;The block list is not the only catalogue of vulnerable Windows drivers. The community-maintained LOLDrivers project [@loldrivers-io] -- &quot;Living Off The Land Drivers&quot; -- collects vulnerable, malicious, and known-malicious Windows drivers in one place. Every entry carries YAML metadata and where possible YARA, Sigma, ClamAV, and Sysmon rules, plus a pre-compiled App Control deny policy that can be deployed standalone [@gh-loldrivers] [@loldrivers-io]. As of the source verification for this article, LOLDrivers carried approximately 2,132 driver entries -- considerably more than the Microsoft-shipped list.&lt;/p&gt;
&lt;p&gt;Check Point Research called out the dual-use problem in their 2024 piece [@cpr-byovd]: a public catalogue of vulnerable drivers is also a reading list for attackers. The same researchers ran the methodology in reverse: &quot;we conducted a mass hunt for new drivers that may be vulnerable, uncovering thousands of potentially at-risk drivers.&quot; [@cpr-byovd] Defenders use the list for hardening; attackers use it for shopping. Both effects are real.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Defenders who can tolerate compatibility risk can compile the source XML from the block-rules page [@ms-driver-block-rules] into an App Control policy and deploy it directly, picking up the entries Microsoft holds back from the in-box list. Optionally layer the LOLDrivers App Control policy [@gh-loldrivers] on top for community-curated coverage. Test in audit mode first -- both lists are more aggressive than the shipped baseline and may flag drivers your environment depends on [@ms-driver-block-rules] [@gh-loldrivers].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;A WDAC rule evaluator, in miniature&lt;/h3&gt;
&lt;p&gt;The semantics of an App Control policy are simple enough to model in a few lines. Deny rules win; allow rules are consulted next; the default action handles whatever is left.&lt;/p&gt;
&lt;p&gt;{`
// Simplified model of the App Control / WDAC rule-evaluation engine.
// Deny rules win, allow rules permit the remainder, and an explicit
// default action handles images neither denied nor allowed.&lt;/p&gt;
&lt;p&gt;const policy = {
  denyByHash:    new Set([&quot;c1d5cf8c43e7679b782630e93f5e6420ca1749a7&quot;]), // Capcom.sys
  denyByName:    new Set([&quot;RTCore64.sys&quot;]),
  denyBySigner:  new Set([&quot;CN=Some Compromised Publisher, O=Example&quot;]),
  allowBySigner: new Set([&quot;CN=Microsoft Windows, O=Microsoft Corporation&quot;]),
  defaultAction: &quot;BLOCK&quot;,
};&lt;/p&gt;
&lt;p&gt;function evaluate(image, policy) {
  if (policy.denyByHash.has(image.sha1)) return &quot;BLOCK (hash on deny list)&quot;;
  if (policy.denyByName.has(image.fileName)) return &quot;BLOCK (name on deny list)&quot;;
  if (policy.denyBySigner.has(image.signer)) return &quot;BLOCK (signer on deny list)&quot;;
  if (policy.allowBySigner.has(image.signer)) return &quot;ALLOW (signer on allow list)&quot;;
  return policy.defaultAction === &quot;ALLOW&quot;
    ? &quot;ALLOW (default)&quot;
    : &quot;BLOCK (default)&quot;;
}&lt;/p&gt;
&lt;p&gt;const cases = [
  { sha1: &quot;c1d5cf8c43e7679b782630e93f5e6420ca1749a7&quot;, fileName: &quot;Capcom.sys&quot;,
    signer: &quot;CN=CAPCOM Co., Ltd.&quot; },
  { sha1: &quot;0000000000000000000000000000000000000000&quot;, fileName: &quot;RTCore64.sys&quot;,
    signer: &quot;CN=Micro-Star International Co., Ltd.&quot; },
  { sha1: &quot;1111111111111111111111111111111111111111&quot;, fileName: &quot;ntfs.sys&quot;,
    signer: &quot;CN=Microsoft Windows, O=Microsoft Corporation&quot; },
];
for (const c of cases) console.log(c.fileName, &quot;-&amp;gt;&quot;, evaluate(c, policy));
`}&lt;/p&gt;
&lt;p&gt;Naming the weakness is genuinely new. But the list only ever lists what someone has already found. The window between disclosure and enforcement is months, and Microsoft documents that the shipped list is by design weaker than the published one. What gets the rest of the way?&lt;/p&gt;
&lt;h2&gt;8. The 2026 Stack: Defence in Depth Made Concrete&lt;/h2&gt;
&lt;p&gt;On a default-configured Windows 11 22H2 machine in 2026, a kernel driver that tries to load passes through five distinct gates. Each one closes a blind spot the previous one cannot reach.&lt;/p&gt;
&lt;p&gt;The order matters, and so do the dependencies. The gates are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Kernel-Mode Code Signing.&lt;/strong&gt; The Authenticode chain must terminate at a Microsoft-owned root. The chain check rejects unsigned drivers and drivers chained to non-Microsoft roots, except under the documented grandfathering carve-outs [@ms-kmcs-policy] [@ms-kmcs-policy].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Vulnerable Driver Block List.&lt;/strong&gt; SKCI consults &lt;code&gt;DriverSiPolicy.p7b&lt;/code&gt; for hash, file-name, and signer-level deny rules. The list is default-on for every client device since Windows 11 22H2 [@ms-blogs-win11-2022], and is updated quarterly through Microsoft Learn&apos;s published source XML and monthly through Windows servicing [@ms-driver-block-rules] [@ms-blogs-win11-2022].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HVCI / SKCI.&lt;/strong&gt; The Code Integrity engine runs in VTL1, verifies signatures at section-mapping time rather than only at &lt;code&gt;IoLoadDriver&lt;/code&gt;, and enforces W^X on kernel memory. The policy engine is structurally out of reach of a fully compromised VTL0 kernel [@ms-hvci-vbs].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;App Control / Smart App Control.&lt;/strong&gt; Enterprise admins author explicit App Control allowlists; consumer devices on clean Windows 11 installs run Smart App Control [@ms-sac-faq], a Microsoft-authored allowlist policy backed by cloud reputation [@ms-sac-faq] [@ms-appcontrol].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Defender ASR.&lt;/strong&gt; On Microsoft Defender for Endpoint deployments, the &quot;Block abuse of exploited vulnerable signed drivers&quot; ASR rule extends block-list coverage to HVCI-off environments [@ms-asr-rules].&lt;/li&gt;
&lt;/ol&gt;

The Windows 11 22H2+ consumer-facing front end for App Control for Business. SAC enforces a Microsoft-authored policy and supplements it with cloud reputation lookups from the Intelligent Security Graph. SAC is only available on clean installs and is shipped in evaluation mode by default; once turned on, it also unconditionally enforces the vulnerable driver block list [@ms-sac-faq].

The cloud-backed reputation service that Smart App Control consults to predict whether a given binary is safe. When confident, ISG approves the binary; when unconfident, SAC falls back to signature checks; absent both, the binary is blocked [@ms-sac-faq].
&lt;h3&gt;Orthogonality, not redundancy&lt;/h3&gt;
&lt;p&gt;The five gates look redundant from a distance. They are not. Each closes a class of failure the others cannot reach. The orthogonality is the reason for the stack.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Gate&lt;/th&gt;
&lt;th&gt;Catches&lt;/th&gt;
&lt;th&gt;Misses&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;KMCS&lt;/td&gt;
&lt;td&gt;Unsigned and cross-cert-only-signed drivers&lt;/td&gt;
&lt;td&gt;Signed-but-vulnerable drivers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block list&lt;/td&gt;
&lt;td&gt;Known-vulnerable signed drivers (post-disclosure)&lt;/td&gt;
&lt;td&gt;Unknown-vulnerable signed drivers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HVCI / SKCI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;g_CiOptions&lt;/code&gt;-patching from VTL0; writable+executable kernel pages&lt;/td&gt;
&lt;td&gt;Behavioural BYOVD inside a properly-signed driver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WDAC / SAC&lt;/td&gt;
&lt;td&gt;Anything not on the allowlist (enterprise) or unknown-reputation (consumer)&lt;/td&gt;
&lt;td&gt;Allowlisted drivers with unknown defects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defender ASR&lt;/td&gt;
&lt;td&gt;Block-list entries on HVCI-off machines (where the rule is enabled)&lt;/td&gt;
&lt;td&gt;Drivers not on Microsoft&apos;s blocklist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The matrix is the practical justification for the stack. If &lt;code&gt;DriverSiPolicy.p7b&lt;/code&gt; had perfect coverage there would be no need for SAC; if SAC had a complete allowlist there would be no need for the block list; if HVCI proved driver safety rather than driver identity there would be no need for either. None of those preconditions hold, and section 9 explains why they cannot.&lt;/p&gt;
&lt;h3&gt;Smart App Control&apos;s particulars&lt;/h3&gt;
&lt;p&gt;SAC merits a few specifics because its behaviour differs from the rest of the stack in ways that surprise readers. First, it is consumer-facing and only available on clean Windows 11 installs -- an upgrade does not get SAC. Second, SAC ships in &lt;em&gt;evaluation mode&lt;/em&gt; by default. Windows watches user behaviour, and if the user mostly runs cloud-reputable software, SAC quietly flips to &lt;em&gt;enforce&lt;/em&gt;; if the user runs a lot of niche or self-developed software, SAC quietly flips to &lt;em&gt;off&lt;/em&gt;. Third, until a 2024 servicing change [@ms-sac-faq] made SAC re-enableable from Windows Security, turning SAC off used to require a clean install to bring it back [@ms-sac-faq]. Fourth, on enterprise-managed devices, SAC turns itself off automatically after 48 hours; managed environments are expected to deploy WDAC instead [@ms-appcontrol].&lt;/p&gt;
&lt;p&gt;The cold-start failure mode is worth knowing. A small independent hardware vendor whose driver has never been seen at scale lacks a cloud reputation when SAC asks about it. The fallback is signature, but a signed driver from an unknown publisher does not always clear SAC&apos;s confidence threshold. Small IHVs occasionally find their drivers blocked on consumer hardware running SAC for that reason alone.&lt;/p&gt;

flowchart TD
    A[Driver image requested] --&amp;gt; B[Gate 1: KMCS Authenticode chain]
    B --&amp;gt; C{&quot;Microsoft-rooted?&quot;}
    C -- &quot;No&quot; --&amp;gt; X[Refuse]
    C -- &quot;Yes&quot; --&amp;gt; D[Gate 2: DriverSiPolicy.p7b]
    D --&amp;gt; E{&quot;On block list?&quot;}
    E -- &quot;Yes&quot; --&amp;gt; X
    E -- &quot;No&quot; --&amp;gt; F[Gate 3: HVCI / SKCI section mapping]
    F --&amp;gt; G{&quot;Signature OK, W^X satisfied?&quot;}
    G -- &quot;No&quot; --&amp;gt; X
    G -- &quot;Yes&quot; --&amp;gt; H[Gate 4: App Control / SAC]
    H --&amp;gt; I{&quot;On allowlist or reputable?&quot;}
    I -- &quot;No&quot; --&amp;gt; X
    I -- &quot;Yes&quot; --&amp;gt; J[Gate 5: Defender ASR rule applicable]
    J --&amp;gt; K[Driver loads into VTL0 kernel]
&lt;h3&gt;Verifying what the machine actually does&lt;/h3&gt;
&lt;p&gt;The state of the stack on any given Windows machine is observable. The Win32_DeviceGuard WMI class exposes a &lt;code&gt;SecurityServicesRunning&lt;/code&gt; array whose integer codes name the security services currently active. The aside below covers the practitioner-facing details.&lt;/p&gt;

Two commands answer most of the question. From an elevated PowerShell prompt, `Get-CimInstance -Namespace root\Microsoft\Windows\DeviceGuard -ClassName Win32_DeviceGuard` returns a structure whose `SecurityServicesRunning` array enumerates the services in operation; a value of **1** indicates **Credential Guard**, a value of **2** indicates **HVCI / Memory Integrity**, and additional values cover newer services (System Guard Secure Launch, SMM Firmware Measurement, Kernel-mode Hardware-enforced Stack Protection, and Hypervisor-Enforced Paging Translation) [@ms-hvci-vbs]. `bcdedit /enum {default}` shows whether `hypervisorlaunchtype` is set to `Auto`, the prerequisite for VBS being on at all. The block list file itself lives at `%windir%\system32\CodeIntegrity\DriverSiPolicy.p7b`; if it is missing, the in-box list is not deployed on that machine. None of these tell you whether your Defender ASR rule is active without a separate `Get-MpPreference` check.
&lt;p&gt;A toy decoder helps make the WMI surface concrete.&lt;/p&gt;
&lt;p&gt;{`
// Mirror of the integer codes the Win32_DeviceGuard WMI class reports
// for SecurityServicesRunning. Documented on Microsoft Learn under
// the Memory Integrity / HVCI guidance.&lt;/p&gt;
&lt;p&gt;const SERVICE_NAMES = {
  1: &quot;Credential Guard&quot;,
  2: &quot;Hypervisor-protected Code Integrity (HVCI / Memory Integrity)&quot;,
  3: &quot;System Guard Secure Launch&quot;,
  4: &quot;SMM Firmware Measurement&quot;,
  5: &quot;Kernel-mode Hardware-enforced Stack Protection&quot;,
  6: &quot;Kernel-mode Hardware-enforced Stack Protection (Audit mode)&quot;,
  7: &quot;Hypervisor-Enforced Paging Translation&quot;,
};&lt;/p&gt;
&lt;p&gt;function explain(servicesRunning) {
  if (!servicesRunning.length) {
    return &quot;No VBS-rooted security services are running on this device.&quot;;
  }
  return servicesRunning
    .map((code) =&amp;gt; SERVICE_NAMES[code] || (&quot;unknown service &quot; + code))
    .map((s) =&amp;gt; &quot;  - &quot; + s)
    .join(&quot;\n&quot;);
}&lt;/p&gt;
&lt;p&gt;console.log(&quot;Sample 1: HVCI on, Credential Guard on&quot;);
console.log(explain([1, 2]));
console.log(&quot;\nSample 2: nothing running&quot;);
console.log(explain([]));
console.log(&quot;\nSample 3: full stack on a Secured-core PC&quot;);
console.log(explain([1, 2, 3, 4, 5]));
`}&lt;/p&gt;
&lt;p&gt;Five gates is a lot of work to do what one ideal gate could not. The reason for the inflation is uncomfortable: the one ideal gate cannot, in principle, exist.&lt;/p&gt;
&lt;h2&gt;9. The Undecidability Wall&lt;/h2&gt;
&lt;p&gt;Why does Windows need five layers to do what one perfect signature ought to do? Because the perfect signature is mathematically impossible.&lt;/p&gt;
&lt;p&gt;The third reframe of this article is the one that turns engineering frustration into theoretical inevitability. The property of interest -- &quot;this signed driver, when exercised through its IOCTL surface, can be coerced into giving an attacker an arbitrary kernel-write primitive&quot; -- is a non-trivial semantic property of the driver&apos;s program text. Rice&apos;s theorem says that for any non-trivial semantic property of programs, the predicate is undecidable on the class of all programs. No algorithm exists that, in finite time, answers correctly for every input.&lt;/p&gt;
&lt;p&gt;A useful way to state the bound: if $P$ is the set of all kernel drivers and $\text{Unsafe}(p) = 1$ iff driver $p$ exposes a kernel-write primitive through its IOCTL handler, then no total computable function $f: P \to {0, 1}$ satisfies $f = \text{Unsafe}$. Every approximation either over-blocks ($f(p) = 1$ when $\text{Unsafe}(p) = 0$, false positives, broken drivers) or under-blocks ($f(p) = 0$ when $\text{Unsafe}(p) = 1$, false negatives, BYOVD in the wild). The signing pipeline scans for the obvious cases; sophisticated dynamic analysers will catch more of the not-obvious cases; but the unrestricted version of the problem has no complete solution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Whether an arbitrary signed driver can be coerced into giving an attacker a kernel-write primitive is undecidable. No static signing scheme can ever block exactly the unsafe drivers. The Windows answer is therefore not a single perfect gate; it is defence in depth that narrows, but does not close, the gap.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Microsoft&apos;s formal acknowledgement&lt;/h3&gt;
&lt;p&gt;Microsoft has been formally clear about a related point for years: the administrator-to-kernel transition is not, in the MSRC servicing-criteria [@elastic-admin] sense, a security boundary [@elastic-admin]. Elastic Security Labs put the position in plain English: &quot;the blocklist&apos;s deployment model can be slow to adapt to new threats, with updates automatically deployed typically only once or twice a year. Users can manually update their blocklists, but such interventions bring us out of &apos;secure by default&apos; territory ... When determining which vulnerabilities to fix, the Microsoft Security Response Center (MSRC) uses the concept of a security boundary.&quot; [@elastic-admin]&lt;/p&gt;

Administrator-to-kernel is not a security boundary, in the MSRC servicing-criteria sense. The defence-in-depth mechanisms described here mitigate it; from the impossibility result, none can close it.
&lt;p&gt;The MSRC framing is engineering policy. The undecidability result is theoretical inevitability. They land in the same place: an attacker who has administrator privilege, who can pick from the entire history of signed Windows drivers, who is patient, is not stopped by any number of signature checks. The defence-in-depth mechanisms make the attacker work harder; they raise the cost; they shrink the surface of viable signed drivers. They do not close the structural gap.&lt;/p&gt;
&lt;h3&gt;Closeable gaps and irreducible gaps&lt;/h3&gt;
&lt;p&gt;It is worth separating two kinds of gap.&lt;/p&gt;
&lt;p&gt;The published-vs-shipped block list gap is a &lt;em&gt;policy&lt;/em&gt; decision, not an engineering limit. Microsoft documents that &quot;it&apos;s often necessary for us to hold back some blocks to avoid breaking existing functionality.&quot; [@ms-driver-block-rules]The published-vs-shipped gap is the closeable part. An administrator who can author or import an App Control policy can deploy the published XML directly and pick up Microsoft&apos;s full curation. The irreducible part of the gap sits behind it: even the published list lists only what someone has already disclosed. The undecidability result applies to &lt;em&gt;finding&lt;/em&gt; unsafe drivers, not to &lt;em&gt;listing&lt;/em&gt; known-unsafe ones. Defenders willing to accept compatibility risk can close it on their own machines today.&lt;/p&gt;
&lt;p&gt;The gap that cannot close is the one between the published list and the universe of vulnerable drivers Microsoft has not yet learned about. That is where the undecidability result bites. No amount of pipeline tightening eliminates the class of design flaws whose recognition requires understanding what the driver&apos;s IOCTL handler will do under all possible inputs.&lt;/p&gt;
&lt;h3&gt;What static methods &lt;em&gt;can&lt;/em&gt; achieve&lt;/h3&gt;
&lt;p&gt;Quantifying what the existing layers achieve is more useful than lamenting what they cannot. The complexity bounds for each layer are well-defined.&lt;/p&gt;
&lt;p&gt;Authenticode signature verification is bounded below by one public-key operation and one cryptographic hash over the PE image, regardless of policy. SKCI&apos;s per-section cost is dominated by that constant. The Memory Integrity page is conspicuously silent on a published benchmark number; in practice the overhead is small but non-zero on Intel Kabylake-and-later or AMD Zen-2-and-later silicon with MBEC/GMET hardware acceleration, and meaningfully higher on the emulated Restricted-User-Mode fallback path that older silicon falls back to [@ms-hvci-vbs].&lt;/p&gt;
&lt;p&gt;WDAC allowlist evaluation is $O(\log r)$ per image on $r$ rules with a hashed index, or $O(r)$ on the naïve linear scan; the deny-rule check in &lt;code&gt;DriverSiPolicy.p7b&lt;/code&gt; follows the same bound.&lt;/p&gt;
&lt;p&gt;The gap between achievable static enforcement and the ideal &quot;block all and only the unsafe drivers&quot; is, in the limit, irreducible.&lt;/p&gt;
&lt;h3&gt;Three axes that can be improved&lt;/h3&gt;
&lt;p&gt;If the gap cannot close, it can be narrowed along three independent axes -- and the improvements that matter, look like one of these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reactiveness.&lt;/strong&gt; The disclosure-to-enforcement latency is months today. Forthcoming WHCP submission-time analyses can compress it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coverage of unknown-bad signed drivers.&lt;/strong&gt; Reputation, allowlists, and dynamic analysis at scale extend coverage beyond what a static deny list lists.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visibility into binary contents.&lt;/strong&gt; SBOMs answer &quot;what is inside this driver?&quot; -- a question the signature alone never asked.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each axis is the answer to a different blind spot. None substitutes for another. Section 11 returns to the SBOM axis specifically because it is the one Microsoft is building into the submission flow right now.&lt;/p&gt;
&lt;p&gt;Static signing has hit a wall it cannot push through. The only way forward is to widen the question. Two of the answers exist on other operating systems. The third is being built now.&lt;/p&gt;
&lt;h2&gt;10. The Other Two Operating Systems&lt;/h2&gt;
&lt;p&gt;Linux solved the signing half and pushed the curated-denylist half down to distribution vendors. macOS solved both by making third-party drivers stop being drivers.&lt;/p&gt;
&lt;h3&gt;Linux: signatures without a curated denylist&lt;/h3&gt;
&lt;p&gt;Linux has supported in-kernel module signing since version 3.7 (December 2012), under the configuration symbol &lt;code&gt;CONFIG_MODULE_SIG&lt;/code&gt;. The kernel documentation [@docs-kernel-module-sig] catalogues the supported algorithms: &quot;The built-in facility currently only supports the RSA, NIST P-384 ECDSA and NIST FIPS-204 ML-DSA public key signing standards.&quot; [@docs-kernel-module-sig] The choice of signature scheme is a build-time decision, and the kernel can be told to use a key embedded in the kernel image, a key loaded into the trusted keyring at runtime, or a Machine Owner Key managed by &lt;code&gt;shim&lt;/code&gt; and the platform&apos;s UEFI boot stack.&lt;/p&gt;
&lt;p&gt;The structural decision that matters is the enforcement mode. &lt;code&gt;CONFIG_MODULE_SIG_FORCE&lt;/code&gt; is the toggle. The kernel documentation describes the two settings cleanly: &quot;If this is off (ie. &apos;permissive&apos;), then modules for which the key is not available and modules that are unsigned are permitted, but the kernel will be marked as being tainted ... If this is on (ie. &apos;restrictive&apos;), only modules that have a valid signature that can be verified by a public key in the kernel&apos;s possession will be loaded.&quot; [@docs-kernel-module-sig]&lt;/p&gt;
&lt;p&gt;Most mainstream distributions ship permissive: unsigned modules taint the kernel but load. The defender-shipping-restrictive-enforcement model is real on Secure-Boot-on RHEL and modern Ubuntu, paired with the Linux &lt;em&gt;lockdown&lt;/em&gt; security module, which restricts certain root-level kernel-modification paths even on signed builds.The Linux lockdown LSM is the closest mainline-Linux analogue to HVCI&apos;s policy-out-of-reach property. The &lt;code&gt;kernel_lockdown(7)&lt;/code&gt; man page [@man7-kernel-lockdown] describes lockdown as &quot;designed to prevent both direct and indirect access to a running kernel image&quot; and enumerates the restricted surfaces: &lt;code&gt;/dev/mem&lt;/code&gt;, &lt;code&gt;/dev/kmem&lt;/code&gt;, &lt;code&gt;/dev/kcore&lt;/code&gt;, kprobes, BPF, MSR alteration, ACPI table overrides, and unsigned kexec [@man7-kernel-lockdown]. It is a partial analogue, not equivalent: lockdown still runs in the same trust domain as the kernel it polices, so a sufficient kernel exploit defeats it. HVCI&apos;s VTL0/VTL1 split is structurally stronger.&lt;/p&gt;
&lt;p&gt;What Linux does not have is the equivalent of &lt;code&gt;DriverSiPolicy.p7b&lt;/code&gt;. There is no kernel-level curated denylist of &quot;we have learned this module is unsafe; refuse to load it by name&quot;. Defenders rely on per-distribution CVE trackers, on &lt;code&gt;modprobe.blacklist&lt;/code&gt;, and on &lt;code&gt;udev&lt;/code&gt; rules to keep specific modules out. The G5 generation -- naming the &lt;em&gt;weakness&lt;/em&gt; rather than the publisher -- has no mainline Linux equivalent at the kernel-loader level.&lt;/p&gt;
&lt;h3&gt;macOS: DriverKit removes the surface&lt;/h3&gt;
&lt;p&gt;Apple&apos;s answer is structurally different. Starting with macOS Catalina 10.15 [@apple-legacy-extensions] in 2019, Apple deprecated legacy kernel extensions for third parties and pushed them onto the DriverKit [@apple-driverkit] framework instead [@apple-legacy-extensions] [@apple-driverkit].&lt;/p&gt;

Apple&apos;s user-space driver framework, introduced with macOS Catalina 10.15. Third-party drivers ship as `.dext` user-space extensions linked against a curated IOKit subset; they receive IOKit messages from the kernel and respond with the same operations they used to perform in ring zero, but the code itself runs in user mode under sandbox restrictions. The kernel side of the new model exposes a controlled message surface; the third-party side cannot directly execute kernel code.
&lt;p&gt;A &lt;code&gt;.dext&lt;/code&gt; runs in user space under a sandbox profile. It can claim devices, register for IOKit interrupts, and exchange messages with kernel-side broker code -- but it cannot, in any usable sense, execute arbitrary code in the kernel address space. The Capcom.sys class of vulnerability cannot be expressed in DriverKit: there is no IOCTL surface whose handler runs in ring zero, because the handler does not run in ring zero. Apple reinforces the boundary further with System Integrity Protection [@apple-sip] (since 2015) and, on Apple Silicon, Kernel Integrity Protection (KIP), which makes the kernel page tables read-only after boot [@apple-sip].&lt;/p&gt;
&lt;p&gt;The price was paid by Apple&apos;s IHV community. Whole categories of third-party drivers -- deep audio, virtualisation, certain security tools -- spent years migrating, and some categories took multiple macOS releases before a DriverKit equivalent of a particular kext capability existed. Apple Silicon requires explicit reduced-security mode to load &lt;em&gt;any&lt;/em&gt; legacy kext at all: Apple&apos;s Platform Security guide [@apple-kext-aux] records that &quot;Kexts must be explicitly enabled for a Mac with Apple silicon by holding the power button at startup to enter into One True Recovery (1TR) mode, then downgrading to Reduced Security and checking the box to enable kernel extensions&quot; [@apple-kext-aux].&lt;/p&gt;
&lt;h3&gt;Why Windows cannot copy Apple&lt;/h3&gt;
&lt;p&gt;The reason Windows cannot make Apple&apos;s move in the short term is operational, not architectural. Windows&apos; IHV installed base is orders of magnitude larger and less centrally controlled. Microsoft does not own its hardware vendors the way Apple owns Macs. Breaking compatibility with twenty years of shipped kernel drivers would impose unbounded migration cost on third parties Microsoft cannot direct.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Windows (2026)&lt;/th&gt;
&lt;th&gt;Linux (mainline + RHEL-class hardening)&lt;/th&gt;
&lt;th&gt;macOS (Catalina+ / Apple Silicon)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Default signature enforcement&lt;/td&gt;
&lt;td&gt;Mandatory on x64 since 2006&lt;/td&gt;
&lt;td&gt;Permissive (taints kernel); restrictive on hardened distros&lt;/td&gt;
&lt;td&gt;Mandatory; legacy kexts deprecated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Curated denylist of signed-but-vulnerable artefacts&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DriverSiPolicy.p7b&lt;/code&gt;, default-on since 22H2&lt;/td&gt;
&lt;td&gt;None at kernel loader; per-distro CVE trackers&lt;/td&gt;
&lt;td&gt;Not needed -- third-party kexts removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Policy engine isolated from kernel it polices&lt;/td&gt;
&lt;td&gt;HVCI in VTL1&lt;/td&gt;
&lt;td&gt;Lockdown LSM (same trust domain)&lt;/td&gt;
&lt;td&gt;KIP and SIP on Apple Silicon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Third-party drivers in kernel&lt;/td&gt;
&lt;td&gt;Yes, still the model&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No -- DriverKit user-space dexts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operational price of the model&lt;/td&gt;
&lt;td&gt;Compatibility carve-outs, opt-outs&lt;/td&gt;
&lt;td&gt;Permissive default&lt;/td&gt;
&lt;td&gt;Multi-year IHV migration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Windows cannot move drivers to user space at Apple&apos;s speed. But it can look at &lt;em&gt;what is inside&lt;/em&gt; a driver in a way the signature alone never could. And it has been quietly building that capability since 2022.&lt;/p&gt;
&lt;h2&gt;11. What Comes Next: SBOM, Artifact Signing, Dynamic Analysis&lt;/h2&gt;
&lt;p&gt;If signatures cannot answer &quot;is this driver safe&quot;, and the block list can only ever answer &quot;is this driver known-unsafe&quot;, the next question Windows has to learn how to ask is &quot;what is inside this driver?&quot;&lt;/p&gt;
&lt;h3&gt;SBOM for drivers&lt;/h3&gt;
&lt;p&gt;A Software Bill of Materials is a structured inventory of the components, dependencies, and versions inside a software artefact. The mainstream community formats are SPDX (now at version 3.0) and CycloneDX; Microsoft contributes to and ships an open-source tool, microsoft/sbom-tool [@gh-sbom-tool], that produces SPDX-compatible SBOMs as part of a build pipeline [@gh-sbom-tool]. The repository description is plain: &quot;The SBOM tool is a highly scalable and enterprise ready tool to create SPDX 2.2 and SPDX 3.0 compatible SBOMs for any variety of artifacts. The tool uses the Component Detection libraries to detect components and the ClearlyDefined API to populate license information for these components.&quot; [@gh-sbom-tool]&lt;/p&gt;

A machine-readable inventory of components and dependencies inside a software artefact. For a Windows kernel driver, an SBOM lists the third-party static libraries linked into the PE, the open-source code paths bundled with the driver, and the versions of each, in a format (SPDX, CycloneDX) that automated tools can consume to answer &quot;is any component of this driver subject to a known vulnerability?&quot;
&lt;p&gt;The piece that affects Windows drivers specifically is the Windows Hardware Compatibility Program SBOM requirement. The Microsoft Q&amp;amp;A entry on Hardware Dev Center and CRA compliance [@ms-qa-cra] is candid: &quot;The WHCP SBOM requirement (Device.DevFund.Security.SoftwareBillofMaterials) has been deferred and will only be enforced starting in H2 2026.&quot; [@ms-qa-cra] The deferral aligns the WHCP rollout with the European Union&apos;s Cyber Resilience Act compliance window.&lt;/p&gt;

The EU Cyber Resilience Act sets phased compliance obligations for products with digital elements sold into the EU market. Among them is a requirement to produce a machine-readable SBOM that customers and regulators can inspect. Microsoft&apos;s WHCP SBOM mandate, scheduled for H2 2026, is the Windows-specific implementation of the same requirement, applied to kernel drivers submitted through the Hardware Dev Center. For regulated-industry IHVs, the WHCP gate and the CRA gate land at the same time and concern the same artefact [@ms-qa-cra].
&lt;p&gt;There is a structural problem an SBOM does not solve on its own. If the SBOM ships separately from the driver, an attacker who controls the distribution path can substitute a clean-looking SBOM for a contaminated driver. The WHCP submission flow is expected to bind the SBOM cryptographically to the artefact it describes so that a recipient can verify the binding, but the public documentation for the binding mechanism is still light beyond the WHCP SBOM mandate itself [@ms-qa-cra] [@ms-qa-cra].&lt;/p&gt;
&lt;h3&gt;Dynamic analysis at submission time&lt;/h3&gt;
&lt;p&gt;The other axis of improvement is reactiveness. Today, the typical disclosure-to-enforcement cycle for a new BYOVD driver looks like this: vendor ships, attacker exploits, researcher discloses, Microsoft adds to the quarterly published list, Windows servicing pushes to clients. The latency is months. Two recent research programmes show how dynamic analysis at scale can compress it.&lt;/p&gt;
&lt;p&gt;The first is the EURECOM/Politecnico di Milano NDSS 2026 paper on the authors&apos; publication page [@eurecom-paper]. The team built a DRAKVUF-based instrumentation layer called Kernelmon and traced every kernel function executed by signed drivers under malware-loaded workloads [@eurecom-paper]. The numbers are unusually concrete: the paper PDF [@eurecom-paper-pdf] reports that the team &quot;analyzed 8,779 malware samples that load 773 distinct signed drivers. It flagged suspicious behavior in 48 drivers, and subsequent manual verification led to the responsible disclosure of seven previously unknown vulnerable drivers&quot; [@eurecom-paper-pdf]. The companion S3 blog post [@eurecom-s3-blog] corroborates the 48-flagged / 7-disclosed numbers and notes that one of the seven received CVE-2024-26506 [@eurecom-s3-blog]. The technique is dynamic: it runs the driver under a hypervisor, watches what its IOCTL handlers actually do, and flags patterns characteristic of the BYOVD class.&lt;/p&gt;
&lt;p&gt;The second is Check Point Research&apos;s 2024 work [@cpr-byovd], which built a mass-hunt methodology around import-table signatures of risky kernel APIs and ran it across the global driver corpus. &quot;Using the same methodology, we conducted a mass hunt for new drivers that may be vulnerable, uncovering thousands of potentially at-risk drivers.&quot; [@cpr-byovd] The technique is static: it asks &lt;em&gt;what does the driver import?&lt;/em&gt; rather than &lt;em&gt;what does it do under exercise?&lt;/em&gt; Combined, the two approaches cover complementary halves of the surface.&lt;/p&gt;
&lt;p&gt;Neither currently gates Hardware Dev Center submissions. Both are candidates for the kind of submission-time check that would compress disclosure-to-enforcement latency from quarters to days.&lt;/p&gt;
&lt;h3&gt;Empirical patterns the defences have to recognise&lt;/h3&gt;
&lt;p&gt;Cisco Talos&apos;s BYOVD work, summarised in their &lt;em&gt;Exploring vulnerable Windows drivers&lt;/em&gt; post [@talos-byovd], classifies the post-load payloads attackers actually run [@talos-byovd]. Three behaviour classes dominate: token-swap escalation that overwrites the access token in the &lt;code&gt;_EPROCESS&lt;/code&gt; structure to reach SYSTEM; unsigned-code-loading that uses the kernel-write primitive to disable DSE or patch CI state; and EDR-killing that clears the kernel callback registrations endpoint detection products rely on. Each is a target for the dynamic analyses above, each is detectable by import-table heuristics, and each is what defenders see in the wild today.&lt;/p&gt;
&lt;p&gt;The historical roots are old. The Microsoft Security blog tracing the Vulnerable &amp;amp; Malicious Driver Reporting Center is direct: &quot;Multiple malware attacks, including RobinHood, Uroburos, Derusbi, GrayFish, and Sauron, have leveraged driver vulnerabilities (for example CVE-2008-3431, CVE-2013-3956, CVE-2009-0824, and CVE-2010-1592).&quot; [@ms-vdrc-blog] The payload classes have stayed remarkably stable for fifteen years.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The structural gap between &lt;em&gt;signed&lt;/em&gt; and &lt;em&gt;safe&lt;/em&gt; cannot close. It can be narrowed along three independent axes. Reactiveness: how long disclosure-to-enforcement takes (closeable by submission-time dynamic analysis along the lines of the EURECOM NDSS 2026 paper [@eurecom-paper] [@eurecom-paper] and Check Point&apos;s mass-hunt methodology [@cpr-byovd] [@cpr-byovd]). Coverage of unknown-bad signed drivers (extended by reputation-backed allowlists like Smart App Control and by WDAC enterprise policies). Visibility into binary contents (the H2 2026 WHCP SBOM mandate [@ms-qa-cra] and the SBOM-to-artefact binding the submission flow is expected to enforce [@ms-qa-cra]). Each axis closes a different blind spot. None substitutes for another.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Threats the stack cannot yet absorb&lt;/h3&gt;
&lt;p&gt;Three problems remain open and uncovered by the published roadmap. The Smart App Control cold-start window leaves small IHVs whose drivers have no cloud reputation to fall through to signature, and signature alone is exactly what we already established does not answer the question. BYOVD on HVCI-off environments, prevalent in older anti-cheat configurations and on enterprise machines with legacy ISV drivers, still admits the &lt;code&gt;g_CiOptions&lt;/code&gt;-patching family from VTL0 because there is no VTL1 to keep the policy out of reach. And the shipped-vs-published block list gap, while operationally rational and individually closeable by a willing administrator, is a gap any default-on customer carries.&lt;/p&gt;
&lt;p&gt;None of those closes by algorithmic improvement. Each closes only by widening the question.&lt;/p&gt;
&lt;p&gt;What started as a yes/no signature check has become a continually expanding set of questions Windows asks before it will hand a driver the keys to ring zero. None of those questions is sufficient. All of them are necessary. And the next one is already being written into the WHCP submission flow.&lt;/p&gt;
&lt;h2&gt;12. What This Means in Practice&lt;/h2&gt;
&lt;p&gt;Three audiences, three things to do.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Administrators.&lt;/strong&gt; Confirm the stack is on. &lt;code&gt;Get-CimInstance -Namespace root\Microsoft\Windows\DeviceGuard -ClassName Win32_DeviceGuard&lt;/code&gt; returns a &lt;code&gt;SecurityServicesRunning&lt;/code&gt; array; a &lt;code&gt;2&lt;/code&gt; in the array confirms HVCI. A &lt;code&gt;DriverSiPolicy.p7b&lt;/code&gt; in &lt;code&gt;%windir%\system32\CodeIntegrity\&lt;/code&gt; confirms the in-box block list is deployed. If you can tolerate the compatibility risk, compile the published block-rules XML [@ms-driver-block-rules] into an App Control policy and deploy it (audit mode first) [@ms-driver-block-rules]. If you run Windows Server 2016, you have to deploy an explicit policy yourself because the in-box default does not apply there [@ms-driver-block-rules]. If you ship through the Hardware Dev Center, schedule the H2 2026 WHCP SBOM gate now [@ms-qa-cra]. Subscribe to the Vulnerable &amp;amp; Malicious Driver Reporting Center cadence for new disclosures [@ms-vdrc-blog].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Driver authors.&lt;/strong&gt; Assume your IOCTL surface will be read by Check Point&apos;s import-table mass hunt [@cpr-byovd] and exercised by EURECOM&apos;s Kernelmon [@eurecom-paper] [@cpr-byovd] [@eurecom-paper]. Any handler that takes a user-supplied address and returns kernel data, or that dispatches a user-supplied function pointer, will end up on a block list on its current trajectory.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Researchers.&lt;/strong&gt; The field is wide open. The undecidability result is real, but the practical gap between what current analyses detect and what is, in principle, detectable for any specific vulnerability class is large. The NDSS 2026 paper found seven CVE-worthy drivers in a corpus of 773. The next paper will find more.&lt;/p&gt;
&lt;h3&gt;Every layer is somebody&apos;s incident report&lt;/h3&gt;
&lt;p&gt;Every layer in the 2026 stack exists because the previous one lost to a named adversary. Sony BMG XCP retired advisory signing. Stuxnet retired the assumption that a valid chain is a safe chain. Capcom.sys retired the assumption that a safe chain is a safe driver. RTCore64.sys, gdrv.sys, and KProcessHacker retired the assumption that the BYOVD class would burn itself out. Each entry on &lt;code&gt;DriverSiPolicy.p7b&lt;/code&gt; is somebody&apos;s incident report, recorded in the most permanent place Microsoft can put it -- the kernel loader&apos;s deny list.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Windows 11 22H2 ships with a list of drivers Microsoft will not load. The next list will be longer. The story has been adversarial since 1996 and the trajectory does not reverse: every layer was added because the previous one met an attacker. The structural gap is undecidable; the engineering gap, narrowable; the work, unfinished.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Frequently Asked Questions&lt;/h2&gt;


No. HVCI verifies the Authenticode signature at section-mapping time and enforces a write-xor-execute invariant on kernel memory; it does not analyse the driver&apos;s IOCTL surface. A signed driver with an unsafe IOCTL passes HVCI unchanged and proceeds to execute its handler in kernel mode with kernel privilege. That is what the Vulnerable Driver Block List is for: HVCI gates *who decides*; the block list gates *what gets decided*. See the Memory Integrity page [@ms-hvci-vbs] [@ms-hvci-vbs].

Yes. Microsoft publishes the source XML on the Microsoft-recommended driver block rules page [@ms-driver-block-rules] [@ms-driver-block-rules]. You can compile it into a binary App Control policy with the standard tooling and deploy it directly, picking up entries Microsoft holds back from the in-box list. Test in audit mode first because the published list is more inclusive than the shipped list and may flag drivers your environment depends on. Many defenders layer the LOLDrivers App Control policy [@gh-loldrivers] on top for community-curated coverage [@gh-loldrivers].

Windows Server 2016 does not enforce the block list by default, even when Memory Integrity is on. The block-rules page [@ms-driver-block-rules] calls this out explicitly [@ms-driver-block-rules]. If you administer Server 2016, deploy an explicit App Control policy to get the same coverage as the default-on 22H2 client.

App Control for Business (the engine formerly known as WDAC) is a policy *you* author. You define what signers, hashes, and paths are allowed; you ship and enforce the policy yourself. Smart App Control is a Microsoft-authored policy bundled with cloud reputation lookups via the Intelligent Security Graph. SAC is the consumer-friendly front end; App Control is the enterprise back end. SAC&apos;s default policy ships at `%windir%\schemas\CodeIntegrity\ExamplePolicies\SmartAppControl.xml`. SAC is consumer-only and turns itself off after 48 hours on enterprise-managed devices, where the expectation is that the operator deploys an App Control policy directly. See the Smart App Control FAQ [@ms-sac-faq] and the App Control for Business overview [@ms-appcontrol] [@ms-sac-faq] [@ms-appcontrol].

Increasingly yes. Major anti-cheat vendors have shipped HVCI-compatible kernel components since around 2023, but a meaningful tail of older configurations still requires HVCI off. On those configurations, the `g_CiOptions`-patching technique TrustedSec describes [@trustedsec-gcioptions] is back in play because the policy variable is no longer protected behind VTL1 [@trustedsec-gcioptions]. Audit your gaming-rig population if you care about coverage.

The in-box block list is Microsoft-curated with explicit compatibility holdbacks; the LOLDrivers catalogue [@loldrivers-io] is community-curated, considerably more inclusive (approximately 2,132 entries as of the source verification for this article), and ships with App Control deny policies, Sigma, YARA, ClamAV, and Sysmon detection content alongside the entries [@loldrivers-io] [@gh-loldrivers]. For threat hunting, use both. For enforcement, layer the LOLDrivers App Control policy on top of the in-box list if your environment can tolerate the compatibility risk. Check Point Research [@cpr-byovd] has documented the dual-use externality of any such public list -- attackers also read them -- but the defender net benefit of broader coverage outweighs the marginal attacker advantage on most environments [@cpr-byovd].

&lt;p&gt;&amp;lt;StudyGuide slug=&quot;vulnerable-driver-block-list-hvci-and-the-driver-signing-lifecycle&quot; keyTerms={[
  { term: &quot;Authenticode&quot;, definition: &quot;Microsoft&apos;s PKCS#7 code-signing format, used in Windows since 1996. Attests to publisher identity; does not analyse program behaviour.&quot; },
  { term: &quot;KMCS&quot;, definition: &quot;Kernel-Mode Code Signing. The mandatory load-time signature policy on 64-bit Windows since Vista x64 in 2006.&quot; },
  { term: &quot;BYOVD&quot;, definition: &quot;Bring Your Own Vulnerable Driver. An attack pattern in which an adversary installs a signed but design-vulnerable third-party driver to gain kernel capability.&quot; },
  { term: &quot;HVCI&quot;, definition: &quot;Hypervisor-protected Code Integrity, also called Memory Integrity. The Code Integrity engine running in VTL1 under a Hyper-V root, isolated from the VTL0 kernel.&quot; },
  { term: &quot;VTL&quot;, definition: &quot;Virtual Trust Level. VTL0 is the normal Windows kernel; VTL1 is the Secure Kernel and trustlets. VTL1 can read VTL0 memory but not vice versa.&quot; },
  { term: &quot;DriverSiPolicy.p7b&quot;, definition: &quot;The Microsoft-signed App Control deny policy that lists known-vulnerable signed kernel drivers and is default-on for all Windows 11 22H2 client devices.&quot; },
  { term: &quot;App Control for Business&quot;, definition: &quot;Microsoft&apos;s policy-driven application control engine, formerly WDAC. Used for both deny lists (the block list) and enterprise allowlists.&quot; },
  { term: &quot;Smart App Control&quot;, definition: &quot;Consumer-facing front end for App Control, backed by ISG cloud reputation. Available on clean Windows 11 22H2+ installs only.&quot; },
  { term: &quot;SBOM&quot;, definition: &quot;Software Bill of Materials. Machine-readable inventory of components and dependencies. Mandatory for WHCP submissions from H2 2026.&quot; },
  { term: &quot;DriverKit&quot;, definition: &quot;Apple&apos;s user-space driver framework. Third-party drivers ship as sandboxed dexts rather than kernel extensions; the BYOVD class is eliminated by construction.&quot; },
]} questions={[
  { q: &quot;Why did the Windows kernel-driver signing policy have to wait until Vista x64 to become mandatory?&quot;, a: &quot;The advisory SetupAPI-prompt model on 32-bit Windows could not be made mandatory without breaking compatibility with decades of unsigned drivers. The x64 architecture was a young platform with relatively few drivers in the field, which let Microsoft make the load-time signature requirement mandatory without disrupting an installed base.&quot; },
  { q: &quot;What single property of HVCI makes the g_CiOptions patching technique stop working?&quot;, a: &quot;HVCI runs the signature-verification and policy-consultation logic inside VTL1&apos;s Secure Kernel and uses Kernel Data Protection, exposed to VTL0 drivers as MmProtectDriverSection, to mark the VTL0 page containing g_CiOptions read-only at the second-level address translation level. The variable still resides in ci.dll&apos;s VTL0 data section, but a VTL0 ring-zero write to it faults because the SLAT mapping refuses the write -- and a live-kernel debugger attached to VTL0 cannot bypass that protection either.&quot; },
  { q: &quot;Why does Microsoft document that the published block list is more inclusive than the shipped one?&quot;, a: &quot;Some entries in the published list would block drivers that legitimate environments still depend on. Microsoft holds those entries back from the in-box DriverSiPolicy.p7b to avoid breaking existing functionality, while leaving them available in the source XML for defenders who can author their own App Control policies and accept the compatibility risk.&quot; },
  { q: &quot;Why is the BYOVD class undecidable to gate at the signing stage?&quot;, a: &quot;Whether an arbitrary signed driver exposes a kernel-write primitive through its IOCTL surface is a non-trivial semantic property of the driver&apos;s program text. Rice&apos;s theorem says no algorithm decides such properties for all programs. Static and dynamic analyses catch decidable subsets; the unrestricted class admits no complete solution.&quot; },
  { q: &quot;Why can Windows not simply move third-party drivers to user space the way macOS DriverKit did?&quot;, a: &quot;Apple owns its hardware vendors and could impose a multi-year migration on a comparatively centralised vendor community. Windows&apos; third-party IHV base is much larger and more independent; breaking compatibility with twenty years of shipped kernel drivers would impose unbounded migration cost on parties Microsoft does not direct.&quot; },
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-kernel</category><category>code-signing</category><category>hvci</category><category>byovd</category><category>driver-block-list</category><category>secure-kernel</category><category>app-control</category><category>kmcs</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>