# Above the Kernel: The Windows Security Wars Part 4 (2015-2019)

> Windows 10 ships Virtualization-Based Security and finally puts the credential store above the kernel -- in the same five years that ransomware became a billion-dollar industry.

*Published: 2026-05-27*
*Canonical: https://paragmali.com/blog/above-the-kernel-the-windows-security-wars-part-4-2015-2019*
*License: CC BY 4.0 - https://creativecommons.org/licenses/by/4.0/*

---
<TLDR>
Between July 2015 and December 2019, Windows shipped its largest structural security discontinuity since the NT design itself: Virtualization-Based Security (VBS), which moves the credential store and the kernel code-integrity policy into a Secure Kernel running at a privilege level the NT kernel cannot reach. In the same five-year window, ransomware industrialized from spray-and-pray to double extortion -- WannaCry, NotPetya, Ryuk, REvil, Maze -- and a third axis, Meltdown / Spectre, proved the CPU itself could be the attacker's primitive. The paradox of simultaneity is the whole story: a kernel-isolated 2017 Enterprise laptop and a paralyzed NHS trust both ran "Windows" that May 12, and the difference between them was not architecture but operations -- a missing patch on a network nobody had segmented.
</TLDR>

## 1. Two Scenes, One Five-Year Window

**Scene A.** A red-team operator, sometime in late 2016, sits in front of a freshly-imaged Windows 10 1607 Enterprise laptop with Credential Guard enabled. They open an elevated PowerShell, drop `mimikatz.exe` to disk, launch it, type `privilege::debug`. The prompt returns `'20' OK`. They type `sekurlsa::logonpasswords`. Output scrolls. The `NTLM` and `Kerberos` fields, where the cached hash and the Ticket Granting Ticket would normally appear, are empty. Not denied. Not access-restricted. Empty. The local LSASS process still exists; it still answers requests; the API surface is intact. But the secrets the operator came to read no longer live in this kernel.

**Scene B.** 11:00 a.m. UTC, May 12, 2017. The Royal London Hospital's radiology department. A workstation displays a red ransom note in eight languages. By 4:00 p.m., the National Audit Office will later determine, the attack has disrupted at least 34 percent of NHS trusts in England; some 19,000 patient appointments will be cancelled; ambulances will divert; junior doctors will hand-write prescriptions on paper [@nao-wannacry]. The exploit that delivered the worm to that machine, CVE-2017-0144, is one of the SMBv1 remote code execution flaws patched in Microsoft Security Bulletin MS17-010 [@ms-ms17-010] [@nvd-cve-2017-0144]. The patch shipped on March 14, 2017. It is, on May 12, one month and twenty-eight days old [@ms-ms17-010].

Both scenes happened. Both Windows boxes ran versions of the same operating system released in the same five-year window. Neither scene is hyperbole.

How can both be true at once? And what does the answer teach us about architectural defense -- its limits and its genuine accomplishments?

## 2. The Same-Privilege Paradox (1993-2014)

Here is a sentence to carry through the rest of this article: **a defense that lives at the same privilege level as the attacker can always be turned off.**

That sentence is the lesson of every Windows defense built between NT 3.51 in 1993 and Windows 8.1 in 2013. It is also the reason VBS had to exist at all.

Consider the pattern. The NT security model rests on access tokens and privileges. The privilege named `SeDebugPrivilege` lets a holder open any other process and read its memory. Local administrators get it by default; Mimikatz, released by Benjamin Delpy in May 2011, weaponized it [@wired-mimikatz]. Once an attacker reached local SYSTEM, `SeDebugPrivilege` let them walk into the Local Security Authority Subsystem Service (LSASS) and lift NTLM hashes and Kerberos tickets verbatim. The privilege check was working exactly as designed; the design assumed that whoever had the privilege deserved the data.

In 2005, with x64 versions of Windows Server 2003 SP1 and Windows XP, Microsoft introduced Kernel Patch Protection -- PatchGuard -- alongside Kernel-Mode Code Signing [@ms-patchguard]. PatchGuard's job was to detect modifications to critical kernel structures (the SSDT, the IDT, the GDT) and bugcheck the machine if it saw tampering. It was a watchdog inside the kernel watching the kernel.

By 2007, the indie research journal `Uninformed` published Skywing's third installment in a public series demonstrating how a kernel-mode attacker could disarm PatchGuard by rewriting its own code paths in-place [@skywing-patchguard]. The bypass was not a clever exploit; it was an inevitability. A monitor running in ring 0 has no privilege the rootkit lacks.

Driver Signing Enforcement followed the same logic and met the same fate [@ms-patchguard] [@skywing-patchguard]. So did Authenticode, AppLocker, and every other gate placed at the attacker's reachable privilege level. James Forshaw's August 2016 Project Zero work on AppContainer escape via shadow object directories rounded out the pattern: even the lowest-privilege sandboxes on Windows could be punctured by symbolic-link redirection executed at the sandbox's own privilege level [@pz-forshaw-shadow].

By 2012, three independent vectors had converged on the same insight. Bromium, co-founded by Xen architect Ian Pratt, shipped vSentry: a Type-1 micro-hypervisor that wrapped every risky task -- a browser tab, an opened document, an email attachment -- in its own micro-VM running underneath the Windows kernel [@wiki-bromium] [@silicon-bromium]. Microsoft's own massive investment in Hyper-V for Server 2012 had matured the company's hypervisor codebase. Intel's broad consumer-silicon rollout of Extended Page Tables and Second-Level Address Translation made hardware-assisted virtualization the default rather than the exception.

<Definition term="Same-privilege paradox">
The structural observation that any defensive mechanism running at the same CPU privilege level as the attacker can be disabled by the attacker. Gates at ring 3 fall to ring 3 code; gates at ring 0 fall to ring 0 code. The only structural escape is to relocate the defender to a privilege level the attacker cannot reach.
</Definition>

<Mermaid caption="Every named Windows defense built 1993-2014 lived at the attacker's reachable privilege level, and each one fell to a same-privilege primitive">
gantt
    title Windows defenses 1993-2014 and what disarmed each one
    dateFormat YYYY
    axisFormat %Y
    section Ring 3 gates
    SeDebugPrivilege (NT 1993)     :done, sedebug, 1993, 2011
    Mimikatz weaponization         :crit, mimi, 2011, 2012
    AppContainer (Win 8 2012)      :done, appc, 2012, 2016
    Symbolic link bypass (Forshaw) :crit, fshaw, 2016, 2017
    LSA Protection (RunAsPPL)      :done, ppl, 2013, 2015
    mimidrv.sys PPL bit removal    :crit, mimidrv, 2015, 2016
    section Ring 0 gates
    PatchGuard (Server 2003 SP1)   :done, pg, 2005, 2007
    Skywing PatchGuard bypass      :crit, sky, 2007, 2008
    Driver Signing Enforcement     :done, dse, 2007, 2012
</Mermaid>

The shared pattern in those tracks is not a series of individual failures. It is one structural failure repeated. Each "broken" line is a same-privilege primitive arriving on schedule and turning off the gate above it.

If every same-privilege defense fails the same way, what does a defense that does not live at the same privilege level look like?

## 3. Why Every Pre-VBS Credential Fix Failed

Picture a penetration tester in early 2015 working on a Windows 8.1 Pro host. The customer has done its homework. LSA Protection is enabled per Microsoft's guidance: the registry key `HKLM\SYSTEM\CurrentControlSet\Control\Lsa\RunAsPPL` is set to `1`, so the operating system launches `lsass.exe` as a [Protected Process Light](/blog/protected-process-light-when-the-administrator-isnt-enough/) [@ms-lsa-protection]. The tester opens Mimikatz, types `privilege::debug`, gets `OK`, and runs `sekurlsa::logonpasswords`. Access denied. The user-mode `OpenProcess` call against a PPL target fails for any non-PPL caller, regardless of how much administrator the caller has.

That looks like a win for the defender. It is not.

The tester drops to disk the signed Mimikatz driver, `mimidrv.sys`. They load it with a single `sc create / sc start` pair. From kernel mode, the driver locates the `EPROCESS` structure for LSASS and clears the `Protection` bits in the `_PS_PROTECTION` field. From the same elevated PowerShell, the tester re-runs `sekurlsa::logonpasswords`. The hashes scroll past.

The PPL bit was a gate. The gate was at the same ring as the lever that opened the gate. The lever was a signed kernel driver shipped by the same project that shipped the dumper.

itm4n, who maintains the most-cited reference write-up on RunAsPPL behavior, puts the point in one sentence: "Credential Guard and LSA Protection are actually complementary" [@itm4n-runasppl]. They are complementary because they live at different privilege boundaries. PPL is a same-privilege gate inside VTL0. Credential Guard, as we will see in Section 5, is something structurally different.

<PullQuote>
"Credential Guard and LSA Protection are actually complementary." -- itm4n, "Do You Really Know About LSA Protection (RunAsPPL)?"
</PullQuote>

Microsoft did not stop at PPL. Between 2013 and 2014 the company shipped three credential-theft mitigations, each genuinely useful, none structurally sufficient.

| Defense (year) | What it stops | What still works |
|---|---|---|
| Restricted Admin RDP (KB2871997, April 2014) | RDP no longer pushes plaintext or NTLM credentials to the destination machine | Lateral movement via pass-the-hash from a locally-captured hash; any local credential extraction on the source machine |
| Protected Users security group (Server 2012 R2, Oct 2013) | Disables NTLM and CredSSP credential delegation for member accounts; pre-Windows 8.1 cached creds purged | Plaintext credential capture during interactive sign-in; non-member accounts; pass-the-ticket once a TGT is obtained |
| LSA Protection / RunAsPPL (Win 8.1, Oct 2013) [@ms-lsa-protection] | User-mode `OpenProcess` against `lsass.exe` for non-PPL callers fails; conventional Mimikatz from user-land is blocked | A kernel-mode primitive (`mimidrv.sys`, BYOVD, or a vulnerable signed driver) clears the PPL bits from `_PS_PROTECTION` and the dump proceeds |

Read the right-hand column as a single sentence. *Every defense in the left column was bypassed by the same class of move: the attacker reached a privilege at or above the privilege of the gate, and then the gate opened.*

That is not a flaw in any one of these features. That is the same-privilege paradox arriving in three different costumes.

<Sidenote>itm4n's full write-up is worth reading end-to-end if you defend Windows endpoints. The author's `PPLdump` proof-of-concept builds the BYOVD-against-PPL attack as a single tool, and the post is unambiguous that PPL is a "same-privilege gate" while Credential Guard is a "cross-privilege isolation" -- the exact distinction this section turns on.</Sidenote>

The reader who has watched a working defender press-release call any of these features "the answer to Mimikatz" will recognize the move by now. Every fix between 2013 and 2014 was at the attacker's privilege level. Every fix between 2013 and 2014 fell to a primitive at that privilege level. The pattern is not implementation bug. The pattern is structure.

If incremental fixes at the attacker's privilege level cannot work, what does a structural fix look like?

## 4. Three Generations Toward Cross-Privilege Isolation

The structural answer arrived in three generations, only one of which worked.

**Generation A2 -- the kernel monitors the kernel (2005-2014).** PatchGuard, KMCS, Driver Signing Enforcement. We have already met this generation. Microsoft did not abandon these defenses; the Windows kernel still bugchecks on PatchGuard violations today. But by 2014 the security research community had collectively documented enough kernel-mode bypasses that nobody serious treated PatchGuard as a primary defense [@ms-patchguard] [@skywing-patchguard]. Its function was to raise the cost of low-skill kernel rootkits, not to stop a SYSTEM-privileged attacker.

**Generation A3 -- the process is sandboxed (2008-2015).** Internet Explorer's Protected Mode (2006), Chrome's renderer sandbox (2008), and Microsoft's own [AppContainer model](/blog/appcontainer-and-lowbox-tokens-windowss-capability-sandbox/) in Windows 8 (2012) reduced the privilege of risky processes -- the browser tab, the document parser, the network listener -- below that of the parent user [@ms-appcontainer]. The threat model is RCE-in-renderer. The threat model is *not* SYSTEM-privilege takeover, because a sandbox does not stop credential theft once an attacker is already inside the user's session at full privilege. James Forshaw's August 2016 demonstration of AppContainer escape via shadow object directories closed the chapter [@pz-forshaw-shadow]. Sandboxes remain essential at the edge; they do not solve the post-exploitation problem.

**Generation A4 -- cross-privilege isolation (2012-2015).** Bromium's vSentry, launched commercially in September 2012, was the first product to deliver the idea that mattered: a Type-1 micro-hypervisor running underneath the Windows kernel, with each risky task placed in its own micro-VM [@silicon-bromium] [@wiki-bromium]. The hypervisor sits at a privilege level the guest kernel cannot reach. If the guest kernel falls, the micro-VM is destroyed and the rest of the host is untouched. By 2015, Microsoft had taken the same architectural idea and built it into the operating system. Generation A4 is the only generation in which the defender's privilege level changes.

<Mermaid caption="Three generations of post-NT Windows defense -- only the third changes the defender's privilege level">
flowchart LR
    A1[Generation A2<br/>2005-2014<br/>Kernel monitors kernel<br/>PatchGuard, KMCS, DSE]
    A2[Generation A3<br/>2008-2015<br/>Process sandbox<br/>AppContainer, Protected Mode]
    A3[Generation A4<br/>2012-2015<br/>Cross-privilege isolation<br/>Bromium uVisor, then VBS]
    A1 --> R1[Outcome<br/>Same ring as attacker<br/>Same-privilege bypass]
    A2 --> R2[Outcome<br/>Below user privilege<br/>Wrong threat model for SYSTEM-takeover]
    A3 --> R3[Outcome<br/>Above guest kernel<br/>Defender unreachable from VTL0]
</Mermaid>

The structural lesson, said plainly: *the only escape from the same-privilege paradox is to move the defender's privilege level, not to harden the gate.*

<Aside label="Bromium's commercial lineage">
HP Inc. acquired Bromium in September 2019 [@wiki-bromium]. The uVisor concept survived as HP Sure Click, a vertical-market product shipped on HP business notebooks. Bromium's contribution to the public story of Windows security is that it shipped the cross-privilege-isolation thesis as a working commercial product three years before Microsoft put it in the box. The reader who sees "Bromium" in a vendor presentation now knows the lineage: same idea, narrower market, earlier ship date.
</Aside>

What did Microsoft actually ship?

## 5. The Breakthrough: VBS, the Secure Kernel, and Trustlets

On July 29, 2015, Microsoft shipped Windows 10 version 1507, build 10240 [@wiki-win10-versions]. The same release window delivered five components -- Virtualization-Based Security, Credential Guard, Device Guard with Windows Defender Application Control, the Antimalware Scan Interface, and Control Flow Guard. One week later, on August 6, Alex Ionescu walked onto the Black Hat USA stage in Las Vegas and explained the internals in a deck titled *Battle of SKM and IUM: How Windows 10 Rewrites OS Architecture* [@ionescu-bh2015].

That deck is the load-bearing primary for the rest of this section. Where the prose below cites an internal mechanism -- an EKU OID, a process attribute, a syscall ordinal -- it is reading Ionescu first and Microsoft Learn second.

<Definition term="Virtualization-Based Security (VBS)">
A Windows security architecture that uses hardware virtualization extensions (Intel VT-x, AMD-V) and Second-Level Address Translation to run two isolated kernel environments on the same physical machine: the conventional NT kernel and a stripped-down Secure Kernel. Microsoft's official framing is that VBS "creates an isolated virtual environment that becomes the root of trust of the OS that assumes the kernel can be compromised" [@ms-vbs].
</Definition>

### 5.1 Hyper-V as the substrate

VBS does not invent a new hypervisor. It reuses the [Hyper-V hypervisor](/blog/above-ring-zero-how-the-windows-hypervisor-became-a-security/) Microsoft had already shipped for Server 2008 and matured through Server 2012 [@ms-tlfs-vsm]. On a machine with VBS enabled, the Windows boot path is: UEFI Secure Boot -> Hyper-V hypervisor -> Hyper-V root partition. Inside that root partition, the NT kernel runs in one Virtual Trust Level and the [Secure Kernel](/blog/the-windows-secure-kernel/) runs in another.

<Definition term="Virtual Trust Level (VTL)">
A Hyper-V hypervisor abstraction that partitions a single virtual machine into multiple privilege domains. Higher-numbered VTLs are strictly more privileged than lower-numbered ones; lower VTLs cannot read or write higher-VTL memory. The Hyper-V Top-Level Functional Specification reserves up to 16 VTLs, of which only VTL0 (NT kernel) and VTL1 (Secure Kernel) are used in shipped Windows configurations [@ms-tlfs-vsm].
</Definition>

A process running with full SYSTEM privilege in VTL0 sees the conventional NT API surface. It can call `NtReadVirtualMemory` on any VTL0 process. It cannot read VTL1 memory at all, because the hypervisor's Extended Page Tables for VTL1 simply do not map VTL1 pages into the VTL0 address space. The Mimikatz dumper that read `lsass.exe` in 2011 is technically still running on the new machine. It is just reading the empty husk of LSASS, because the secret bytes were never copied into VTL0 in the first place.

### 5.2 The Secure Kernel

`securekernel.exe`, the binary that backs VTL1, is on the order of a few hundred kilobytes. It has no device drivers. It has no graphics stack. Its scheduler is minimal [@ionescu-bh2015]. Its paging is handled by asking the VTL0 NT kernel for help -- the Secure Kernel treats the NT kernel as an untrusted resource manager that may return a page or not, and signs and encrypts anything it sends out to be paged. The smallness is not aesthetic. Smallness is part of the threat model. The Secure Kernel is small so that its attack surface is enumerable, and so that the team responsible for its correctness can review every line.<Sidenote>The audited binary size is also why VBS does not run user applications in VTL1. The Secure Kernel hosts only "trustlets" -- a tightly bounded set of Microsoft-signed processes designed to do one cryptographic or measurement task each. Putting your code in VTL1 is not on the application developer's path; it is a privilege Microsoft grants its own modules.</Sidenote>

### 5.3 Isolated User Mode and trustlets

Above the Secure Kernel, in user-mode VTL1, runs a stripped-down user-mode environment Microsoft calls Isolated User Mode (IUM). The processes hosted by IUM are called [trustlets](/blog/vbs-trustlets-what-actually-runs-in-the-secure-kernel/).

<Definition term="Isolated User Mode (IUM)">
The VTL1 user-mode environment in which trustlets execute. IUM provides a deliberately reduced syscall surface compared to VTL0 user mode -- Ionescu's BH 2015 deck enumerates an approximately 48-syscall allow-list, all routed through the Secure Kernel rather than through `ntoskrnl.exe` [@ionescu-bh2015].
</Definition>

<Definition term="Trustlet">
A Microsoft-signed process that runs in Isolated User Mode and is protected from VTL0 inspection. A binary becomes a trustlet only by passing five gates at process creation, all enumerated in Ionescu's Black Hat 2015 deck [@ionescu-bh2015]: (1) a process attribute set on the `NtCreateProcessEx` call, (2) two Enhanced Key Usage OIDs in the Authenticode signature at Signature Level 12 -- the Microsoft Windows System Component Verification EKU `1.3.6.1.4.1.311.10.3.6` and the IUM EKU `1.3.6.1.4.1.311.10.3.37`, (3) a `.tpolicy` PE section, (4) a Trustlet Instance GUID, and (5) loading via the trustlet-specific loader that enforces the syscall allow-list.
</Definition>

<Sidenote>The two EKU OIDs are worth memorizing because they are the primary way a defender or auditor can tell, by inspecting a signed binary, whether it is permitted to run as a trustlet at all. Ionescu's deck flagged a typographic error in one OID on a slide; cross-cite Microsoft documentation for the canonical form. The OIDs above are the canonical form [@ionescu-bh2015].</Sidenote>

The five-gate pattern matters because it explains what an attacker has to do to *create* a trustlet, and the answer is: forge a Microsoft signature. The five gates are not security in series; they are security in identity. A binary either has the EKUs Microsoft issues or it does not.

### 5.4 The canonical 1507-era trustlet roster

Three trustlets shipped in the first 1507 wave. Ionescu's deck enumerates their integer IDs [@ionescu-bh2015]:

- **Trustlet ID 1 -- LSAISO** (the Local Security Authority Isolated). The Credential Guard secret-keeper. Holds the NTLM hashes, the Kerberos Ticket Granting Tickets, and any other credentials Credential Guard is protecting.
- **Trustlet ID 2 -- vTPM**. The virtual Trusted Platform Module used by Hyper-V shielded VMs in the Server 2016 timeframe.
- **Trustlet ID 3 -- the Biometrics trustlet** (Windows Hello). Holds biometric template data; in later Windows 11 documentation the same isolation primitive is marketed as Enhanced Sign-in Security (ESS), but that name is a Windows 11-era rebrand and post-dates the 2015 enumeration.

ID 0 in the IUM trustlet table is reserved as a system bootstrap slot per the table's 1-indexing convention; the publicly available 1507-era material -- Ionescu's Black Hat USA 2015 deck and the *Windows Internals* 7th edition Chapter 7 -- does not separately attest ID 0 as an end-user-deployable trustlet, so it is best read as a system-reserved slot rather than as a named credential-isolation primitive [@ionescu-bh2015] [@mspress-windows-internals-7e].

<Definition term="LSAISO (Trustlet ID 1)">
The trustlet that backs Credential Guard. The conventional LSASS process continues to run in VTL0 and answers the same API calls it always did, but on a Credential Guard-enabled system the NTLM hash and Kerberos TGT are stored inside LSAISO in VTL1. When LSASS needs to use a credential -- for example, to construct a Kerberos pre-authentication response -- it crosses the secure-call channel to LSAISO, which performs the cryptographic operation inside VTL1 and returns only the derived result. The raw secret never crosses the VTL boundary back into VTL0 [@ms-credential-guard].
</Definition>

### 5.5 The secure-call channel

VTL0 and VTL1 talk via a small set of secure-call ordinals. The canonical primitive Ionescu names is `IumSetTrustletInstance` at ordinal `0x80000001`, paired with a handful of agent-trustlet RPC patterns [@ionescu-bh2015]. The semantic invariant is the same on every call: VTL0 sends a request, VTL1 performs work on protected data, VTL1 returns either a result the requester is permitted to see or a failure. The secret never leaves VTL1.

<Mermaid caption="VBS architecture: Hyper-V hosts VTL0 (NT kernel and user processes) and VTL1 (Secure Kernel and trustlets) side by side">
flowchart TB
    HW[Hardware<br/>CPU with VT-x/AMD-V<br/>SLAT, IOMMU, TPM 2.0]
    UEFI[UEFI Secure Boot]
    HV[Hyper-V hypervisor]
    HW --> UEFI --> HV
    subgraph VTL0[VTL0 -- NT environment]
        NTK[NT kernel<br/>ntoskrnl.exe, drivers]
        UMP[User-mode processes<br/>LSASS, services, apps]
        NTK --- UMP
    end
    subgraph VTL1[VTL1 -- Secure environment]
        SK[Secure Kernel<br/>securekernel.exe]
        IUM[Isolated User Mode<br/>trustlets: LSAISO, vTPM, ESS]
        SK --- IUM
    end
    HV --> VTL0
    HV --> VTL1
    VTL0 -.secure-call channel.-> VTL1
    ATK[Attacker reach<br/>caps at VTL0 SYSTEM] -.-> NTK
</Mermaid>

The diagram is worth reading twice. The attacker's reachable privilege ceiling is the dashed line into VTL0. Everything above the secure-call channel is, by hardware-enforced page-table convention, unreachable from below.

<Mermaid caption="The five gates a process must pass at creation to become a trustlet">
sequenceDiagram
    participant App as Caller
    participant NT as NT kernel
    participant Loader as Trustlet loader
    participant SK as Secure Kernel
    App->>NT: NtCreateProcessEx with trustlet process attribute
    NT->>Loader: Validate Authenticode signature
    Loader->>Loader: Check EKU 1.3.6.1.4.1.311.10.3.6
    Loader->>Loader: Check EKU 1.3.6.1.4.1.311.10.3.37
    Loader->>Loader: Parse .tpolicy PE section
    Loader->>SK: Assign Trustlet Instance GUID
    SK->>SK: Install reduced syscall allow-list
    SK-->>App: Trustlet process handle
</Mermaid>

### 5.6 The conceptual hinge

Stop here and reread the architecture. The NT kernel is still compromisable. A driver bug, a BYOVD attack, a kernel race condition -- all of those still pop SYSTEM in VTL0 the same way they did in 2014. VBS does not pretend otherwise. The Microsoft Learn VBS landing page is explicit that VBS "assumes the kernel can be compromised" [@ms-vbs]. The defensive invariant has nothing to do with keeping attackers out of the NT kernel. The defensive invariant is that the secrets they came for are not in the NT kernel.

> **Key idea:** VBS does not protect the NT kernel from compromise. It guarantees that even a fully-compromised NT kernel cannot reach the secrets held in VTL1 trustlets.

That sentence is the entire defensive thesis of Windows 10. Once a reader has it, every component shipped between 1507 and 1909 -- Credential Guard, HVCI, AMSI, CFG, Process Mitigation Policies -- reads as a follow-on instance of the same trust-topology move, modulated by what is hardware-rooted versus software-instrumented.

LSAISO holds the NTLM hash and the Kerberos TGT. That handles credential theft. What about the rest of the attack surface?

## 6. The 2019 Defensive Stack

By Windows 10 version 1909, shipped November 12, 2019 [@ms-release-info] [@wiki-win10-versions], the VBS architecture had grown a six-feature shipping stack -- Credential Guard, HVCI, WDAC, AMSI, CFG, and Process Mitigation Policies -- plus a cloud-backed endpoint detection and response backend in Defender Advanced Threat Protection. Each closes a specific attack class. Each has a deliberate, named bypass surface. The mature defender's question by the end of 2019 was no longer "is it deployed" but "which class is left."

### 6.1 Credential Guard

Microsoft's documentation describes [Credential Guard's scope](/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/) precisely: it "prevents credential theft attacks by protecting NTLM password hashes, Kerberos Ticket Granting Tickets (TGTs), and credentials stored by applications as domain credentials" [@ms-credential-guard]. Mechanism: LSA in VTL0 retains the API surface; the secret bytes relocate to LSAISO in VTL1; the secure-call dispatch performs the cryptographic step and returns derived output. The Mimikatz LSASS-scrape family -- `sekurlsa::logonpasswords`, `sekurlsa::tickets`, `lsadump::secrets` -- returns empty fields on a Credential Guard-enabled system because the bytes it scans for are no longer in the address space it can read.

What Credential Guard does *not* stop is worth naming, because the apologist failure mode is to claim it stops everything. It does not stop pass-the-ticket replay of a TGT captured before Credential Guard was enabled. It does not stop sign-in-time keylogging that scrapes the plaintext password as the user types it. It does not stop a stolen-DC-krbtgt attack that forges Golden Tickets offline. And it does not retroactively scrub credentials presented over RDP outside Restricted Admin mode. Each of those is a meaningful threat. Each lives in a class Credential Guard was not engineered to address.

<Mermaid caption="Credential Guard secure-call sequence: LSA in VTL0 asks LSAISO in VTL1 to perform Kerberos pre-authentication; the raw secret never crosses the boundary">
sequenceDiagram
    participant App as Application
    participant LSA as LSA (VTL0)
    participant SCD as Secure-call dispatch
    participant ISO as LSAISO (VTL1)
    App->>LSA: LsaCallAuthenticationPackage
    LSA->>SCD: secure-call with TGT request
    SCD->>ISO: forwarded across VTL boundary
    ISO->>ISO: derive Kerberos session key with stored TGT
    ISO-->>SCD: derived session key (raw TGT stays in VTL1)
    SCD-->>LSA: derived result
    LSA-->>App: success
</Mermaid>

### 6.2 HVCI

<Definition term="Hypervisor-Protected Code Integrity (HVCI)">
A Windows VBS feature, also marketed as Memory Integrity, that uses the Hyper-V hypervisor to enforce write-XOR-execute on VTL0 kernel pages via Extended Page Tables. Microsoft's documentation calls HVCI a "critical component that protects and hardens Windows by running kernel mode code integrity within the isolated virtual environment of VBS" [@ms-hvci]. The practical effect is that the classical kernel code-injection attack class -- write shellcode into a kernel page, then execute -- is closed.
</Definition>

[HVCI](/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/) shipped first in Windows 10 1507 in limited form, and rolled out broadly with the 1607 Anniversary Update. Its enforcement is hardware-accelerated by Intel's Mode-Based Execute Control or AMD's equivalent Guest Mode Execute Trap [@ms-hvci]. On supported silicon, the kernel-page W^X check happens in EPT permission bits with no measurable per-page-fault overhead. The attack class HVCI does not close is not "rootkit"; the attack class HVCI does close is "kernel code injection". An attacker can still call existing kernel functions in unintended sequences -- the data-only kernel attack -- and that is a known and acknowledged residual.

### 6.3 WDAC

Windows Defender Application Control, the rebranded successor to Device Guard's code-integrity component, enforces kernel-mode and user-mode code-integrity policy authored in XML and compiled to a binary `.cip` file [@ms-wdac]. The policy is consulted at every image load by `CI.dll`. Signed-policy mode binds the policy to a signing key and rejects updates that are not co-signed by the same key, which is the canonical answer to the "attacker rewrites the policy file from SYSTEM" objection.

WDAC's known weaknesses are not architectural. They are XML-authoring complexity (production policies routinely run to thousands of rules), bring-your-own-vulnerable-driver against permissive driver allow-lists, and abuse of legitimately-signed Living-Off-the-Land binaries -- `rundll32.exe`, `regsvr32.exe`, `msbuild.exe` -- that pass any signature-based allow-list because Microsoft signed them itself. AppLocker, the older peer technology that ships in Pro SKUs, is functionally subsumed; new deployments default to WDAC [@ms-wdac].

### 6.4 AMSI

The [Antimalware Scan Interface](/blog/amsi-the-pre-execution-window-defender/) is a Component Object Model interface that lets script-host runtimes -- PowerShell, Windows Script Host (JScript and VBScript), Office VBA, and WMI -- hand a freshly-deobfuscated string buffer to the configured anti-malware provider before executing it [@ms-amsi].

<Definition term="Antimalware Scan Interface (AMSI)">
A user-mode COM interface introduced in Windows 10 1507 that allows scripting and macro hosts to submit a buffer (typically a deobfuscated script body) to the configured anti-malware provider for inspection before execution. Lee Holmes's June 9, 2015 Microsoft Security Blog post announced AMSI alongside the Windows 10 1507 ship [@ms-leeholmes-amsi]. Microsoft Defender is the default provider; third-party engines register via `IAntimalwareProvider`.
</Definition>

AMSI matters because pre-AMSI, an obfuscated PowerShell command line was opaque to the anti-malware engine until after it had run. AMSI runs the engine on the post-deobfuscation buffer. The engine sees the cleartext.

The bypass class AMSI exposes is a deliberate tradeoff. AMSI is a hook from user-mode script hosts. An attacker who already has code execution in the same user-mode process can patch the AMSI hook out -- the canonical reflection trick sets `AmsiUtils.amsiInitFailed` to `True` via .NET reflection, and MDSec's June 2018 PowerShell AMSI evasion write-up walks through the family in detail [@mdsec-amsi-bypass]. AMSI is a hook, not a sandbox. The bypass surface is part of the design tradeoff.

<Aside label="Why phased AMSI matters">
AMSI did not ship as a single event. Windows 10 1507 (July 2015) brought PowerShell 5.0, Windows Script Host, and Office VBA macro coverage. Office 365 client applications integrated AMSI for Office VBA macros in September 2018 per Microsoft's announcement [@ms-office-amsi]. The Windows 10 1903 release in May 2019 added the AMSI-for-WMI provider [@ms-win10-1903]. The same product name covered four very different runtimes, and the runtime that was missing from your endpoint was the runtime an attacker used. Treat "AMSI is enabled" as a question with four sub-questions until 1903.
</Aside>

### 6.5 Control Flow Guard

Burow, Carr, Nash, Larsen, Brunthaler, Payer, and Franz's 2017 ACM Computing Surveys review *Control-Flow Integrity: Precision, Security, and Performance* is the academic reference that classifies what [CFG](/blog/control-flow-integrity-on-windows-cfg-xfg-and-the-cet-shadow/) actually is [@burow-cfi-csur2017]. In the Burow et al. taxonomy, CFG is forward-edge, coarse-grained, software CFI.

<Definition term="Control Flow Guard (CFG)">
A platform security feature that "was created to combat memory corruption vulnerabilities" by validating indirect call targets against a compile-time-known set of valid functions [@ms-cfg]. The compiler emits a call to `__guard_check_icall_fptr` before every indirect call; the runtime consults an OS-maintained bitmap of valid call targets in the loaded process image; an invalid target traps to the kernel and the process is terminated.
</Definition>

The mechanism is small enough to describe in code. The OS maintains a per-process bitmap indexed by 16-byte-aligned function addresses; each bit indicates whether that address is a valid indirect-call target. Before every indirect call, the compiler emits a bitmap lookup. If the bit is clear, the program is terminated.

<RunnableCode lang="js" title="CFG indirect-call check (pseudocode)">{`
// Simulated CFG bitmap and indirect-call check
const bitmap = new Uint8Array(1024);

function markValidTarget(addr) {
  // Each bit covers a 16-byte-aligned function address
  const bitIndex = (addr >> 4);
  bitmap[bitIndex >> 3] |= (1 << (bitIndex & 7));
}

function guardCheckIcall(targetAddr) {
  const bitIndex = (targetAddr >> 4);
  const isValid = (bitmap[bitIndex >> 3] >> (bitIndex & 7)) & 1;
  if (!isValid) {
    throw new Error('CFG violation: terminate process');
  }
}

markValidTarget(0x1400);
markValidTarget(0x1500);

guardCheckIcall(0x1400);
console.log('Valid call site allowed.');

try {
  guardCheckIcall(0x1410);
} catch (e) {
  console.log(e.message);
}
`}</RunnableCode>

The known limits of CFG are the limits Burow et al. enumerate for forward-edge, coarse-grained, software CFI in general [@burow-cfi-csur2017]. CFG protects only forward edges -- indirect calls and indirect jumps -- so an attacker who corrupts a return address is unaffected by CFG and needs a backward-edge defense (Intel Control-flow Enforcement Technology shadow stacks, in the Part 5 story). CFG's bitmap is coarse: any function whose address is taken is a valid target. And non-CFG-instrumented DLLs in the process create gaps; the bitmap has no bit set for code the compiler did not see.

### 6.6 Process Mitigation Policies

[Per-app process mitigation policies](/blog/process-mitigation-policies-cfg-acg-cig-and-the-layer-betwee/), exposed in 1709 (October 2017) through the Windows Defender Exploit Guard GUI and the PowerShell `Set-ProcessMitigation` cmdlet [@ms-exploit-protection] [@ms-set-processmitigation], unified the menagerie of legacy Enhanced Mitigation Experience Toolkit settings into a documented, group-policy-deployable per-process opt-in. The kernel-side `PROCESS_MITIGATION_POLICY_INFORMATION` API shipped in Windows 8; the per-app management surface arrived three years later. Each policy in the 1709 set closes a specific exploitation primitive at the per-process boundary. The ones worth knowing by mechanism:

**Arbitrary Code Guard (ACG).** ACG refuses to commit a page as `PAGE_EXECUTE_READWRITE` and refuses any `VirtualProtect` request that adds executable permission to a page that was previously non-executable. The kernel's `MiArbitraryUserPointer` and `MiAllocateVirtualMemory` paths fail those requests with `STATUS_DYNAMIC_CODE_BLOCKED`. The effect is process-level W^X: an attacker who lands a write primitive cannot turn it into a JIT-the-shellcode-then-execute primitive. The Microsoft Edge content process is the canonical example. Edge's JavaScript JIT runs *out-of-process* in a separate JIT-only process and ships compiled code to the renderer through a one-way shared-memory channel, so the renderer itself never needs an RWX page. The flag name is `PROCESS_CREATION_MITIGATION_POLICY_PROHIBIT_DYNAMIC_CODE_ALWAYS_ON` [@ms-set-processmitigation].

**Code Integrity Guard (CIG).** CIG refuses to load any DLL whose Authenticode signature does not chain to a Microsoft trust root. The PE load path in `MiLoadImage` validates the signature and fails with `STATUS_INVALID_IMAGE_HASH` or `STATUS_INVALID_SIGNATURE` if the policy is violated. This closes the "drop a malicious DLL in the search path and let `LoadLibrary` find it" exploitation class for a content process. The flag is `PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON`. CIG composes with WDAC at the system level: CIG is the per-process narrow case, WDAC is the system policy.

**Strict Handle Check.** Strict Handle Check terminates the process on the first invalid handle reference rather than returning `STATUS_INVALID_HANDLE` and recovering. Closes handle-reuse and type-confusion exploitation where the attacker substitutes a handle of a different type and rides the resulting use-after-free, which is a recurring browser-sandbox bug pattern. The flag is `PROCESS_CREATION_MITIGATION_POLICY_STRICT_HANDLE_CHECKS_ALWAYS_ON`.

**Image Load mitigations.** Three related policies harden the DLL loader. `PreferSystem32Images` makes the loader prefer `\Windows\System32` before searching the application directory, defeating the classic DLL search-order hijack (a malicious `version.dll` planted in the app directory). `NoLowMandatoryLabelImages` refuses to load DLLs whose mandatory integrity label is Low, closing the "browser sandbox creates a Low-IL file, then the parent process loads it" class. `NoRemoteImages` refuses to load DLLs from UNC paths, defeating cross-machine DLL injection.

**Disable Win32k System Calls.** Any syscall whose service-table index is in the Win32k range -- the second syscall service table -- is rejected at the entry-stub level. The mitigation removes the GDI and USER attack surface from the process. The Win32k subsystem has historically been the largest source of kernel CVEs, so processes that do not need a window station -- content processes, network services -- can opt out wholesale. The flag is `PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON`. Edge content processes ship with it on. Chromium's `--disable-win32k-lockdown` flag is the dual-use override developers reach for when something downstream breaks.

The 1709 set also keeps the conventional triad -- ASLR with bottom-up randomization, Data Execution Prevention, and a NoCFG-allowed-RWX refusal -- applied per-process.

The Edge content process is the canonical "stack of mitigations" example. It enables almost the full PMP suite simultaneously: ACG, CIG, Disable Win32k, the Image Load mitigations, Strict Handle Check, AppContainer, and an AC sandbox. That stack is what makes an Edge content-process RCE *not* equivalent to a SYSTEM-level Windows compromise. The attacker has compromised the renderer, but still faces a sandbox escape, then an elevation of privilege, then (depending on the target) a credential-extraction step before reaching anything Credential Guard then closes.

### 6.7 Defender ATP, later Defender for Endpoint

The cloud-backed endpoint detection and response backend launched as Windows Defender Advanced Threat Protection in 2016 and was renamed [Microsoft Defender for Endpoint](/blog/from-cmdexe-to-a-kusto-row-in-90-seconds-how-sysmon-and-defe/) in September 2020 [@ms-mde-overview].

<Sidenote>"Defender ATP" and "Defender for Endpoint" are the same product. The 2020 rename matters only for citation literacy: pre-2020 sources cite ATP, post-2020 sources cite MDE, and confusing the two as separate products is a common reading error.</Sidenote>

**What MDE actually sees.** The sensor consumes a curated set of Event Tracing for Windows providers and file-system and registry events: `Microsoft-Windows-Kernel-Process` for process create and exit; `Microsoft-Windows-Kernel-Image` for image load; the file-system minifilter for create, write, and delete; the registry transaction log for create and write; `Microsoft-Windows-Kernel-Network` for network connections; the LSA and Kerberos authentication providers for authentication events; the AMSI script-content stream for post-deobfuscation script bodies; the Defender behavioral-engine fire events; and the per-process Code Integrity event stream that surfaces HVCI violations. That last stream is the SOC's anchor for HVCI-violation telemetry and is the one piece of integration no third-party EDR can replicate, because it depends on running inside the VBS substrate Microsoft also ships.

**Detection latency tiering.** The cloud-correlation pipeline operates in two tiers. Single-event high-confidence detections -- a known-malicious hash, an AMSI Mimikatz string match, a Cobalt Strike named-pipe pattern -- fire in seconds to low minutes. Behavioral aggregation across a process tree -- Ryuk-style staging behavior, Big Game Hunting lateral-movement patterns, Emotet-to-TrickBot-to-Ryuk chains -- fires in minutes to low hours. The two-tier architecture is the detection-philosophy distinction MDE held against its 2019 EDR competitors.

**The 2019 EDR competitor field.** Four credible competitors shipped comparable cloud-correlation architectures by the 2019 cutline. CrowdStrike Falcon was the cloud-native sensor with the heaviest cloud-side intelligence pipeline of the era; CrowdStrike Inc. was founded in 2011 with the cloud-native vision, and the Threat Graph correlation platform debuted with Falcon in June 2013 and has expanded continuously since. Carbon Black carried the legacy Bit9 application-allow-list lineage with a behavioral hybrid layered on top, and was acquired by VMware in October 2019. SentinelOne shipped a lighter kernel agent with on-endpoint behavioral analytics, founded in 2013. Cylance staked out the divergent philosophical position of pre-LLM-era machine-learning static analysis with no behavioral pipeline at all, and was acquired by BlackBerry in February 2019.

All four offered cloud-correlation EDR by the 2019 cutline. MDE's distinguishing feature was OS-native integration with Defender, the ETW providers, and the VBS substrate -- specifically, the per-process Code Integrity event stream the third-party agents could not see.

Together, the six VBS-anchored pillars plus Defender for Endpoint constitute what a 2019 defender meant by "the modern Windows endpoint." A reasonable summary is the head-to-head table:

| Pillar | Privilege model | Closes | Known residual |
|---|---|---|---|
| Credential Guard | Cross-VTL isolation | Mimikatz LSASS-scrape family | Pre-CG TGTs, sign-in keyloggers, stolen-DC krbtgt |
| HVCI | Cross-VTL kernel W^X | Classical kernel code injection | BYOVD, data-only kernel attacks |
| WDAC | Kernel-enforced CI policy | Unsigned and unauthorized code | LOLBins, BYOVD against permissive policies |
| AMSI | User-mode COM hook | Post-deobfuscation script visibility | In-process hook patches |
| CFG | Compiler-inserted forward-edge CFI | ROP gadget chains via indirect call | Return-address corruption, non-CFG DLLs |
| Process Mitigation Policies | Per-app opt-in mitigations | Per-process exploit primitives | Apps that do not opt in |

<Sidenote>The Windows kernel performance impact of KVA Shadow on older silicon will preview in Section 10 -- MariaDB's MyISAM workload regressed 37 to 40 percent on Haswell-era CPUs when the Meltdown mitigations landed [@mariadb-kpti]. That is the empirical anchor for "more significant slowdowns" in Terry Myerson's January 2018 tiered guidance [@ms-myerson-meltdown].</Sidenote>

This is the stack Microsoft shipped. In the same five years, three other OS communities -- Linux, Apple, and ChromeOS -- shipped their own answers to overlapping problems, and the formal-verification community produced a fourth. How do those four answers compare?

## 7. Competing Approaches: Linux KPTI, Apple T2, ChromeOS, seL4

Microsoft's VBS is one of four serious architectural answers shipped in the 2015-2019 window. The others made different bets. Reading them side by side is the fastest way to see what VBS chose and what it gave up.

### 7.1 Linux KPTI vs Windows KVA Shadow

Linux Kernel Page-Table Isolation (KPTI) and Microsoft's KVA Shadow are parallel responses to the same forced architectural change. Both descend from Gruss et al.'s 2017 ESORICS paper "KASLR is Dead: Long Live KASLR," which introduced KAISER -- the technique of stripping kernel mappings out of the user-mode page-table view to defeat side-channel attacks on Kernel Address Space Layout Randomization [@gruss-kaiser]. KAISER landed before Meltdown was public. When the Project Zero coordinated disclosure broke on January 3, 2018, it was the structural retrofit both kernels needed [@pz-meltdown-spectre].

Linux merged KPTI into mainline before the 4.15 release in January 2018, with backports into 4.14, 4.9, and 4.4 LTS branches gated by `CONFIG_PAGE_TABLE_ISOLATION` [@lwn-kpti] [@kroah-meltdown]. Microsoft shipped KVA Shadow in the January 9, 2018 cumulative update. Both implementations split the per-process page-table into a user-mode shadow and a full kernel-mode view, swap CR3 at every user-kernel transition, and lean on the Process Context Identifier feature in Skylake-and-later silicon to amortize the TLB-flush penalty. The fact that two OSes with very different histories converged on functionally identical code, within days of each other, is the lesson: the x86 page-table format dictated the answer. Neither team designed the mechanism. The hardware bug did.

### 7.2 Apple T2: a second processor instead of a second privilege level

Apple shipped the [T2 chip](/blog/apple-secure-enclave-vs-microsoft-pluton-two-roads-to-hardwa/) in the iMac Pro on December 14, 2017, and rolled it across the Mac line through 2018 [@apple-t2]. The T2 is a separate Arm-based co-processor with its own boot ROM, AES engine, Secure Enclave, and Memory Protection Engine that encrypts the enclave's DRAM region with an ephemeral key [@apple-secure-enclave]. Where Microsoft answered the same-privilege paradox by adding a second privilege level on the same CPU, Apple answered it by adding a second physical CPU.

The tradeoff is stark. T2 has no cross-VTL Spectre v2 problem because the secret lives on a different silicon die. T2 also costs an extra SoC in every machine's bill of materials, requires a second firmware-update pipeline, and demanded hardware replacements when the checkm8 bootrom vulnerability hit the T2's A10-derived bootrom in 2020 [@ironpeak-t2].<Sidenote>The T2's predecessor in the 2016 Touch Bar MacBook Pro, the T1, was S2-based; the T2 itself derives from the A10 Fusion CPU found in the iPhone 7, per ironpeak's October 2020 analysis.</Sidenote> VBS runs on existing Intel and AMD silicon with no incremental hardware cost; T2 requires Apple to ship custom silicon in every box. Both architectures relocate the secret. They relocate it to different places.

### 7.3 ChromeOS: do not ship a Secure Kernel because you do not ship a general-purpose kernel

ChromeOS does not deploy a Secure Kernel. It deploys verified boot. The architecture is: firmware-write-protected hardware root, signed kernel partition with the dm-verity root hash baked in, and a read-only root filesystem mounted with dm-verity active so every block read is checked against a signed Merkle tree at runtime [@chromeos-verified-boot] [@dm-verity]. The user-facing surface is the Chrome browser, with per-site renderers and utility processes confined by seccomp-bpf sandboxes. There is no LSASS to scrape, no Active Directory TGT to steal, no general-purpose third-party kernel-driver supply to attack.

The architectural lesson is that VBS solves the problem of "we shipped a large general-purpose kernel and we cannot retract that decision." ChromeOS sidesteps the problem by not shipping that kernel in the first place. ChromeOS is the principled alternative for an OS whose threat model assumes a single-application workload.

### 7.4 seL4: the verification path VBS chose not to take

seL4 is approximately 8,700 lines of C plus 600 lines of assembly, machine-checked against an Isabelle/HOL abstract specification with roughly 200,000 lines of proof script, and verified end-to-end from spec to C to binary [@klein-sel4-sosp2009] [@klein-sel4-cacm] [@sewell-sel4-pldi]. The 2009 SOSP paper established the proof chain, the 2010 CACM Research Highlight recapped it for a wider audience, and the 2013 PLDI follow-on closed the compiler gap by translation-validating GCC output against the C source. The total effort: on the order of 20 person-years for a microkernel one-tenth the size of `securekernel.exe`.

Microsoft's Secure Kernel is roughly 150 kilobytes of unverified C code [@ionescu-bh2015]. A meaningful verification would require an Isabelle-level specification of the secure-call interface, refinement proofs through the C source, translation validation to the shipped binary, a formal model of Hyper-V's SLAT enforcement, and a credible story for microarchitectural side channels that seL4 in 2009 did not have to address. A plausible order-of-magnitude estimate is 100 to 200 person-years for the structural pieces alone. No shipping general-purpose OS -- macOS, iOS, ChromeOS, or Windows -- has chosen that path. seL4 itself runs in specialized embedded and defense deployments, not on desktops.

| Approach | Trust root | Verification | Strengths | Open residuals | Deployment scale |
|---|---|---|---|---|---|
| Windows VBS (2015) | Hyper-V hypervisor + UEFI Secure Boot | None (unverified C) | Ships on existing silicon at Windows scale | BYOVD, secure-call bugs, cross-VTL side channels | Hundreds of millions of endpoints |
| Linux KPTI (2018) | Page-table split per process | None | Forced retrofit; correct in mainline within weeks | Spectre family beyond v3 | Server-side and developer workstation majority |
| Apple T2 (2017) | Second physical processor | None (different threat model) | No cross-VTL side-channel surface | Firmware bugs require hardware fix | All Intel Macs 2018-2022 |
| seL4 (2009) | Microkernel + Isabelle/HOL proof chain | Functional correctness, integrity, non-interference | Formally guaranteed against named bug classes | Outside-TCB hardware and side channels | Specialized embedded / defense |

Each of these four answers makes a different tradeoff against the same problem. Windows chose "second privilege level, large attack surface, ship-at-scale." What does that tradeoff leave on the table -- where are VBS's irreducible residuals?

## 8. What VBS Cannot Defend Against

Every architecturally honest defense names its bypass classes before its critics do. VBS, at the 2019 cutline, has six enumerable bypasses plus one structural caveat about availability. None of them undermines the architectural claim that the LSASS-scrape attack class is closed. All of them shape the operator's deployment decisions.

<Definition term="Bring Your Own Vulnerable Driver (BYOVD)">
An attack class in which an adversary loads a legitimately Microsoft-co-signed third-party kernel driver that contains an exploitable bug. The driver passes Driver Signing Enforcement and HVCI's code-integrity check because it is signed; the bug gives the attacker arbitrary kernel-mode primitives (read, write, execute) without requiring a Microsoft-issued signature. BYOVD is the dominant in-the-wild HVCI and Credential Guard bypass class through the 2019 cutline.
</Definition>

**Bypass class one -- BYOVD.** A vulnerable signed driver provides the same kernel-mode primitives PatchGuard-era rootkits relied on. With kernel-mode arbitrary write, an attacker can disable HVCI on a per-process basis, clear the PPL bits on a target, or hook secure-call dispatch sites. Microsoft formally acknowledged BYOVD as a class with the October 2022 Vulnerable Driver Blocklist update KB5020779 [@ms-vuln-driver-kb], operationalized through the same `microsoft-recommended-driver-block-rules` document used by Windows Defender Application Control [@ms-vuln-driver-blockrules]. That arrived three years after the cutline of this article, which is part of the lesson: the dominant residual at 2019 was not closed by Windows 10 itself.

**Bypass class two -- hypervisor and secure-kernel vulnerabilities.** The Secure Kernel is not infallible code. Saar Amar and Daniel King's Black Hat USA 2020 talk "Breaking VSM by Attacking SecureKernel" disclosed CVE-2020-0917 and CVE-2020-0918 in the secure-call interface handlers `SkmmUnmapMdl` and `SkmiReleaseUnknownPTEs` [@amar-king-bh2020]. The Amar-King work landed after this article's window, but the bypass-class anchor it establishes -- VTL0 to VTL1 escape via the secure-call interface -- was already known to insiders by 2019. The steady-state finding rate for that class is on the order of one to three critical bugs per year.

**Bypass class three -- hardware and DMA attacks.** A peripheral device attached over Thunderbolt or PCIe can, in the absence of an Input-Output Memory Management Unit enforcement, read and write physical memory directly. The 2019 NDSS paper "Thunderclap" demonstrated DMA reads of VTL0 and VTL1 memory on machines without Kernel DMA Protection enabled [@markettos-thunderclap]. The Windows mitigation is IOMMU enforcement plus Kernel DMA Protection, both of which require firmware support that mixed-vintage hardware does not always have.

**Bypass class four -- microarchitectural side channels.** Spectre variant 2 -- branch target injection -- is the only Spectre-family variant whose threat model overlaps the VBS boundary, because mispredicting an indirect call inside a secure-call handler can leak data across the VTL boundary. The mitigation is enabling Indirect Branch Restricted Speculation around the secure-call entry. Section 10 walks the larger story; here it is enough to note that microarchitectural side channels are an open surface against VBS that grows with each new variant.

**Bypass class five -- trustlet-signing-root compromise.** Every trustlet is identified by two Authenticode EKUs that Microsoft signs at Signature Level 12 [@ionescu-bh2015]. If an attacker controls either the signing key or the issuing infrastructure that hands out the IUM EKU, they can ship a malicious binary that the Secure Kernel admits as a legitimate trustlet -- with the same VTL1 access as LSAISO.

This class was theoretical at the 2019 cutline. Microsoft's July 2023 Storm-0558 disclosure put it on the forward roadmap: an Azure consumer-MSA signing key was used to forge enterprise tokens [@ms-storm-0558], and the September 2023 root-cause investigation traced the original key acquisition to a crash dump that crossed from production into a corporate debugging environment that the actor had already compromised [@msrc-storm-0558-keyacq]. The Storm-0558 incident was a token-signing-key compromise rather than a trustlet-signing-key compromise, but the architectural lesson is identical. A signing root is a single point of trust whose compromise admits arbitrary binaries to the protected privilege level.

**Bypass class six -- the VTL0 agent surface.** Most VBS features ship a VTL0 process that brokers requests to a VTL1 trustlet. LSA in VTL0 brokers credential operations to LSAISO. The System Guard runtime attestation agent and the Windows Defender Application Guard broker likewise mediate between user-mode applications and their VTL1 counterparts.

Bugs in those agents are still VTL0 bugs. An agent that mishandles user-controlled input before the secure-call dispatch -- a parsing error, a use-after-free, a type confusion -- can leak partial information or trigger unintended VTL1 operations even when the Secure Kernel's API is sound. The failure surface is in VTL0; the consequences can reach into VTL1 by routing through the agent. This is the everyday-engineering residual that shows up in routine MSRC advisories rather than in conference papers.

**Caveat -- availability is not a VBS invariant.** The Hyper-V Top-Level Functional Specification is explicit on this point [@ms-tlfs-vsm]. VTL0 can deny service to VTL1 by refusing to schedule the Secure Kernel, by refusing to provide pages for paging, or by refusing to dispatch secure-calls. Confidentiality and integrity are protected. Availability is not. A compromised NT kernel can stop a trustlet from running. The VBS designers made that tradeoff deliberately, because guaranteeing availability would require the Secure Kernel to manage its own scheduler and paging, which would balloon its trusted code base out of audit range.

<PullQuote>
"VTL0 can DOS VTL1 by design." -- Microsoft Hyper-V Top-Level Functional Specification, Virtual Secure Mode
</PullQuote>

| Bypass class | Attack family | Residual mitigation at 2019 |
|---|---|---|
| BYOVD | Vulnerable signed driver as kernel-mode primitive | Microsoft-recommended block rules (manual at 2019; default-on with KB5020779 in Oct 2022) |
| Hypervisor / Secure Kernel bugs | Secure-call interface vulnerabilities | Patch velocity; reduce secure-call surface; formal verification research |
| Hardware / DMA | Pre-IOMMU PCIe / Thunderbolt DMA reads | Kernel DMA Protection + IOMMU enforcement (firmware-dependent) |
| Microarchitectural side channels | Spectre v2 cross-VTL leakage | IBRS on secure-call entry; per-variant microcode mitigations |
| Trustlet-signing-root compromise | Forged or stolen IUM EKU signing key | Signing-infrastructure hardening; no operator-side control at 2019 |
| VTL0 agent surface | Bugs in LSA, System Guard agent, WDAG broker | Conventional MSRC patching; harden agent input validation |

> **Note:** Five observations on the residual map. BYOVD is the *dominant* in-the-wild residual at the 2019 cutline -- it is what attackers actually used to bypass HVCI and Credential Guard, and the canonical Microsoft mitigation came three years late. The secure-call interface is the *quietest* residual: most readers had never heard of it before Amar-King in 2020. Microarchitectural side channels are the *interaction* class that links the bypass map in Section 8 to the third axis in Section 10. Trustlet-signing-root compromise is the *forward* class -- theoretical at 2019, made concrete by Storm-0558 in 2023. VTL0 agent bugs are the *everyday-engineering* class that shows up in routine MSRC advisories. Knowing which residual matters for which threat model is half of operational VBS deployment.

> **Key idea:** Every architecturally honest defense names its bypass classes before its critics do. VBS has six: BYOVD, hypervisor secure-call bugs, hardware DMA, microarchitectural side channels, trustlet-signing-root compromise, and the VTL0 agent surface. The architectural gap is small. The deployment gap, as the next section will show, is much larger.

These are the architectural residuals. The operational residuals turned out to be bigger by orders of magnitude. The path from a kernel-isolated 2017 Enterprise laptop to a paralyzed hospital starts with a missed patch.

## 9. The Offensive Story: Ransomware Industrialization (2017-2019)

Between May 12, 2017 and November 21, 2019, the criminal Windows-attack industry went through five generations of business-model evolution in thirty months. Worm-spray ransomware. State-actor wiper. Targeted enterprise extortion. Ransomware-as-a-Service. Encryption plus exfiltration -- the double-extortion playbook. None of the five required novel exploitation against VBS-class defenses. They required only that VBS-class defenses not be deployed.

The 2017-2019 arc has a predecessor that explains the rest. In September 2013, Symantec Security Response reported a new family of Windows ransomware called CryptoLocker, distributed by Evgeniy Bogachev's peer-to-peer Gameover Zeus botnet, encrypting victim files with per-victim 2048-bit RSA keys and demanding payment in Bitcoin or MoneyPak. Ransom demands ran in the low three figures to low four figures: enough to be commercially viable against consumers, capped by what consumers could pay.

On June 2, 2014, a joint operation -- the FBI, Europol, the UK National Crime Agency, Dutch and German law-enforcement, plus Symantec, Dell SecureWorks, CrowdStrike, F-Secure, Microsoft, Trend Micro, and McAfee -- executed Operation Tovar [@doj-operation-tovar] [@europol-operation-tovar] [@fbi-goz]. The operation seized the Gameover Zeus command-and-control and sinkholed the peer-to-peer overlay; FireEye and Fox-IT used the recovered keypair database to stand up a free decryption portal for CryptoLocker victims.

Operation Tovar disrupted the vector. It did not disrupt the business model. Within months, CryptoWall surpassed CryptoLocker in infection volume under different operators [@secureworks-cryptowall]. The lesson the next five years would teach is that *takedown alone does not solve the ransomware problem*: the underlying economics -- encryption plus extortion against a Bitcoin-receivable -- are the asset, and the operators are commodity. From CryptoLocker forward, the criminal arc forks into the worm-spray fork (WannaCry, NotPetya, Bad Rabbit) and the targeted-enterprise fork (SamSam, Ryuk, REvil, Maze) that converge at Maze double extortion in November 2019.

### 9.1 WannaCry (May 12, 2017)

The patch-gap timeline is the spine of the WannaCry story. Microsoft published Security Bulletin MS17-010 on March 14, 2017, patching CVE-2017-0143 through CVE-2017-0148 in the [SMBv1 server](/blog/the-connection-that-refused-to-downgrade-twenty-five-years-o/) [@ms-ms17-010] [@nvd-cve-2017-0144]. Thirty-one days later, on April 14, 2017, the Shadow Brokers leaked the NSA Equation Group's "Lost in Translation" toolkit, which included the EternalBlue exploit weaponizing CVE-2017-0144 over SMBv1 and DoublePulsar, a kernel-mode SMB backdoor [@wiki-eternalblue]. Twenty-eight days after that, on May 12, 2017, WannaCry began propagating. Total patch-to-outbreak window: fifty-nine days.

The exploit, mechanically, is two pieces. EternalBlue exploits a race condition in the SMBv1 Transaction2 subcommand processing in `srv.sys`, achieving controlled kernel-pool corruption that lets the attacker write a controlled `SrvNet` buffer into a controlled location -- enough to land kernel-mode code execution. DoublePulsar plants a kernel-mode backdoor that listens for follow-on shellcode over SMB. Sean Dillon's RiskSense paper *EternalBlue: Exploit Analysis and Port to Microsoft Windows 10* (2018) is the canonical reverse-engineering account [@dillon-risksense-eternalblue].

<Mermaid caption="EternalBlue lands kernel-mode code execution via SMBv1 Trans2 race; DoublePulsar plants a backdoor for the ransomware payload">
sequenceDiagram
    participant Atk as Attacker
    participant Srv as srv.sys (SMBv1)
    participant Krn as Kernel pool
    participant DP as DoublePulsar
    Atk->>Srv: SMBv1 Trans2 request with crafted parameters
    Srv->>Krn: pool allocation hits race condition
    Atk->>Srv: groom SrvNet buffer
    Srv->>Krn: controlled overwrite, ring 0 execution
    Krn->>DP: install kernel-mode backdoor
    Atk->>DP: deliver ransomware payload over SMB
    DP-->>Atk: payload running as SYSTEM
</Mermaid>

The propagation halted at 15:03 UTC on May 12, 2017 when Marcus Hutchins, a then-22-year-old British researcher writing as MalwareTech, registered an unregistered domain hard-coded into the WannaCry binary as a kill-switch test. Hutchins thought he was sinkholing for telemetry. He had accidentally stopped the worm [@malwaretech-killswitch].<Sidenote>The kill-switch domain registration is well-attested at 15:03 UTC; the moment global propagation visibly slowed lagged the registration by minutes to hours as the sinkhole DNS record propagated through caching resolvers worldwide.</Sidenote>

Damage at the National Health Service was severe but not maximal: the National Audit Office's October 2017 investigation reports that the attack disrupted at least 34 percent of trusts in England, NHS England identified 6,912 cancelled appointments, and the estimate of total cancelled appointments was over 19,000 [@nao-wannacry]. The NAO is clear that no NHS organization paid the ransom. The British government and NHS England later attributed the WannaCry outbreak to North Korea, formally on December 19, 2017, in a White House press briefing that coordinated attribution with the United Kingdom, Australia, Canada, New Zealand, and Japan [@wh-wannacry].

CISA, then US-CERT, had issued an alert during the May 12 outbreak window [@cisa-may-2017-ransomware]. Global damage estimates ran to around four billion US dollars across cancelled production, recovery costs, and downtime at Renault-Nissan plants, FedEx, Telefonica, Deutsche Bahn, and the NHS.

The architectural lesson of WannaCry is not that VBS failed. VBS was not running on the affected NHS workstations, which were largely unpatched Windows 7 boxes. The architectural lesson of WannaCry is that *patch velocity remained the dominant defense in 2017*, and that the deployment-gap problem was, and remains, the larger lever than the architectural-gap problem.

### 9.2 NotPetya (June 27, 2017)

Six weeks later, on June 27, 2017, the world saw what an actually-state-actor-grade Windows campaign looks like. The vector was a supply-chain compromise of M.E.Doc, the Ukrainian tax-and-accounting software whose update channel pushed the malicious binary to thousands of M.E.Doc-running endpoints [@talos-medoc]. ESET's TeleBots write-up confirmed the operator: the BlackEnergy-lineage Sandworm group [@eset-telebots].

The payload self-propagated using EternalBlue plus EternalRomance plus credential reuse via a bundled Mimikatz-style routine, then encrypted Master File Tables and boot sectors. Kaspersky's analysis -- "Schroedinger's Pet(ya)" -- is the canonical evidence that the malware was a wiper masquerading as ransomware: "After an analysis of the encryption routine of the malware used in the Petya/ExPetr attacks, we have thought that the threat actor cannot decrypt victims' disk, even if a payment was made" [@kaspersky-petya]. The Salsa20 key derivation made decryption impossible by design.

The Maersk story, told most memorably in Andy Greenberg's WIRED feature and at book length in his 2019 Doubleday volume *Sandworm: A New Era of Cyberwar and the Hunt for the Kremlin's Most Dangerous Hackers*, is the iconic case [@wired-notpetya] [@greenberg-sandworm-book]. Maersk's IT department recovered from a single, accidentally-offline domain controller in Ghana [@wired-notpetya] [@greenberg-sandworm-book].

The aggregate damage estimate from the February 15, 2018 White House attribution statement is "billions of dollars in damage" with the headline language: "In June 2017, the Russian military launched the most destructive and costly cyber-attack in history" [@wh-notpetya]. The UK's National Cyber Security Centre issued parallel attribution to the Russian military [@ncsc-russia-notpetya]. The US Department of Justice indicted six GRU Unit 74455 officers on October 19, 2020 -- Andrienko, Detistov, Frolov, Kovalev, Ochichenko, Pliskin -- for NotPetya, Olympic Destroyer, and related campaigns [@doj-gru-notpetya].

<PullQuote>
"In June 2017, the Russian military launched the most destructive and costly cyber-attack in history." -- White House Press Secretary statement, February 15, 2018
</PullQuote>

<Aside label="The DOJ October 2020 GRU indictment">
The October 19, 2020 indictment in the Western District of Pennsylvania names the six GRU officers and ties them to NotPetya, Olympic Destroyer, the OPCW intrusion, the 2015 and 2016 Ukrainian power grid attacks, and the 2017 French election hack-and-leak [@doj-gru-notpetya]. The indictment lands three years after this article's primary window closes, but the canonical US attribution record for NotPetya lives in that document.
</Aside>

The architectural lesson of NotPetya is *not* patch velocity. NotPetya owned its initial victims through a trusted update channel; patch cadence does not help against an installer signed by your software vendor. The lesson is that **build-pipeline integrity is the next frontier**, and SolarWinds in December 2020 -- the Part 5 chapter of this series -- will make that lesson industry-canonical.

### 9.3 Bad Rabbit (October 24, 2017)

Bad Rabbit was a four-month-later, smaller-scale cousin. Distribution was via drive-by infection from compromised Russian and Ukrainian media sites, with a payload masquerading as an Adobe Flash Player installer. Lateral movement used EternalRomance, not EternalBlue, and Kaspersky's analysis confirms code overlap with NotPetya [@kaspersky-bad-rabbit]. The blast radius was Slavic-language-region targeted. One paragraph of treatment matches the historical importance: enough to triangulate Sandworm, not enough to change the architectural story.

### 9.4 The Big Game Hunting Transition (2018-2019)

By the second half of 2018, ransomware crews had decided that mass spray was leaving money on the table. The pattern crystallized into what CrowdStrike named, in late 2018 and early 2019, *big game hunting* [@crowdstrike-ryuk].

<Definition term="Big Game Hunting">
A targeted ransomware business model in which a human operator gains access to a victim network, performs hands-on-keyboard reconnaissance, escalates to Domain Admin, locates backup infrastructure, and deploys ransomware enterprise-wide in a single coordinated event. Ransom demands scale to victim revenue. CrowdStrike's January 2019 write-up of WIZARD SPIDER's Ryuk operations is the standard reference for the term [@crowdstrike-ryuk].
</Definition>

The proto-Big-Game-Hunting predecessor is SamSam, operated from December 2015 through November 2018 by the Iranian operators Faramarz Shahi Savandi and Mohammad Mehdi Shah Mansouri. SamSam combined Internet-facing RDP brute force and JBoss exploitation with manual lateral movement and ransomware-of-the-domain-controller, caused more than \$30 million in aggregate damages, and collected more than \$6 million in ransom payments, per the November 28, 2018 DOJ indictment of Savandi and Mansouri [@doj-samsam]. The thirty-million figure is the DOJ's *damages / losses* characterization, not the *demanded ransom* amount: per-victim SamSam demands ran in the five- to fifty-thousand-dollar range, and the aggregate damages include downtime, recovery, and unrecovered ransom rather than the operators' headline ask. SamSam was the phase from 2016 forward; CrowdStrike named the phase in 2018.

The named-and-canonical Big Game Hunting lineage runs through three families.

**Ryuk** first appeared in August 2018, operated by CrowdStrike's WIZARD SPIDER (the TrickBot crew). Check Point's first-wave analysis identified the code overlap with the earlier HERMES ransomware, originally attributed to the Lazarus Group, though Check Point notes the toolchain overlap rather than asserting shared operations [@checkpoint-ryuk]. The killchain Cybereason later detailed was the Emotet -> TrickBot -> Ryuk trifecta: a phishing-delivered Emotet loader, TrickBot for credential theft and lateral movement, hands-on-keyboard reconnaissance, and Ryuk for the encryption payload.

**REvil** -- also called Sodinokibi -- emerged in April 2019. The Talos analysis published April 30, 2019 attributed first observed in-the-wild exploitation of CVE-2019-2725 to a Sodinokibi-deploying campaign active since at least April 17, 2019 [@talos-sodinokibi]; April 30 is the *publication* date of the Talos write-up, not the first-observed exploitation date. Secureworks attributed the operation to the GOLD SOUTHFIELD group and noted Sodinokibi was "likely associated with the GandCrab ransomware due to similar code and the emergence of REvil as GandCrab activity declined" [@secureworks-revil].

**Maze** entered the field in May 2019 [@malwarebytes-maze-2020].

<Mermaid caption="The 2018-2019 Big Game Hunting killchain: a human-operated intrusion sequence, not a single-shot exploit">
flowchart LR
    A[Spear-phish<br/>Emotet loader]
    B[TrickBot<br/>credential theft]
    C[Hands-on-keyboard<br/>lateral movement]
    D[Domain Admin]
    E[Backup-network<br/>reconnaissance]
    F[Mass deployment<br/>SCCM, GPO, PsExec]
    G[Exfiltration]
    H[Encryption]
    I[Leak-site pressure]
    A --> B --> C --> D --> E --> F --> H
    E --> G --> I
    H --> I
</Mermaid>

### 9.5 Maze and Double Extortion (November 21, 2019)

The fifth-generation business model arrived in late 2019. Maze's operators attacked the security-staffing firm Allied Universal in November 2019. When Allied Universal refused to pay, Maze threatened to release the stolen files publicly. In December 2019, Maze published a leak site listing victims who had not paid, with sample data to prove possession. Brian Krebs broke the story on December 16, 2019: "Less than 48 hours ago, the cybercriminals behind the Maze Ransomware strain erected a Web site on the public Internet... that changed at the end of last month, when the crooks behind Maze Ransomware threatened Allied Universal that if they did not pay the ransom, they would release their files" [@krebs-maze].

<Definition term="Double extortion">
A ransomware business model in which the operator exfiltrates victim data before encrypting it, then threatens public disclosure of the data as a separate pressure axis if the ransom is not paid. Maze, beginning with the November 2019 Allied Universal case and the December 2019 dedicated leak site, is the canonical first systematic deployment [@krebs-maze]. Snatch had threatened similar disclosure earlier in October 2019, but did not operate dedicated leak-site infrastructure [@sophos-snatch].
</Definition>

The economic logic is simple. The ransomware-only business model assumed the victim's only pressure point was the encrypted data -- which meant good backups defeated the extortion. Double extortion adds a second pressure axis (public disclosure) that backups do not address. The pattern propagated industry-wide in 2020; **exfil-then-encrypt is now the standard ransomware business model.**

### 9.6 The synthesis: a paradox of layers

Now the synthesis. The Enterprise laptop with Credential Guard enabled, in Scene A of Section 1, sat above the VBS architecture. The unpatched SMBv1 Windows 7 box on the NHS network, in Scene B, sat below it -- on a vintage of Windows that predated Credential Guard entirely and on a network nobody had segmented around the wormable SMBv1 protocol. Both ran "Windows" in the same five-year window. The difference between them was not architectural rigor. The difference was operational rigor: patches applied, segmentation configured, SMBv1 disabled, supported SKUs deployed, VBS enabled.

VBS is a *structural defense* for the credential store on a properly-configured Enterprise endpoint. Patching is an *operational defense* for the network-edge attack surface. They protect orthogonal layers of the stack. A correct defense at one layer is consistent with a catastrophic miss at the other.

> **Key idea:** The paradox of simultaneity: Microsoft's largest structural defensive break in twenty years and the criminal and state-actor world's largest operational expansion in twenty years happened in the same five-year window because they live at different layers of the defense stack.

There is one more axis, and it is orthogonal to both VBS and patch velocity. The CPU itself was the attacker's primitive.

## 10. The Third Axis: Meltdown, Spectre, KVA Shadow, Retpoline (2018-2019)

On January 3, 2018, the security industry's calendar acquired a new entry. Jann Horn at Google Project Zero, Moritz Lipp and colleagues at Graz University of Technology, Paul Kocher independent, and a coordination of six other institutions disclosed that out-of-order execution on every Intel CPU shipped since the mid-1990s could be turned against the kernel-user privilege boundary [@pz-meltdown-spectre]. None of the Windows defenses shipped in the prior thirty months touched the attack class. None could. The attacker's primitive was the CPU.

The Google Project Zero blog post enumerates three variants. **Variant 1**, bounds check bypass, became CVE-2017-5753. **Variant 2**, branch target injection, became CVE-2017-5715. **Variant 3**, rogue data cache load, became CVE-2017-5754 and was named Meltdown [@pz-meltdown-spectre] [@ms-myerson-meltdown]. Variants 1 and 2 together became the family named Spectre. The peer-reviewed papers landed later: Meltdown at USENIX Security 2018 with Lipp as lead author and an authorship list including Schwarz, Gruss, Prescher, Haas, Fogh, Horn, Mangard, Kocher, Genkin, Yarom, and Hamburg [@lipp-meltdown-usenix]; Spectre at IEEE S&P 2019 with Kocher as lead author [@kocher-spectre-ieee].<Sidenote>The Meltdown paper's authorship list does not include "Strackx" -- that name belongs to the later Foreshadow / L1TF paper. The audit on this article's research stage flagged the attribution error; the corrected roster is the one cited above [@lipp-meltdown-usenix].</Sidenote>

Windows shipped three mitigations in response. **KVA Shadow** is Microsoft's name for what Linux calls Kernel Page-Table Isolation -- the technique descended from Gruss et al.'s 2017 KAISER paper. The mechanism is to maintain two page tables per process. The "user" page table maps only the user address space and a minimal kernel trampoline. The "kernel" page table maps the full kernel. Every user-mode-to-kernel-mode transition swaps the CR3 register to install the kernel page table; every return swaps it back. The kernel page-table entries that previously sat in the same virtual address space as the user, and that Meltdown exploited speculatively, are no longer mapped during user-mode execution.

<Mermaid caption="KVA Shadow CR3 swap on syscall transition: the kernel page-table only appears between syscall entry and exit, closing the Meltdown speculative-execution leak">
sequenceDiagram
    participant U as User-mode process
    participant CPU as CPU
    participant K as Kernel
    U->>CPU: syscall instruction
    CPU->>CPU: swap CR3 to kernel page-table
    CPU->>K: dispatch kernel handler
    K->>K: execute handler logic
    K->>CPU: prepare return
    CPU->>CPU: swap CR3 to user shadow page-table
    CPU-->>U: return to user mode
</Mermaid>

**Retpoline** is the Spectre v2 mitigation. The technique, due to Paul Turner at Google in early 2018, replaces every indirect branch with a return-based thunk that the speculative-execution unit cannot mis-train into the attacker's chosen target. Microsoft backported Retpoline into Windows 10 1809 via the KB4482887 cumulative update on March 1, 2019, and enabled it by default via cloud configuration on May 14, 2019; the canonical write-up sits on the Windows Kernel team's TechCommunity blog (first posted December 6, 2018; updated through May 14, 2019) [@ms-retpoline]. The timing matters because Windows 10 1809 reached RTM on November 13, 2018: on supposedly-Retpoline-protected 1809 boxes there were roughly six months of unprotected Spectre v2 surface between the 1809 RTM and the May 14, 2019 cloud-enable.

**IBRS, IBPB, and STIBP** -- Indirect Branch Restricted Speculation, Indirect Branch Predictor Barrier, Single Thread Indirect Branch Predictor -- are the CPU-MSR-controlled mitigations delivered through Intel and AMD microcode updates that Windows manages via the kernel.

The performance cost was not uniform. Terry Myerson's January 9, 2018 Microsoft Security Blog post tiers it: Skylake-and-newer client CPUs saw "single-digit slowdowns"; Haswell-era and older systems saw "more significant slowdowns"; Server 2016 and SQL workloads saw "even more significant slowdowns" [@ms-myerson-meltdown]. The MariaDB community published one of the most-cited empirical anchors: on Haswell-era hardware doing MyISAM table scans, KPTI cost 37 to 40 percent in the worst case [@mariadb-kpti]. A 40 percent regression for a SQL workload is an unmistakable signal that the page-table swap dominates short-syscall-heavy code paths.

> **Note:** Operators who use the `FeatureSettingsOverride` and `FeatureSettingsOverrideMask` registry knobs to disable KVA Shadow, Retpoline, or IBRS in pursuit of benchmark numbers are running an operationally unpatched Meltdown-vulnerable system. The performance numbers in benchmark blogs that "disable mitigations" are reporting the speed of a hardware configuration whose threat model is January 2018.

The lesson here is structural. *VBS does not help against microarchitectural attacks because VBS protects against software primitives; the CPU itself is the attacker's primitive.* The only point at which the microarchitectural axis touches VBS is Spectre v2 cross-VTL leakage during secure-call dispatch, and the answer there is to set IBRS on secure-call entry -- the same MSR-level control that protects any indirect branch in privileged code.

VBS, patch velocity, microarchitectural mitigations. Three axes of defense, each addressing a different attack primitive. Where does that leave the operator on December 31, 2019?

## 11. Operating Windows 10 in the 2017-2019 Threat Environment

A defender at the 2019 cutline who reads only the architecture papers will deploy VBS and feel safe. A defender who reads only the breach reports will assume nothing works. The truth is structurally bounded.

**For enterprise administrators.** Enable Credential Guard plus HVCI on Enterprise SKUs from 1607 forward [@ms-credential-guard] [@ms-hvci]. Deploy WDAC with audit-mode-first rollout, then enforce [@ms-wdac]. Patch within 30 days of MSRC release -- the WannaCry lesson is fifty-nine days. Disable SMBv1 outright. Inventory unused signed kernel drivers and remove them. Stand up Defender for Endpoint or an equivalent EDR. Treat segmentation between user subnets and server subnets as a deployable security control, not an architectural aspiration.

> **Note:** Production WDAC policies routinely run to thousands of rules. The canonical mitigation for XML-authoring complexity is reference-monitor-mode rollouts: ship the policy in audit mode, collect 7 to 14 days of `MicrosoftWindows-CodeIntegrity/Operational` events from real users, refine the allow-list against the captured baseline, then move to enforce. Skipping audit mode reliably produces a Tuesday morning of broken business workflows [@ms-wdac].

**For application developers.** Compile with `/guard:cf` to opt into CFG instrumentation [@ms-cfg]. Set per-app Process Mitigation Policies via `Set-ProcessMitigation` [@ms-set-processmitigation], picking the subset (ACG, CIG, Strict Handle Checks, Disable Win32k System Calls) that fits your runtime. Sign your binaries with Authenticode using a hardware-backed key. If your application reads credentials, make sure they never touch LSASS; use the CredUI or Web Account Manager surface, which integrates with Credential Guard cleanly.

**For security researchers.** Read Ionescu's Black Hat USA 2015 deck plus the Weston-Ionescu OPCDE 2018 "Inside the Octagon" before claiming a "VBS bypass" [@ionescu-bh2015] [@opcde-inside-octagon]. Categorize any bypass you find into one of the six classes named in Section 8 -- BYOVD, hypervisor or secure-call bugs, hardware DMA, microarchitectural side channels, trustlet-signing-root compromise, or VTL0-agent surface. Cross-cite Microsoft Learn for any specification-level claim about VTL semantics. The Yosifovich, Ionescu, Russinovich, and Solomon *Windows Internals* 7th edition, Part 1 (May 2017) remains the canonical textbook anchor for the 1507-to-1607 era architecture [@mspress-windows-internals-7e].

**For SOC analysts.** EternalBlue and DoublePulsar signatures are still recurring in unmanaged-edge devices in 2024 and 2025 [@hunterstrategy-eternalblue]. Train detection rules on the SMB signal, not just the WannaCry payload signature.<MarginNote>The DoublePulsar implant responds to a specific SMB Trans2 SESSION_SETUP subcommand with a non-zero Multiplex ID, which is the most-cited single-packet network signature for triage.</MarginNote> The Emotet -> TrickBot -> Ryuk killchain pattern is the operational anchor for human-operated ransomware detection; the IOCs change every quarter, but the kill-chain stages do not. PrintNightmare, a 2021 Part-5 story, reuses the same SMB-style propagation pattern.

<Spoiler kind="solution" label="Quick check: is Credential Guard actually running?">
On a Windows 10 or 11 Enterprise host, run `msinfo32.exe`, find the "Virtualization-based security Services Running" row, and confirm it lists `Credential Guard`. From PowerShell, `Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard | Select SecurityServicesRunning` returns an array whose value `1` corresponds to Credential Guard and value `2` to HVCI. If the array is empty, VBS is configured but no isolated services have started, and the LSAISO trustlet is not actually protecting credentials on that machine.
</Spoiler>

By the end of 2019, the architectural floor is named. The operational floor is named. Three axes are not yet closed.

## 12. What 2015-2019 Did Not Solve

Five problems leave this window open. Each is a chapter of Part 5 or Part 6, and each is open because the architectural gap and the deployment gap are at different sizes.

**Supply-chain integrity.** NotPetya proved that build-pipeline compromise is the dominant remaining attack class against well-defended estates [@talos-medoc] [@eset-telebots]. Microsoft's Security Development Lifecycle codifies pre-release secure-engineering practice [@ms-sdl], but SDL stops at the binary the build pipeline emits; it does not certify that the binary any verifier can rebuild matches that binary.

The 2015-2019 window saw two structural answers begin to mature. Debian's reproducible-builds project, in continuous progress since 2013, reached approximately 94 percent reproducibility by mid-2017 [@lwn-debian-reproducible]; the Tor Project's deterministic-builds work in 2014 framed the watering-hole-attack defense the discipline existed to address [@tor-deterministic-builds]. The Linux Foundation's Sigstore project, announced March 9, 2021, finally shipped a free transparency-log signing infrastructure for software artifacts [@lf-sigstore], and the NIST SP 800-218 Secure Software Development Framework codified the practice into a federal expectation in February 2022 [@nist-ssdf]. SolarWinds in December 2020 -- the Part 5 chapter -- forced the industry to take this open problem seriously.

The architectural distinction is between code-signing-as-supply-chain-integrity (signs whatever the build pipeline emits, regardless of pipeline compromise) and reproducible-build-as-supply-chain-integrity (signs only binaries any verifier can independently reproduce from source). At the 2019 cutline, reproducible builds are not the deployment norm; by the mid-2020s they are still not the norm for proprietary Windows-side software.

**The hypervisor and secure-call interface.** Amar and King's 2020 work on `SkmmUnmapMdl` and `SkmiReleaseUnknownPTEs` disclosed two kernel-strong VTL1 bugs reachable from VTL0 -- CVE-2020-0917 and CVE-2020-0918 -- and set the public-disclosure baseline at roughly one to three secure-call interface bugs per year [@amar-king-bh2020] [@msrc-cve-2020-0917].

Microsoft's response posture is enforcement, not formal verification. The Hyper-V Bounty program pays up to \$250,000 for a guest-to-host escape, with corresponding lower tiers for partial escapes and architectural vulnerabilities [@ms-hyperv-bounty]. The Microsoft Security Servicing Criteria treats secure-kernel and HVCI bypasses as Servicing Tier 1, meaning they are silently serviced through the normal patch cadence rather than coordinated as headline incidents [@ms-servicing-criteria]. The Saar-Amar-style Hyperseed fuzzer remains the internal-tooling baseline.

The open question is whether a formally-verified secure-call interface is achievable for Microsoft's deployed codebase. seL4 establishes that verification is feasible at roughly nine thousand lines of C [@klein-sel4-sosp2009]; `securekernel.exe` is approximately 150 kilobytes with substantial integration surface. The 2019 answer is "not yet." The cadence of CVEs since suggests the answer through 2024 remains "not yet."

**The BYOVD pipeline.** Microsoft's October 2022 default-on Vulnerable Driver Blocklist (KB5020779) blocks known-bad signed drivers reactively, by hash [@ms-vuln-driver-kb] [@ms-vuln-driver-blockrules]. The blocklist is fed by Microsoft's IHV-partnership submission flow, and Windows Defender Application Control consumes the same policy at the system level. The LOLDrivers community catalog tracks several hundred vulnerable signed drivers as of 2024 [@loldrivers], far more than the curated subset KB5020779 covers.

The structural distinction is between known-bad drivers blocked by hash -- the current approach -- and retroactive driver-signing revocation, which would block by certificate. Hash-based blocking handles the dominant in-the-wild surface; certificate-based revocation breaks legitimate deployments that rely on older signed drivers with Authenticode timestamps that pre-date the revocation. Microsoft has not solved that tradeoff at the 2019 cutline. KB5020779 (October 2022) is the partial answer. Full retroactive revocation remains open.

**Microarchitectural side channels in cross-VTL boundaries.** Spectre v2 leakage across the VTL0 to VTL1 boundary invalidates Credential Guard's confidentiality invariant if VTL0 can poison the indirect branch predictor that VTL1 consumes during a secure-call handler return; IBRS on secure-call entry is the standing mitigation, but every new microarchitectural class re-prices the defense.

LVI (Load Value Injection, CVE-2020-0551, March 2020), RIDL and ZombieLoad (May 2019, microarchitectural data sampling), and Inception (USENIX Security 2023, AMD-SB-7005 against Zen 3 and Zen 4 [@usenix-inception] [@amd-sb-7005]) each open a new variant. The structural answer the industry is moving toward is microarchitecturally-partitioned CPUs: Intel TDX [@intel-tdx] and AMD SEV-SNP [@amd-sev-snp] both ship hardware-isolated virtual machines with per-VM memory encryption that close the cross-VTL leakage class by construction. Both are datacenter-only at the 2019 cutline; neither lands on mainstream Windows endpoints until well after the article's window. The 2019 operational state is IBRS-plus-microcode mitigation, re-priced each time a new variant lands.

**Big Game Hunting defense when backups stop being a deterrent.** Maze's double-extortion playbook neutralized the backup-equipped defender's bargaining position [@krebs-maze]. Three research directions are open.

Cryptographic data-at-rest segmentation -- file-level encryption keyed to per-team hardware security modules, so a single compromised account cannot exfiltrate the full data corpus -- is the most direct technical answer. Segmented backup storage, in which the backup network is operationally isolated from the production network and authenticates only out-of-band, is the operational pattern that the segmented-tier-zero Active Directory work in this window points toward. Zero-knowledge backup storage, in which the storage provider holds only customer-encrypted blobs and cannot itself be compelled into the leak chain, is the architectural backstop.

Cyber-insurance market design is the fourth axis: after the Mondelez-versus-Zurich act-of-war dispute, the insurance industry restructured but did not solve the moral-hazard problem of ransom-coverage as a payment channel. Maze itself ceased operations in October 2020. The playbook persisted under Conti, LockBit, and successor groups through 2024.

Part 5 picks up at December 2020 with SolarWinds. Part 6 closes with the [CrowdStrike Falcon outage](/blog/the-day-85-million-devices-couldnt-boot----and-how-microsoft/) and the post-Pluton trust topology. The next five years will not be quieter.

## 13. Frequently Asked Questions

<FAQ title="Frequently asked questions">

<FAQItem question="Does Mimikatz still work against Credential Guard?">
Mimikatz still works, but the attack family Credential Guard was engineered against returns empty. The LSASS-scrape modules -- `sekurlsa::logonpasswords`, `sekurlsa::tickets`, `lsadump::secrets` -- read the bytes Credential Guard relocates into LSAISO in VTL1 [@ms-credential-guard], so the data is no longer where Mimikatz scans. What still works against a CG-enabled host is anything outside that threat model: pass-the-ticket replay of a TGT captured before CG was enabled, sign-in-time keylogging, stolen-DC krbtgt forgery, or BYOVD-grade kernel primitives that take advantage of secure-kernel bugs.
</FAQItem>

<FAQItem question="Doesn't HVCI have public bypasses?">
Yes. Six classes, all enumerated in Section 8 -- BYOVD with a vulnerable signed driver, hypervisor or secure-kernel vulnerabilities such as the 2020 Amar-King work on `SkmmUnmapMdl` [@amar-king-bh2020], pre-IOMMU hardware DMA, microarchitectural side channels, trustlet-signing-root compromise, and bugs in the VTL0 agents that broker requests to VTL1. None of those undermines the architectural claim that classical kernel-mode code injection is closed by HVCI's enforcement of write-XOR-execute on VTL0 kernel pages [@ms-hvci]. The bypass classes shape deployment posture; they do not invalidate the model.
</FAQItem>

<FAQItem question="Wasn't AMSI defeated by amsiInitFailed?">
Yes, in PowerShell user space. The Matt Graeber reflection trick that sets `AmsiUtils.amsiInitFailed` to true short-circuits AMSI within the running PowerShell process. MDSec's June 2018 write-up walks the family [@mdsec-amsi-bypass]. AMSI is a hook, not a sandbox; the bypass surface is part of the design tradeoff. The defender's response is the Defender behavioral pipeline and cloud telemetry, plus Constrained Language Mode and PowerShell logging that capture the bypass attempt itself as a high-confidence signal.
</FAQItem>

<FAQItem question="Why isn't this article about Hyper-V Shielded VMs or vTPM?">
Both are 2016+ Server features that build on the VBS substrate, but they were not the primary endpoint-security story in 2015-2019. The vTPM trustlet (Trustlet ID 2 in Ionescu's enumeration [@ionescu-bh2015]) supports Hyper-V Shielded VMs in the Server 2016 timeframe; that is a datacenter, not an endpoint, story. The Part 4 endpoint thesis is Credential Guard, HVCI, WDAC, AMSI, CFG, and Process Mitigation Policies.
</FAQItem>

<FAQItem question="Wasn't WannaCry an NSA attack?">
No. WannaCry used EternalBlue, an NSA-developed exploit that the Shadow Brokers leaked in their April 14, 2017 "Lost in Translation" dump [@wiki-eternalblue]. The operators of WannaCry were the Lazarus Group, attributed to North Korea by the United States, the United Kingdom, Australia, Canada, New Zealand, and Japan in a coordinated December 19, 2017 statement [@wh-wannacry]. The architectural lesson -- that a leaked nation-state SMB worm hit unpatched estates fifty-nine days after Microsoft shipped MS17-010 [@ms-ms17-010] -- is independent of who fired the weapon.
</FAQItem>

<FAQItem question="Wasn't NotPetya just ransomware?">
No. Kaspersky and CrowdStrike independently confirmed that the Salsa20 key derivation in NotPetya made decryption impossible by design [@kaspersky-petya]. The ransom payment screen was a decoy; the malware was a wiper. US, UK, Canadian, and Australian governments attributed the operation to Russian military intelligence (GRU Sandworm / Unit 74455) on February 15, 2018 [@wh-notpetya] [@ncsc-russia-notpetya]. The October 19, 2020 US Department of Justice indictment named six GRU officers [@doj-gru-notpetya].
</FAQItem>

<FAQItem question="What's the difference between CFG and Intel CET?">
Control Flow Guard is forward-edge, software-only, compiler-instrumented Control-Flow Integrity per the Burow et al. ACM CSUR 2017 taxonomy [@burow-cfi-csur2017] [@ms-cfg]. It validates the targets of indirect calls and jumps against a compile-time-known bitmap. Intel Control-flow Enforcement Technology adds a hardware-enforced shadow stack -- a backward-edge defense that protects return addresses. CET on Windows is a Part 5 story; here it suffices to say that CFG and CET defend orthogonal edges of the control-flow graph.
</FAQItem>

</FAQ>

## 14. Three Boxes, Three Outcomes

A 2017 red-team operator can dump LSASS on an unprotected Windows 7 box in less than a minute. The same operator, against a 1607 Enterprise laptop with Credential Guard enabled, sees an empty buffer where the NTLM hash should be. A 2017 NHS workstation, fifty-nine days behind on MS17-010, sees a ransom note. Three Windows boxes. Three outcomes. One five-year window.

The structural defense -- VBS, the Secure Kernel, LSAISO -- did exactly what its designers said it would do, in a way that was independently verifiable from the empty Mimikatz output buffer. The operational defense -- patch within a month, segment SMBv1, disable legacy protocols -- did exactly what its proponents said it would do, on the boxes where it was applied. The paradox of simultaneity is just the shape of the same picture seen from both sides.

Part 5 takes the story forward into supply-chain compromise, hardware-rooted attestation, and the Intel CET shadow stack. The next five years did not solve the six bypass classes named here. They named more of them.

<StudyGuide slug="above-the-kernel-windows-security-wars-part-4" keyTerms={[
  { term: "Virtualization-Based Security (VBS)", definition: "Windows security architecture that uses hardware virtualization extensions and Second-Level Address Translation to run the NT kernel and a Secure Kernel as separate Virtual Trust Levels on the same machine." },
  { term: "Virtual Trust Level (VTL)", definition: "Hyper-V hypervisor abstraction in which higher-numbered VTLs are strictly more privileged than lower-numbered ones. Shipped Windows uses VTL0 for the NT kernel and VTL1 for the Secure Kernel." },
  { term: "Trustlet", definition: "A Microsoft-signed process that runs in VTL1 Isolated User Mode and is protected from VTL0 inspection. Trustlets are gated at creation by five mechanical checks including two specific Enhanced Key Usage OIDs." },
  { term: "LSAISO", definition: "Trustlet ID 1; the Credential Guard secret-keeper. Holds NTLM hashes, Kerberos TGTs, and other credential material in VTL1 while LSA in VTL0 retains the API surface." },
  { term: "HVCI", definition: "Hypervisor-Protected Code Integrity. Uses the Hyper-V hypervisor to enforce write-XOR-execute on VTL0 kernel pages via Extended Page Tables, closing the classical kernel code-injection attack class." },
  { term: "Same-privilege paradox", definition: "The structural observation that any defense at the same CPU privilege level as the attacker can be disabled by the attacker. The only structural escape is to relocate the defender." },
  { term: "BYOVD", definition: "Bring Your Own Vulnerable Driver. An attack class in which the adversary loads a legitimately Microsoft-co-signed third-party driver with an exploitable bug to obtain kernel-mode primitives." },
  { term: "Big Game Hunting", definition: "Targeted ransomware business model in which a human operator performs hands-on-keyboard reconnaissance and deploys ransomware enterprise-wide at high ransom demand. Named by CrowdStrike in 2018." },
  { term: "Double extortion", definition: "Ransomware business model that exfiltrates victim data before encrypting, then threatens public disclosure as a second pressure axis. Maze's November 2019 Allied Universal case is the canonical first systematic deployment." },
  { term: "KVA Shadow", definition: "Microsoft's Meltdown mitigation. Maintains two page tables per process and swaps CR3 at every user/kernel transition, so the kernel page-table entries that Meltdown exploited speculatively are not mapped during user-mode execution." }
]} />
