mrxsmb.sys — feature-staged SMB-over-QUIC compression message routing
KB5082052
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 forFeature_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 theFeature_Servicing_SmbCompressionOverQuicFixfeature 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(0x1c0046fe4unpatched /0x1c0047074patched) — 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 SMB2TRANSFORM_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 whenFeature_Servicing_SmbCompressionOverQuicFix__private_IsEnabledDeviceUsage()returns true, also matches0x424d53fc(\xfcSMB, the SMB2COMPRESSION_TRANSFORM_HEADERmagic) via the range test(value - 0x424d53fc) <= 1. When the feature is disabled, the helper checks only0x424d53fd, 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)
- SMB-over-QUIC transport in use (explicitly configured QUIC client connection), with SMB 3.1.1 compression negotiated.
- The
Feature_Servicing_SmbCompressionOverQuicFixfeature flag enabled (otherwise the patched helper is byte-for-byte equivalent to the unpatched compare). - 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 or0x400). - The
byte_1C005DA0C & 8config 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
0x400into 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(0x1c0046fe4unpatched /0x1c0047074patched)- Similarity Score: 0.9923
- Change Type: Feature-staged routing correction (not security-relevant).
- Key Changes: Replaced the inline 4-byte compare against
0x424d53fdwith a call to the new helperSmbQuicIsIndicationTransformedMessage, which additionally recognizes0x424d53fcwhenFeature_Servicing_SmbCompressionOverQuicFixis enabled and otherwise reproduces the original single-magic check. Stack frame grew by 16 bytes (0xB8to0xC8). 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/0x424d53fdare the MS-SMB2COMPRESSION_TRANSFORM_HEADER/TRANSFORM_HEADERprotocol 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.