1. Overview

  • Unpatched Binary: mrxsmb_unpatched.sys
  • Patched Binary: mrxsmb_patched.sys
  • Overall Similarity Score: 0.9916
  • Diff Statistics: 1139 matched, 1 changed, 1138 identical, 0 unmatched. The one functional change is in SmbQuicReceiveEvent; the patched build also adds one helper (SmbQuicIsIndicationTransformedMessage) and the two WIL feature-staging stubs for Feature_Servicing_SmbCompressionOverQuicFix. Every other function differs only by relocation churn (shifted call targets, renamed WPP trace symbols, locret_ label addresses).
  • Verdict: The patch adds recognition of the SMB2 compression transform magic (\xfcSMB / 0x424d53fc) to the SMB-over-QUIC receive path so that compressed indications are routed to the buffered reassembly path instead of the inline dispatch path. The new behavior is gated behind the Feature_Servicing_SmbCompressionOverQuicFix feature flag, and the previous behavior (recognize only \xfdSMB / 0x424d53fd) is retained as the fallback branch. There is no demonstrable memory-corruption primitive: the inline path copies a length-matched, 0x400-capped fragment into a fixed receive buffer and hands the message to the SMB2 dispatcher, which validates the protocol id. This is a staged interoperability/servicing correction, not a delivered memory-safety fix.

2. Change Summary

  • Severity: None (no security-relevant change).
  • Change Class: Feature-staged protocol-message routing correction (SMB-over-QUIC compression), gated behind a WIL feature flag with the old path retained.
  • Affected Function: SmbQuicReceiveEvent (0x1c0046fe4 unpatched / 0x1c0047074 patched) — the SMB-over-QUIC stream receive/decode handler.

What actually changed: In the large/fragmented-message branch of SmbQuicReceiveEvent, the code peeks the first 4 bytes of the pending message body to decide whether it is a "transform header" message (which must be reassembled into a contiguous non-paged pool buffer before it can be processed) or an ordinary message (which is copied inline into the fixed receive buffer at [rdi+0x88] and dispatched to the SMB2 handler).

  • Unpatched: the peek compares the 4 bytes against a single constant, 0x424d53fd (\xfdSMB, the SMB2 TRANSFORM_HEADER/encrypted magic). Only that value is routed to the reassembly path.
  • Patched: the inline compare is replaced by a call to the new helper SmbQuicIsIndicationTransformedMessage (0x1c0046e3c). That helper performs the same 4-byte peek and then, only when Feature_Servicing_SmbCompressionOverQuicFix__private_IsEnabledDeviceUsage() returns true, also matches 0x424d53fc (\xfcSMB, the SMB2 COMPRESSION_TRANSFORM_HEADER magic) via the range test (value - 0x424d53fc) <= 1. When the feature is disabled, the helper checks only 0x424d53fd, reproducing the unpatched behavior exactly.

Because the compressed-magic recognition is gated by a feature-staging flag and the pre-existing behavior is retained as the else branch, this is a staged rollout rather than an unconditionally delivered change.

Why there is no reachable memory-corruption impact: When an unrecognized-magic message reaches the inline path, the code copies v16 = min(remaining_in_fragment, 0x400) bytes into the fixed receive buffer [rdi+0x88] and passes that same length v16 (plus the byte-swapped total message size) to the SMB2 dispatcher (*(*(ctx+0x168)+0x10))(...). The copy length is capped and matched to the destination, so no overflow occurs in this function. The dispatched message is then subject to the SMB2 response parser's own protocol-id / structure validation; a body beginning with 0xfc 'SMB' is neither a valid SMB2 (0xfe 'SMB') nor a valid transform (0xfd 'SMB') header. The report does not establish any out-of-bounds access, controlled write, or type-confused pointer dereference resulting from this routing difference.

Attack surface (for context): SmbQuicReceiveEvent is on the SMB-over-QUIC client receive path (QUIC/UDP transport, not TCP/445). The real call chain into it is the MsQuic stream callback: 1. SmbQuicClientStreamCallback (0x1c006c7b0) — MsQuic stream event callback 2. SmbQuicStreamEventRecv (0x1c0047cd0) — receive-event handler 3. SmbQuicReceiveEvent (0x1c0046fe4 unpatched / 0x1c0047074 patched)

SMB-over-QUIC is an explicitly configured transport; the affected compression routing is additionally gated by the SmbCompressionOverQuicFix feature flag.

3. Decompiled Change

// --- UNPATCHED SmbQuicReceiveEvent @ 0x1c0046fe4 (inline peek/compare) ---
// v9  = current offset into the indication
// v16 = min(remaining_in_fragment, 0x400)
if ( (byte_1C005DA0C & 8) != 0 )      // config/debug gate -> reassembly path
    break;
LODWORD(v32) = 0;
SmbQuicCopyIndicationToBufferEx((__int64)Mdl, &v32, v9, 4u, nullptr);  // peek 4 bytes
if ( (_DWORD)v32 == 1112364029 )      // 0x424d53fd (\xfdSMB) only -> reassembly path
    break;
v18 = *(void **)(BugCheckParameter2 + 136);   // [ctx+0x88] fixed receive buffer
if ( (int)SmbQuicCopyIndicationToBufferEx((__int64)Mdl, v18, v9, v16, nullptr) < 0 )  // v16 <= 0x400
    goto LABEL_56;
v7 = (*(...)(*(_QWORD *)(BugCheckParameter2 + 360) + 16LL))(   // [ctx+0x168]+0x10 SMB2 dispatch
       BugCheckParameter2, 0, v16, v14, ... );

// --- PATCHED SmbQuicReceiveEvent @ 0x1c0047074 (helper call) ---
if ( (byte_1C005DA0C & 8) != 0 || SmbQuicIsIndicationTransformedMessage(v31, v9) )
    break;                             // reassembly path for \xfdSMB, and \xfcSMB when feature on

// --- NEW HELPER SmbQuicIsIndicationTransformedMessage @ 0x1c0046e3c ---
bool SmbQuicIsIndicationTransformedMessage(__int64 a1, unsigned int a2)
{
  int v3 = 0;
  SmbQuicCopyIndicationToBufferEx(a1, &v3, a2, 4u, nullptr);   // peek 4 bytes
  if ( Feature_Servicing_SmbCompressionOverQuicFix__private_IsEnabledDeviceUsage() != 0 )
    return (unsigned int)(v3 - 1112364028) <= 1;   // 0x424d53fc OR 0x424d53fd
  else
    return v3 == 1112364029;                        // 0x424d53fd only (unpatched behavior)
}

4. Assembly Analysis

Unpatched peek and inline dispatch (SmbQuicReceiveEvent @ 0x1c0046fe4):

00000001C0047320  cmp     r13d, 4
00000001C0047324  jb      loc_1C00474A3            ; < 4 bytes -> reassembly path
00000001C004732A  test    cs:byte_1C005DA0C, 8
00000001C0047331  jnz     loc_1C00474A3            ; config gate -> reassembly path
00000001C0047337  mov     rcx, [rbp+57h+Mdl]
00000001C004733B  lea     rdx, [rbp+57h+var_80]
00000001C004733F  and     dword ptr [rbp+57h+var_80], r15d   ; zero local
00000001C0047343  mov     r9d, 4
00000001C004734E  mov     r8d, r14d               ; current offset
00000001C0047351  call    SmbQuicCopyIndicationToBufferEx    ; peek 4 bytes
00000001C0047356  cmp     dword ptr [rbp+57h+var_80], 424D53FDh  ; only \xfdSMB
00000001C004735D  jz      loc_1C00474A3           ; -> reassembly path
00000001C0047363  mov     rbx, [rdi+88h]          ; fixed receive buffer
00000001C0047369  mov     r9d, r13d               ; length (capped to 0x400)
00000001C004737C  call    SmbQuicCopyIndicationToBufferEx    ; length-matched copy
00000001C0047381  test    eax, eax
00000001C0047383  js      loc_1C0047450
00000001C0047389  mov     rax, [rdi+168h]
00000001C00473CD  call    cs:__guard_dispatch_icall_fptr     ; SMB2 dispatch [ctx+0x168]+0x10

Patched replacement (SmbQuicReceiveEvent @ 0x1c0047074):

00000001C00473B0  cmp     r13d, 4
00000001C00473B4  jb      loc_1C004751B
00000001C00473BA  test    cs:byte_1C005DA0C, 8
00000001C00473C1  jnz     loc_1C004751B
00000001C00473C7  mov     rcx, [rbp+57h+var_88]
00000001C00473CB  mov     edx, r14d
00000001C00473CE  call    SmbQuicIsIndicationTransformedMessage
00000001C00473D3  test    al, al
00000001C00473D5  jnz     loc_1C004751B           ; \xfdSMB, and \xfcSMB when feature on
00000001C00473DB  mov     rbx, [rdi+88h]

New helper (SmbQuicIsIndicationTransformedMessage @ 0x1c0046e3c):

00000001C0046E3C  sub     rsp, 38h
00000001C0046E45  mov     r8d, edx                ; offset
00000001C0046E4E  lea     rdx, [rsp+38h+arg_10]   ; local 4-byte buffer
00000001C0046E53  mov     r9d, 4
00000001C0046E59  call    SmbQuicCopyIndicationToBufferEx        ; peek 4 bytes
00000001C0046E5E  call    Feature_Servicing_SmbCompressionOverQuicFix__private_IsEnabledDeviceUsage
00000001C0046E63  test    eax, eax
00000001C0046E65  jz      short loc_1C0046E78     ; feature off -> \xfdSMB only
00000001C0046E67  mov     eax, [rsp+38h+arg_10]
00000001C0046E6B  add     eax, 0BDB2AC04h         ; value - 0x424d53fc
00000001C0046E70  cmp     eax, 1
00000001C0046E73  setbe   al                      ; TRUE for 0x424d53fc OR 0x424d53fd
00000001C0046E76  jmp     short loc_1C0046E83
00000001C0046E78  cmp     [rsp+38h+arg_10], 424D53FDh
00000001C0046E80  setz    al                      ; TRUE for 0x424d53fd only
00000001C0046E83  add     rsp, 38h
00000001C0046E87  retn

Feature-staging gate (Feature_Servicing_SmbCompressionOverQuicFix__private_IsEnabledDeviceUsage @ 0x1c002110c, patched build only):

00000001C0021116  mov     eax, cs:Feature_Servicing_SmbCompressionOverQuicFix__private_featureState
00000001C0021120  test    al, 10h
00000001C0021122  jz      short loc_1C0021129
00000001C0021124  and     eax, 1                  ; cached enable bit
00000001C0021127  jmp     short loc_1C0021138
00000001C0021129  ...
00000001C0021133  call    Feature_Servicing_SmbCompressionOverQuicFix__private_IsEnabledFallback

This is a standard Windows feature-staging (WIL) gate. The same address 0x1c002110c in the unpatched build is an unrelated ETW template (McTemplateK0dhsr1qqbr4qbr6hzr8qbr10_EtwWriteTransfer); the function was matched by content, not by reused address.

5. Trigger Conditions (for the routing difference)

  1. SMB-over-QUIC transport in use (explicitly configured QUIC client connection), with SMB 3.1.1 compression negotiated.
  2. The Feature_Servicing_SmbCompressionOverQuicFix feature flag enabled (otherwise the patched helper is byte-for-byte equivalent to the unpatched compare).
  3. A server response whose body begins with the compression transform magic \xfcSMB (0x424d53fc) that takes the large/fragmented-message branch (message size exceeds the in-fragment remaining bytes or 0x400).
  4. The byte_1C005DA0C & 8 config gate not set (present identically in both builds; when set, both builds skip the peek and go straight to the reassembly path).

When these hold, the unpatched build copies the compressed fragment inline and dispatches it to the SMB2 handler, whereas the patched build (feature on) routes it to the reassembly path. No memory-corruption effect is demonstrated for either outcome.

6. Impact Assessment

  • No memory-corruption primitive is demonstrable from this change. The inline copy is length-matched and capped to 0x400 into a fixed receive buffer; the dispatched message is validated by the SMB2 response parser's protocol-id/structure checks.
  • The worst realistic consequence of the unpatched routing is functional: a compressed SMB-over-QUIC response could be handed to the ordinary SMB2 dispatcher and rejected (invalid protocol id), i.e., compression-over-QUIC would not be handled on that path. This is an interoperability/correctness concern, not a security vulnerability.
  • No out-of-bounds read/write, controlled pointer dereference, use-after-free, information leak, or control-flow hijack is supported by the two binaries.

7. Reproduction Notes

To observe the routing difference (not a crash), the patched behavior activates only when Feature_Servicing_SmbCompressionOverQuicFix is enabled. With the feature disabled, SmbQuicIsIndicationTransformedMessage returns identical results to the unpatched inline compare. The relevant observation point is the 4-byte peek at 0x1c0047351 (unpatched) / the call SmbQuicIsIndicationTransformedMessage at 0x1c00473ce (patched): inspect the peeked 4 bytes and the taken branch. No BSOD or memory-corruption outcome is expected or demonstrated.

8. Changed Functions — Full Triage

  • SmbQuicReceiveEvent (0x1c0046fe4 unpatched / 0x1c0047074 patched)
  • Similarity Score: 0.9923
  • Change Type: Feature-staged routing correction (not security-relevant).
  • Key Changes: Replaced the inline 4-byte compare against 0x424d53fd with a call to the new helper SmbQuicIsIndicationTransformedMessage, which additionally recognizes 0x424d53fc when Feature_Servicing_SmbCompressionOverQuicFix is enabled and otherwise reproduces the original single-magic check. Stack frame grew by 16 bytes (0xB8 to 0xC8). All other variance is register/stack-slot renumbering from the larger frame.
  • SmbQuicIsIndicationTransformedMessage (0x1c0046e3c, patched only) — new helper implementing the peek + feature-gated magic check.
  • Feature_Servicing_SmbCompressionOverQuicFix__private_IsEnabledDeviceUsage / __private_IsEnabledFallback (patched only) — standard WIL feature-staging stubs.

An independent function-by-function comparison of both builds (matching by content across relocations) confirms no other function has a logic change; every other differing function differs only in shifted call targets, renamed WPP trace symbols, and locret_ label addresses.

9. Unmatched Functions

  • Removed: None.
  • Added: SmbQuicIsIndicationTransformedMessage (0x1c0046e3c), Feature_Servicing_SmbCompressionOverQuicFix__private_IsEnabledDeviceUsage (0x1c002110c), Feature_Servicing_SmbCompressionOverQuicFix__private_IsEnabledFallback (0x1c0021144).

10. Confidence & Caveats

  • Confidence Level: High that this is not a security-relevant memory-safety fix.
  • Rationale: The behavioral difference is limited to which internal path a \xfcSMB (compression transform) SMB-over-QUIC message takes, it is gated behind a feature-staging flag with the prior behavior retained as fallback, and the inline path performs a length-matched, capped copy followed by a validated SMB2 dispatch. No out-of-bounds access, controlled write, or type-confused dereference is present in either build.
  • Caveat: 0x424d53fc/0x424d53fd are the MS-SMB2 COMPRESSION_TRANSFORM_HEADER / TRANSFORM_HEADER protocol ids. The patch correctly extends recognition to the compression id, but as a staged interoperability correction on the SMB-over-QUIC path, not as a fix for a demonstrable kernel memory-corruption vulnerability.