1. Overview

  • Unpatched Binary: http_unpatched.sys
  • Patched Binary: http_patched.sys
  • Overall Similarity: 0.8777 (87.77%)
  • Diff Statistics:
  • Matched Functions: 3843
  • Changed Functions: 2596
  • Identical Functions: 1247
  • Unmatched (Unpatched/Patched): 0 / 0

Verdict: No security-relevant change was found in the HTTP request/chunked/trailer parsing path. The function originally flagged, UlParseHttp (at 0x14003F570 in the unpatched build, 0x14000CCE0 in the patched build), differs only by non-security rebuild churn: a software-tracing (WPP) infrastructure rebuild, relocation of configuration-flag globals and lookup tables, and decompiler register-allocation noise. The trailer-length and chunked-parsing bounds checks are present and identical in both builds. The large "changed function" count reflects a whole-binary recompilation plus new HTTP/3 (QUIC) feature code in the patched build, not a targeted security fix.


2. Assessment Summary

  • Severity: Informational (no vulnerability confirmed)
  • Original candidate class: Integer Overflow leading to Kernel Pool Buffer Overflow (CWE-190 / CWE-122)
  • Function examined: UlParseHttp0x14003F570 (unpatched) / 0x14000CCE0 (patched)

Finding: The two builds of UlParseHttp implement the same logic. A normalized comparison (with register/variable renaming and data-section addresses factored out) shows the only differences are:

  1. WPP software-tracing rebuild. Every trace call in the function switched trace GUID (WPP_5ac9026a465d3ee62fffa26905995282_Traceguids in the unpatched build to WPP_65b36ddc0b9a331a14c686f0a9ec63d8_Traceguids in the patched build), and the WPP emit macros gained a leading numeric message-id argument (e.g. 1038, 1294, 782, 2573). This is a binary-wide change: the old trace GUID appears 250 times in the unpatched decompilation and 0 times in the patched one; the new GUID appears 0 times in the unpatched build and 233 times in the patched build.
  2. Relocated configuration-flag globals. The runtime flag word tested throughout the function moved in the data section: qword_14018BC90 became xmmword_1401A4CE0, and byte_14018BC8D became xmmword_1401A4CD0. The bit tests against these flags are unchanged (same masks, same branches).
  3. Relocated lookup tables. Static tables referenced by the parser shifted by a fixed offset (for example the header-class table base +1621696 became +1724160, a delta of 102464 bytes; unk_1401734DC became unk_14018B75C). Only the addresses moved; the indexing and comparisons are identical.
  4. Decompiler register-allocation and cast noise. Differences such as V = (unsigned int)V versus V = V are artifacts of recompilation, not logic changes.

No overflow check was added or removed. No checked-arithmetic helper was introduced. The chunked-length and trailer-length accumulation is byte-for-byte equivalent in both builds.

Direction: There is no unpatched-vulnerable / patched-fixed direction here, because both builds already contain the same trailer and chunked-encoding validation.


3. Why the Integer-Overflow / Pool-Overflow Theory Does Not Hold

The candidate mechanism (unchecked accumulation of trailer-header lengths leading to an undersized pool allocation and an oversized copy) is not present in these binaries:

  • The "new" trailer strings exist in both builds. EndlessTrailer, TrailerDisallowed, and HeadersAfterTrailers each appear once in the unpatched .sys and once in the patched .sys. They were not introduced by the patch, so they cannot be evidence of a newly added trailer limit.
  • The trailer-length bound check is already present in the unpatched build. UlpCheckTrailerLength (0x1400C9CC0 unpatched / 0x1400CA434 patched) compares the accumulated trailer length against a per-request limit (*(_DWORD *)(request + 4380)) in both builds. The comparison and the reject path are identical; only the surrounding trace calls changed.
  • No checked-arithmetic wrapper is used in either build. RtlULongAdd appears zero times in both decompilations. The claim that the patch added RtlULongAdd-style arithmetic is not supported by either binary.
  • The helper functions cited in the original theory were misidentified. The addresses attributed to a pool allocator and a memory-copy routine resolve to unrelated functions: 0x1400A5D50 is McTemplateK0qxsqqbr4_EtwWriteTransfer (an ETW trace-write template, not a pool allocator), 0x14006D1FC is ParseChunkLength, and 0x14006D3D0 is ParseEol. There is no undersized-allocation-then-oversized-copy sequence in UlParseHttp.

4. Function Correlation and Call Path

  • Parser function: UlParseHttp
  • Unpatched: 0x14003F570
  • Patched: 0x14000CCE0
  • These are the same function relocated by the rebuild, correlated by symbol name and by identical logic.
  • Caller: UlpParseNextRequest (0x140011470, unpatched) calls UlParseHttp while dispatching an incoming request. This caller relationship is real.
  • Chunked-length handling: UlParseHttp calls ParseChunkLength (0x14006D1FC, unpatched) with the same arguments in both builds.

The "chunked" string is referenced by the request parser in both builds (for example the lea r9, aChunked at 0x1400437AE in the unpatched build); this only confirms the code path parses chunked encoding, which is expected and unchanged.


5. Assembly / Decompilation Comparison

Representative excerpts from the normalized comparison of UlParseHttp. The pattern below repeats throughout the function: a flag-global relocation plus a WPP macro change, with the surrounding control flow unchanged.

Unpatched (0x14003F570):
    if ( (qword_14018BC90 & 0x2000) != 0 )
        WPP_SF_qiqLqq(39, &WPP_5ac9026a..._Traceguids, a1, ...);

Patched (0x14000CCE0):
    if ( (BYTE1(xmmword_1401A4CE0) & 0x40) != 0 )
        WPP_SF_qiqLqq(1038, 39, &WPP_65b36ddc..._Traceguids, a1, ...);

The chunked-length call is identical in both builds (only the result-variable name differs in the decompiler output):

    RequestHeaderEnd = ParseChunkLength(
        <state>, (*(_DWORD *)(a1 + 2200) & 0x80) != 0, <len>, m,
        &<local>, a1 + 2136, &<local>);

The length-accumulation additions (v += v) that the original theory pointed at appear in both builds with the same operands and the same 32-bit width. No comparison, branch, or helper call guarding an allocation size was added between the two builds.


6. Trailer-Length Validation (present in both builds)

UlpCheckTrailerLength enforces the per-request trailer-length limit identically in both builds:

    accumulated = *trailer_len_field + a3;
    if ( accumulated >= *(_DWORD *)(request + 4380) )   // reject over-limit
        ... reject path ...

Both builds compute the same sum and compare it against the same limit field before accepting more trailer data. The only difference is the trace GUID and the WPP message-id argument. This is the check that would have to be missing for the proposed overflow to exist; it is present in the unpatched build.


7. Nature of the Overall Diff (2596 changed functions)

The high changed-function count is consistent with a version/toolchain rebuild rather than a point security fix:

  • The WPP trace GUID was replaced across the whole binary (0 references remaining to the old GUID in the patched build), so essentially every function that logs is reported as "changed."
  • Configuration-flag globals and static tables were relocated, shifting address constants in many functions.
  • The patched build adds new HTTP/3 (QUIC) trailer-handling code that is absent in the unpatched build, for example UxDuoDispatchTrailersCatalogParcel, UxDuoInitiateTrailersSend, UxDuoCompareDisallowedTrailerEntries, UxQuicStreamAddHeadersOrTrailersToTracker, and UxQuicStreamInitiateTrailersSend. These are new features, not modifications to the classic request parser.

8. Changed Functions — Triage

  • UlParseHttp0x14003F570 (unpatched) / 0x14000CCE0 (patched)
  • Similarity: 0.44 (as reported by the diff), driven almost entirely by the WPP macro/GUID change and address relocations rather than logic.
  • Change Type: Not security-relevant.
  • Notes: Same parsing logic in both builds. Differences are tracing rebuild, relocated flag globals and lookup tables, and register-allocation noise. No bounds check, allocation, copy, or accumulation logic changed.

The remaining changed functions are attributable to the same binary-wide tracing rebuild, data-section relocation, and the addition of HTTP/3 (QUIC) feature code in the patched build.


9. Unmatched Functions

  • Added: None reported by the diff at the matching stage. Note that the patched build does contain additional HTTP/3 (QUIC) trailer functions relative to the unpatched build (see Section 7); these are new feature code, not security remediation of the request parser.
  • Removed: None.

No standalone sanitization routine was introduced or removed in the request/chunked/trailer parsing path.


10. Confidence & Caveats

  • Confidence Level: High that this pair contains no security-relevant change in the analyzed parser.
  • Rationale:
  • The trailer-limit strings (EndlessTrailer, TrailerDisallowed, HeadersAfterTrailers) are present in both binaries, so they are not evidence of a new patch behavior.
  • RtlULongAdd is absent from both builds; no checked-arithmetic wrapper was added.
  • UlpCheckTrailerLength enforces the trailer-length limit identically in both builds.
  • The UlParseHttp diff is fully explained by a WPP tracing rebuild, relocated globals/tables, and decompiler noise.
  • Scope of verification: UlParseHttp and UlpCheckTrailerLength were compared directly between the two builds; helper symbol names were confirmed against the disassembly. The 2596-function delta is consistent with a whole-binary rebuild plus HTTP/3 feature additions.
  • Bottom line: This binary pair does not straddle a chunked/trailer integer-overflow fix. The originally proposed remote kernel pool overflow is not exploitable in these binaries because the guarding checks already exist in the unpatched build.