CVE-2024-35250 — Kernel Streaming KSPROPSETID_DrmAudioStream Arbitrary Call

Last updated: 2026-04-12
Severity: High
Component: ks.sys / ksthunk.sys (Kernel Streaming)
Bug Class: Access Mode Mismatch (Proxying to Kernel) → Arbitrary Call
Privilege Escalation: User → SYSTEM
Patch: July 2024 Patch Tuesday

Vulnerability Summary

A logic vulnerability in Windows Kernel Streaming where ks.sys’s UnserializePropertySet function calls KsSynchronousIoControlDevice with KernelMode(0), allowing user-supplied data to reach ksthunk.sys’s CheckIrpForStackAdjustmentNative with elevated RequestorMode. The ksthunk handler for KSPROPSETID_DrmAudioStream performs an arbitrary call using user-controlled data when RequestorMode == KernelMode. This was used in Pwn2Own Vancouver 2024 by DEVCORE (Angelboy). The vulnerability existed since Windows 7 — approximately 20 years.


Root Cause Analysis

Step 1: KsSynchronousIoControlDevice Always Uses KernelMode

ks.sys’s UnserializePropertySet (triggered by KSPROPERTY_TYPE_UNSERIALIZESET flag) copies user data and re-issues the IOCTL internally:

// ks.sys UnserializePropertySet:
New_KsProperty_req = ExAllocatePoolWithTag(NonPagedPoolNx, InSize, 0x7070534Bu);
memmove(New_KsProperty_req, CurrentStackLocation->Type3InputBuffer, InSize);
status = KsSynchronousIoControlDevice(
    CurrentStackLocation->FileObject,
    0,  // ← KernelMode hardcoded
    CurrentStackLocation->Parameters.DeviceIoControl.IoControlCode,
    New_KsProperty_req,
    InSize,
    OutBuffer,
    OutSize,
    &BytesReturned);

This sets Irp->RequestorMode = KernelMode(0) in the new IRP.

Step 2: ksthunk Bypasses User Check

ksthunk.sys’s CheckIrpForStackAdjustmentNative checks for KSPROPSETID_DrmAudioStream:

if (*Type3InputBuffer->Set == KSPROPSETID_DrmAudioStream
    && !type3inputbuf.Id
    && (type3inputbuf.Flags & 2)) {
    if (irp->RequestorMode) {       // UserMode = 1 → error
        return STATUS_INVALID_DEVICE_REQUEST;
    }
    // KernelMode = 0 → proceeds to arbitrary call!
    result = (*(PFUNC)(Type3InputBuffer + 0x38))(
        *UserBuffer,   // first arg: user-controlled
        0,
        v19);
}

The function pointer at Type3InputBuffer + 0x38 is fully user-controlled, as is the first argument.


Exploitation Technique

kCFG Bypass via RtlSetAllBits

Since arbitrary function pointers are blocked by kCFG (Kernel Control Flow Guard), the attacker must use a valid CFG target. RtlSetAllBits (exported from ntoskrnl.exe) accepts a _RTL_BITMAP:

struct _RTL_BITMAP {
    ULONG  SizeOfBitMap;
    ULONG* Buffer;  // pointer to bitmap data
};

By setting Buffer → Token->Privileges.Enabled and SizeOfBitMap = large_value, RtlSetAllBits sets all privilege bits in the token → enables all privileges including SeDebugPrivilege.

EoP Flow

  1. Open audio device with KSPROPSETID_DrmAudioStream support (any audio device; mic/headphone)
  2. Send IOCTL_KS_PROPERTY with KSPROPERTY_TYPE_UNSERIALIZESET flag and KSPROPSETID_DrmAudioStream GUID
  3. ks.sys UnserializePropertySet calls KsSynchronousIoControlDevice(KernelMode)
  4. ksthunk sees KernelMode → proceeds to Type3InputBuffer+0x38 function call
  5. Type3InputBuffer+0x38 = &RtlSetAllBits (valid kCFG target)
  6. *UserBuffer = &fake_RTL_BITMAP (first arg points to bitmap over Token->Privileges)
  7. All privilege bits set → SeDebugPrivilege enabled
  8. OpenProcess(PROCESS_ALL_ACCESS, winlogon_pid)CreateProcess inheriting SYSTEM token

Key Primitives Used

  • KsSynchronousIoControlDevice with hardcoded KernelMode (design flaw)
  • RtlSetAllBits as kCFG-valid arbitrary write gadget
  • Token privilege abuse (all privileges enabled)

Mitigations Bypassed

  • kCFG (bypassed via legitimate CFG target RtlSetAllBits)
  • kASLR (bypassed via NtQuerySystemInformation)
  • SMEP (kernel code executes from kernel, no user shellcode)

Proof-of-Concept Notes

  • Requires an audio device with KSPROPSETID_DrmAudioStream (any mic, headphones, audio interface)
  • On Hyper-V without audio: use CVE-2024-30084 double fetch to trigger via MSKSSRV (present everywhere)
  • Combined chain (CVE-2024-30084 + CVE-2024-35250) works on any Windows system
  • 100% reliable exploitation, no races required for CVE-2024-35250 alone

Patch Analysis

Microsoft patched in July 2024. The fix validates RequestorMode in the KSPROPSETID_DrmAudioStream handler path before performing the function call — or restricts the conditions under which the call is made regardless of RequestorMode.


References

  • Angelboy (DEVCORE), “Streaming vulnerabilities from Windows Kernel - Proxying to Kernel - Part I”, devco.re, 2024-08-23
  • MSRC: CVE-2024-35250 — msrc.microsoft.com/update-guide/vulnerability/CVE-2024-35250
  • Pwn2Own Vancouver 2024 — zerodayinitiative.com
  • See also: Cve 2024 30084 (double fetch companion)
  • See also: Kernel Streaming (full attack surface)