Skip to content

Latest commit

 

History

History
124 lines (89 loc) · 5.25 KB

File metadata and controls

124 lines (89 loc) · 5.25 KB

PatchGuard (Kernel Patch Protection) Internals

Overview

PatchGuard, officially known as Kernel Patch Protection (KPP), is a Windows security feature introduced in Windows Vista x64 that protects critical kernel structures from unauthorized modification. When tampering is detected, PatchGuard triggers a bug check (BSOD) with code CRITICAL_STRUCTURE_CORRUPTION (0x109).

Architecture

Initialization

PatchGuard initializes during the late stages of kernel boot, specifically during Phase 1 initialization in ntoskrnl.exe. The initialization process:

  1. Context Allocation: A large structure (PG_CONTEXT, typically 4KB-64KB) is allocated from the NonPagedPool with a specific pool tag.
  2. Baseline Capture: Checksums are computed for all protected structures (SSDT, IDT, GDT, critical code sections, MSR values).
  3. Timer Setup: A kernel timer with an associated DPC (Deferred Procedure Call) is created with a randomized interval.
  4. Encryption: The entire PG context is XOR-encrypted with an obfuscation key before being stored in memory.

Protected Structures

PatchGuard monitors the following kernel structures:

Structure Description Check Method
SSDT System Service Descriptor Table Checksum of entire table
Shadow SSDT Win32k system call table Checksum (Win10+)
IDT Interrupt Descriptor Table Per-entry validation
GDT Global Descriptor Table Critical entry checks
MSR LSTAR SYSCALL entry point Value comparison
MSR CSTAR SYSENTER compat entry Value comparison
ntoskrnl .text Kernel code section Sampled page checksums
HalDispatchTable HAL function table Pointer validation
CI.dll Code Integrity module Code checksum
KdDebuggerEnabled Debug state variables Value validation
KPRCB fields Processor block critical fields Checksum

Verification Cycle

Each PatchGuard check follows this sequence:

Timer fires -> DPC executes -> Decrypt PG_CONTEXT -> Perform checks ->
  -> If OK: Re-encrypt context, re-arm timer with new random interval
  -> If Modified: KeBugCheckEx(0x109, ...)

The DPC routine:

  1. Acquires necessary locks
  2. Decrypts the PG_CONTEXT using the stored XOR key
  3. Iterates through each protected region
  4. Recomputes checksums and compares against baselines
  5. If all checks pass, re-encrypts the context and re-arms the timer
  6. If any check fails, calls KeBugCheckEx with detailed parameters

Timer Mechanism

PatchGuard uses kernel timers (KTIMER) with associated DPCs to schedule its checks. Key characteristics:

  • Randomized intervals: Between 5 seconds and 10 minutes (Windows 10+)
  • Multiple trigger mechanisms: Timer DPCs, work items, APCs, and exception-based triggers
  • Anti-debugging: Timer intervals change when a debugger is detected
  • Per-processor: Some checks are scheduled on specific processors

Encryption

The PG context is encrypted when not in active use:

  • Windows Vista/7: Simple single-key XOR (same key for all blocks)
  • Windows 8/8.1: Rolling key XOR (key advances per block)
  • Windows 10: Multi-key XOR with block-index-dependent sub-keys
  • Windows 11: Hybrid encryption with AES-like substitution rounds

Key storage: The primary key is derived from a combination of:

  • RDTSC value at initialization time
  • Address of the PG context itself
  • ntoskrnl base address
  • A constant seed embedded in the kernel binary

Exception Handling

PatchGuard makes extensive use of Structured Exception Handling (SEH):

  • The verification DPC is wrapped in multiple nested __try/__except blocks
  • Exception filters check for specific exception codes
  • PG installs vectored exception handlers as backup detection
  • Some PG code paths intentionally trigger exceptions to transfer control flow (anti-analysis technique)

Anti-Analysis Techniques

PatchGuard employs several techniques to resist analysis:

  1. Code obfuscation: PG code uses indirect calls, encrypted function pointers, and junk instructions
  2. Context encryption: The PG context is encrypted when not in use
  3. Timer randomization: Check intervals are unpredictable
  4. Multiple entry points: PG checks can be triggered via DPCs, work items, APCs, or exceptions
  5. Integrity self-checking: PG verifies its own code has not been modified
  6. Decoy structures: False PG contexts may be placed in memory to mislead analysis
  7. Anti-debugging: PG behavior changes when a kernel debugger is attached

Bug Check Parameters

When PatchGuard triggers a crash, KeBugCheckEx is called with:

  • Bug Check Code: 0x109 (CRITICAL_STRUCTURE_CORRUPTION)
  • Parameter 1: Address of the modified structure
  • Parameter 2: Type of modification detected
  • Parameter 3: Expected value
  • Parameter 4: Actual value found

Pool Allocations

PatchGuard uses specific pool tags for its allocations:

  • MkPg: Main PG context
  • MkTm: Timer-related structures
  • MkWi: Work item allocations
  • MkGr: Generic PG allocations

Starting with Windows 11 23H2, pool tags may be obfuscated with a per-boot XOR mask.

References

  • Microsoft documentation on Kernel Patch Protection
  • Windows Internals, 7th Edition (Yosifovich, Ionescu, Russinovich, Solomon)
  • Public research papers on KPP analysis