Levels/Security & authentication/Kernel Patch Protection (PatchGuard) & HyperGuard

Level 2 · Chapter 14

Kernel Patch Protection (PatchGuard) & HyperGuard

Periodic, deliberately obfuscated integrity checks that bugcheck the machine the moment core kernel state looks tampered with.

Every mechanism described anywhere in this course — access checks, process protection, exploit mitigations — ultimately trusts one foundational thing: that the kernel enforcing all of it hasn't itself been modified by a driver running in kernel mode. Kernel Patch Protection, almost universally known by its original codename PatchGuard, is specifically what makes that assumption hold on 64-bit Windows.

An alarm that doesn't announce itself

The core design idea is unusual compared to most of what this course has covered: PatchGuard doesn't block a write to protected kernel structures the way an access check blocks an unauthorized object open. Instead, scattered through the kernel are self-checking routines — deliberately obfuscated, running at unpredictable intervals rather than on a fixed, discoverable schedule — that periodically re-verify a set of structures and code regions haven't changed since they were last known-good. If a verification fails, the response isn't a quiet log entry or a blocked operation; it's an immediate, deliberately destructive kernel bugcheck (0x109: CRITICAL_STRUCTURE_CORRUPTION). The design goal is explicit: a 64-bit Windows kernel that's been tampered with should crash rather than keep running in a state nothing can vouch for anymore.

What it actually watches

The specific set of protected structures isn't published and has shifted across Windows releases by design — publishing an exact list would just hand attackers a checklist of what to avoid touching. But the categories are well understood from historical analysis: the system service table (SSDT), the kernel's own code pages, the IDT and GDT, and other core dispatch structures that pre-x64-era software — both legitimate security products and plenty of malware — used to patch directly and routinely. That history is exactly why these became the target: hooking the SSDT to intercept every system call was a completely ordinary technique on 32-bit Windows, used by antivirus engines and rootkits alike, and PatchGuard's arrival on x64 is precisely what ended that era.

Why detection is delayed, and why that's deliberate

An attacker who understood exactly when a check ran, and what exactly it verified, could plausibly time a patch-then-revert sequence to slip through undetected. PatchGuard's checking code is intentionally spread out, re-generated and re-obfuscated across updates, and run on a schedule that isn't fixed or predictable from outside — the combination is specifically meant to make "patch it, then patch it back before the next check" an unreliable strategy rather than a solved problem. This is also why PatchGuard detections, when they do happen, often come as a surprise crash well after whatever actually caused the tampering — the delay is a feature of the design, not a bug in it.

HyperGuard: moving the vantage point outside the kernel entirely

PatchGuard's checking code still runs inside the kernel it's protecting, which leaves a theoretical gap: a sufficiently privileged kernel-mode attacker — one who's already achieved arbitrary kernel code execution some other way — could in principle find and disable or patch around PatchGuard's own checking routines, since they're just more kernel code. HyperGuard closes that specific gap by moving the vantage point a level up: on a machine with Hyper-V and VBS active, the hypervisor — running at a trust boundary the ordinary kernel cannot reach into or modify, exactly as described in Virtualization & the hypervisor — independently monitors the same category of critical kernel-mode state from completely outside it. A kernel-mode attacker who could tamper with or disable in-kernel PatchGuard checks has no equivalent path to reach code running at the hypervisor's trust level.

A worked example: why security products stopped hooking the SSDT

Before x64 PatchGuard, a common architecture for antivirus and host-intrusion-prevention products was direct SSDT hooking: replace a system call table entry with a pointer to your own inspection code, then call through to the original. It worked, and it was also exactly the kind of modification malware authors used for the same reason — to intercept and hide from system calls. When PatchGuard arrived on 64-bit Windows, this entire approach stopped being viable for anyone, security vendors included, since the kernel now treats that modification as tampering rather than as a particular vendor's legitimate use case. The industry's actual response is a large part of why modern defensive tooling looks the way it does: minifilters for file-system interception, registered callbacks for process/thread notifications, and ETW for broad visibility — all supported extension points, rather than direct structure patching.

A common mistake

Assuming PatchGuard prevents kernel exploitation is a common and consequential misreading of what it actually does. It does nothing to stop an attacker from achieving kernel-mode code execution in the first place — that's the job of the kernel's own attack surface reduction, driver signing enforcement, and the broader hardening this course covers elsewhere. What PatchGuard guarantees is narrower and different: that certain categories of persistent, stealthy tampering, once achieved, become detectable and fatal rather than silently permanent. Conflating "detects tampering after the fact" with "prevents compromise in the first place" misunderstands the actual threat model it was built for.

Where this connects