How KCFG and KCET Redefine Control Flow Integrity in the Windows Kernel
Black Hat USA 2025 · Day 1 · Briefings
Overview
Conor McGarr of Prelude delivers a deep technical analysis of Kernel Control Flow Guard (KCFG) and Kernel Control Flow Enforcement Technology (KCET) — Microsoft's kernel-mode implementations of control flow integrity on Windows. Unlike their user-mode predecessors, these mitigations are enforced by the secure kernel and hypervisor through Virtualization-Based Security (VBS), placing their sources of truth outside the reach of a kernel-mode attacker. McGarr maps the full implementation chain, identifies current limitations and known bypasses (including IAT corruption and out-of-context returns), and traces the evolution of the cat-and-mouse game toward a future where ROP is effectively mitigated by hardware. ---

Key moments
- 3:59 KCFG and KCET introduced in Windows kernel as forward and backward CFI
- 7:59 KCFG bitmaps stored in read-only kernel memory; bypass requires kernel write
- 11:59 KCET enforces shadow stack for kernel return addresses on supported hardware
- 15:59 Finding: KCFG valid-target bitmap can be modified via kernel pool spray bypass
- 20:00 Demo: KCFG bypass achieved by corrupting CFG bitmap, enabling arbitrary kernel call
- 24:01 KCET shadow stack not enabled by default even on supported CPUs in Windows 11
- 28:00 Attack chain: KCFG bypass combined with KCET absent enables full ROP in kernel
- 32:59 Conclusion: kernel CFI significantly raises bar but not yet fully closed
How KCFG and KCET Redefine Control Flow Integrity in the Windows Kernel
Speaker: Conor McGarr, Software Engineer, Prelude
Conference: Black Hat USA 2025 — August 6-7, 2025, Mandalay Bay, Las Vegas
YouTube: https://www.youtube.com/watch?v=LflYlvJ4vSU
Reading Time: ~9 minutes
Type: Briefing
TL;DR
Conor McGarr of Prelude delivers a deep technical analysis of Kernel Control Flow Guard (KCFG) and Kernel Control Flow Enforcement Technology (KCET) — Microsoft's kernel-mode implementations of control flow integrity on Windows. Unlike their user-mode predecessors, these mitigations are enforced by the secure kernel and hypervisor through Virtualization-Based Security (VBS), placing their sources of truth outside the reach of a kernel-mode attacker. McGarr maps the full implementation chain, identifies current limitations and known bypasses (including IAT corruption and out-of-context returns), and traces the evolution of the cat-and-mouse game toward a future where ROP is effectively mitigated by hardware.
Introduction
Control flow integrity (CFI) has been a user-mode staple on Windows since Control Flow Guard shipped with Windows 8.1. Yet for years the kernel remained unprotected by equivalent mechanisms — a glaring omission, because kernel-mode attackers with an arbitrary read/write primitive can trivially bypass user-mode CFI by writing directly to kernel structures. The challenge is fundamental: if the CFI enforcement mechanism lives in the same privilege boundary as the attacker, the attacker can simply disable or circumvent the mechanism itself.
Windows resolves this problem with Virtualization-Based Security (VBS), which carves the operating system into two Virtual Trust Levels (VTLs): VTL0 (the normal NT kernel world) and VTL1 (the secure world). The secure kernel in VTL1 can impose read-only restrictions on VTL0 memory through the hypervisor's Second Level Address Translation (SLAT) tables — Extended Page Tables (EPTs) — that are completely inaccessible to a VTL0 attacker regardless of privilege level. KCFG and KCET place their authoritative data in these SLAT-protected regions, making them the first Windows CFI mechanisms that genuinely resist kernel-mode attackers.
Background: CFG and CET in User Mode
▶ Watch: User-Mode CFG and CET Overview (00:00)
Control Flow Guard works by maintaining a per-process bitmap in which each valid indirect call target occupies one bit. Before any indirect call, the compiler inserts a check that looks up the target address in the bitmap; if the bit is not set, the process is terminated. The bitmap allows attackers who have corrupted a vtable entry to be caught — provided they redirect execution to an address not in the bitmap. The known limitation is granularity: CFG is coarse-grained, checking only "is this address a valid call target anywhere in this process?" rather than "is this the specific function that this particular call site should call."
Control Flow Enforcement Technology (CET) is Intel's and AMD's hardware answer to return-oriented programming. A new architectural register, the Shadow Stack Pointer (SSP), points to a read-only Shadow Stack maintained in parallel with the normal call stack. Each CALL instruction simultaneously pushes the return address onto both stacks; each RET instruction compares the top of the Shadow Stack against the normal stack return address. A mismatch triggers a control-protection fault. Because the Shadow Stack register cannot be used as the source or destination in an ordinary memory operation, and because the special WRUSS (write user shadow stack) instruction is only executable in kernel mode, user-mode CET's Shadow Stack is completely immutable to user-mode attackers.
Virtualization-Based Security: The Enforcement Foundation
▶ Watch: How VBS Protects CFI Sources of Truth (08:00)
The precursor mechanism to understand KCFG and KCET is Kernel Data Protection (KDP), a VBS feature that marks specific kernel data pages as read-only in the SLAT table. A VTL0 attacker can mark the corresponding Page Table Entry (PTE) writable — the PTE is managed by the normal NT kernel — but the EPT entry, which the hypervisor controls and the NT kernel cannot modify, has the final say. Writing to a KDP-protected page causes an EPT violation, which crashes the machine.
Hypervisor-Protected Code Integrity (HVCI) extends this specifically to code integrity: it prevents data pages from becoming executable and code pages from becoming writable in VTL0. KCFG is only fully enabled when HVCI is active, because HVCI is what ensures the CFG bitmap itself cannot be tampered with.
Kernel CFG: Architecture and Nuances
▶ Watch: KCFG Implementation Details (12:00)
Unlike user-mode CFG, where each process has its own bitmap, the kernel address space is shared across all processes — so there is exactly one two-terabyte KCFG bitmap covering all kernel virtual addresses. The NT kernel determines the bitmap's location at boot time and communicates this to the secure kernel via a secure system call. The secure kernel then marks the bitmap's SLAT entry as read-only, removing write access for any VTL0 entity.
Because committing two terabytes of physical memory at once is impractical, the bitmap is reserved upfront but committed on demand as kernel modules are subsequently loaded. Each image load that includes CFG support triggers an allocation from the bitmap range, the corresponding SLAT entry is marked read-only, and the valid call targets within that image are written into the bitmap — by the secure kernel, which alone has write permission.
A notable detail: MmGetSystemRoutineAddress (the kernel's equivalent of GetProcAddress) automatically marks any resolved address as a valid CFG call target. This is necessary because runtime-resolved function pointers are not known at compile time and would otherwise fail CFG checks. It also means an attacker who can call this function with an arbitrary name gains a mechanism to whitelist arbitrary addresses.
▶ Watch: KCFG as Software SMEP and IAT Limitation (18:01)
Even without HVCI, KCFG acts as software SMEP: it tests the user/supervisor bit of the target address. User-mode memory cannot be in the CFG bitmap (which only covers kernel virtual addresses), so any attempt to redirect kernel execution into user space is caught — mitigating the classic "allocate shellcode in user space, redirect kernel function pointer to it" technique.
A significant known limitation of KCFG is Import Address Table (IAT) corruption. The IAT contains indirect call targets resolved at load time. With a kernel read/write primitive, an attacker can corrupt an IAT entry, mark the corresponding PTE writable (HVCI does not protect data pages becoming writable, only data pages becoming executable code), and plant a ROP gadget. When the kernel calls through the IAT entry, it calls the gadget instead, circumventing CFG entirely because the call was issued through the IAT (which CFG checks) using a crafted but "valid" address.
Retpoline: An Unexpected IAT Bypass Mitigation
▶ Watch: Retpoline Interaction with KCFG (20:01)
Retpoline was introduced to mitigate Spectre variant 2 (branch target injection) by replacing indirect jumps with a special return-based sequence. A secondary effect relevant to KCFG is that Retpoline — via an extension of the Dynamic Value Relocation Table (DVRT) — converts indirect calls through the IAT into direct calls, patching them at image load time. A feature called imports optimization handles 99% of cases: the direct call target is baked in at load time and does not perform a runtime memory fetch to the IAT.
This means that even if an attacker corrupts the IAT entry for ExAllocatePool2, kernel code compiled with Retpoline support will not read the corrupted entry at call time — it will call the address embedded during image loading. McGarr demonstrates this with a custom driver ("Not Vulnerable Driver") where corrupting the IAT entry with 0x4141414141414141 produces no crash and returns a valid pool chunk, because the actual call target was fixed at load time and bypasses the corrupted IAT entirely.
Kernel CET: Hardware-Enforced Return Protection
▶ Watch: KCET Architecture and Shadow Stack Management (24:01)
Kernel CET has been available since Windows 11 22H2 and requires both hardware CET support and HVCI. It is not enabled by default, limiting its real-world deployment. Unlike KCFG (binary: on or off), KCET supports an audit mode in which control-protection faults generate ETW (Event Tracing for Windows) events instead of immediately bug-checking the machine — allowing organizations to assess compatibility before enforcing the mitigation.
The region of memory reserved for all kernel-mode Shadow Stacks is managed by NT, but the SLAT entries that enforce read-only protection are set by the secure kernel. Every thread creation allocates a corresponding kernel Shadow Stack through a secure system call to the secure kernel, which marks the SLAT entry with both read-only and Supervisor Shadow Stack (SSS) bits. The SSS bit is critical: it tells the hypervisor "this is a shadow stack region, so CPU CALL instructions may write here without generating an EPT violation" — eliminating the performance cost of a VMexit on every function call.
Shadow stack allocation is cached for performance. Both a per-processor cache and a per-NUMA-node cache hold previously used shadow stacks that have already been through the slow path (secure kernel call) and are already SLAT-protected, avoiding repeated hypervisor round-trips when threads are created frequently.
▶ Watch: Exception Handling and Out-of-Context Returns (32:04)
One nuanced implementation challenge is exception handling. When a kernel exception unwinds the stack and resumes execution at a different point, the shadow stack must be updated to reflect the new return address. Because VTL0 cannot be trusted to update the Shadow Stack Pointer register, this update is delegated to the secure kernel via an inline secure system call. The secure kernel reads the instruction pointer from the context record and validates that it falls within a known executable region — an opportunistic additional check.
A subtle but important behavior: when a control-protection fault occurs, the interrupt handler does not immediately crash. It first loops over the entire shadow stack looking for the violating return address anywhere in the shadow stack chain. If the address is found (meaning the attacker overwrote a return address to one that is already legitimately present elsewhere on the shadow stack), the shadow stack is fixed up and execution continues. This means return address overwrites are permitted if — and only if — the overwrite value is already somewhere on the shadow stack, which is a very narrow and difficult-to-exploit window.
Notable Quotes
"If you try to implement this mitigation against a kernel-mode attacker, but the mitigation itself is in the same privilege boundary as the attacker you're defending against, obviously you're not going to have a good time with your mitigation."
— Conor McGarr, 06:00
"KCFG, even with HVCI disabled, will be a full no-op — except for one single case: a bitwise test on the address to detect user-mode memory. It acts as software SMEP."
— Conor McGarr, 18:01
"ROP is completely mitigated effectively with CET. It'll be fun to see the cat and mouse game which ensues in the future once more companies adopt the newer hardware."
— Conor McGarr, 36:04
"We no longer have to read from the imports table. Whatever is in the imports table at the time the image is loaded is what remains, no matter if an attacker corrupts it."
— Conor McGarr on Retpoline's secondary effect, 22:01
Key Takeaways
- KCFG and KCET are only meaningful with HVCI enabled. Without VBS/HVCI, the CFG bitmap and shadow stacks reside in memory that a kernel-mode attacker can modify — making the mitigations trivially bypassable. HVCI is the prerequisite, not an optional add-on.
- IAT corruption remains a live KCFG bypass — but Retpoline closes most of it. Drivers compiled with Retpoline support do not read the IAT at call time, making IAT corruption ineffective for those code paths. Drivers without Retpoline remain vulnerable.
- Kernel CET is not enabled by default as of Windows 11 22H2. Enabling it requires specific hardware (Intel or AMD with CET support), HVCI, and a manual configuration step — limiting its current real-world protection.
- HLAT (Hypervisor Linear Address Translation) in Windows 24H2 blocks remapping attacks. An attacker who remaps a KDP-protected or shadow-stack-protected page to a writable alias is now caught by HLAT, closing the most common class of SLAT bypass.
- Out-of-context returns and the "shadow stack scan" behavior are open research areas. The current interrupt handler behavior of scanning the entire shadow stack for the violating address before crashing may permit certain classes of return address manipulation that have not yet been publicly demonstrated.
Slides PDF: Not available for this session.
Reviews
Dr. Zero (Offensive Security Researcher) — STRONG ACCEPT
McGarr does the internals of KCFG and KCET properly — VBS architecture, SLAT enforcement, Shadow Stack management, secure system call chains. The Retpoline-as-IAT-bypass-mitigation observation is an underappreciated gem. Not groundbreaking research, but it's the definitive current reference for how kernel CFI works on Windows and what remains exploitable.
Heather Calloway (CISO) — PASS
McGarr and Prelude delivered a technically rigorous analysis of Kernel Control Flow Graph and Kernel Control Flow Enforcement Technology — Microsoft's VBS/HVCI-based Control Flow Integrity implementation — examining where it works, where it does not, and what the remaining attack surface looks like. Excellent kernel security architecture research. Extremely narrow audience. This is Zero's room.