In this blog post, we will explore different types of out-of-bounds (OOB) vulnerabilities in Windows kernel drivers. Our objective is to demonstrate how simple mistakes in memory management, structure handling, and loops can introduce serious OOB vulnerabilities in custom kernel drivers. We will write realistic, purpose-built kernel drivers containing intentional vulnerabilities to showcase OOB reads, OOB writes, and loop-based overflow.
What is Out-of-Bounds?
Out-of-bounds (OOB) occurs when a program accesses memory outside the boundaries of a valid buffer or data structure. This can lead to information leaks, memory corruption, or privilege escalation in kernel-mode drivers. OOB bugs typically arise from incorrect index calculations, pointer mismanagement, or faulty loop conditions.
Out-of-Bounds Read Custom Network Driver
An out-of-bounds read (OOBR) happens when a program reads past the end of a buffer due to invalid size assumptions. In kernel mode, it can leak uninitialized memory or sensitive kernel pointers, bypassing mitigations like KASLR. Common causes include mismatched struct sizes, missing length checks, and bad loop bounds. These flaws can sometimes escalate into arbitrary read/write vulnerabilities.
We made a custom driver that takes a user-supplied structure containing SourcePort
and DestPort
, where DestPort
is (mis)used as an offset into memory.

The DestPort
field in the structure is user-controlled and treated as a raw offset. In the vulnerable code line, DestPort
is directly added to the base pointer hdr
without any validation or bounds checking. If an attacker supplies a large DestPort
value, leakPtr
will point outside the intended buffer. This results in an out-of-bounds memory access, which can leak sensitive kernel memory or cause a crash. The flaw stems from trusting unvalidated user input as a pointer offset.
PoC: Out-of-Bounds Kernel Memory Leak via DestPort Offset
This PoC opens a handle to the vulnerable device and crafts a fake TCP header structure. It repeatedly sets various large values to DestPort
, which is used as an offset for an out-of-bounds read in the driver. By sending these crafted packets with DeviceIoControl
, the PoC attempts to leak kernel memory.

The loop iterates through multiple DestPort
values (offsets) from 0x80 to 0x1000 in steps of 0x80. This increases coverage to trigger out-of-bounds reads at various memory locations.

PoC Output: Memory Leak Results in dbgview
This output shows leaked 8-byte (QWORD) values from different memory offsets specified via DestPort
. Some offsets reveal kernel pointers (e.g., 0xFFFF860D748E70A0
), indicating successful out-of-bounds reads, while others return zero or unrelated data. This confirms arbitrary memory disclosure.


This !pool
output shows the leaked address belongs to a non-paged pool allocation tagged AlIn
, which is used for ALPC (Advanced Local Procedure Call) internal structures in the Windows kernel. The memory region is actively allocated and contains sensitive kernel data, confirming the seriousness of the out-of-bounds leak.
Out-of-Bounds Write Custom Driver
Out-of-bounds (OOB) write occurs when a program writes data past the end (or before the start) of a valid memory buffer. It corrupts adjacent memory regions, leading to crashes, data corruption, or potential code execution. This driver demonstrates a simple out-of-bounds (OOB) write vulnerability in kernel mode.

The driver defines a fixed-size array targetBuffer[10]
(10 bytes). It blindly copies length bytes from a user-supplied buffer without checking if length > 10
. If the user sends more than 10 bytes, RtlCopyMemory
writes past the end of the array. This causes an out-of-bounds write, corrupting adjacent kernel memory and leading to crashes or exploitation
PoC — Triggering Out-of-Bounds Write via IOCTL
The PoC opens a handle to the vulnerable driver using CreateFileW
targeting the OobArrayDevice
. It constructs a malicious input buffer of 100 bytes, filling it entirely with the byte 0x41 (ASCII ‘A’).

This results in an out-of-bounds write of 90 extra bytes, overwriting adjacent kernel stack memory with 0x41 patterns — leading to memory corruption (and likely will result in a crash).
WinDbg Analysis—Confirming Out-of-Bounds Write in Kernel Stack
After triggering the vulnerability, the driver printed the kernel address of targetBuffer: targetBuffer @ FFFFFE0378E377F0
. In WinDbg, the dq
command (dq FFFFFE0378E377F0
) dumps 64-bit quadwords starting from the buffer address.

We clearly observe repeated 0x41414141 patterns (ASCII ‘A’) overflowing well beyond the 10-byte array—confirming an out-of-bounds write onto adjacent kernel stack memory. This explains why a blue screen of death (BSOD) or kernel memory corruption occurs; we’ve clobbered critical stack data following the array.
Mimicking a Vulnerability Inspired by RTKVHD64.sys
In this post, we demonstrate a simplified but realistic mimic of a vulnerability pattern observed in Realtek’s RTKVHD64.sys
audio driver. While the original vulnerability details and reverse engineering insights will be covered in later posts, here we focus on replicating a kernel out-of-bounds arbitrary write bug within a custom Windows driver.
Our vulnerable driver (VulnAudioDriver.sys
) exposes a controlled IOCTL interface, closely resembling patterns seen in RTKVHD64.sys
handling of kernel structures and user-controlled indices.

The MEVT structure contains an array of 63 EVT objects. Without a bounds check, an attacker can specify input_index >= 63
, leading to memory accesses beyond the array, corrupting adjacent kernel memory. Such unchecked indexed access patterns, especially when manipulating kernel object fields, can lead to privilege escalation, kernel memory corruption, or even arbitrary kernel writes.

This code directly casts the user-supplied input_index into an array access (gMevt->array[input_index]
) without validating bounds, enabling out-of-bounds memory access. The attacker controls both the spinlock pointer (KSPIN_LOCK* spinlock
) and the event pointer (PVOID* event_ptr
), allowing manipulation of arbitrary kernel addresses. When KeAcquireSpinLock(spinlock, &oldIrql)
is called on a user-controlled pointer, it can trigger memory corruption or cause a controlled kernel crash.
[Note: The following line is added purely for blog demonstration purposes and is not part of the original vulnerable code.]*event_ptr = userInput->value_to_write;
demonstrates how an attacker-controlled value can be written to an arbitrary kernel memory location, showcasing a powerful arbitrary write primitive for exploitation or crashing.
Proof-of-Concept (PoC) Trigger for VulnAudioDriver
Arbitrary Write
This simple user-mode PoC crafts a malicious USER_INPUT
structure with an out-of-bounds index (input_index = 10000
) and sends it to the vulnerable driver via DeviceIoControl
. The attacker controls both the memory location and the value to be written.

Setting input_index = 10000
deliberately exceeds the valid bounds of the array[63], which only permits indices 0–62. This triggers an out-of-bounds access, letting the attacker compute a pointer far outside the intended object. As a result, the attacker gains an arbitrary kernel memory write primitive by overwriting unintended kernel memory. By exploiting the unchecked array access, the driver writes to arbitrary kernel memory, leading to corruption.

When executed, this reliably causes a blue screen of death (BSOD) due to illegal memory access, demonstrating the severity of the arbitrary write primitive.
Conclusion
To identify out-of-bounds read and write vulnerabilities in kernel drivers, focus on patterns where user-controlled indices are used to access fixed-size arrays without proper bounds validation. Carefully examine IOCTL handlers and input structures where fields like input_index
directly influence array offsets or pointer dereferences. Unchecked indexed access into kernel structures—especially arrays of objects or pointers—can lead to memory corruption if user-supplied indices exceed the allocated range. Pay close attention when the indexed elements are pointers, function tables, or kernel object fields, as these can escalate simple OOB bugs into powerful arbitrary read or write primitives. Always trace how user inputs flow into array accesses and check if validation (e.g., index < array_size) is missing or insufficient.
Reference
RTKVHD64.sys: https://hackyboiz.github.io/2021/06/29/l0ch/2021-06-29/