Kernel CFG / kCET

Kernel CFG / kCET

TL;DR: Kernel CFG (kCFG) validates indirect call targets against a per-process bitmap; kernel CET shadow stacks validate returns. Together they shrink the gadget budget and push exploitation toward data-only attacks.

What it is

  • kCFG — kernel-mode Control Flow Guard. Indirect calls (call rax, call [rcx+0x10]) are prefixed with __guard_check_icall_fptr-style stubs that consult a sparse bitmap of valid call targets. Calls to mid-function bytes or to non-function pointers crash the kernel via a bug check.
  • kCET — Control-flow Enforcement Technology in kernel mode. The CPU maintains a shadow stack for the kernel; every ret checks the shadow value against the regular stack. Tampering = #CP exception → bug check.

Both rely on hardware (CET) or PE metadata (CFG GFIDS table); both are enabled only when hvci-vbs is on (HVCI vouches for the integrity of the bitmap and shadow-stack page tables).

Preconditions / where it applies

  • Windows 10 1809+ (kCFG with HVCI) and Windows 11/Server 2022 (kCET on Tiger Lake+, Zen 3+ CPUs).
  • Attacker has a kernel write or call-target hijack primitive but must keep the chain within validated targets.
  • Only modules compiled with /guard:cf participate; older third-party drivers may be opt-out and become weak links — see hvci-vbs for the driver-blocklist angle.

Technique

Bypass strategies (high-level — all hard, all situational):

  1. Stay in valid targets. Walk the GFIDS list and chain only addresses that the bitmap accepts. Many useful sinks (HalpSetSystemInformation, nt!NtAllocateVirtualMemory style stubs) are valid CFG targets and still let you reach a primitive.
  2. Data-only. Don’t hijack control flow. With AR/AW (arbitrary-read-write-primitives) you can copy tokens, overwrite ACLs, or patch _KTHREAD.PreviousMode and call Nt* syscalls — no ret or indirect call needed.
  3. Find non-CFG modules. Third-party signed drivers loaded into the kernel without /guard:cf execute indirect calls without bitmap checks; their function pointers (callbacks, IRP dispatch table) are call gadgets if their image is mapped.
  4. CET caveats. CET shadow-stack pages live in PTEs marked with a special bit checked by the CPU; without an HVCI bypass you cannot make a normal kernel page act as shadow. Therefore most CET bypasses depend first on an HVCI bypass via a vulnerable driver (see hvci-vbs and loldrivers.io).
  5. Disable from a primitive. If you achieve an early AR/AW before chains are needed, clearing KeFeatureBits / patching cfg_check_icall_fptr to a ret is sometimes possible on builds without HVCI — but not on modern enforced configurations.

Detection and defence

  • Enable HVCI + MBEC and Microsoft’s Vulnerable Driver Blocklist; that closes the most reliable bypass route.
  • Audit third-party drivers for /guard:cf and /CETCOMPAT; recompile or remove.
  • Telemetry: bug-check KERNEL_SECURITY_CHECK_FAILURE (0x139) sub-codes 5 (CFG) and 38/39 (CET) are direct evidence of a thwarted attempt.

References

See also: control-flow-guard, xfg, hvci-vbs.