Skip to navigation Skip to main content Skip to footer

Technical Advisory: Microsoft Windows – uaspstor.sys – Device Controlled Kernel Pool OOB Write Via REPORT LUNS (CVE-2026-68839)

By Alex Plaskett

08 October 2026

Vendor: Microsoft    
Vendor URL: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-68839
Versions affected: See MSRC advisory
Systems Affected: Microsoft Windows
Author: Alex Plaskett 
Risk: Medium – In this advisory the vector is physical USB for LPE, however, in Microsoft advisory it is noted this can be exploited remotely over a network.
Methodology: Agentic Vulnerability Identification and Exploitation

 

1. Summary

uaspstor.sys (the Microsoft inbox USB Attached SCSI Protocol storage driver) contains a kernel non-paged pool buffer overflow in its post-processing of the SCSI REPORT LUNS (opcode `0xA0`) response. The driver caches a per-device LUN table that it allocates exactly once (sized from the device's first REPORT LUNS response) but whose element count it updates on every REPORT LUNS completion from the device-supplied LUN LIST LENGTH.

A malicious UAS device that returns a small LUN list on the first REPORT LUNS and a larger one on a subsequent REPORT LUNS drives the fill loop past the original allocation, writing device-controlled 8-byte values at a 32-byte stride beyond the buffer.

Primitive: linear/sparse non-paged pool overflow; attacker controls both the overflow length (LUN count) and the overflow contents (the LUN entries).

Trigger: two REPORT LUNS responses from the device (no userland). The storage stack (storport) issues REPORT LUNS automatically during bus scan, and re-issues it on a device-supplied REPORTED LUNS DATA HAS CHANGED unit attention (sense `06/3F/0E`).

Affected function: UaspPostProcessSrb

Root cause: the cached LUN table (`devext+0x468` / `+1128`) is allocated only when its pointer is `NULL`, but the LUN count (`devext+0x3E8` / `+1000`) is overwritten with the raw device value on every call; the fill loop is bounded by the (new, larger) count with no re-clamp to the (old, smaller) allocation.

Binary verified: C:\Windows\System32\drivers\uaspstor.sys` v10.0.29599.1000 (Win11 Insider 29599)


2. Impact

This advisory demonstrates local impact of the vulnerability using a physical USB device.

However, Microsoft states “Heap-based buffer overflow in Windows USB Mass Storage Class Driver allows an unauthorized attacker to execute code over a network”, demonstrating that it may be possible to trigger the vulnerability remotely.

 

3. Vulnerability Details

UaspPostProcessSrb (called from QueueUpdateCompletion at on SRB completion, when the data-in phase completed — `*(BYTE*)(SRB+3)==1`):

void __fastcall UaspPostProcessSrb(__int64 a1 /*devext*/, __int64 a2 /*SRB ctx*/)
{
  if ( *(unsigned __int8 *)(a2 + 72) == 160 )          // CDB[0] == 0xA0  (REPORT LUNS)
  {
    v4 = *(unsigned int **)(a2 + 24);                  // SRB DataBuffer (device data-in)
    v5 = _byteswap_ulong(*v4);                         // LUN LIST LENGTH (device-controlled, BE)
    if ( v5 )
    {
      v6 = v5 >> 3;                                     // device-controlled LUN entry count
      v7 = *(_QWORD *)(a1 + 1128) == 0;                // is the cached table already allocated?
      *(_DWORD *)(a1 + 1000) = v6;                      // count := device value  (ALWAYS)
      if ( !v7                                          // ...allocate ONLY if it was NULL:
           || (Pool = UaspAllocatePool(a1, 32LL * v6),  // size = 32 * (first-call count)
               (*(_QWORD *)(a1 + 1128) = Pool) != 0) )
      {
        v9 = 0;
        for ( i = 8; (unsigned int)v9 < *(_DWORD *)(a1 + 1000); v9 = v9 + 1 )  // bound = NEW count
        {
          i += 8;
          if ( i <= *(_DWORD *)(a2 + 16) )              // DataTransferLength: guards the READ only
            *(_QWORD *)(32LL * v9 + *(_QWORD *)(a1 + 1128))   // <-- OOB WRITE (line 2488)
                = *(_QWORD *)&v4[2 * v9 + 2];                 //     device-controlled qword
        }
      }
    }
  }
}

 

  • (LUN count): initialized to `1` at device setup (line 5470); set to the device value. 
  • (LUN table): allocated only at line 2481; freed/nulled only inside UaspFreeResources(a1, 1), reached from adapter teardown / device-removal / init-failure. The bulk/device reset path BulkResetDeviceWorkItem, does not touch Therefore, an undersized table persists across a UA-driven rescan.
  1. Call 1 (first REPORT LUNS, at bus scan): Device returns `LUN LIST LENGTH = 8` → `v6 = 1` → allocate `32` bytes; `+1000 = 1`. Self-consistent, no overflow.
  2. Device induces a rescan - returns REPORTED LUNS DATA HAS CHANGED (`06/3F/0E`) unit attention on some later command → storport re-issues REPORT LUNS. No adapter teardown → `+1128` (32 bytes) persists.
  3. Call 2: the `!v7` short-circuit skips reallocation. Device returns `LUN LIST LENGTH = 0x7F8` → `v6 = 255` → `+1000 = 255`. The loop writes up to min(255, DataTransferLength/8 − 1) device qwords at 32-byte stride into the 32-byte buffer → controlled non-paged pool overflow (potentially ~8 KB past the allocation).

Device-controlled inputs (all from the USB device, no userland)

  • LUN LIST LENGTH (first 4 bytes of each REPORT LUNS data-in response, big-endian) → sets both the one-time allocation size and the per-call fill count.
  • LUN entry bytes (the 8-byte entries following the header) → the overflow contents.
  • Unit attention `06/3F/0E` on a later command → induces storport to re-issue REPORT LUNS without tearing down the adapter (keeps the small cache).

 
4. Crash Output

uaspstor!UaspPostProcessSrb+0x98:  mov qword ptr [rdx+rcx],rax   ds:ffffafce`71d13000=?? (guard page)
  rcx=ffffafce71d12fe0  (32-byte LUN table in special pool, ends at ...fe0)
  rdx=0x20              (32-byte stride; entry v9=1 -> +0x20 = ...13000 = guard page)
  rax=0x100             (device-supplied LUN-1 entry qword: 00 01 00 ...)
Stack: UaspPostProcessSrb <- QueueUpdateCompletion+0x104 <- SenseIUCompletion <- StatusPipeCompletion
       <- PipeCompletionRoutine <- nt!Iov*CompleteRequest <- USBXHCI!Bulk_Transfer_CompleteCancelable
PROCESS_NAME: System    FAILURE_BUCKET_ID: AV_VRF_uaspstor!UaspPostProcessSrb    IMAGE_NAME: uaspstor.sys

TRAP_FRAME:  fffff8033257abd0 -- (.trap 0xfffff8033257abd0)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=4142434445464748 rbx=0000000000000000 rcx=ffffe0172ef12fe0
rdx=0000000000000020 rsi=0000000000000000 rdi=0000000000000000
rip=fffff803352a2108 rsp=fffff8033257ad60 rbp=0000000000080158
 r8=0000000000000001  r9=0000000000000018 r10=0000000009c409f8
r11=ffffe0172ebd6f00 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
uaspstor!UaspPostProcessSrb+0x98:
fffff803`352a2108 4889040a        mov     qword ptr [rdx+rcx],rax ds:ffffe017`2ef13000=????????????????
Resetting default scope


5. Vendor Communication

15th June 2026 – Issue reported to Microsoft
8th September 2026 – Microsoft releases update

 

6. About NCC Group


NCC Group is a global expert in cybersecurity and risk mitigation, working with businesses to protect their brand, value and reputation against the ever-evolving threat landscape. With our knowledge, experience and global footprint, we are best placed to help businesses identify, assess, mitigate & respond to the risks they face. We are passionate about making the Internet safer and revolutionizing the way in which organizations think about cybersecurity.