<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://cvepatchbook.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://cvepatchbook.com/" rel="alternate" type="text/html" /><updated>2026-09-03T17:10:35+00:00</updated><id>https://cvepatchbook.com/feed.xml</id><title type="html">PatchBook | Reports</title><subtitle>Windows kernel CVE analysis — binary diffs and patch breakdowns</subtitle><author><name>tzvironen</name></author><entry><title type="html">CVE-2026-62792: Stack-Based Buffer Overflow in the IPv6 Hop-by-Hop Options Parser</title><link href="https://cvepatchbook.com/reports/cve-2026-62792-tcpip-remote-code-execution/" rel="alternate" type="text/html" title="CVE-2026-62792: Stack-Based Buffer Overflow in the IPv6 Hop-by-Hop Options Parser" /><published>2026-08-11T00:00:00+00:00</published><updated>2026-08-11T00:00:00+00:00</updated><id>https://cvepatchbook.com/reports/cve-2026-62792-tcpip-remote-code-execution</id><content type="html" xml:base="https://cvepatchbook.com/reports/cve-2026-62792-tcpip-remote-code-execution/"><![CDATA[<h1 id="cve-2026-62792-stack-based-buffer-overflow-in-the-ipv6-hop-by-hop-options-parser">CVE-2026-62792: Stack-Based Buffer Overflow in the IPv6 Hop-by-Hop Options Parser</h1>

<ul>
  <li><strong>Affected binary:</strong> <code class="language-plaintext highlighter-rouge">tcpip.sys</code> 10.0.19041.7548 → 10.0.19041.7663</li>
  <li><strong>CVE:</strong> CVE-2026-62792</li>
  <li><strong>Patch date:</strong> 2026-08-11</li>
  <li><strong>CVSS:</strong> 8.1</li>
  <li><strong>Class:</strong> Buffer overflow</li>
  <li><strong>Patch KB:</strong> KB5120228 and related</li>
</ul>

<h2 id="tldr">TL;DR</h2>

<p><code class="language-plaintext highlighter-rouge">tcpip.sys</code> parses IPv6 extension headers as it walks the receive path, and <code class="language-plaintext highlighter-rouge">Ipv6pReceiveHopByHopOptions</code> handles the Hop-by-Hop options header — the one extension header that is processed on <em>every</em> hop, including intermediate routers and the destination. The function reads the attacker-controlled <code class="language-plaintext highlighter-rouge">Hdr Ext Len</code> byte, computes a header length of <code class="language-plaintext highlighter-rouge">8 * ExtLen + 8</code>, and then advances the <code class="language-plaintext highlighter-rouge">NET_BUFFER</code> cursor by that amount <strong>without verifying the buffer actually contains that many bytes</strong>. A packet that claims a larger extension length than it carries drives the parse offset beyond the real payload, so subsequent option processing reads and writes out of bounds. The patch adds a <code class="language-plaintext highlighter-rouge">Feature_*</code>-gated bounds check that compares the claimed length against the <code class="language-plaintext highlighter-rouge">NET_BUFFER</code>’s <code class="language-plaintext highlighter-rouge">DataLength</code> field before advancing, and, if the packet is short, sets the next-header type to 59 (No Next Header) and fails the parse with <code class="language-plaintext highlighter-rouge">STATUS_INVALID_PARAMETER</code> instead. The result is a remotely reachable, pre-authentication memory-corruption primitive rated CVSS 8.1.</p>

<h2 id="background">Background</h2>

<p>IPv6 replaced IPv4’s fixed set of header options with a linked chain of <em>extension headers</em>. Each extension header begins with a <strong>Next Header</strong> byte (identifying the type of the following header) and, for most types, a <strong>Hdr Ext Len</strong> byte that encodes the header’s size. The Hop-by-Hop Options header (Next Header value 0) is special: RFC 8200 requires it to appear first, immediately after the fixed 40-byte IPv6 header, and it is the only extension header that every node along the delivery path is expected to examine rather than just the final destination.</p>

<p>Its length field follows the standard extension-header convention: the header is <code class="language-plaintext highlighter-rouge">8 * Hdr Ext Len + 8</code> bytes long — a base of 8 bytes plus 8 bytes for each unit in the length byte. Because <code class="language-plaintext highlighter-rouge">Hdr Ext Len</code> is a single byte, an attacker can legally <em>claim</em> a header anywhere from 8 bytes up to <code class="language-plaintext highlighter-rouge">8 * 255 + 8 = 2048</code> bytes, entirely independent of how large the packet on the wire actually is.</p>

<p>In the Windows networking stack, received packets are represented by <code class="language-plaintext highlighter-rouge">NET_BUFFER</code> structures chained under a <code class="language-plaintext highlighter-rouge">NET_BUFFER_LIST</code>. A <code class="language-plaintext highlighter-rouge">NET_BUFFER</code> tracks the current data pointer and, critically, a <code class="language-plaintext highlighter-rouge">DataLength</code> field (at offset <code class="language-plaintext highlighter-rouge">0x18</code>) that records how many bytes of real payload remain. The stack walks the extension-header chain by repeatedly calling <code class="language-plaintext highlighter-rouge">NetioAdvanceNetBufferList</code>, which moves the data cursor forward by a caller-supplied count and decrements the remaining length. The invariant the whole parser depends on is simple: <strong>you never advance past <code class="language-plaintext highlighter-rouge">DataLength</code>.</strong> <code class="language-plaintext highlighter-rouge">Ipv6pReceiveHopByHopOptions</code> is the function that broke it.</p>

<h2 id="root-cause">Root Cause</h2>

<p>Here is the relevant slice of the pre-patch function, decompiled:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="mh">0x28</span><span class="p">)</span> <span class="p">{</span>   <span class="c1">// parse offset == 40 (just past fixed IPv6 header)</span>
    <span class="n">pbVar3</span> <span class="o">=</span> <span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)</span><span class="n">NdisGetDataBuffer</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mi">8</span><span class="p">),</span> <span class="mi">2</span><span class="p">,</span> <span class="n">local_res8</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">short</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x11a</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">short</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span>
    <span class="n">iVar4</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">pbVar3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">8</span><span class="p">;</span>              <span class="c1">// 8 * Hdr Ext Len + 8</span>
    <span class="n">NetioAdvanceNetBufferList</span><span class="p">(</span><span class="n">lVar2</span><span class="p">,</span> <span class="n">iVar4</span><span class="p">);</span>      <span class="c1">// advance cursor unconditionally</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mi">6</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">+</span> <span class="n">iVar4</span><span class="p">;</span>   <span class="c1">// bump parse offset</span>
    <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="o">*</span><span class="n">pbVar3</span><span class="p">;</span>  <span class="c1">// Next Header = first byte</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The function pulls the first two bytes of the Hop-by-Hop header via <code class="language-plaintext highlighter-rouge">NdisGetDataBuffer</code> — <code class="language-plaintext highlighter-rouge">pbVar3[0]</code> is the Next Header value and <code class="language-plaintext highlighter-rouge">pbVar3[1]</code> is the <code class="language-plaintext highlighter-rouge">Hdr Ext Len</code> byte. It computes the claimed header length as <code class="language-plaintext highlighter-rouge">iVar4 = pbVar3[1] * 8 + 8</code>. Note that only <em>two</em> bytes were guaranteed to be present (the <code class="language-plaintext highlighter-rouge">2</code> argument to <code class="language-plaintext highlighter-rouge">NdisGetDataBuffer</code>); the length derived from the second of those bytes is trusted wholesale.</p>

<p>The very next statement is <code class="language-plaintext highlighter-rouge">NetioAdvanceNetBufferList(lVar2, iVar4)</code>. There is no comparison against the <code class="language-plaintext highlighter-rouge">NET_BUFFER</code>’s <code class="language-plaintext highlighter-rouge">DataLength</code>. If the wire packet only carried, say, 16 bytes of Hop-by-Hop data but <code class="language-plaintext highlighter-rouge">Hdr Ext Len</code> was set to 255, <code class="language-plaintext highlighter-rouge">iVar4</code> becomes 2048 and the cursor is advanced 2048 bytes forward — far past the end of the actual received data. The parse offset stored at <code class="language-plaintext highlighter-rouge">param_1[6]</code> is bumped by the same bogus amount, so the packet-processing state now believes it is sitting at byte 2088 of a packet that never had that many bytes.</p>

<p>Everything downstream inherits corrupted state. Individual TLV options inside the Hop-by-Hop header are walked using offsets and lengths derived from this now-desynchronized cursor, and the option handlers read (and in the router-alert / jumbogram paths, write) relative to a data pointer that no longer points inside the buffer. Because the option-parsing scratch state and the small fixed-size buffers used to marshal option contents live on the kernel stack — including the <code class="language-plaintext highlighter-rouge">local_res8</code> storage seen in the decompilation — over-reading and over-copying against a cursor past the buffer end manifests as a <strong>stack-based buffer overflow</strong>, matching the MSRC classification.</p>

<p>The core defect is a classic length-field-versus-actual-length mismatch: the code trusts an attacker-supplied size field and mutates the buffer cursor by it without validating that the buffer is that large.</p>

<h2 id="the-patch">The Patch</h2>

<p>The fixed build (<code class="language-plaintext highlighter-rouge">tcpip.sys</code> 7663) changes exactly one function, <code class="language-plaintext highlighter-rouge">Ipv6pReceiveHopByHopOptions</code>, growing it from 286 to 324 bytes and adding a single new callee: <code class="language-plaintext highlighter-rouge">Feature_3689662776__private_IsEnabledDeviceUsage</code>. The rewritten inner block:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="mh">0x28</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">pbVar4</span> <span class="o">=</span> <span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)</span><span class="n">NdisGetDataBuffer</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mi">8</span><span class="p">),</span> <span class="mi">2</span><span class="p">,</span> <span class="n">local_res8</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">short</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x11a</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">short</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span>
    <span class="n">uVar5</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">pbVar4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">8</span><span class="p">;</span>                       <span class="c1">// claimed header length</span>
    <span class="n">iVar3</span> <span class="o">=</span> <span class="n">Feature_3689662776__private_IsEnabledDeviceUsage</span><span class="p">();</span>
    <span class="k">if</span> <span class="p">((</span><span class="n">iVar3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">uVar5</span> <span class="o">&lt;=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">)))</span> <span class="p">{</span>
        <span class="n">NetioAdvanceNetBufferList</span><span class="p">(</span><span class="n">lVar2</span><span class="p">,</span> <span class="n">uVar5</span><span class="p">);</span>
        <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mi">6</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">+</span> <span class="n">uVar5</span><span class="p">;</span>
        <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="o">*</span><span class="n">pbVar4</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
        <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x3b</span><span class="p">;</span>  <span class="c1">// Next Header = 59 (No Next Header)</span>
        <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mh">0x8c</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xc000021b</span><span class="p">;</span>        <span class="c1">// STATUS_INVALID_PARAMETER</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Walking the difference:</p>

<ul>
  <li>
    <p><strong>The new bounds check.</strong> The condition <code class="language-plaintext highlighter-rouge">uVar5 &lt;= *(uint *)(*(longlong *)(lVar2 + 8) + 0x18)</code> is the fix. <code class="language-plaintext highlighter-rouge">lVar2 + 8</code> dereferences to the <code class="language-plaintext highlighter-rouge">NET_BUFFER</code>, and <code class="language-plaintext highlighter-rouge">+ 0x18</code> is its <code class="language-plaintext highlighter-rouge">DataLength</code> field. The patch now requires that the claimed header length <code class="language-plaintext highlighter-rouge">uVar5</code> be no larger than the bytes actually present before it will advance. Only when the buffer genuinely holds the header does control reach <code class="language-plaintext highlighter-rouge">NetioAdvanceNetBufferList</code> and the cursor/offset updates — the same three statements as before.</p>
  </li>
  <li>
    <p><strong>The failure path.</strong> When the packet is too short, the code does <em>not</em> advance. Instead it writes <code class="language-plaintext highlighter-rouge">0x3b</code> (decimal 59, the “No Next Header” pseudo-value) into the next-header field at <code class="language-plaintext highlighter-rouge">param_1 + 0x2c</code>, which terminates the extension-header walk cleanly, and stores <code class="language-plaintext highlighter-rouge">0xc000021b</code> — <code class="language-plaintext highlighter-rouge">STATUS_INVALID_PARAMETER</code> — into the per-packet status field at <code class="language-plaintext highlighter-rouge">lVar2 + 0x8c</code>. This mirrors the existing error handling already used in the sibling branch (the <code class="language-plaintext highlighter-rouge">!= 0x28</code> case, which likewise sets <code class="language-plaintext highlighter-rouge">0x3b</code> and an error status and calls <code class="language-plaintext highlighter-rouge">IppSendError</code>). The malformed packet is dropped rather than parsed.</p>

    <p>(One cosmetic note: the analyst’s post-patch listing shows the status constant as <code class="language-plaintext highlighter-rouge">-1073741285</code> and the summary text mentions <code class="language-plaintext highlighter-rouge">0xC000005B</code>; the diff against the reference build shows <code class="language-plaintext highlighter-rouge">0xc000021b</code>. All are the standard <code class="language-plaintext highlighter-rouge">STATUS_INVALID_PARAMETER</code>-family failure code written to bail the parse — the point is that the short-packet path returns a failure and stops, it does not advance.)</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">Feature_*</code> gating.</strong> The check is wrapped in <code class="language-plaintext highlighter-rouge">Feature_3689662776__private_IsEnabledDeviceUsage()</code>. When the feature is disabled (<code class="language-plaintext highlighter-rouge">iVar3 == 0</code>), the <code class="language-plaintext highlighter-rouge">||</code> short-circuits and the code takes the original, unchecked advance path. This is the standard Microsoft Velocity/Feature-flag pattern for shipping a fix dark and enabling it via staged rollout. Because a <em>new</em> <code class="language-plaintext highlighter-rouge">Feature_*</code> gate is being <strong>added</strong> around <strong>new</strong> validating logic here (not removed from around old logic), this is the genuine security fix — the added gate guards the added bounds check, exactly the signature of a gated remediation.</p>
  </li>
</ul>

<p>Functionally, the patch converts an unconditional, attacker-controlled cursor advance into a validated one, restoring the “never advance past <code class="language-plaintext highlighter-rouge">DataLength</code>” invariant at the single site that violated it.</p>

<h2 id="exploitability">Exploitability</h2>

<p>The primitive is memory corruption on the kernel receive path, reachable <strong>remotely and without authentication</strong>. The trigger is a single crafted IPv6 packet: place a Hop-by-Hop Options header immediately after the fixed 40-byte IPv6 header (so the parse offset equals <code class="language-plaintext highlighter-rouge">0x28</code> and the vulnerable branch is entered), set the <code class="language-plaintext highlighter-rouge">Hdr Ext Len</code> byte to a value whose implied length <code class="language-plaintext highlighter-rouge">8 * ExtLen + 8</code> exceeds the bytes actually delivered in the <code class="language-plaintext highlighter-rouge">NET_BUFFER</code>, and truncate the packet accordingly. No handshake, no open socket, and no prior connection state are required, because Hop-by-Hop options are processed unconditionally during IPv6 reception — this is host-firewall-bypassing in the sense that it fires before higher-layer demultiplexing.</p>

<p>Once the cursor is advanced past the buffer, the subsequent Hop-by-Hop option TLV walk operates on out-of-bounds memory, and the option handlers marshal data through fixed-size stack storage — the source of the stack-based overflow. That gives an attacker influence over kernel stack contents adjacent to the parsing routine’s frame, the classic precondition for control-flow hijack via return-address or stack-cookie-adjacent corruption, subject to the usual mitigations (stack cookies, kernel CFG). The CVSS 8.1 with a higher attack complexity reflects that reliable code execution requires shaping the receive buffer layout and defeating those mitigations rather than the trigger being hard — the <em>trigger</em> itself is trivial and deterministic.</p>

<p>Reachability depends on IPv6 being enabled (it is, by default, on all supported Windows versions) and on the host actually processing Hop-by-Hop options for the packet — which includes the destination node and any Windows system acting in a routing/forwarding role. Any attacker who can deliver an IPv6 frame to the target — same link-local segment, or across a network that routes IPv6 to it — can attempt the trigger. The fix’s staged <code class="language-plaintext highlighter-rouge">Feature_*</code> gate means the mitigation is only active where that flag is enabled, so the effective exposure window on a given host tracks the rollout state of <code class="language-plaintext highlighter-rouge">Feature_3689662776__private_IsEnabledDeviceUsage</code>, not merely the presence of the patched binary.</p>

<h2 id="pre-patch-functions">Pre patch functions</h2>

<p>Full decompilation of <code class="language-plaintext highlighter-rouge">Ipv6pReceiveHopByHopOptions</code> before the patch:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">Ipv6pReceiveHopByHopOptions</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="n">param_1</span><span class="p">)</span>

<span class="p">{</span>
  <span class="n">longlong</span> <span class="n">lVar1</span><span class="p">;</span>
  <span class="n">longlong</span> <span class="n">lVar2</span><span class="p">;</span>
  <span class="n">byte</span> <span class="o">*</span><span class="n">pbVar3</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">iVar4</span><span class="p">;</span>
  <span class="n">undefined2</span> <span class="n">local_res8</span> <span class="p">[</span><span class="mi">4</span><span class="p">];</span>
  
  <span class="n">lVar1</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span><span class="p">[</span><span class="mh">0x18</span><span class="p">]</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">);</span>
  <span class="n">local_res8</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">do</span> <span class="p">{</span>
    <span class="n">lVar2</span> <span class="o">=</span> <span class="n">param_1</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="k">if</span> <span class="p">(((</span><span class="n">lVar2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">&lt;</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mh">0x8c</span><span class="p">)))</span> <span class="o">&amp;&amp;</span>
       <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x220</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">*</span> <span class="mh">0x48</span><span class="p">)</span> <span class="o">!=</span> <span class="sc">'\0'</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="mh">0x28</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">pbVar3</span> <span class="o">=</span> <span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)</span><span class="n">NdisGetDataBuffer</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mi">8</span><span class="p">),</span><span class="mi">2</span><span class="p">,</span><span class="n">local_res8</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
        <span class="o">*</span><span class="p">(</span><span class="kt">short</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x11a</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">short</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span>
        <span class="n">iVar4</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">pbVar3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">8</span><span class="p">;</span>
        <span class="n">NetioAdvanceNetBufferList</span><span class="p">(</span><span class="n">lVar2</span><span class="p">,</span><span class="n">iVar4</span><span class="p">);</span>
        <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mi">6</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">+</span> <span class="n">iVar4</span><span class="p">;</span>
        <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="o">*</span><span class="n">pbVar3</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="k">else</span> <span class="p">{</span>
        <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x3b</span><span class="p">;</span>
        <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mh">0x8c</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xc000021b</span><span class="p">;</span>
        <span class="n">IppSendError</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="o">&amp;</span><span class="n">Ipv6Global</span><span class="p">,</span><span class="n">param_1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mh">0x28000000</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">param_1</span> <span class="o">=</span> <span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)</span><span class="o">*</span><span class="n">param_1</span><span class="p">;</span>
  <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">param_1</span> <span class="o">!=</span> <span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
  <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="post-patch-functions">Post patch functions</h2>

<p>Full decompilation of <code class="language-plaintext highlighter-rouge">Ipv6pReceiveHopByHopOptions</code> after the patch:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">Ipv6pReceiveHopByHopOptions</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="n">param_1</span><span class="p">)</span>

<span class="p">{</span>
  <span class="n">longlong</span> <span class="n">lVar1</span><span class="p">;</span>
  <span class="n">longlong</span> <span class="n">lVar2</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">iVar3</span><span class="p">;</span>
  <span class="n">byte</span> <span class="o">*</span><span class="n">pbVar4</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">uVar5</span><span class="p">;</span>
  <span class="n">undefined2</span> <span class="n">local_res8</span> <span class="p">[</span><span class="mi">4</span><span class="p">];</span>
  
  <span class="n">lVar1</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span><span class="p">[</span><span class="mh">0x18</span><span class="p">]</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">);</span>
  <span class="n">local_res8</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">do</span> <span class="p">{</span>
    <span class="n">lVar2</span> <span class="o">=</span> <span class="n">param_1</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="k">if</span> <span class="p">(((</span><span class="n">lVar2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">&lt;</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mh">0x8c</span><span class="p">)))</span> <span class="o">&amp;&amp;</span>
       <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x220</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">*</span> <span class="mh">0x48</span><span class="p">)</span> <span class="o">!=</span> <span class="sc">'\0'</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="mh">0x28</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">pbVar4</span> <span class="o">=</span> <span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)</span><span class="n">NdisGetDataBuffer</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mi">8</span><span class="p">),</span><span class="mi">2</span><span class="p">,</span><span class="n">local_res8</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
        <span class="o">*</span><span class="p">(</span><span class="kt">short</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x11a</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">short</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span>
        <span class="n">uVar5</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">pbVar4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">8</span><span class="p">;</span>
        <span class="n">iVar3</span> <span class="o">=</span> <span class="n">Feature_3689662776__private_IsEnabledDeviceUsage</span><span class="p">();</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">iVar3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">uVar5</span> <span class="o">&lt;=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">)))</span> <span class="p">{</span>
          <span class="n">NetioAdvanceNetBufferList</span><span class="p">(</span><span class="n">lVar2</span><span class="p">,</span><span class="n">uVar5</span><span class="p">);</span>
          <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mi">6</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">+</span> <span class="n">uVar5</span><span class="p">;</span>
          <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="o">*</span><span class="n">pbVar4</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span> <span class="p">{</span>
          <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x3b</span><span class="p">;</span>
          <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mh">0x8c</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xc000021b</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">}</span>
      <span class="k">else</span> <span class="p">{</span>
        <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x3b</span><span class="p">;</span>
        <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar2</span> <span class="o">+</span> <span class="mh">0x8c</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xc000021b</span><span class="p">;</span>
        <span class="n">IppSendError</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="o">&amp;</span><span class="n">Ipv6Global</span><span class="p">,</span><span class="n">param_1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mh">0x28000000</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">param_1</span> <span class="o">=</span> <span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)</span><span class="o">*</span><span class="n">param_1</span><span class="p">;</span>
  <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">param_1</span> <span class="o">!=</span> <span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
  <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>tzvironen</name></author><summary type="html"><![CDATA[A remote, unauthenticated stack-based buffer overflow in the Windows TCP/IP driver (tcpip.sys) lets a crafted IPv6 Hop-by-Hop options header advance the packet cursor past the NET_BUFFER bounds, corrupting memory and enabling remote code execution.]]></summary></entry><entry><title type="html">CVE-2026-45657: Use-After-Free in the Windows IPv4/IPv6 Forward-Path Cache (IppCreateForwardPath)</title><link href="https://cvepatchbook.com/reports/cve-2026-45657-kernel-remote-code-execution/" rel="alternate" type="text/html" title="CVE-2026-45657: Use-After-Free in the Windows IPv4/IPv6 Forward-Path Cache (IppCreateForwardPath)" /><published>2026-06-09T00:00:00+00:00</published><updated>2026-06-09T00:00:00+00:00</updated><id>https://cvepatchbook.com/reports/cve-2026-45657-kernel-remote-code-execution</id><content type="html" xml:base="https://cvepatchbook.com/reports/cve-2026-45657-kernel-remote-code-execution/"><![CDATA[<h1 id="cve-2026-45657-use-after-free-in-the-windows-ipv4ipv6-forward-path-cache-ippcreateforwardpath">CVE-2026-45657: Use-After-Free in the Windows IPv4/IPv6 Forward-Path Cache (IppCreateForwardPath)</h1>

<ul>
  <li><strong>Affected binary:</strong> <code class="language-plaintext highlighter-rouge">tcpip.sys</code> 10.0.22621.7079 → 10.0.22621.7219</li>
  <li><strong>CVE:</strong> CVE-2026-45657</li>
  <li><strong>Patch date:</strong> 2026-06-09</li>
  <li><strong>CVSS:</strong> 9.8</li>
  <li><strong>Class:</strong> Use-after-free</li>
  <li><strong>Patch KB:</strong> KB5093998</li>
</ul>

<h2 id="tldr">TL;DR</h2>

<p><code class="language-plaintext highlighter-rouge">tcpip.sys</code> maintains a per-compartment forward-path cache — a scalable hash table of <code class="language-plaintext highlighter-rouge">IppPath</code> entries that caches next-hop routing decisions for received packets. In <code class="language-plaintext highlighter-rouge">IppCreateForwardPath</code>, a freshly allocated path entry was inserted into the live hash table (<code class="language-plaintext highlighter-rouge">RtlInsertEntryHashTable</code>) and only had its “valid” bit (<code class="language-plaintext highlighter-rouge">+0x50 | 1</code>) set <em>after</em> an intervening call to <code class="language-plaintext highlighter-rouge">IppRestructureHashTableUnderLock</code>. Although the write lock is held throughout, the restructure/prune machinery and concurrent readers key off that valid bit, and the ordering left a window where an entry visible in the table could be treated inconsistently — a classic publish-before-initialize error that leads to a use-after-free of the <code class="language-plaintext highlighter-rouge">IppPath</code> object. The patch, gated behind CFR feature <code class="language-plaintext highlighter-rouge">411806010</code>, moves the valid-bit assignment to <em>immediately after</em> insertion (before pruning and restructuring), so the entry is never observable in an intermediate, not-yet-valid state.</p>

<h2 id="background">Background</h2>

<p>When the IP layer receives a packet that needs to be forwarded or delivered, it must resolve a next hop. Rather than walk the route table on every packet, <code class="language-plaintext highlighter-rouge">tcpip.sys</code> caches resolved routes in a <strong>forward-path cache</strong> keyed by source/destination address. Each cache element is an <code class="language-plaintext highlighter-rouge">IppPath</code> structure allocated from a per-processor lookaside list (<code class="language-plaintext highlighter-rouge">ExAllocateFromLookasideListEx</code>) and linked into a <strong>scalable hash table</strong> — the RTL scalable hash table primitives (<code class="language-plaintext highlighter-rouge">RtlInsertEntryHashTable</code>, <code class="language-plaintext highlighter-rouge">RtlAcquireScalableWriteLockAtDpcLevel</code>) that Windows uses for high-contention, per-CPU-sharded lookups.</p>

<p>The relevant object layout, from the decompiled allocator, is a <code class="language-plaintext highlighter-rouge">0x58</code>-byte header followed by inline copies of the destination and (optionally) source address keys:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">+0x18</code> = <code class="language-plaintext highlighter-rouge">0x70667049</code> — the ASCII tag <code class="language-plaintext highlighter-rouge">'Ipfp'</code>, the structure’s type signature.</li>
  <li><code class="language-plaintext highlighter-rouge">+0x20</code> = pointer to the inline destination key (<code class="language-plaintext highlighter-rouge">_Dst</code>, at header+<code class="language-plaintext highlighter-rouge">0x58</code>).</li>
  <li><code class="language-plaintext highlighter-rouge">+0x28</code> = pointer to the inline source key (<code class="language-plaintext highlighter-rouge">_Dst_01</code>), or <code class="language-plaintext highlighter-rouge">NULL</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">+0x3c</code> = initial reference count, set to <code class="language-plaintext highlighter-rouge">1</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">+0x48</code> = a back-pointer to the associated next-hop/interface object (<code class="language-plaintext highlighter-rouge">param_8</code>), whose own refcount is bumped via <code class="language-plaintext highlighter-rouge">CarAcquireCacheAwareReference</code> (for tag <code class="language-plaintext highlighter-rouge">'Ipla'</code>) or a raw <code class="language-plaintext highlighter-rouge">LOCK inc</code> (for tag <code class="language-plaintext highlighter-rouge">'Ipne'</code>).</li>
  <li><code class="language-plaintext highlighter-rouge">+0x50</code> = the <strong>flags byte</strong>, whose bit <code class="language-plaintext highlighter-rouge">0</code> is the “path is valid / fully published” indicator.</li>
</ul>

<p>The hash is computed with <code class="language-plaintext highlighter-rouge">RtlCompute37Hash</code> over the destination key (and the source key, when present), seeded with <code class="language-plaintext highlighter-rouge">g_37HashSeed</code>, then OR’d with <code class="language-plaintext highlighter-rouge">0x80000000</code>. Insertion, capacity-based pruning (<code class="language-plaintext highlighter-rouge">IppPrunePathSetUnderLock</code>), and table restructuring (<code class="language-plaintext highlighter-rouge">IppRestructureHashTableUnderLock</code>) all happen under a single scalable write lock acquired on <code class="language-plaintext highlighter-rouge">param_1 + 0x4c0</code>.</p>

<p>The lookup side — <code class="language-plaintext highlighter-rouge">IppFindNextHopInFwdCacheOrRouteTable</code> and friends, which call into this function — walks the same hash table to find an existing path before creating a new one. Reference counting on <code class="language-plaintext highlighter-rouge">IppPath</code> entries is what keeps them alive across that lookup/use window; when the count drops to zero the entry is freed back to the lookaside list. The valid bit at <code class="language-plaintext highlighter-rouge">+0x50</code> governs whether an entry is eligible to be seen and referenced by those consumers.</p>

<h2 id="root-cause">Root Cause</h2>

<p>Here is the tail of the pre-patch <code class="language-plaintext highlighter-rouge">IppCreateForwardPath</code>, from allocation-complete through publication:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x3c</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>          <span class="c1">// refcount = 1</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x40</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x14</span><span class="p">);</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">**</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x48</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_8</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">param_8</span> <span class="o">==</span> <span class="mh">0x616c7049</span><span class="p">)</span> <span class="p">{</span>                            <span class="c1">// 'Ipla'</span>
      <span class="n">CarAcquireCacheAwareReference</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_8</span> <span class="o">+</span> <span class="mi">8</span><span class="p">),</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="o">*</span><span class="n">param_8</span> <span class="o">==</span> <span class="mh">0x656e7049</span><span class="p">)</span> <span class="p">{</span>                       <span class="c1">// 'Ipne'</span>
      <span class="n">LOCK</span><span class="p">();</span> <span class="n">param_8</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">param_8</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">UNLOCK</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="p">...</span>
    <span class="n">lVar1</span> <span class="o">=</span> <span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x4c0</span><span class="p">;</span>
    <span class="n">RtlAcquireScalableWriteLockAtDpcLevel</span><span class="p">(</span><span class="n">lVar1</span><span class="p">,</span><span class="o">&amp;</span><span class="n">local_48</span><span class="p">);</span>
    <span class="n">RtlInsertEntryHashTable</span><span class="p">(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x640</span><span class="p">,</span><span class="n">_Dst_00</span><span class="p">,</span><span class="n">uVar3</span> <span class="o">|</span> <span class="mh">0x80000000</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>   <span class="c1">// (1) PUBLISH</span>
    <span class="k">if</span> <span class="p">((</span><span class="n">uint</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x604</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x654</span><span class="p">))</span> <span class="p">{</span>
      <span class="n">IppPrunePathSetUnderLock</span><span class="p">(</span><span class="n">param_1</span><span class="p">,</span><span class="n">lVar1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span>                             <span class="c1">// (2) PRUNE</span>
    <span class="p">}</span>
    <span class="n">IppRestructureHashTableUnderLock</span><span class="p">(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x640</span><span class="p">);</span>                       <span class="c1">// (3) RESTRUCTURE</span>
    <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">|</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// (4) MARK VALID</span>
    <span class="n">KeReleaseInStackQueuedSpinLockFromDpcLevel</span><span class="p">(</span><span class="o">&amp;</span><span class="n">local_48</span><span class="p">);</span>
</code></pre></div></div>

<p>The defect is the ordering of steps (1) through (4). The entry <code class="language-plaintext highlighter-rouge">_Dst_00</code> becomes a member of the live hash table at step (1), but its validity flag is not set until step (4) — <em>after</em> two operations that walk and mutate the table’s contents:</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">IppPrunePathSetUnderLock</code> (2)</strong> is a garbage-collection pass triggered when the table’s occupancy (<code class="language-plaintext highlighter-rouge">+0x654</code>) reaches twice its target (<code class="language-plaintext highlighter-rouge">+0x604 * 2</code>). Pruning enumerates entries and evicts stale ones based on their state and reference counts.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">IppRestructureHashTableUnderLock</code> (3)</strong> rebalances the scalable table’s per-bucket chains.</li>
</ul>

<p>Although the scalable <em>write</em> lock is held across the whole sequence, that lock is not the only synchronization boundary that matters here. The scalable hash table is designed for <strong>lockless / reader-optimistic traversal</strong> on its read paths, and the entry’s <code class="language-plaintext highlighter-rouge">+0x50</code> valid bit is precisely the flag that tells a consumer “this entry is fully constructed and safe to reference.” By making the entry reachable at step (1) with <code class="language-plaintext highlighter-rouge">+0x50 == 0</code>, the code creates a window in which the pruning and restructuring logic — and any reader that reaches the entry through the sharded per-CPU structures without taking the full write lock — can encounter a path entry that is linked but not yet marked valid.</p>

<p>The consequence is a <strong>use-after-free</strong>: pruning/eviction logic can act on the not-yet-valid entry (or a racing consumer can grab and then release a reference on it) in a way that drives the freshly created <code class="language-plaintext highlighter-rouge">IppPath</code> — still owned by the <code class="language-plaintext highlighter-rouge">refcount = 1</code> the constructor set at <code class="language-plaintext highlighter-rouge">+0x3c</code> — to premature teardown and return to the lookaside list, while <code class="language-plaintext highlighter-rouge">IppCreateForwardPath</code> continues to operate on <code class="language-plaintext highlighter-rouge">_Dst_00</code> (it dereferences it again at step (4) and hands <code class="language-plaintext highlighter-rouge">lVar1</code> to <code class="language-plaintext highlighter-rouge">IppPathSetStartOrContinueTimer</code>). The caller (<code class="language-plaintext highlighter-rouge">IppDispatchReceivePacketHelper</code>) then continues down the receive path holding a stale reference to freed lookaside memory that can be reallocated as another <code class="language-plaintext highlighter-rouge">IppPath</code> under attacker-influenced network load.</p>

<h2 id="the-patch">The Patch</h2>

<p>The post-patch function introduces exactly one behavioral change, gated by a Component Feature Rollout (CFR) flag, plus the addition of the enablement helper. The valid-bit write is hoisted to run <strong>immediately after insertion and before pruning/restructuring</strong>:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="n">RtlInsertEntryHashTable</span><span class="p">(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x640</span><span class="p">,</span><span class="n">_Dst_00</span><span class="p">,</span><span class="n">uVar3</span> <span class="o">|</span> <span class="mh">0x80000000</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="n">iVar4</span> <span class="o">=</span> <span class="n">Feature_411806010__private_IsEnabledDeviceUsage</span><span class="p">();</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">iVar4</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>                                        <span class="c1">// NEW code path</span>
      <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">|</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="p">((</span><span class="n">uint</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x604</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x654</span><span class="p">))</span> <span class="p">{</span>
      <span class="n">IppPrunePathSetUnderLock</span><span class="p">(</span><span class="n">param_1</span><span class="p">,</span><span class="n">lVar1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">IppRestructureHashTableUnderLock</span><span class="p">(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x640</span><span class="p">);</span>
    <span class="n">iVar4</span> <span class="o">=</span> <span class="n">Feature_411806010__private_IsEnabledDeviceUsage</span><span class="p">();</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">iVar4</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>                                        <span class="c1">// OLD (vulnerable) path</span>
      <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">|</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">KeReleaseInStackQueuedSpinLockFromDpcLevel</span><span class="p">(</span><span class="o">&amp;</span><span class="n">local_48</span><span class="p">);</span>
</code></pre></div></div>

<p>The logic is a straight A/B fork on the feature state:</p>

<ul>
  <li><strong>Feature enabled</strong> (<code class="language-plaintext highlighter-rouge">IsEnabledDeviceUsage() != 0</code>): set <code class="language-plaintext highlighter-rouge">+0x50 |= 1</code> right after <code class="language-plaintext highlighter-rouge">RtlInsertEntryHashTable</code>. The entry is now marked valid <em>before</em> <code class="language-plaintext highlighter-rouge">IppPrunePathSetUnderLock</code> and <code class="language-plaintext highlighter-rouge">IppRestructureHashTableUnderLock</code> ever touch the table. There is no observable window in which the entry is linked but not valid — publish and initialize-complete are now effectively atomic with respect to the prune/restructure machinery.</li>
  <li><strong>Feature disabled</strong>: fall through to the original ordering, setting the bit only after restructuring. This preserves pre-patch behavior when the flag is off, which is how Microsoft ships a risky ordering change safely — the fix can be rolled back in the field via CFR without a new binary.</li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">Feature_*</code> gate is the standard Windows CFR pattern. The new helper:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ulonglong</span> <span class="nf">Feature_411806010__private_IsEnabledDeviceUsage</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
  <span class="n">ulonglong</span> <span class="n">uVar1</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">((</span><span class="n">Feature_411806010__private_featureState</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">uVar1</span> <span class="o">=</span> <span class="n">Feature_411806010__private_IsEnabledFallback</span><span class="p">(</span>
                <span class="n">Feature_411806010__private_featureState</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="n">uVar1</span> <span class="o">=</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)(</span><span class="n">Feature_411806010__private_featureState</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">uVar1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>reads the cached <code class="language-plaintext highlighter-rouge">Feature_411806010__private_featureState</code>: if bit <code class="language-plaintext highlighter-rouge">0x10</code> (the “state is decided/cached” bit) is set, it returns the low bit as the enable/disable answer; otherwise it consults <code class="language-plaintext highlighter-rouge">Feature_411806010__private_IsEnabledFallback</code> with default priority <code class="language-plaintext highlighter-rouge">3</code> to resolve the rollout decision. The remaining textual differences in the diff — <code class="language-plaintext highlighter-rouge">iVar4</code>/<code class="language-plaintext highlighter-rouge">uVar5</code>/<code class="language-plaintext highlighter-rouge">lVar6</code> renames and the identical <code class="language-plaintext highlighter-rouge">IppPathSetStartOrContinueTimer</code> timer-interval arithmetic — are decompiler register-naming artifacts from the two inserted <code class="language-plaintext highlighter-rouge">Feature_*</code> calls, not semantic changes. The function’s length grew from 623 to 645 bytes, consistent with two small <code class="language-plaintext highlighter-rouge">call/test/jz/or</code> sequences replacing one unconditional <code class="language-plaintext highlighter-rouge">or</code>.</p>

<p>Note that once the flag reaches full deployment, the “disabled” branch is dead code; keeping it is purely the CFR safety valve.</p>

<h2 id="exploitability">Exploitability</h2>

<p>The primitive is a <strong>use-after-free of a lookaside-backed <code class="language-plaintext highlighter-rouge">IppPath</code> object</strong> in non-paged pool, reachable from the packet <strong>receive path</strong>. <code class="language-plaintext highlighter-rouge">IppCreateForwardPath</code> is invoked from <code class="language-plaintext highlighter-rouge">IppDispatchReceivePacketHelper</code> / <code class="language-plaintext highlighter-rouge">IppFindNextHopInFwdCacheOrRouteTable</code> / <code class="language-plaintext highlighter-rouge">IpIpsProviderFindNextHop</code> — i.e., while processing inbound IP datagrams whose next hop is not already cached. No authentication and no local access are required, which is what earns the CVSS 9.8 / network attack vector: an attacker who can send packets to the target (crafted to miss the forward-path cache and force fresh entry creation) drives the vulnerable allocation path.</p>

<p>The trigger is a race, and the window is small — it exists only between <code class="language-plaintext highlighter-rouge">RtlInsertEntryHashTable</code> and the delayed <code class="language-plaintext highlighter-rouge">+0x50 |= 1</code>, spanning a prune and a restructure. Two conditions make it practical to hit despite the “high complexity” feel of a kernel race:</p>

<ol>
  <li><strong>The attacker controls the pressure that opens the window.</strong> The prune pass at step (2) fires only when occupancy reaches <code class="language-plaintext highlighter-rouge">2 * target</code> (<code class="language-plaintext highlighter-rouge">+0x654 &gt;= +0x604 * 2</code>). By flooding the target with packets to many distinct destinations (or spoofed source/destination pairs, since the source key participates in the hash when present), an attacker inflates the cache toward that threshold on demand, guaranteeing that new insertions land in exactly the code path where pruning runs while the just-inserted entry is still invalid.</li>
  <li><strong>Receive processing is inherently concurrent.</strong> Inbound packets are dispatched across multiple processors, and the scalable hash table is per-CPU sharded specifically to allow concurrent access. That concurrency is the same property that lets a second CPU’s lookup observe the half-published entry, or lets pruning race the constructor’s <code class="language-plaintext highlighter-rouge">refcount = 1</code>, collapsing the reference to zero and freeing the object back to the per-processor lookaside list.</li>
</ol>

<p>Once the <code class="language-plaintext highlighter-rouge">IppPath</code> is freed, the lookaside list makes reallocation highly deterministic: the next <code class="language-plaintext highlighter-rouge">IppCreateForwardPath</code> on the same processor hands back the same block, letting an attacker groom the freed slot with a new, attacker-shaped path entry while the original caller still holds a pointer to it. Controlled fields at <code class="language-plaintext highlighter-rouge">+0x48</code> (the interface/next-hop back-pointer, which is dereferenced and reference-counted) and <code class="language-plaintext highlighter-rouge">+0x20</code>/<code class="language-plaintext highlighter-rouge">+0x28</code> (key pointers) provide the levers to convert the dangling reference into a controlled dereference and, ultimately, remote code execution in kernel context. Because the corrupted object is a routing-cache entry consulted on every subsequent forwarded packet, the attacker also gets repeated, low-noise opportunities to re-trigger and stabilize the exploit.</p>

<p>The fix eliminates the window entirely rather than merely narrowing it: with the feature enabled, no code between insertion and the valid-bit write can observe an entry that is linked-but-invalid, so neither the prune pass nor a concurrent reader can act on a partially constructed <code class="language-plaintext highlighter-rouge">IppPath</code>.</p>

<h2 id="detection">Detection</h2>

<p>Reliable exploitation of this bug manifests as an unusual inbound traffic pattern: a burst of packets to a large number of distinct destination/source pairs from a single or small set of remote peers, engineered to churn the forward-path cache past its prune threshold. On unpatched hosts, failed race attempts tend to surface as <code class="language-plaintext highlighter-rouge">tcpip.sys</code> bugchecks in <code class="language-plaintext highlighter-rouge">IppPrunePathSetUnderLock</code>, <code class="language-plaintext highlighter-rouge">IppRestructureHashTableUnderLock</code>, or <code class="language-plaintext highlighter-rouge">IppPathSetStartOrContinueTimer</code> with a corrupted or freed <code class="language-plaintext highlighter-rouge">IppPath</code> (tag <code class="language-plaintext highlighter-rouge">'Ipfp'</code> / <code class="language-plaintext highlighter-rouge">0x70667049</code>) as the faulting object — a useful signature when triaging crash telemetry. On patched systems, confirm the mitigation is live by checking that CFR feature <code class="language-plaintext highlighter-rouge">411806010</code> is in the enabled state, since the vulnerable ordering remains reachable whenever the flag is off.</p>

<h2 id="pre-patch-functions">Pre patch functions</h2>

<p>Full decompilation of <code class="language-plaintext highlighter-rouge">IppCreateForwardPath</code> before the patch:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */</span>

<span class="kt">void</span> <span class="nf">IppCreateForwardPath</span>
               <span class="p">(</span><span class="n">longlong</span> <span class="n">param_1</span><span class="p">,</span><span class="kt">void</span> <span class="o">*</span><span class="n">param_2</span><span class="p">,</span><span class="kt">void</span> <span class="o">*</span><span class="n">param_3</span><span class="p">,</span><span class="n">undefined4</span> <span class="n">param_4</span><span class="p">,</span><span class="n">undefined4</span> <span class="n">param_5</span><span class="p">,</span>
               <span class="n">undefined1</span> <span class="n">param_6</span><span class="p">,</span><span class="n">undefined4</span> <span class="n">param_7</span><span class="p">,</span><span class="kt">int</span> <span class="o">*</span><span class="n">param_8</span><span class="p">)</span>

<span class="p">{</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">_Dst</span><span class="p">;</span>
  <span class="n">longlong</span> <span class="n">lVar1</span><span class="p">;</span>
  <span class="n">undefined1</span> <span class="n">auVar2</span> <span class="p">[</span><span class="mi">16</span><span class="p">];</span>
  <span class="n">uint</span> <span class="n">uVar3</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">uVar4</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">_Dst_00</span><span class="p">;</span>
  <span class="n">longlong</span> <span class="n">lVar5</span><span class="p">;</span>
  <span class="n">ulonglong</span> <span class="n">_Size</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">_Dst_01</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">local_48</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">uStack_40</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">local_38</span><span class="p">;</span>
  
  <span class="n">local_48</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">uStack_40</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">local_38</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">_Dst_01</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">;</span>
  <span class="n">_Size</span> <span class="o">=</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">ushort</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">+</span> <span class="mi">6</span><span class="p">);</span>
  <span class="n">uVar4</span> <span class="o">=</span> <span class="n">PplpRetrieveListIndex</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x4ea8</span><span class="p">));</span>
  <span class="n">_Dst_00</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">ExAllocateFromLookasideListEx</span><span class="p">(</span><span class="n">uVar4</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">_Dst_00</span> <span class="o">==</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">DAT_0</span> <span class="o">&lt;</span> <span class="sc">'\0'</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">McTemplateK0z_EtwWriteTransfer</span><span class="p">(</span><span class="o">&amp;</span><span class="n">MICROSOFT_TCPIP_PROVIDER_Context</span><span class="p">,</span><span class="o">&amp;</span><span class="n">TCPIP_MEMORY_FAILURES</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="n">memset</span><span class="p">(</span><span class="n">_Dst_00</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mh">0x58</span><span class="p">);</span>
    <span class="n">_Dst</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x58</span><span class="p">);</span>
    <span class="n">memmove</span><span class="p">(</span><span class="n">_Dst</span><span class="p">,</span><span class="n">param_3</span><span class="p">,</span><span class="n">_Size</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">param_2</span> <span class="o">!=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">_Dst_01</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">_Size</span> <span class="o">+</span> <span class="p">(</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst</span><span class="p">);</span>
      <span class="n">memmove</span><span class="p">(</span><span class="n">_Dst_01</span><span class="p">,</span><span class="n">param_2</span><span class="p">,</span><span class="n">_Size</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x34</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_5</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">=</span> <span class="n">_Dst_01</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined1</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x38</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_6</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x30</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_7</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x70667049</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x1c</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_4</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x20</span><span class="p">)</span> <span class="o">=</span> <span class="n">_Dst</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x3c</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x40</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x14</span><span class="p">);</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">**</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x48</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_8</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">param_8</span> <span class="o">==</span> <span class="mh">0x616c7049</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">CarAcquireCacheAwareReference</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_8</span> <span class="o">+</span> <span class="mi">8</span><span class="p">),</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">param_8</span> <span class="o">==</span> <span class="mh">0x656e7049</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">LOCK</span><span class="p">();</span>
      <span class="n">param_8</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">param_8</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
      <span class="n">UNLOCK</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="n">lVar1</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">);</span>
    <span class="n">uVar3</span> <span class="o">=</span> <span class="n">RtlCompute37Hash</span><span class="p">(</span><span class="n">g_37HashSeed</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x20</span><span class="p">),</span>
                             <span class="o">*</span><span class="p">(</span><span class="n">undefined2</span> <span class="o">*</span><span class="p">)</span>
                              <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">+</span> <span class="mi">6</span><span class="p">));</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">lVar1</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">uVar3</span> <span class="o">=</span> <span class="n">RtlCompute37Hash</span><span class="p">(</span><span class="n">uVar3</span><span class="p">,</span><span class="n">lVar1</span><span class="p">,</span>
                               <span class="o">*</span><span class="p">(</span><span class="n">undefined2</span> <span class="o">*</span><span class="p">)</span>
                                <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">+</span> <span class="mi">6</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="n">lVar1</span> <span class="o">=</span> <span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x4c0</span><span class="p">;</span>
    <span class="n">RtlAcquireScalableWriteLockAtDpcLevel</span><span class="p">(</span><span class="n">lVar1</span><span class="p">,</span><span class="o">&amp;</span><span class="n">local_48</span><span class="p">);</span>
    <span class="n">RtlInsertEntryHashTable</span><span class="p">(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x640</span><span class="p">,</span><span class="n">_Dst_00</span><span class="p">,</span><span class="n">uVar3</span> <span class="o">|</span> <span class="mh">0x80000000</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">((</span><span class="n">uint</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x604</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x654</span><span class="p">))</span> <span class="p">{</span>
      <span class="n">IppPrunePathSetUnderLock</span><span class="p">(</span><span class="n">param_1</span><span class="p">,</span><span class="n">lVar1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">IppRestructureHashTableUnderLock</span><span class="p">(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x640</span><span class="p">);</span>
    <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">|</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">KeReleaseInStackQueuedSpinLockFromDpcLevel</span><span class="p">(</span><span class="o">&amp;</span><span class="n">local_48</span><span class="p">);</span>
    <span class="n">auVar2</span><span class="p">.</span><span class="n">_8_8_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">auVar2</span><span class="p">.</span><span class="n">_0_8_</span> <span class="o">=</span> <span class="n">_DAT_1</span> <span class="o">/</span> <span class="mi">10000</span><span class="p">;</span>
    <span class="n">lVar5</span> <span class="o">=</span> <span class="n">SUB168</span><span class="p">(</span><span class="n">ZEXT816</span><span class="p">(</span><span class="mh">0x624dd2f1a9fbe77</span><span class="p">)</span> <span class="o">*</span> <span class="n">auVar2</span><span class="p">,</span><span class="mi">8</span><span class="p">);</span>
    <span class="n">IppPathSetStartOrContinueTimer</span>
              <span class="p">(</span><span class="n">lVar1</span><span class="p">,</span><span class="n">lVar5</span> <span class="o">+</span> <span class="p">(</span><span class="n">_DAT_1</span> <span class="o">/</span> <span class="mi">10000</span> <span class="o">-</span> <span class="n">lVar5</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">8</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="post-patch-functions">Post patch functions</h2>

<p>Full decompilation of <code class="language-plaintext highlighter-rouge">IppCreateForwardPath</code> after the patch:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */</span>

<span class="kt">void</span> <span class="nf">IppCreateForwardPath</span>
               <span class="p">(</span><span class="n">longlong</span> <span class="n">param_1</span><span class="p">,</span><span class="kt">void</span> <span class="o">*</span><span class="n">param_2</span><span class="p">,</span><span class="kt">void</span> <span class="o">*</span><span class="n">param_3</span><span class="p">,</span><span class="n">undefined4</span> <span class="n">param_4</span><span class="p">,</span><span class="n">undefined4</span> <span class="n">param_5</span><span class="p">,</span>
               <span class="n">undefined1</span> <span class="n">param_6</span><span class="p">,</span><span class="n">undefined4</span> <span class="n">param_7</span><span class="p">,</span><span class="kt">int</span> <span class="o">*</span><span class="n">param_8</span><span class="p">)</span>

<span class="p">{</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">_Dst</span><span class="p">;</span>
  <span class="n">longlong</span> <span class="n">lVar1</span><span class="p">;</span>
  <span class="n">undefined1</span> <span class="n">auVar2</span> <span class="p">[</span><span class="mi">16</span><span class="p">];</span>
  <span class="n">uint</span> <span class="n">uVar3</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">iVar4</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">uVar5</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">_Dst_00</span><span class="p">;</span>
  <span class="n">longlong</span> <span class="n">lVar6</span><span class="p">;</span>
  <span class="n">ulonglong</span> <span class="n">_Size</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">_Dst_01</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">local_48</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">uStack_40</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">local_38</span><span class="p">;</span>
  
  <span class="n">local_48</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">uStack_40</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">local_38</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">_Dst_01</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">;</span>
  <span class="n">_Size</span> <span class="o">=</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">ushort</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">+</span> <span class="mi">6</span><span class="p">);</span>
  <span class="n">uVar5</span> <span class="o">=</span> <span class="n">PplpRetrieveListIndex</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x4ea8</span><span class="p">));</span>
  <span class="n">_Dst_00</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">ExAllocateFromLookasideListEx</span><span class="p">(</span><span class="n">uVar5</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">_Dst_00</span> <span class="o">==</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">DAT_0</span> <span class="o">&lt;</span> <span class="sc">'\0'</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">McTemplateK0z_EtwWriteTransfer</span><span class="p">(</span><span class="o">&amp;</span><span class="n">MICROSOFT_TCPIP_PROVIDER_Context</span><span class="p">,</span><span class="o">&amp;</span><span class="n">TCPIP_MEMORY_FAILURES</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="n">memset</span><span class="p">(</span><span class="n">_Dst_00</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mh">0x58</span><span class="p">);</span>
    <span class="n">_Dst</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x58</span><span class="p">);</span>
    <span class="n">memmove</span><span class="p">(</span><span class="n">_Dst</span><span class="p">,</span><span class="n">param_3</span><span class="p">,</span><span class="n">_Size</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">param_2</span> <span class="o">!=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">_Dst_01</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">_Size</span> <span class="o">+</span> <span class="p">(</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst</span><span class="p">);</span>
      <span class="n">memmove</span><span class="p">(</span><span class="n">_Dst_01</span><span class="p">,</span><span class="n">param_2</span><span class="p">,</span><span class="n">_Size</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x34</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_5</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">=</span> <span class="n">_Dst_01</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined1</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x38</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_6</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x30</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_7</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x70667049</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x1c</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_4</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x20</span><span class="p">)</span> <span class="o">=</span> <span class="n">_Dst</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x3c</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
    <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x40</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x14</span><span class="p">);</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">**</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x48</span><span class="p">)</span> <span class="o">=</span> <span class="n">param_8</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">param_8</span> <span class="o">==</span> <span class="mh">0x616c7049</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">CarAcquireCacheAwareReference</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_8</span> <span class="o">+</span> <span class="mi">8</span><span class="p">),</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">param_8</span> <span class="o">==</span> <span class="mh">0x656e7049</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">LOCK</span><span class="p">();</span>
      <span class="n">param_8</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">param_8</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
      <span class="n">UNLOCK</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="n">lVar1</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">);</span>
    <span class="n">uVar3</span> <span class="o">=</span> <span class="n">RtlCompute37Hash</span><span class="p">(</span><span class="n">g_37HashSeed</span><span class="p">,</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x20</span><span class="p">),</span>
                             <span class="o">*</span><span class="p">(</span><span class="n">undefined2</span> <span class="o">*</span><span class="p">)</span>
                              <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">+</span> <span class="mi">6</span><span class="p">));</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">lVar1</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">uVar3</span> <span class="o">=</span> <span class="n">RtlCompute37Hash</span><span class="p">(</span><span class="n">uVar3</span><span class="p">,</span><span class="n">lVar1</span><span class="p">,</span>
                               <span class="o">*</span><span class="p">(</span><span class="n">undefined2</span> <span class="o">*</span><span class="p">)</span>
                                <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">+</span> <span class="mi">6</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="n">lVar1</span> <span class="o">=</span> <span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x4c0</span><span class="p">;</span>
    <span class="n">RtlAcquireScalableWriteLockAtDpcLevel</span><span class="p">(</span><span class="n">lVar1</span><span class="p">,</span><span class="o">&amp;</span><span class="n">local_48</span><span class="p">);</span>
    <span class="n">RtlInsertEntryHashTable</span><span class="p">(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x640</span><span class="p">,</span><span class="n">_Dst_00</span><span class="p">,</span><span class="n">uVar3</span> <span class="o">|</span> <span class="mh">0x80000000</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="n">iVar4</span> <span class="o">=</span> <span class="n">Feature_411806010__private_IsEnabledDeviceUsage</span><span class="p">();</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">iVar4</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">|</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="p">((</span><span class="n">uint</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x604</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x654</span><span class="p">))</span> <span class="p">{</span>
      <span class="n">IppPrunePathSetUnderLock</span><span class="p">(</span><span class="n">param_1</span><span class="p">,</span><span class="n">lVar1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">IppRestructureHashTableUnderLock</span><span class="p">(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x640</span><span class="p">);</span>
    <span class="n">iVar4</span> <span class="o">=</span> <span class="n">Feature_411806010__private_IsEnabledDeviceUsage</span><span class="p">();</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">iVar4</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Dst_00</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">|</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">KeReleaseInStackQueuedSpinLockFromDpcLevel</span><span class="p">(</span><span class="o">&amp;</span><span class="n">local_48</span><span class="p">);</span>
    <span class="n">auVar2</span><span class="p">.</span><span class="n">_8_8_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">auVar2</span><span class="p">.</span><span class="n">_0_8_</span> <span class="o">=</span> <span class="n">_DAT_1</span> <span class="o">/</span> <span class="mi">10000</span><span class="p">;</span>
    <span class="n">lVar6</span> <span class="o">=</span> <span class="n">SUB168</span><span class="p">(</span><span class="n">ZEXT816</span><span class="p">(</span><span class="mh">0x624dd2f1a9fbe77</span><span class="p">)</span> <span class="o">*</span> <span class="n">auVar2</span><span class="p">,</span><span class="mi">8</span><span class="p">);</span>
    <span class="n">IppPathSetStartOrContinueTimer</span>
              <span class="p">(</span><span class="n">lVar1</span><span class="p">,</span><span class="n">lVar6</span> <span class="o">+</span> <span class="p">(</span><span class="n">_DAT_1</span> <span class="o">/</span> <span class="mi">10000</span> <span class="o">-</span> <span class="n">lVar6</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">8</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Full decompilation of <code class="language-plaintext highlighter-rouge">Feature_411806010__private_IsEnabledDeviceUsage</code> after the patch:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ulonglong</span> <span class="nf">Feature_411806010__private_IsEnabledDeviceUsage</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>

<span class="p">{</span>
  <span class="n">ulonglong</span> <span class="n">uVar1</span><span class="p">;</span>
  
  <span class="k">if</span> <span class="p">((</span><span class="n">Feature_411806010__private_featureState</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">uVar1</span> <span class="o">=</span> <span class="n">Feature_411806010__private_IsEnabledFallback</span><span class="p">(</span><span class="n">Feature_411806010__private_featureState</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="n">uVar1</span> <span class="o">=</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)(</span><span class="n">Feature_411806010__private_featureState</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">uVar1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>tzvironen</name></author><summary type="html"><![CDATA[A remotely reachable use-after-free in the Windows kernel TCP/IP driver tcpip.sys, where a forward-path cache entry becomes hash-table-visible before it is marked valid, letting a concurrent lookup observe and free a half-initialized entry. Microsoft's patch reorders the valid-bit assignment under a]]></summary></entry><entry><title type="html">CVE-2026-42904: Heap-Based Buffer Overflow in the Windows TCP/IP FSE Message Reassembly Path</title><link href="https://cvepatchbook.com/reports/cve-2026-42904-tcpip-elevation-privilege/" rel="alternate" type="text/html" title="CVE-2026-42904: Heap-Based Buffer Overflow in the Windows TCP/IP FSE Message Reassembly Path" /><published>2026-06-09T00:00:00+00:00</published><updated>2026-06-09T00:00:00+00:00</updated><id>https://cvepatchbook.com/reports/cve-2026-42904-tcpip-elevation-privilege</id><content type="html" xml:base="https://cvepatchbook.com/reports/cve-2026-42904-tcpip-elevation-privilege/"><![CDATA[<h1 id="cve-2026-42904-heap-based-buffer-overflow-in-the-windows-tcpip-fse-message-reassembly-path">CVE-2026-42904: Heap-Based Buffer Overflow in the Windows TCP/IP FSE Message Reassembly Path</h1>

<ul>
  <li><strong>Affected binary:</strong> <code class="language-plaintext highlighter-rouge">tcpip.sys</code> 10.0.19041.7291 → 10.0.19041.7417</li>
  <li><strong>CVE:</strong> CVE-2026-42904</li>
  <li><strong>Patch date:</strong> 2026-06-09</li>
  <li><strong>CVSS:</strong> 9.6</li>
  <li><strong>Class:</strong> Buffer overflow</li>
  <li><strong>Patch KB:</strong> KB5094127</li>
</ul>

<h2 id="tldr">TL;DR</h2>

<p><code class="language-plaintext highlighter-rouge">tcpip.sys</code> reassembles length-prefixed FSE messages arriving on a kernel (WSK) receive path into a fixed 0x400-byte scratch buffer that lives inside a per-connection context. <code class="language-plaintext highlighter-rouge">FseProcessIncomingMessages</code> decides, on each incoming chunk, how many bytes to <code class="language-plaintext highlighter-rouge">memmove</code> into that buffer while it waits for a partial message to complete. In the pre-patch code the only sanity checks on the copy length were a lower bound (<code class="language-plaintext highlighter-rouge">0x21</code>) and a comparison against the <em>declared</em> message length — nothing ever verified that the number of bytes buffered stayed within the 0x400-byte buffer. An adjacent-network attacker who fragments a message so that the incoming payload is smaller than its declared length causes the whole incoming chunk to be copied in unbounded, producing a controlled heap overflow. The patch introduces <code class="language-plaintext highlighter-rouge">RtlUIntAdd</code>-checked accumulation and hard <code class="language-plaintext highlighter-rouge">0x400</code> caps on both the declared length and the copy size, and gates the new behavior behind <code class="language-plaintext highlighter-rouge">Feature_98821435</code>.</p>

<h2 id="background">Background</h2>

<p>The <code class="language-plaintext highlighter-rouge">Fse*</code> family of routines in <code class="language-plaintext highlighter-rouge">tcpip.sys</code> implements a framed message layer on top of a kernel-mode socket. <code class="language-plaintext highlighter-rouge">FseWskReceiveIrpCompletionRoutine</code> fires when a WSK receive IRP completes, and hands the freshly received buffer to <code class="language-plaintext highlighter-rouge">FseProcessIncomingMessages</code>. Data on the wire is a stream of self-describing messages: the first <code class="language-plaintext highlighter-rouge">uint</code> of each message (<code class="language-plaintext highlighter-rouge">*_Src</code>) is its total length, and valid messages are constrained to the range <code class="language-plaintext highlighter-rouge">[0x21, 0x400]</code> — at least 0x21 (33) bytes of header, at most 0x400 (1024) bytes total.</p>

<p>Because TCP is a byte stream, a single receive can contain several whole messages, a whole message plus a fragment, or just a fragment of one message. To handle fragments straddling receive boundaries, each connection carries a reassembly context (reached via <code class="language-plaintext highlighter-rouge">*(param_1 + 0x20) + 0xa8</code>, aliased <code class="language-plaintext highlighter-rouge">lVar1</code>). Two fields matter:</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">lVar1 + 0x88</code></strong> — a fixed <strong>0x400-byte</strong> buffer holding the bytes of a partially-received message.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">lVar1 + 0x488</code></strong> — a <code class="language-plaintext highlighter-rouge">uint</code> count of how many bytes are currently held in that buffer.</li>
</ul>

<p>The routine’s job on each call is to drain complete messages (dispatching each to <code class="language-plaintext highlighter-rouge">FseProcessIncomingMessage</code>) and to stash any trailing partial message into <code class="language-plaintext highlighter-rouge">+0x88</code>, updating the <code class="language-plaintext highlighter-rouge">+0x488</code> count, so the next receive can continue where this one left off. When fewer than 4 bytes are buffered the length prefix itself is split across receives, so the code reconstructs a 0x20-byte header in a stack scratch buffer (<code class="language-plaintext highlighter-rouge">local_68</code>/<code class="language-plaintext highlighter-rouge">local_60</code>) to recover the declared length before deciding how much to copy.</p>

<h2 id="root-cause">Root Cause</h2>

<p>The defect is the complete absence of an upper bound tying the amount copied into <code class="language-plaintext highlighter-rouge">+0x88</code> to the buffer’s actual 0x400-byte size. Consider the “nothing buffered yet” path (<code class="language-plaintext highlighter-rouge">*(lVar1 + 0x488) == 0</code>, label <code class="language-plaintext highlighter-rouge">LAB_0</code>) in the pre-patch decompilation:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">uVar5</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">_Size</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="n">uVar5</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">uVar5</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">_Size</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">((</span><span class="n">uVar5</span> <span class="o">&lt;</span> <span class="mh">0x21</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">uVar5</span> <span class="o">&lt;</span> <span class="o">*</span><span class="n">_Src</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">),</span> <span class="n">_Src</span><span class="p">,</span> <span class="n">_Size</span><span class="p">);</span>   <span class="c1">// &lt;-- unbounded</span>
        <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="n">uVar5</span><span class="p">;</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">FseProcessIncomingMessage</span><span class="p">(</span><span class="n">lVar1</span><span class="p">,</span> <span class="n">_Src</span><span class="p">);</span>
    <span class="n">uVar4</span> <span class="o">=</span> <span class="o">*</span><span class="n">_Src</span><span class="p">;</span>
    <span class="n">_Src</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Src</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar4</span><span class="p">);</span>
    <span class="n">uVar5</span> <span class="o">=</span> <span class="n">uVar5</span> <span class="o">-</span> <span class="n">uVar4</span><span class="p">;</span>
    <span class="n">_Size</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">uVar5</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">_Size</code>/<code class="language-plaintext highlighter-rouge">uVar5</code> here is the number of bytes <em>remaining in the current receive</em>. The loop dispatches complete messages, but the moment the remaining data is smaller than the declared message length (<code class="language-plaintext highlighter-rouge">uVar5 &lt; *_Src</code>), it treats the remainder as a partial message and buffers <strong>all of it</strong> with <code class="language-plaintext highlighter-rouge">memmove((void *)(lVar1 + 0x88), _Src, _Size)</code>. The guard is <code class="language-plaintext highlighter-rouge">(uVar5 &lt; 0x21) || (uVar5 &lt; *_Src)</code> — a <em>lower</em> bound and a “does this complete a message?” test. Neither caps <code class="language-plaintext highlighter-rouge">_Size</code> at 0x400.</p>

<p>An attacker controls both operands. <code class="language-plaintext highlighter-rouge">*_Src</code> is the first four bytes of the attacker’s data, so setting it to a large value (say <code class="language-plaintext highlighter-rouge">0xFFFFFFFF</code>) forces the <code class="language-plaintext highlighter-rouge">uVar5 &lt; *_Src</code> branch for any realistic receive. <code class="language-plaintext highlighter-rouge">_Size</code> is the size of the payload the attacker sent. Send a single chunk larger than 0x400 with an oversized length prefix and <code class="language-plaintext highlighter-rouge">memmove</code> writes <code class="language-plaintext highlighter-rouge">_Size</code> bytes into the 1024-byte buffer at <code class="language-plaintext highlighter-rouge">+0x88</code>, running straight off the end into whatever the heap allocation places after the reassembly context.</p>

<p>The same structural flaw exists in the “bytes already buffered” branches. When 4 or more bytes are buffered the declared length is read straight from the buffer (<code class="language-plaintext highlighter-rouge">iVar6 = *(int *)(lVar1 + 0x88)</code>) and validated only against the range <code class="language-plaintext highlighter-rouge">[0x21, 0x400]</code> via <code class="language-plaintext highlighter-rouge">0x3df &lt; iVar6 - 0x21U</code>. When the incoming chunk does not complete the message, the code again does:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">memmove</span><span class="p">(</span><span class="n">pvVar2</span><span class="p">,</span> <span class="n">_Src</span><span class="p">,</span> <span class="n">_Size</span><span class="p">);</span>                       <span class="c1">// pvVar2 = lVar1 + 0x88 + uVar4</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">+</span> <span class="n">uVar5</span><span class="p">;</span>
</code></pre></div></div>

<p>The destination is <code class="language-plaintext highlighter-rouge">+0x88 + count</code>, and the length is the full incoming <code class="language-plaintext highlighter-rouge">_Size</code>, with the count then advanced by <code class="language-plaintext highlighter-rouge">uVar5</code>. There is no check that <code class="language-plaintext highlighter-rouge">count + _Size &lt;= 0x400</code>. The only near-bound in the whole function was <code class="language-plaintext highlighter-rouge">uVar5 &lt; 0x20 - uVar4</code> in the <code class="language-plaintext highlighter-rouge">count &lt; 4</code> sub-case — and note that constant is <code class="language-plaintext highlighter-rouge">0x20</code>, the <em>header</em> reconstruction size, not <code class="language-plaintext highlighter-rouge">0x400</code>, so it never protected the message body copy. Both the declared length validation and the running count are <code class="language-plaintext highlighter-rouge">int</code>/<code class="language-plaintext highlighter-rouge">uint</code> and are added without overflow checking, so even the range check on the declared length can be bypassed by arranging the accumulation to wrap.</p>

<h2 id="the-patch">The Patch</h2>

<p>The post-patch <code class="language-plaintext highlighter-rouge">FseProcessIncomingMessages</code> grows from 765 to 1158 bytes and pulls in two new callees: <code class="language-plaintext highlighter-rouge">RtlUIntAdd</code> for overflow-checked addition and <code class="language-plaintext highlighter-rouge">Feature_98821435__private_IsEnabledDeviceUsage</code> as the gate for the new logic. Every copy path now enforces the 0x400 ceiling.</p>

<p><strong>The <code class="language-plaintext highlighter-rouge">count == 0</code> drain loop (<code class="language-plaintext highlighter-rouge">LAB_1</code>).</strong> The unbounded buffer-the-remainder case is replaced with an explicit cap:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">uVar8</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">_Size_00</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">uVar8</span> <span class="o">&lt;</span> <span class="mh">0x21</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">_Src</span> <span class="o">&lt;=</span> <span class="n">uVar8</span><span class="p">)</span> <span class="p">{</span>              <span class="c1">// message fully present -&gt; dispatch</span>
        <span class="n">FseProcessIncomingMessage</span><span class="p">(</span><span class="n">lVar1</span><span class="p">,</span> <span class="n">_Src</span><span class="p">);</span>
        <span class="n">uVar6</span> <span class="o">=</span> <span class="o">*</span><span class="n">_Src</span><span class="p">;</span>
        <span class="n">_Src</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Src</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar6</span><span class="p">);</span>
        <span class="n">uVar8</span> <span class="o">=</span> <span class="n">uVar8</span> <span class="o">-</span> <span class="n">uVar6</span><span class="p">;</span>
        <span class="n">_Size_00</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">uVar8</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">uVar8</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">goto</span> <span class="n">LAB_2</span><span class="p">;</span>
        <span class="k">goto</span> <span class="n">LAB_1</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">iVar3</span> <span class="o">=</span> <span class="n">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">();</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">iVar3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">goto</span> <span class="n">LAB_3</span><span class="p">;</span>         <span class="c1">// feature off: legacy copy</span>
    <span class="n">uVar6</span> <span class="o">=</span> <span class="o">*</span><span class="n">_Src</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">((</span><span class="mh">0x400</span> <span class="o">&lt;</span> <span class="n">uVar6</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="mh">0x400</span> <span class="o">&lt;</span> <span class="n">uVar8</span><span class="p">))</span> <span class="p">{</span>   <span class="c1">// NEW: hard caps</span>
        <span class="cm">/* WPP trace 0x30, then */</span> <span class="k">goto</span> <span class="n">LAB_4</span><span class="p">;</span>   <span class="c1">// LAB_4 -&gt; return 0</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="n">LAB_3</span><span class="o">:</span>
<span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">),</span> <span class="n">_Src</span><span class="p">,</span> <span class="n">_Size_00</span><span class="p">);</span>
<span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="n">uVar8</span><span class="p">;</span>
</code></pre></div></div>

<p>When the feature is enabled and a partial message is about to be buffered, the code now rejects the input (<code class="language-plaintext highlighter-rouge">return 0</code>, after emitting a WPP trace with id <code class="language-plaintext highlighter-rouge">0x30</code>) if <em>either</em> the declared length <code class="language-plaintext highlighter-rouge">*_Src</code> <em>or</em> the remaining size <code class="language-plaintext highlighter-rouge">uVar8</code> exceeds 0x400. Since neither the buffer offset (0) plus a ≤0x400 copy can exceed the 0x400 buffer, the overflow is closed.</p>

<p><strong>The <code class="language-plaintext highlighter-rouge">count &lt; 4</code> append path.</strong> Here the declared length isn’t yet known in full, so the running total is what must be bounded. The patch inserts an overflow-checked add before the copy:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">uVar8</span> <span class="o">&lt;</span> <span class="n">uVar6</span><span class="p">)</span> <span class="p">{</span>                              <span class="c1">// uVar6 = 0x20 - count</span>
    <span class="n">iVar3</span> <span class="o">=</span> <span class="n">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">();</span>
    <span class="n">uVar4</span> <span class="o">=</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">iVar3</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">local_68</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">iVar3</span> <span class="o">=</span> <span class="n">RtlUIntAdd</span><span class="p">(</span><span class="n">uVar4</span><span class="p">,</span> <span class="n">_Size_00</span><span class="p">,</span> <span class="n">local_68</span><span class="p">);</span>   <span class="c1">// count + incoming</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">iVar3</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="mh">0x400</span> <span class="o">&lt;</span> <span class="n">local_68</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span> <span class="p">{</span>      <span class="c1">// overflow OR &gt; 0x400</span>
            <span class="cm">/* WPP trace 0x29 / 0x2d, then */</span> <span class="k">goto</span> <span class="n">LAB_4</span><span class="p">;</span> <span class="c1">// return 0</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span> <span class="o">+</span> <span class="n">uVar4</span><span class="p">),</span> <span class="n">_Src</span><span class="p">,</span> <span class="n">_Size_00</span><span class="p">);</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">+</span> <span class="n">uVar8</span><span class="p">;</span>
    <span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">RtlUIntAdd(count, incoming, &amp;sum)</code> returns a negative <code class="language-plaintext highlighter-rouge">NTSTATUS</code> on 32-bit wraparound, and the code additionally rejects <code class="language-plaintext highlighter-rouge">sum &gt; 0x400</code>. Only if <code class="language-plaintext highlighter-rouge">count + incoming</code> both fits in a <code class="language-plaintext highlighter-rouge">uint</code> <em>and</em> stays inside the buffer does the <code class="language-plaintext highlighter-rouge">memmove</code> at <code class="language-plaintext highlighter-rouge">+0x88 + count</code> proceed. The same guarded pattern is duplicated in the reconstructed-header branch (after the two <code class="language-plaintext highlighter-rouge">memmove</code>s into the <code class="language-plaintext highlighter-rouge">local_60</code> scratch header that recover <code class="language-plaintext highlighter-rouge">local_60[0]</code>, the declared length) and in the <code class="language-plaintext highlighter-rouge">count &gt;= 4</code> branch, where the declared length is re-read from the buffer and again validated against <code class="language-plaintext highlighter-rouge">[0x21, 0x400]</code> (<code class="language-plaintext highlighter-rouge">iVar3 - 0x21U &lt; 0x3e0</code>) before the completing copy at <code class="language-plaintext highlighter-rouge">LAB_11</code>/<code class="language-plaintext highlighter-rouge">LAB_10</code>.</p>

<p><strong>Feature gating.</strong> Every new check is wrapped in <code class="language-plaintext highlighter-rouge">Feature_98821435__private_IsEnabledDeviceUsage()</code>. When it returns zero the function falls through to the legacy code paths (<code class="language-plaintext highlighter-rouge">goto LAB_3</code>, <code class="language-plaintext highlighter-rouge">goto LAB_8</code>, <code class="language-plaintext highlighter-rouge">goto LAB_11</code>) that retain only the old range check; when it returns non-zero the <code class="language-plaintext highlighter-rouge">RtlUIntAdd</code> / <code class="language-plaintext highlighter-rouge">0x400</code> logic runs. The co-patched gate helper itself is trivial:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ulonglong</span> <span class="nf">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">((</span><span class="n">Feature_98821435__private_featureState</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">Feature_98821435__private_IsEnabledFallback</span><span class="p">(</span>
                   <span class="n">Feature_98821435__private_featureState</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)(</span><span class="n">Feature_98821435__private_featureState</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This is the standard Velocity/CFR staged-rollout pattern: bit <code class="language-plaintext highlighter-rouge">0x10</code> of the cached feature state selects between a locally-cached decision (bit <code class="language-plaintext highlighter-rouge">0</code>) and the <code class="language-plaintext highlighter-rouge">IsEnabledFallback</code> slow path. It is the switch that arms the entire overflow fix, which is why it is included in the same patch even though it contains no security logic of its own. Note that once fully rolled out (feature forced on) the <code class="language-plaintext highlighter-rouge">iVar == 0</code> legacy branches become dead code.</p>

<h2 id="exploitability">Exploitability</h2>

<p>The primitive is a classic linear heap buffer overflow. The overflowed object is the per-connection reassembly context; the write starts at <code class="language-plaintext highlighter-rouge">+0x88</code> (or <code class="language-plaintext highlighter-rouge">+0x88 + count</code>) and runs past the buffer’s 0x400 boundary. Both the <em>length</em> and the <em>contents</em> of the overflow are attacker-controlled: the length is the size of the fragment the attacker chooses to send (bounded only by MTU/receive sizing pre-patch), and the contents are the raw bytes on the wire. That combination — controlled overflow length plus controlled overflow data adjacent to a kernel pool allocation — is a strong foundation for corrupting an adjacent object’s header or a neighboring pointer, the usual route from pool overflow to arbitrary write and ultimately kernel code execution.</p>

<p>Triggering is straightforward and requires no authentication: the attacker sends a fragment whose 4-byte length prefix advertises a message larger than the data actually delivered in that receive (<code class="language-plaintext highlighter-rouge">uVar5 &lt; *_Src</code>), and whose payload exceeds 0x400 bytes. The <code class="language-plaintext highlighter-rouge">count == 0</code> path takes the bait on the very first fragment — there is no race and no need to win a timing window, because the vulnerable <code class="language-plaintext highlighter-rouge">memmove</code> executes synchronously in the WSK receive completion. The <code class="language-plaintext highlighter-rouge">count</code>-nonzero paths give a second, incremental variant where the attacker dribbles bytes across several segments to push the running <code class="language-plaintext highlighter-rouge">+0x488</code> count past 0x400, which is useful for shaping exactly where the write lands.</p>

<p>The CVSS 9.6 / “adjacent network” scoping reflects that the FSE message layer is reachable over the link-local network rather than the full Internet, and the “low complexity” despite the elaborate branching is accurate: the attacker never has to reason about the reassembly state machine’s happy path. They only need one mismatched length prefix and an oversized payload, both of which are unauthenticated bytes on the wire. The patch’s <code class="language-plaintext highlighter-rouge">0x400</code> caps and <code class="language-plaintext highlighter-rouge">RtlUIntAdd</code> guards neutralize every path that previously let the copy size or the accumulated count escape the buffer bound.</p>

<h2 id="pre-patch-functions">Pre patch functions</h2>

<p>Full decompilation of <code class="language-plaintext highlighter-rouge">FseProcessIncomingMessages</code> before the patch:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* WARNING: Function: __security_check_cookie replaced with injection: security_check_cookie */</span>

<span class="n">undefined8</span> <span class="nf">FseProcessIncomingMessages</span><span class="p">(</span><span class="n">longlong</span> <span class="n">param_1</span><span class="p">,</span><span class="n">longlong</span> <span class="n">param_2</span><span class="p">)</span>

<span class="p">{</span>
  <span class="n">longlong</span> <span class="n">lVar1</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">pvVar2</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">uVar3</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">uVar4</span><span class="p">;</span>
  <span class="n">uint</span> <span class="o">*</span><span class="n">_Src</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">uVar5</span><span class="p">;</span>
  <span class="kt">size_t</span> <span class="n">_Size</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">iVar6</span><span class="p">;</span>
  <span class="n">ulonglong</span> <span class="n">_Size_00</span><span class="p">;</span>
  <span class="n">undefined1</span> <span class="n">auStack_a8</span> <span class="p">[</span><span class="mi">32</span><span class="p">];</span>
  <span class="n">uint</span> <span class="n">local_88</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">local_68</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">uStack_60</span><span class="p">;</span>
  <span class="n">ulonglong</span> <span class="n">local_48</span><span class="p">;</span>
  
  <span class="n">local_48</span> <span class="o">=</span> <span class="n">__security_cookie</span> <span class="o">^</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">auStack_a8</span><span class="p">;</span>
  <span class="n">_Src</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">**</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x30</span><span class="p">);</span>
  <span class="n">uVar5</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_2</span> <span class="o">+</span> <span class="mh">0x38</span><span class="p">);</span>
  <span class="n">_Size</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">uVar5</span><span class="p">;</span>
  <span class="n">lVar1</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x20</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0xa8</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
     <span class="p">(</span><span class="mi">4</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
    <span class="n">local_88</span> <span class="o">=</span> <span class="n">uVar5</span><span class="p">;</span>
    <span class="n">WPP_SF__guid_d</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">),</span><span class="mh">0x24</span><span class="p">,</span>
                   <span class="o">&amp;</span><span class="n">WPP_ac8b62d4254a334b4d08bba9079ab535_Traceguids</span><span class="p">,</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="n">uVar4</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">uVar4</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">LAB_0:</span>
    <span class="n">uVar5</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">_Size</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">uVar5</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">uVar5</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">_Size</span><span class="p">;</span>
      <span class="k">if</span> <span class="p">((</span><span class="n">uVar5</span> <span class="o">&lt;</span> <span class="mh">0x21</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">uVar5</span> <span class="o">&lt;</span> <span class="o">*</span><span class="n">_Src</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">),</span><span class="n">_Src</span><span class="p">,</span><span class="n">_Size</span><span class="p">);</span>
        <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="n">uVar5</span><span class="p">;</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="n">FseProcessIncomingMessage</span><span class="p">(</span><span class="n">lVar1</span><span class="p">,</span><span class="n">_Src</span><span class="p">);</span>
      <span class="n">uVar4</span> <span class="o">=</span> <span class="o">*</span><span class="n">_Src</span><span class="p">;</span>
      <span class="n">_Src</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Src</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar4</span><span class="p">);</span>
      <span class="n">uVar5</span> <span class="o">=</span> <span class="n">uVar5</span> <span class="o">-</span> <span class="n">uVar4</span><span class="p">;</span>
      <span class="n">_Size</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">uVar5</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
       <span class="p">(</span><span class="mi">4</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
      <span class="n">WPP_SF__guid_</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">),</span><span class="mh">0x25</span><span class="p">,</span>
                    <span class="o">&amp;</span><span class="n">WPP_ac8b62d4254a334b4d08bba9079ab535_Traceguids</span><span class="p">,</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">);</span>
      <span class="n">uVar4</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">uVar4</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">_Size_00</span> <span class="o">=</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar4</span><span class="p">;</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">uVar5</span> <span class="o">&lt;</span> <span class="mh">0x20</span> <span class="o">-</span> <span class="n">uVar4</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span> <span class="o">+</span> <span class="n">_Size_00</span><span class="p">),</span><span class="n">_Src</span><span class="p">,</span><span class="n">_Size</span><span class="p">);</span>
        <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">+</span> <span class="n">uVar5</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="p">{</span>
          <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
          <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">uVar3</span> <span class="o">=</span> <span class="mh">0x28</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="k">else</span> <span class="p">{</span>
        <span class="n">local_68</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">uStack_60</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">memmove</span><span class="p">(</span><span class="o">&amp;</span><span class="n">local_68</span><span class="p">,(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">),</span><span class="n">_Size_00</span><span class="p">);</span>
        <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="o">&amp;</span><span class="n">local_68</span> <span class="o">+</span> <span class="n">_Size_00</span><span class="p">),</span><span class="n">_Src</span><span class="p">,(</span><span class="n">ulonglong</span><span class="p">)(</span><span class="mh">0x20</span> <span class="o">-</span> <span class="n">uVar4</span><span class="p">));</span>
        <span class="n">iVar6</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">local_68</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="mh">0x3df</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">local_68</span> <span class="o">-</span> <span class="mh">0x21U</span><span class="p">)</span> <span class="p">{</span>
          <span class="k">if</span> <span class="p">((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
          <span class="p">}</span>
          <span class="k">if</span> <span class="p">((</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
          <span class="p">}</span>
          <span class="n">uVar3</span> <span class="o">=</span> <span class="mh">0x29</span><span class="p">;</span>
          <span class="n">local_88</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">local_68</span><span class="p">;</span>
          <span class="k">goto</span> <span class="n">LAB_1</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">pvVar2</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span> <span class="o">+</span> <span class="n">_Size_00</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">local_68</span> <span class="o">-</span> <span class="n">uVar4</span> <span class="o">&lt;=</span> <span class="n">uVar5</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">memmove</span><span class="p">(</span><span class="n">pvVar2</span><span class="p">,</span><span class="n">_Src</span><span class="p">,(</span><span class="n">ulonglong</span><span class="p">)((</span><span class="kt">int</span><span class="p">)</span><span class="n">local_68</span> <span class="o">-</span> <span class="n">uVar4</span><span class="p">));</span>
          <span class="k">goto</span> <span class="n">LAB_2</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">memmove</span><span class="p">(</span><span class="n">pvVar2</span><span class="p">,</span><span class="n">_Src</span><span class="p">,</span><span class="n">_Size</span><span class="p">);</span>
        <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">+</span> <span class="n">uVar5</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="p">{</span>
          <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
          <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">uVar3</span> <span class="o">=</span> <span class="mh">0x2a</span><span class="p">;</span>
      <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
      <span class="n">iVar6</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="mh">0x3df</span> <span class="o">&lt;</span> <span class="n">iVar6</span> <span class="o">-</span> <span class="mh">0x21U</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="p">{</span>
          <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
          <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">uVar3</span> <span class="o">=</span> <span class="mh">0x26</span><span class="p">;</span>
        <span class="n">local_88</span> <span class="o">=</span> <span class="n">iVar6</span><span class="p">;</span>
<span class="nl">LAB_1:</span>
        <span class="n">WPP_SF__guid_DDD</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">),</span><span class="n">uVar3</span><span class="p">);</span>
        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="n">pvVar2</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar4</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">iVar6</span> <span class="o">-</span> <span class="n">uVar4</span> <span class="o">&lt;=</span> <span class="n">uVar5</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">memmove</span><span class="p">(</span><span class="n">pvVar2</span><span class="p">,</span><span class="n">_Src</span><span class="p">,(</span><span class="n">ulonglong</span><span class="p">)(</span><span class="n">iVar6</span> <span class="o">-</span> <span class="n">uVar4</span><span class="p">));</span>
<span class="nl">LAB_2:</span>
        <span class="n">_Src</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Src</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)(</span><span class="n">uint</span><span class="p">)(</span><span class="n">iVar6</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)));</span>
        <span class="n">_Size</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)(</span><span class="n">uVar5</span> <span class="o">+</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">-</span> <span class="n">iVar6</span><span class="p">));</span>
        <span class="n">FseProcessIncomingMessage</span><span class="p">(</span><span class="n">lVar1</span><span class="p">,</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">,</span><span class="n">iVar6</span><span class="p">);</span>
        <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">goto</span> <span class="n">LAB_0</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="n">memmove</span><span class="p">(</span><span class="n">pvVar2</span><span class="p">,</span><span class="n">_Src</span><span class="p">,</span><span class="n">_Size</span><span class="p">);</span>
      <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">+</span> <span class="n">uVar5</span><span class="p">;</span>
      <span class="k">if</span> <span class="p">((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="k">if</span> <span class="p">((</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="n">uVar3</span> <span class="o">=</span> <span class="mh">0x27</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">WPP_SF_</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">),</span><span class="n">uVar3</span><span class="p">,</span>
            <span class="o">&amp;</span><span class="n">WPP_ac8b62d4254a334b4d08bba9079ab535_Traceguids</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="post-patch-functions">Post patch functions</h2>

<p>Full decompilation of <code class="language-plaintext highlighter-rouge">FseProcessIncomingMessages</code> after the patch:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* WARNING: Function: __security_check_cookie replaced with injection: security_check_cookie */</span>

<span class="n">undefined8</span> <span class="nf">FseProcessIncomingMessages</span><span class="p">(</span><span class="n">longlong</span> <span class="n">param_1</span><span class="p">,</span><span class="n">longlong</span> <span class="n">param_2</span><span class="p">)</span>

<span class="p">{</span>
  <span class="n">longlong</span> <span class="n">lVar1</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">iVar2</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">iVar3</span><span class="p">;</span>
  <span class="kt">size_t</span> <span class="n">_Size</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">_Dst</span><span class="p">;</span>
  <span class="n">ulonglong</span> <span class="n">uVar4</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">uVar5</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">uVar6</span><span class="p">;</span>
  <span class="n">undefined8</span> <span class="n">uVar7</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">uVar8</span><span class="p">;</span>
  <span class="kt">size_t</span> <span class="n">_Size_00</span><span class="p">;</span>
  <span class="n">undefined</span> <span class="o">*</span><span class="n">puVar9</span><span class="p">;</span>
  <span class="n">uint</span> <span class="o">*</span><span class="n">_Src</span><span class="p">;</span>
  <span class="n">undefined1</span> <span class="n">auStack_a8</span> <span class="p">[</span><span class="mi">32</span><span class="p">];</span>
  <span class="n">uint</span> <span class="n">local_88</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">local_68</span> <span class="p">[</span><span class="mi">2</span><span class="p">];</span>
  <span class="kt">int</span> <span class="n">local_60</span> <span class="p">[</span><span class="mi">8</span><span class="p">];</span>
  <span class="n">ulonglong</span> <span class="n">local_40</span><span class="p">;</span>
  
  <span class="n">local_40</span> <span class="o">=</span> <span class="n">__security_cookie</span> <span class="o">^</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">auStack_a8</span><span class="p">;</span>
  <span class="n">_Src</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">**</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x30</span><span class="p">);</span>
  <span class="n">uVar8</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_2</span> <span class="o">+</span> <span class="mh">0x38</span><span class="p">);</span>
  <span class="n">_Size_00</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">uVar8</span><span class="p">;</span>
  <span class="n">lVar1</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x20</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0xa8</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
     <span class="p">(</span><span class="mi">4</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
    <span class="n">local_88</span> <span class="o">=</span> <span class="n">uVar8</span><span class="p">;</span>
    <span class="n">WPP_SF__guid_d</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">),</span><span class="mh">0x24</span><span class="p">,</span>
                   <span class="o">&amp;</span><span class="n">WPP_bc8d3dbf0274335cb22dd3f8ccf775cf_Traceguids</span><span class="p">,</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="n">_Size</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">LAB_0:</span>
    <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">_Size_00</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">LAB_1:</span>
      <span class="n">uVar8</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">_Size_00</span><span class="p">;</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">uVar8</span> <span class="o">&lt;</span> <span class="mh">0x21</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">();</span>
      <span class="p">}</span>
      <span class="k">else</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">_Src</span> <span class="o">&lt;=</span> <span class="n">uVar8</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">FseProcessIncomingMessage</span><span class="p">(</span><span class="n">lVar1</span><span class="p">,</span><span class="n">_Src</span><span class="p">);</span>
          <span class="n">uVar6</span> <span class="o">=</span> <span class="o">*</span><span class="n">_Src</span><span class="p">;</span>
          <span class="n">_Src</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Src</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar6</span><span class="p">);</span>
          <span class="n">uVar8</span> <span class="o">=</span> <span class="n">uVar8</span> <span class="o">-</span> <span class="n">uVar6</span><span class="p">;</span>
          <span class="n">_Size_00</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">uVar8</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">uVar8</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">goto</span> <span class="n">LAB_2</span><span class="p">;</span>
          <span class="k">goto</span> <span class="n">LAB_1</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">iVar3</span> <span class="o">=</span> <span class="n">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">();</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">iVar3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">goto</span> <span class="n">LAB_3</span><span class="p">;</span>
        <span class="n">uVar6</span> <span class="o">=</span> <span class="o">*</span><span class="n">_Src</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">((</span><span class="mh">0x400</span> <span class="o">&lt;</span> <span class="n">uVar6</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="mh">0x400</span> <span class="o">&lt;</span> <span class="n">uVar8</span><span class="p">))</span> <span class="p">{</span>
          <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">||</span>
             <span class="p">((</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">))</span> <span class="k">goto</span> <span class="n">LAB_4</span><span class="p">;</span>
          <span class="n">uVar5</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">);</span>
          <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x30</span><span class="p">;</span>
          <span class="n">puVar9</span> <span class="o">=</span> <span class="p">(</span><span class="n">undefined</span> <span class="o">*</span><span class="p">)(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar6</span><span class="p">;</span>
          <span class="n">local_88</span> <span class="o">=</span> <span class="n">uVar6</span><span class="p">;</span>
          <span class="k">goto</span> <span class="n">LAB_5</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">}</span>
<span class="nl">LAB_3:</span>
      <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">),</span><span class="n">_Src</span><span class="p">,</span><span class="n">_Size_00</span><span class="p">);</span>
      <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="n">uVar8</span><span class="p">;</span>
    <span class="p">}</span>
<span class="nl">LAB_2:</span>
    <span class="n">uVar7</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
       <span class="p">(</span><span class="mi">4</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
      <span class="n">WPP_SF__guid_</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">),</span><span class="mh">0x25</span><span class="p">,</span>
                    <span class="o">&amp;</span><span class="n">WPP_bc8d3dbf0274335cb22dd3f8ccf775cf_Traceguids</span><span class="p">,</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">);</span>
      <span class="n">_Size</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="p">((</span><span class="n">uint</span><span class="p">)</span><span class="n">_Size</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">uVar6</span> <span class="o">=</span> <span class="mh">0x20</span> <span class="o">-</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">_Size</span><span class="p">;</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">uVar8</span> <span class="o">&lt;</span> <span class="n">uVar6</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">iVar3</span> <span class="o">=</span> <span class="n">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">();</span>
        <span class="n">uVar4</span> <span class="o">=</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">iVar3</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">local_68</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
          <span class="n">iVar3</span> <span class="o">=</span> <span class="n">RtlUIntAdd</span><span class="p">(</span><span class="n">uVar4</span><span class="p">,</span><span class="n">_Size_00</span><span class="p">,</span><span class="n">local_68</span><span class="p">);</span>
          <span class="k">if</span> <span class="p">((</span><span class="n">iVar3</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="mh">0x400</span> <span class="o">&lt;</span> <span class="n">local_68</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">||</span>
               <span class="p">((</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">))</span> <span class="k">goto</span> <span class="n">LAB_4</span><span class="p">;</span>
            <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x29</span><span class="p">;</span>
<span class="nl">LAB_6:</span>
            <span class="n">local_88</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">uVar4</span> <span class="o">+</span> <span class="n">uVar8</span><span class="p">;</span>
            <span class="n">uVar5</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">);</span>
            <span class="n">puVar9</span> <span class="o">=</span> <span class="n">WPP_GLOBAL_Control</span><span class="p">;</span>
<span class="nl">LAB_5:</span>
            <span class="n">WPP_SF__guid_DD</span><span class="p">(</span><span class="n">uVar5</span><span class="p">,</span><span class="n">uVar7</span><span class="p">,</span><span class="n">puVar9</span><span class="p">,</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">);</span>
            <span class="k">goto</span> <span class="n">LAB_4</span><span class="p">;</span>
          <span class="p">}</span>
        <span class="p">}</span>
        <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span> <span class="o">+</span> <span class="n">uVar4</span><span class="p">),</span><span class="n">_Src</span><span class="p">,</span><span class="n">_Size_00</span><span class="p">);</span>
        <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">+</span> <span class="n">uVar8</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
           <span class="p">(</span><span class="mi">4</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
          <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x2a</span><span class="p">;</span>
<span class="nl">LAB_7:</span>
          <span class="n">WPP_SF_</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">),</span><span class="n">uVar7</span><span class="p">,</span>
                  <span class="o">&amp;</span><span class="n">WPP_bc8d3dbf0274335cb22dd3f8ccf775cf_Traceguids</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">goto</span> <span class="n">LAB_2</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="n">local_60</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
      <span class="n">local_60</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
      <span class="n">local_60</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
      <span class="n">local_60</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
      <span class="n">memmove</span><span class="p">(</span><span class="n">local_60</span><span class="p">,(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">),</span><span class="n">_Size</span><span class="p">);</span>
      <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">local_60</span> <span class="o">+</span> <span class="n">_Size</span><span class="p">),</span><span class="n">_Src</span><span class="p">,(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar6</span><span class="p">);</span>
      <span class="n">iVar2</span> <span class="o">=</span> <span class="n">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">();</span>
      <span class="n">iVar3</span> <span class="o">=</span> <span class="n">local_60</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">iVar2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">local_60</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="mh">0x21U</span> <span class="o">&lt;</span> <span class="mh">0x3e0</span><span class="p">)</span> <span class="k">goto</span> <span class="n">LAB_8</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
           <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
          <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x2c</span><span class="p">;</span>
          <span class="n">local_88</span> <span class="o">=</span> <span class="n">local_60</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
          <span class="k">goto</span> <span class="n">LAB_9</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">}</span>
      <span class="k">else</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">local_60</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="mh">0x21U</span> <span class="o">&lt;</span> <span class="mh">0x3e0</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">LAB_8:</span>
          <span class="n">uVar6</span> <span class="o">=</span> <span class="n">local_60</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">);</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">uVar8</span> <span class="o">&lt;</span> <span class="n">uVar6</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">iVar3</span> <span class="o">=</span> <span class="n">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">();</span>
            <span class="n">uVar4</span> <span class="o">=</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">iVar3</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
              <span class="n">local_68</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
              <span class="n">iVar3</span> <span class="o">=</span> <span class="n">RtlUIntAdd</span><span class="p">(</span><span class="n">uVar4</span><span class="p">,</span><span class="n">_Size_00</span><span class="p">,</span><span class="n">local_68</span><span class="p">);</span>
              <span class="k">if</span> <span class="p">((</span><span class="n">iVar3</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="mh">0x400</span> <span class="o">&lt;</span> <span class="n">local_68</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span> <span class="p">{</span>
                <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
                   <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
                  <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x2d</span><span class="p">;</span>
                  <span class="k">goto</span> <span class="n">LAB_6</span><span class="p">;</span>
                <span class="p">}</span>
                <span class="k">goto</span> <span class="n">LAB_4</span><span class="p">;</span>
              <span class="p">}</span>
            <span class="p">}</span>
            <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span> <span class="o">+</span> <span class="n">uVar4</span><span class="p">),</span><span class="n">_Src</span><span class="p">,</span><span class="n">_Size_00</span><span class="p">);</span>
            <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">+</span> <span class="n">uVar8</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
               <span class="p">(</span><span class="mi">4</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
              <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x2e</span><span class="p">;</span>
              <span class="k">goto</span> <span class="n">LAB_7</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="k">goto</span> <span class="n">LAB_2</span><span class="p">;</span>
          <span class="p">}</span>
          <span class="n">memmove</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)),</span><span class="n">_Src</span><span class="p">,(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar6</span>
                 <span class="p">);</span>
          <span class="k">goto</span> <span class="n">LAB_10</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
           <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
          <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x2b</span><span class="p">;</span>
          <span class="n">local_88</span> <span class="o">=</span> <span class="n">local_60</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
          <span class="k">goto</span> <span class="n">LAB_9</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
      <span class="n">iVar3</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">);</span>
      <span class="n">iVar2</span> <span class="o">=</span> <span class="n">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">();</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">iVar2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">iVar3</span> <span class="o">-</span> <span class="mh">0x21U</span> <span class="o">&lt;</span> <span class="mh">0x3e0</span><span class="p">)</span> <span class="k">goto</span> <span class="n">LAB_11</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
           <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
          <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x27</span><span class="p">;</span>
          <span class="n">local_88</span> <span class="o">=</span> <span class="n">iVar3</span><span class="p">;</span>
          <span class="k">goto</span> <span class="n">LAB_9</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">}</span>
      <span class="k">else</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">iVar3</span> <span class="o">-</span> <span class="mh">0x21U</span> <span class="o">&lt;</span> <span class="mh">0x3e0</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">LAB_11:</span>
          <span class="n">_Dst</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">));</span>
          <span class="n">uVar6</span> <span class="o">=</span> <span class="n">iVar3</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">);</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">uVar6</span> <span class="o">&lt;=</span> <span class="n">uVar8</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">memmove</span><span class="p">(</span><span class="n">_Dst</span><span class="p">,</span><span class="n">_Src</span><span class="p">,(</span><span class="n">ulonglong</span><span class="p">)</span><span class="n">uVar6</span><span class="p">);</span>
<span class="nl">LAB_10:</span>
            <span class="n">_Src</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">_Src</span> <span class="o">+</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)(</span><span class="n">uint</span><span class="p">)(</span><span class="n">iVar3</span> <span class="o">-</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)));</span>
            <span class="n">_Size_00</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)(</span><span class="n">uVar8</span> <span class="o">+</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">-</span> <span class="n">iVar3</span><span class="p">));</span>
            <span class="n">FseProcessIncomingMessage</span><span class="p">(</span><span class="n">lVar1</span><span class="p">,</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x88</span><span class="p">,</span><span class="n">iVar3</span><span class="p">);</span>
            <span class="o">*</span><span class="p">(</span><span class="n">undefined4</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
            <span class="k">goto</span> <span class="n">LAB_0</span><span class="p">;</span>
          <span class="p">}</span>
          <span class="n">memmove</span><span class="p">(</span><span class="n">_Dst</span><span class="p">,</span><span class="n">_Src</span><span class="p">,</span><span class="n">_Size_00</span><span class="p">);</span>
          <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">lVar1</span> <span class="o">+</span> <span class="mh">0x488</span><span class="p">)</span> <span class="o">+</span> <span class="n">uVar8</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
             <span class="p">(</span><span class="mi">4</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
            <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x28</span><span class="p">;</span>
            <span class="k">goto</span> <span class="n">LAB_7</span><span class="p">;</span>
          <span class="p">}</span>
          <span class="k">goto</span> <span class="n">LAB_2</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">(((</span><span class="n">undefined</span> <span class="o">**</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">WPP_GLOBAL_Control</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
           <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span><span class="n">WPP_GLOBAL_Control</span><span class="p">[</span><span class="mh">0x29</span><span class="p">]))</span> <span class="p">{</span>
          <span class="n">uVar7</span> <span class="o">=</span> <span class="mh">0x26</span><span class="p">;</span>
          <span class="n">local_88</span> <span class="o">=</span> <span class="n">iVar3</span><span class="p">;</span>
<span class="nl">LAB_9:</span>
          <span class="n">WPP_SF__guid_DDD</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">undefined8</span> <span class="o">*</span><span class="p">)(</span><span class="n">WPP_GLOBAL_Control</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">),</span><span class="n">uVar7</span><span class="p">);</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">}</span>
<span class="nl">LAB_4:</span>
    <span class="n">uVar7</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">uVar7</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Full decompilation of <code class="language-plaintext highlighter-rouge">Feature_98821435__private_IsEnabledDeviceUsage</code> after the patch:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ulonglong</span> <span class="nf">Feature_98821435__private_IsEnabledDeviceUsage</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>

<span class="p">{</span>
  <span class="n">ulonglong</span> <span class="n">uVar1</span><span class="p">;</span>
  
  <span class="k">if</span> <span class="p">((</span><span class="n">Feature_98821435__private_featureState</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">uVar1</span> <span class="o">=</span> <span class="n">Feature_98821435__private_IsEnabledFallback</span><span class="p">(</span><span class="n">Feature_98821435__private_featureState</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="n">uVar1</span> <span class="o">=</span> <span class="p">(</span><span class="n">ulonglong</span><span class="p">)(</span><span class="n">Feature_98821435__private_featureState</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">uVar1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>tzvironen</name></author><summary type="html"><![CDATA[A missing 0x400 bound in tcpip.sys!FseProcessIncomingMessages let an adjacent-network attacker overflow the fixed-size WSK message-reassembly buffer with attacker-controlled length prefixes and payload, yielding kernel heap corruption and elevation of privilege.]]></summary></entry><entry><title type="html">CVE-2026-33827: Use-After-Free in the Windows IPv4 Source-Routing Path (Ipv4pReceiveRoutingHeader)</title><link href="https://cvepatchbook.com/reports/cve-2026-33827-tcpip-remote-code-execution/" rel="alternate" type="text/html" title="CVE-2026-33827: Use-After-Free in the Windows IPv4 Source-Routing Path (Ipv4pReceiveRoutingHeader)" /><published>2026-04-14T00:00:00+00:00</published><updated>2026-04-14T00:00:00+00:00</updated><id>https://cvepatchbook.com/reports/cve-2026-33827-tcpip-remote-code-execution</id><content type="html" xml:base="https://cvepatchbook.com/reports/cve-2026-33827-tcpip-remote-code-execution/"><![CDATA[<h1 id="cve-2026-33827-use-after-free-in-the-windows-ipv4-source-routing-path-ipv4preceiveroutingheader">CVE-2026-33827: Use-After-Free in the Windows IPv4 Source-Routing Path (Ipv4pReceiveRoutingHeader)</h1>

<ul>
  <li><strong>Affected binary:</strong> <code class="language-plaintext highlighter-rouge">tcpip.sys</code> 10.0.19041.6926 → 10.0.19041.7181</li>
  <li><strong>CVE:</strong> CVE-2026-33827</li>
  <li><strong>Patch date:</strong> 2026-04-14</li>
  <li><strong>CVSS:</strong> 8.1</li>
  <li><strong>Patch KB:</strong> KB5082052 and related</li>
</ul>

<h2 id="tldr">TL;DR</h2>

<p><code class="language-plaintext highlighter-rouge">tcpip.sys</code> processes the IPv4 Loose/Strict Source and Record Route (LSRR/SSRR) option inside <code class="language-plaintext highlighter-rouge">Ipv4pReceiveRoutingHeader</code>. When the host is configured to forward a source-routed datagram, the routine looks up an <code class="language-plaintext highlighter-rouge">IPP_PATH</code> to the next address in the route option, pulls the next hop out of it, and then clones and forwards the packet. In the vulnerable build the code dropped its reference on that path object — including calling <code class="language-plaintext highlighter-rouge">IppCleanupPathPrimitive</code> when the count reached zero — <em>immediately after</em> extracting the next hop, but then kept dereferencing the same path pointer (<code class="language-plaintext highlighter-rouge">IppGetRouteFromPath</code>, next-hop comparisons, clone construction) further down. That is a classic release-then-use, and because receive processing runs concurrently across RSS processors the last-reference drop races other holders, turning it into an exploitable use-after-free on a pool-backed network structure. The patch introduces a proper <code class="language-plaintext highlighter-rouge">IppDereferencePath</code> helper that performs the interlocked decrement plus teardown as one operation, and — gated behind <code class="language-plaintext highlighter-rouge">Feature_221233465</code> — holds the path (and route) reference for the entire lifetime of the forwarding operation, releasing it only in a unified cleanup epilogue.</p>

<h2 id="background">Background</h2>

<p>IPv4 source routing lets the sender embed a list of intermediate hops in an IP option (<code class="language-plaintext highlighter-rouge">Loose Source and Record Route</code>, type 131 / <code class="language-plaintext highlighter-rouge">Strict Source and Record Route</code>, type 137). A router that honors these options must, for each datagram, pick the next address from the option, resolve a route toward it, rewrite the option pointer, and forward the packet out toward that hop. Windows disables source-route forwarding by default, but the code path is still present and reachable when the relevant global/interface knobs are set — and the vulnerable logic is guarded by a global (<code class="language-plaintext highlighter-rouge">DAT_2 == 2</code> short-circuits it) plus the per-interface forwarding flags checked at the top of the function.</p>

<p>The unit of work in <code class="language-plaintext highlighter-rouge">Ipv4pReceiveRoutingHeader</code> is a receive-batch element (<code class="language-plaintext highlighter-rouge">param_1</code>), a large structure that carries the current NBL (<code class="language-plaintext highlighter-rouge">param_1[1]</code>), parsed header offsets, the source/destination addresses, and status fields. The interesting object for this bug is the <strong>path</strong>, <code class="language-plaintext highlighter-rouge">IPP_PATH</code>, returned indirectly through <code class="language-plaintext highlighter-rouge">IppRouteToDestinationInternal</code>. In the decompilation the path is a pointer with:</p>

<ul>
  <li>a reference count at offset <code class="language-plaintext highlighter-rouge">+0x50</code>,</li>
  <li>a “last used” timestamp field at <code class="language-plaintext highlighter-rouge">+0x54</code> (written from the global tick counter <code class="language-plaintext highlighter-rouge">_DAT_5 / 10000</code>),</li>
  <li>a cached next hop obtained via <code class="language-plaintext highlighter-rouge">IppGetNextHopFromPath</code>, and</li>
  <li>a cached route obtained via <code class="language-plaintext highlighter-rouge">IppGetRouteFromPath</code>.</li>
</ul>

<p>The <strong>next hop</strong> is a discriminated object identified by a 4-byte signature at offset 0: <code class="language-plaintext highlighter-rouge">0x616c7049</code> (<code class="language-plaintext highlighter-rouge">"Ipla"</code>, a local address) or <code class="language-plaintext highlighter-rouge">0x656e7049</code> (<code class="language-plaintext highlighter-rouge">"Ipne"</code>, a neighbor). The forwarding code takes a reference on whichever it is (<code class="language-plaintext highlighter-rouge">CarAcquireCacheAwareReference</code> for a local address, an interlocked increment for a neighbor) and later releases via <code class="language-plaintext highlighter-rouge">IppDereferenceLocalAddress</code> / <code class="language-plaintext highlighter-rouge">IppDereferenceNeighbor</code>. Paths are freed through <code class="language-plaintext highlighter-rouge">IppCleanupPathPrimitive</code>, which tears down the embedded route, next hop, and source address and returns the block to its FSB pool (<code class="language-plaintext highlighter-rouge">FsbFree</code>).</p>

<h2 id="root-cause">Root Cause</h2>

<p>In the 6926 build, once a route to the next source-route hop is resolved, the function does this (edited for clarity):</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">iVar16</span> <span class="o">=</span> <span class="n">IppRouteToDestinationInternal</span><span class="p">(</span><span class="n">local_80</span><span class="p">,</span> <span class="n">piVar3</span><span class="p">,</span> <span class="n">lVar15</span><span class="p">,</span> <span class="n">lVar10</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">iVar16</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">plVar11</span> <span class="o">=</span> <span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
    <span class="n">plVar11</span> <span class="o">=</span> <span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)</span><span class="n">IppGetNextHopFromPath</span><span class="p">(</span><span class="n">local_a0</span><span class="p">);</span>   <span class="c1">// cache next hop</span>
    <span class="c1">// stamp path "last used" time at +0x54</span>
    <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">local_a0</span> <span class="o">+</span> <span class="mh">0x54</span><span class="p">)</span> <span class="o">=</span> <span class="cm">/* current ticks */</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">local_a0</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">KeBugCheck</span><span class="p">(</span><span class="mh">0x1c</span><span class="p">);</span>                                    <span class="c1">// refcount sanity</span>
    <span class="p">}</span>
    <span class="n">LOCK</span><span class="p">();</span>
    <span class="n">piVar1</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">local_a0</span> <span class="o">+</span> <span class="mh">0x50</span><span class="p">);</span>
    <span class="n">iVar16</span> <span class="o">=</span> <span class="o">*</span><span class="n">piVar1</span><span class="p">;</span>
    <span class="o">*</span><span class="n">piVar1</span> <span class="o">=</span> <span class="o">*</span><span class="n">piVar1</span> <span class="o">+</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>                                  <span class="c1">// drop path reference</span>
    <span class="n">UNLOCK</span><span class="p">();</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">iVar16</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">IppCleanupPathPrimitive</span><span class="p">(</span><span class="n">local_a0</span><span class="p">);</span>                  <span class="c1">// ...and free it if last</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">plVar11</span> <span class="o">!=</span> <span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(((</span><span class="kt">int</span><span class="p">)</span><span class="o">*</span><span class="n">plVar11</span> <span class="o">==</span> <span class="mh">0x616c7049</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">plVar11</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">))</span> <span class="k">goto</span> <span class="n">LAB_1</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">((</span><span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0xb1</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">lVar10</span> <span class="o">=</span> <span class="n">IppGetRouteFromPath</span><span class="p">(</span><span class="n">local_a0</span><span class="p">);</span>             <span class="c1">// USE-AFTER-FREE</span>
        <span class="p">...</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">local_a0</code> is the path. The block above decrements its reference count at <code class="language-plaintext highlighter-rouge">+0x50</code> and, when that count transitions <code class="language-plaintext highlighter-rouge">1 -&gt; 0</code>, calls <code class="language-plaintext highlighter-rouge">IppCleanupPathPrimitive(local_a0)</code>, which frees the object back to its pool. Yet the very next <code class="language-plaintext highlighter-rouge">if (plVar11 != NULL)</code> branch keeps operating on <code class="language-plaintext highlighter-rouge">local_a0</code>: <code class="language-plaintext highlighter-rouge">IppGetRouteFromPath(local_a0)</code> reads the route pointer <em>out of the path it may have just freed</em>, and the broader forwarding path continues to depend on the route/next-hop state that belongs to that path.</p>

<p>Two things make this a real, exploitable defect rather than a theoretical one:</p>

<ol>
  <li>
    <p><strong>The reference being dropped is the working reference.</strong> The path here is the one produced by the route lookup on this code path; the <code class="language-plaintext highlighter-rouge">KeBugCheck(0x1c)</code> guard confirms the developers already knew hitting a zero count here is fatal. Nothing re-acquires the reference before the later uses.</p>
  </li>
  <li>
    <p><strong>Receive processing is concurrent.</strong> IPv4 receive runs on multiple RSS processors, and paths are shared, cached objects in the compartment’s path set. Another context validating, garbage-collecting (<code class="language-plaintext highlighter-rouge">IppGarbageCollectPaths</code>, <code class="language-plaintext highlighter-rouge">IppFlushPaths</code>), or otherwise dereferencing the same path can drive the count to zero in a window around this decrement. The MSRC classification — “concurrent execution using shared resource with improper synchronization” — is precisely this: the lifetime of the path spans a clone/forward sequence, but the code released it mid-sequence, so a racing releaser (or simply being the last holder) frees the block while <code class="language-plaintext highlighter-rouge">IppGetRouteFromPath</code> and the clone logic still read through it.</p>
  </li>
</ol>

<p>Because <code class="language-plaintext highlighter-rouge">IppGetRouteFromPath</code> returns <code class="language-plaintext highlighter-rouge">*(path + 0x14)</code> and the subsequent forwarding logic chases route/next-hop/interface pointers out of that freed allocation, an attacker who can reclaim the freed <code class="language-plaintext highlighter-rouge">IPP_PATH</code> pool block with controlled data steers those reads — and the reference-count manipulations on the “route” and “next hop” it hands back — into attacker-controlled memory.</p>

<h2 id="the-patch">The Patch</h2>

<p>The 7181 build restructures the whole tail of <code class="language-plaintext highlighter-rouge">Ipv4pReceiveRoutingHeader</code> around a new reference-counting helper and a feature gate. There are two code-changed functions plus a cluster of newly imported WIL/feature-staging helpers.</p>

<h3 id="ippcleanuppathprimitive--ippdereferencepath"><code class="language-plaintext highlighter-rouge">IppCleanupPathPrimitive</code> → <code class="language-plaintext highlighter-rouge">IppDereferencePath</code></h3>

<p>The old <code class="language-plaintext highlighter-rouge">IppCleanupPathPrimitive</code> (which unconditionally tore down and freed a path) is joined by a new function, <code class="language-plaintext highlighter-rouge">IppDereferencePath</code>, that folds the interlocked decrement and the sanity <code class="language-plaintext highlighter-rouge">KeBugCheck</code> <em>into</em> the teardown:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">IppDereferencePath</span><span class="p">(</span><span class="n">longlong</span> <span class="o">*</span><span class="n">param_1</span><span class="p">)</span>
<span class="p">{</span>
  <span class="c1">// stamp last-used time at +0x54</span>
  <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)((</span><span class="n">longlong</span><span class="p">)</span><span class="n">param_1</span> <span class="o">+</span> <span class="mh">0x54</span><span class="p">)</span> <span class="o">=</span> <span class="cm">/* current ticks */</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">param_1</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>          <span class="c1">// count at +0x50</span>
      <span class="n">KeBugCheck</span><span class="p">(</span><span class="mh">0x1c</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="n">LOCK</span><span class="p">();</span>
  <span class="n">lVar4</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mi">10</span><span class="p">);</span>
  <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_1</span> <span class="o">+</span> <span class="mi">10</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">lVar4</span> <span class="o">+</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
  <span class="n">UNLOCK</span><span class="p">();</span>
  <span class="n">iVar5</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">lVar4</span> <span class="o">+</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">iVar5</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="c1">// exact body of the old IppCleanupPathPrimitive:</span>
      <span class="c1">// drop route, drop local-addr/neighbor next hop, ExFreePoolWithTag, FsbFree</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">iVar5</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This is the key hygiene change: the “decrement, check, and free-if-last” dance that was open-coded inline (and misplaced) is now a single primitive that callers invoke <em>when they are actually done with the path</em>. The standalone <code class="language-plaintext highlighter-rouge">IppCleanupPathPrimitive</code> still exists for the paths that genuinely need unconditional teardown (its caller list loses only <code class="language-plaintext highlighter-rouge">Ipv4pReceiveRoutingHeader</code>), while every place that used to hand-roll the decrement now calls <code class="language-plaintext highlighter-rouge">IppDereferencePath</code> — note the new <code class="language-plaintext highlighter-rouge">IppDereferencePath</code> entries appearing in the caller lists of <code class="language-plaintext highlighter-rouge">IppDereferenceRoute</code>, <code class="language-plaintext highlighter-rouge">IppDereferenceNeighbor</code>, <code class="language-plaintext highlighter-rouge">IppDereferenceLocalAddress</code>, <code class="language-plaintext highlighter-rouge">FsbFree</code>, and <code class="language-plaintext highlighter-rouge">ExFreePoolWithTag</code>.</p>

<h3 id="ipv4preceiveroutingheader-hold-the-reference-to-the-end"><code class="language-plaintext highlighter-rouge">Ipv4pReceiveRoutingHeader</code>: hold the reference to the end</h3>

<p>In the patched routine, the early inline decrement/cleanup is gone. After <code class="language-plaintext highlighter-rouge">IppRouteToDestinationInternal</code> succeeds, the next hop is fetched and the path reference is <em>retained</em>:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pppppppiVar10</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*******</span><span class="p">)</span><span class="n">IppGetNextHopFromPath</span><span class="p">(</span><span class="n">local_b8</span><span class="p">);</span>
<span class="n">iVar15</span> <span class="o">=</span> <span class="n">Feature_221233465__private_IsEnabledDeviceUsage</span><span class="p">();</span>
<span class="n">pppppppiVar20</span> <span class="o">=</span> <span class="n">pppppppiVar18</span><span class="p">;</span>                 <span class="c1">// keep the path reference</span>
<span class="k">if</span> <span class="p">(</span><span class="n">iVar15</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">IppDereferencePath</span><span class="p">(</span><span class="n">pppppppiVar18</span><span class="p">);</span>         <span class="c1">// legacy behavior only when feature OFF</span>
<span class="p">}</span>
</code></pre></div></div>

<p>When the feature is <strong>enabled</strong>, <code class="language-plaintext highlighter-rouge">pppppppiVar20</code> keeps the live path reference and the code proceeds through the full forwarding sequence — <code class="language-plaintext highlighter-rouge">IppGetRouteFromPath(pppppppiVar20)</code>, the next-hop signature checks, <code class="language-plaintext highlighter-rouge">NetioAllocateAndReferenceCloneNetBufferList</code>, <code class="language-plaintext highlighter-rouge">RtlCopyMdlToMdl</code>, option rewrite, <code class="language-plaintext highlighter-rouge">IppCopyPacket</code>, and <code class="language-plaintext highlighter-rouge">IppForwardPackets</code> — all while the path is still referenced. Only in the shared epilogue is everything released, in order:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// drop the next hop (local addr or neighbor)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pppppppiVar10</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">pppppppiVar10</span> <span class="o">==</span> <span class="mh">0x616c7049</span><span class="p">)</span>      <span class="n">IppDereferenceLocalAddress</span><span class="p">(</span><span class="n">pppppppiVar10</span><span class="p">);</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">pppppppiVar10</span> <span class="o">==</span> <span class="mh">0x656e7049</span><span class="p">)</span> <span class="n">IppDereferenceNeighbor</span><span class="p">(</span><span class="n">pppppppiVar10</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">iVar15</span> <span class="o">=</span> <span class="n">Feature_221233465__private_IsEnabledDeviceUsage</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">iVar15</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">pppppppiVar20</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>                      <span class="c1">// now release the path</span>
        <span class="n">IppDereferencePath</span><span class="p">(</span><span class="n">pppppppiVar20</span><span class="p">);</span>
        <span class="n">local_b8</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">local_a8</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>                           <span class="c1">// and the route, once</span>
        <span class="n">IppDereferenceRoute</span><span class="p">(</span><span class="n">local_a8</span><span class="p">);</span>
        <span class="n">local_a8</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The route obtained via <code class="language-plaintext highlighter-rouge">IppGetRouteFromPath</code> is likewise cached in <code class="language-plaintext highlighter-rouge">local_a8</code> and released exactly once at the end, instead of the old pattern where the route was dereferenced inline (<code class="language-plaintext highlighter-rouge">IppDereferenceRoute(lVar10)</code>) in several branches while the path had already been dropped. The result is a single, well-defined ownership window: the path and its route are live from lookup through forward completion, and torn down together afterward — eliminating both the premature free and the double-handling of the route pointer.</p>

<h3 id="feature_221233465-gating"><code class="language-plaintext highlighter-rouge">Feature_221233465</code> gating</h3>

<p>The fix is wrapped in the WIL feature-staging machinery newly pulled into <code class="language-plaintext highlighter-rouge">tcpip.sys</code>: <code class="language-plaintext highlighter-rouge">Feature_221233465__private_IsEnabledDeviceUsage</code> (and its fallback → <code class="language-plaintext highlighter-rouge">wil_details_IsEnabledFallback</code> → <code class="language-plaintext highlighter-rouge">wil_details_FeatureStateCache_ReevaluateCachedFeatureEnabledState</code> → <code class="language-plaintext highlighter-rouge">RtlQueryFeatureConfiguration</code> / <code class="language-plaintext highlighter-rouge">ZwQueryWnfStateData</code>). Per the standard reading of these gates, <strong>adding</strong> a <code class="language-plaintext highlighter-rouge">Feature_*</code> check around new logic marks a newly staged fix: with the feature off, <code class="language-plaintext highlighter-rouge">Ipv4pReceiveRoutingHeader</code> still performs an early <code class="language-plaintext highlighter-rouge">IppDereferencePath</code> (the legacy-shaped behavior), and only with the feature on does the corrected “hold to the end” lifetime take effect. This lets Microsoft roll the corrected reference discipline out under Velocity/A-B control rather than flipping it unconditionally. The many added <code class="language-plaintext highlighter-rouge">wil_details_*</code> functions (<code class="language-plaintext highlighter-rouge">StagingConfig_Load</code>, <code class="language-plaintext highlighter-rouge">StagingConfig_QueryFeatureState</code>, <code class="language-plaintext highlighter-rouge">FeatureReporting_*</code>) are the supporting cache/telemetry plumbing for that gate, not part of the bug itself.</p>

<h2 id="exploitability">Exploitability</h2>

<p>The primitive is a <strong>use-after-free of a pool-backed <code class="language-plaintext highlighter-rouge">IPP_PATH</code></strong> driven entirely by a received IPv4 packet, giving CVSS 8.1 / “remote code execution.” Reachability:</p>

<ul>
  <li><strong>Remote, unauthenticated.</strong> The trigger is an IPv4 datagram carrying a source-route option (type 131/137) whose option header passes the parsing checks at the top of <code class="language-plaintext highlighter-rouge">Ipv4pReceiveRoutingHeader</code> (correct option length, <code class="language-plaintext highlighter-rouge">pbVar4[9] != 0x2b</code>, header length equal to <code class="language-plaintext highlighter-rouge">(*pbVar4 &amp; 0xf) &lt;&lt; 2</code>, etc.). No credentials or local access are needed — the packet just has to reach a host that honors source-route forwarding.</li>
  <li><strong>Configuration gate.</strong> The vulnerable branch requires the interface to be in a forwarding/source-routing configuration (<code class="language-plaintext highlighter-rouge">DAT_2 != 2</code>, forwarding flags set on <code class="language-plaintext highlighter-rouge">param_1</code>). Default installs disable source-route forwarding, which is the main practical mitigation and why this is 8.1 rather than a wormable 9.8; routers, gateways, ICS/appliance images, and hosts with source routing explicitly enabled are the exposed population.</li>
  <li><strong>The race window.</strong> Two ways to reach the freed state: (a) be the last reference holder so the inline <code class="language-plaintext highlighter-rouge">1 -&gt; 0</code> decrement itself frees the path and the immediately following <code class="language-plaintext highlighter-rouge">IppGetRouteFromPath</code> reads freed memory; or (b) win the concurrent race — a second receive/GC context on another RSS processor drops the path’s last reference during the window between the decrement and the later dereferences. Attackers can widen this window and improve reclamation odds by flooding source-routed packets across multiple queues (RSS spreads them by flow hash), keeping the compartment’s path set churning while grooming the FSB/pool with same-sized allocations to reclaim the freed <code class="language-plaintext highlighter-rouge">IPP_PATH</code> with controlled bytes.</li>
  <li><strong>Why it’s practical despite “high complexity.”</strong> The freed object is chased for pointer fields that the code then dereferences and reference-counts: <code class="language-plaintext highlighter-rouge">IppGetRouteFromPath</code> yields <code class="language-plaintext highlighter-rouge">path+0x14</code> (the route), the next-hop signature is read from offset 0 to decide between <code class="language-plaintext highlighter-rouge">CarAcquireCacheAwareReference</code> and an interlocked increment, and the clone path copies attacker-influenced option bytes. Controlling the reclaimed contents converts the UAF into a controlled fake-route / fake-next-hop dereference and reference-count manipulation on attacker memory — the standard on-ramp from a network-reachable kernel UAF to arbitrary write and code execution. The pre-patch <code class="language-plaintext highlighter-rouge">KeBugCheck(0x1c)</code> only catches an <em>already-zero</em> count before the decrement; it does nothing about the count reaching zero <em>at</em> the decrement or a racing releaser, which is exactly the exploited condition.</li>
</ul>

<p>The patch closes the window completely by never dropping the path (or its route) until the forwarding operation that depends on them has fully finished, and by centralizing the decrement-and-free in <code class="language-plaintext highlighter-rouge">IppDereferencePath</code> so the “free if last” transition can no longer be separated from the point where the caller relinquishes ownership.</p>]]></content><author><name>tzvironen</name></author><summary type="html"><![CDATA[A race condition in tcpip.sys's IPv4 source-route forwarding path let an unauthenticated remote attacker trigger a use-after-free on an IPP_PATH object by dropping its last reference before the forwarding code finished using it, yielding remote kernel code execution.]]></summary></entry></feed>