Heap-based buffer overflow in Kernel Streaming WOW Thunk Service Driver – CVE-2025-53149

Heap-based buffer overflow in Kernel Streaming WOW Thunk Service Driver – CVE-2025-53149

Reading Time: 4 minutes

From time to time, while digging through internals during our research, we stumble upon quirks or vulnerabilities that, although not immediately useful for operations or exploitation, are still noteworthy. Rather than letting these findings fade away, we decided to responsibly disclose them to the vendor. One such case is CVE-2025-53149, a heap-based buffer overflow in the Kernel Streaming WOW Thunk Service Driver, which Microsoft patched on August 12, 2025.

The vulnerable component is the ksthunk.sys driver, SHA-1 68B5B527550731DD657BF8F1E8FA31E895A7F176.

Kernel Streaming

Kernel streaming, often abbreviated as KS, is a foundational technology within the Windows operating system for handling real-time data streams, particularly for multimedia applications. It provides a low-latency, high-performance architecture that allows devices and applications to efficiently process and transport large volumes of data, such as audio and video.

KSThunk, short for “Kernel Streaming WOW Thunk Service,” is a specific component within the Windows operating system that plays a crucial role in maintaining backwards compatibility for multimedia applications. It is a system driver file (ksthunk.sys) that is primarily used on 64-bit versions of Windows. The core purpose of KSThunk is to act as a “thunk” layer: a small piece of code that translates requests between different environments. In this case, it bridges the gap between 32-bit user-mode applications and the 64-bit kernel-mode drivers that manage real-time media streams.

Static analysis

We discovered the vulnerability in the CKSAutomationThunk::HandleArrayProperty() function of the ksthunk.sys driver. Looking at the IOCTL dispatching code in the CKSThunkDevice::DispatchIoctl() function, it can be noted that CKSAutomationThunk::ThunkPropertyIrp() will be called when the calling process is usermode and wow64:

CKSAutomationThunk::ThunkPropertyIrp() perform checks on the input buffer length and reads the KSPROPERTY.Flags. If the two lowest bits are 0, then the function returns 1. But if the KSPROPERTY.Flags has set KSPROPERTY_TYPE_SET or KSPROPERTY_TYPE_GET, then the request is going to be processed with an additional property set, as shown in the image below:

On line 41, a PropertySet can be seen, which is an array of 6 KSPROPERTY_SET structures:

In our context, the most important are KSPROPSETID_VPConfig and KSPROPSETID_VPVBIConfig. They have the same set of items:

The handler for KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE (0xE index) is CKSAutomationThunk::HandleArrayProperty(), which is vulnerable.

This is the function prototype:

NTSTATUS CKSAutomationThunk::HandleArrayProperty(PIRP *Irp, PKSPROPERTY *SystemInputBuffer, unsigned int *SystemOutputBuffer);

It receives a pointer to IRP, a pointer to KSPROPERTY and a pointer to data; in this case, it is an array of numbers. The element in position 0 is the quantity of items in the array.

Important note here, CKSAutomationThunk::ThunkPropertyIrp() works with input and output buffers from userspace. However, CKSAutomationThunk::HandleArrayProperty() receives copies of the buffers from kernel space memory. This region is allocated in non-paged memory by the ks!KspPropertyHandler() function. In fact, both pointers point to the same allocation, but at different offsets within it. SystemOutputBuffer points to the beginning of the memory region while SystemInputBuffer points to SystemOutputBuffer + aligned OutputBufferLength.

Inside the CKSAutomationThunk::HandleArrayProperty() function, there is code to both set and get properties. The vulnerability lies in the getter’s code. First call to KsSynchronousIoControlDevice() checks how many bytes to read, allocates memory, and the second KsSynchronousIoControlDevice() function call reads the array from the device. Next, it copies the array content into the memory pointed to by SystemOutputBuffer. It is easy to note that OutputBufferLength is not correctly checked: it is compared with 0, but not against the value (BytesReturned) returned from the first KsSynchronousIoControlDevice() call:

For this reason, in the cycle (lines 63 – 68), a non-paged heap overflow is possible.

Trigger

In order to trigger this vulnerability, the target system has to have a device with KSPROPSETID_VPConfig or KSPROPSETID_VPVBIConfig property set with KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE item. Unfortunately, were unable to find such devices on our test systems.

Nevertheless, we can at least call this function to trigger the vulnerability. It’s enough to open any device and try to get this property:

KSPROPERTY KsProperty = { 0 };
KsProperty.Set = KSPROPSETID_VPConfig;
KsProperty.Id = KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE;
KsProperty.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_COPYPAYLOAD;
char rx_buffer[0x100];
DeviceIoControl(hDevice, IOCTL_KS_PROPERTY, &KsProperty, sizeof(KSPROPERTY), rx_buffer, sizeof(rx_buffer), &temp, 0);

The stack trace will be the following:

Unfortunately, since there is no proper device in our system, the call to KsSynchronousIoControlDevice() returns an error, and we cannot continue triggering the bug. However, if your system has such a device, it is vulnerable, and you can trigger this bug.

The patch

In the patched version, a check for OutputBufferLength is added. If there is no enough space in the output buffer, the code leads into the RtlLogUnexpectedCodepath() function.

Timeline

  • 14.04.2025 – bug found;

  • 18.04.2025 – bug reported;

  • 20.05.2025 – bug confirmed;

  • 04.06.2025 – bounty awarded;

  • 05.08.2025 – CVE assigned, bounty rejected!?;

  • 12.08.2025 – fix released;

Conclusion

Lesson learned: report bugs to Crowdfense, not to the vendor! 😉

References

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-53149

Share this post