Why Same-Privilege Mitigations Fail Against Kernel Attackers

▶ Watch (00:40)

CFG, available since Windows 8.1, blocks indirect calls by consulting a per-process bitmap of valid call targets. CET, available since Windows 10 1903, adds a hardware shadow stack that stores return addresses the processor compares on every return.

Both mitigations work because the user-kernel boundary keeps attackers out of the data they protect. Move the attacker into kernel mode and that boundary disappears. An attacker with a kernel read-write primitive locates the CFG bitmap, finds its page table entry, marks it writable, and corrupts it. Two extra steps, then the mitigation is gone.

VBS and the Hypervisor Security Boundary

▶ Watch (07:50)

Windows Hyper-V splits the OS into two virtual trust levels. VTL0 is the normal NT kernel. VTL1 is the secure kernel, and it can enforce memory policies on VTL0 through second-level address translation (SLAT) entries that the hypervisor controls. Kernel Data Protection (KDP) shows this in practice: a kernel attacker can mark a page’s PTE writable, but the hypervisor’s extended page table entry overrides it as read-only. Any write attempt triggers an EPT violation and crashes the machine. CFG and CET source-of-truth protection works the same way.

Kernel CFG: Implementation, Limits, and the Repoline Side Effect

▶ Watch (11:48)

KCFG shipped in Windows 10 Redstone 2 (2017) and requires HVCI to be fully active. A single two-terabyte bitmap covers all kernel-mode images, protected read-only through SLAT. The coarse-grained design is a documented weakness: any valid call target from any kernel image can substitute for any other, leaving COOP and JOP viable.

The IAT is documented as unprotected, but the repoline IAT corruption demo (22:23) shows repoline compilation fixes those calls to direct calls at load time, so a corrupted IAT entry has no runtime effect. Return addresses on the stack are a different matter, as the return address overwrite demo (23:17) confirms.

Kernel CET: Shadow Stack Allocation, Caching, and Exception Handling

▶ Watch (24:01)

KCET guards return addresses with hardware shadow stacks, each registered with the secure kernel via a secure system call that marks it read-only in the SLAT table. Two caches (per-processor and per-NUMA-node) avoid a hypervisor call on every thread creation by reusing stacks that already completed the slow path.

Exception handling routes the shadow stack pointer update through a “shadow stack assist” call to the secure kernel. Only the secure kernel can supply the new SSP value. It also validates that the exception context’s instruction pointer falls within a known executable region, an opportunistic CFI check on every exception.

Research Gaps and What Comes Next

▶ Watch (35:16)

Kernel CET has been available only since Windows 11 22H2 and is off by default. Most research still targets KCFG. The coarse bitmap means any valid call target across all loaded kernel images is a usable gadget, making COOP and JOP viable. Windows does not use indirect branch tracking (IBT), the other half of CET that would close that gap.

McGarr flagged out-of-context returns as an underexplored attack path. Hypervisor linear address translation (HLAT), available in Windows 24H2, blocks page-remapping attacks that could otherwise bypass KDP-protected memory. When KCFG, KCET, HVCI, and HLAT run together, the attack surface narrows sharply.

Notable Quotes

the shadow stack is completely immutable to a user mode attacker Connor McGarr · ▶ 5:17

we just have to add two Connor McGarr · ▶ 7:04

ROP is completely mitigated effectively with CCT Connor McGarr · ▶ 33:44

Key Takeaways

  • KCFG and KCET require HVCI and VBS; without them, a kernel attacker can bypass both in two extra steps.
  • Repoline compilation incidentally closes the IAT bypass path against KCFG, even on CPUs that no longer need it.
  • KCET has existed only since Windows 11 22H2, is off by default, and Windows does not use IBT, leaving COOP and JOP viable.