CVE-2024-38063 — Windows TCP/IP IPv6 Integer Underflow → Kernel Heap Overflow

Last updated: 2026-04-15
Severity: Critical (CVSS 9.8)
Component: tcpip.sys (IPv6 stack)
Bug Class: Integer Underflow → Heap-Based Buffer Overflow
Privilege Escalation: Remote → Kernel (RCE / DoS)
Patch: KB5041578, August 13 2024
Related: Tcpip Stack, Integer Overflows, Cve 2021 24086, Cve 2020 16898
Tags: kernel-mode, integer-overflow, oob-write, tcpip, aslr-bypass, remote


Vulnerability Summary

Pre-authentication, zero-click, wormable RCE/DoS in the Windows TCP/IP IPv6 stack. Any system with IPv6 enabled (default on all modern Windows) is reachable from the adjacent network or internet with no user interaction. Credited to Xiao Wei / Kunlun Lab. CVSS 9.8. Affects Windows 10, 11, Server 2008 through 2022. Patch Tuesday August 2024.

The vulnerability is a two-stage integer arithmetic flaw in tcpip.sys:

  1. Integer underflow: A 16-bit subtraction where packet_size = 0 wraps around to 0xFFD0 (65,488).
  2. Allocation/copy mismatch: The allocator uses a 16-bit overflow calculation (→ 48 bytes) while the copy operation uses the full underflowed value (65,488 bytes) → controllable kernel pool heap overflow.

Root Cause Analysis

Stage 1: Packet State Corruption via IppSendErrorList()

The vulnerable function is Ipv6pProcessOptions() in tcpip.sys. Under normal operation, malformed IPv6 extension header packets are handled by IppSendError() on a per-packet basis. However, IppSendErrorList() iterates the entire coalesced linked list and calls IppSendError() on every packet in the list — including packets that were not erroneous.

Within IppSendError(), when called with always_send_icmp = true (triggered by setting the option type > 0x80, e.g., 0x81), a code path is reached that sets packet->packet_size = 0 for all packets in the list. This corrupts the state of any fragment packets that happen to be coalesced with the malformed option packet.

// Vulnerable (pre-patch): IppSendErrorList called for entire coalesced list
IppSendErrorList(param);  // zeroes packet_size for ALL packets in list

// Fixed (post-patch): IppSendError called for the single erroneous packet
if (IsEnabledDeviceUsage_3 == 0) {
    IppSendErrorList(param);  // old path, gated behind feature flag (KIR rollback)
} else {
    IppSendError(param);      // correct path
}

The patch is a single line change in Ipv6pProcessOptions(). Microsoft retained the old code behind Feature_2660322619__private_IsEnabledDeviceUsage_3() — a Known Issue Rollback flag. If the flag is disabled (via registry or Group Policy), the vulnerability re-emerges. This is a significant residual risk.

Stage 2: Integer Underflow in Ipv6pReceiveFragment()

Once packet->packet_size = 0, subsequent fragment packets with Next Header = 44 are processed by Ipv6pReceiveFragment(). The allocation size is computed as:

; AX = LOWORD(packet->packet_size) = 0
; Subtract header size 0x30:
sub  ax, 0x30     ; AX = 0 - 0x30 = 0xFFD0 (16-bit underflow!)
; Result: fragment_size = 0xFFD0 = 65,488

The critical architectural detail: the ax register is 16-bit. The underflow is confined to 16 bits. This is convenient for the attacker: a 32-bit underflow would yield ~4GB which would cause ExAllocatePoolWithTagPriority to fail; the 16-bit underflow produces a “large but feasible” 65,488-byte value.

The underflowed fragment_size (0xFFD0) is stored in reassembly->packet_length / reassembly->fragment_size.

Stage 3: Allocation/Copy Mismatch in Ipv6pReassemblyTimeout()

IPv6 fragment reassembly state persists for 60 seconds before timing out. The timeout handler Ipv6pReassemblyTimeout() performs the actual buffer overflow:

// Allocation size calculation (16-bit arithmetic, overflows):
// fragment_list->net_buffer_length ≈ 0x38
// reassembly->packet_length = 0xFFD0
// DX = 0x38 + 0xFFD0 + 8 = 0x0010 (16-bit overflow wraps to 0x10)
// After + 0x28: allocation = 0x38 bytes ≈ 48 bytes
alloc_buf = ExAllocatePool(tiny_calculated_size);  // 48 bytes

// Copy operation uses FULL underflowed size:
memmove(alloc_buf, reassembly->payload, 0xFFD0);   // copies 65,488 bytes into 48-byte buffer!

The fragment payload is attacker-controlled, making this a controllable kernel pool overflow of ~65KB.


Exploitation Technique

Triggering Packet Coalescing

The exploit requires multiple packets to be in a coalesced linked list simultaneously when Ipv6pProcessOptions() is called. Packet coalescing is a NIC performance optimization — at high throughput, the NIC delivers multiple packets as a single interrupt/batch.

Reliable coalescing strategies:

  • Extreme NIC interrupt moderation mode: maximally batches packets (test environment; bcdedit /set debug on as workaround)
  • Single CPU target: fewer cores → less parallelism → more coalescing
  • High packet volume: flood with 2,400+ packets under normal NIC settings; 2–8 suffice under heavy-load NIC mode

Attack Packet Sequence (ynwarcs PoC)

Three packets are required in one coalesced batch:

  1. Malformed destination options — IPv6 header + Destination Options Extension Header (type 60) + invalid option with type > 0x80 (e.g., 0x81). Triggers IppSendErrorList() with always_send_icmp = true, zeroing packet_size of subsequent packets.
  2. Fragment #1 — IPv6 fragment with Next Header = 44. Gets corrupted packet_size = 0fragment_size underflows to 0xFFD0.
  3. Fragment #2 — Optional; provides attacker-controlled payload data.

Then wait 60 seconds for Ipv6pReassemblyTimeout() to fire.

PoC Code Structure (Python/Scapy)

def build_malicious_option(next_header, header_length, option_type, option_length):
    dest_options_header = 60
    options_header = struct.pack('BBBB', next_header, header_length, option_type, option_length) + b'AAAA'
    return Ether(dst=mac_addr) / IPv6(dst=ip_addr, nh=dest_options_header) / raw(options_header)

# Packet 1: malformed dest options (option_type=0x81 > 0x80 → triggers always_send_icmp=true)
pkt1 = build_malicious_option(next_header=44, header_length=0, option_type=0x81, option_length=0)
# Packet 2: fragment (Next Header already 44 in pkt1's nh field)
pkt2 = Ether(dst=mac_addr) / IPv6(dst=ip_addr, nh=44) / IPv6ExtHdrFragment(...) / payload
# Send in burst to force coalescing; wait 60s for timeout → crash/overflow

RCE Path (Theoretical)

Reliable RCE requires:

  1. KASLR bypass: The overflow corrupts kernel pool memory, but arbitrary code execution needs the kernel base. An information leak (e.g., uninitialized pool memory returned in ICMPv6 echo reply — ~65KB of uninitialized kernel pool is allocated by ExAllocatePoolWithTagPriority) could provide this.
  2. Heap grooming: Place a victim object (function pointer, EPROCESS token, etc.) adjacent to the 48-byte buffer before the overflow fires.
  3. Overwrite control: The fragment payload is attacker-controlled, providing ~65KB of controllable overwrite data.

As of public research: DoS (BSOD) is reliably achieved; full RCE has not been publicly demonstrated. The HAU paper (Kerutt et al., 2025) recalculates CVSS as 7.5–8.2 given the practical difficulty of RCE.


Key Primitives Used

  • 16-bit integer underflow (packet_size = 0, subtract 0x30) → 0xFFD0 large fragment size
  • 16-bit integer overflow (in Ipv6pReassemblyTimeout allocation math) → 48-byte buffer
  • Controllable kernel pool overflow (~65KB of attacker-controlled data)
  • Uninitialized pool data leak (via ExAllocatePoolWithTagPriority without zero-init — potential KASLR defeat)

Mitigations Bypassed

  • Pre-auth / zero-click: No authentication or user interaction
  • Network reachability only: Any host with IPv6 reachable is vulnerable
  • KASLR: Not bypassed in public PoC; theoretically defeatable via the uninitialized pool allocation

Proof-of-Concept Notes

RepositoryAuthorTypeNotes
github.com/ynwarcs/CVE-2024-38063@ynwarcs (Miloš Ynwarcs)DoS PoCPrimary reference; 39-line Python/Scapy; three-packet chain; reliable DoS
github.com/ThemeHackers/CVE-2024-38063ThemeHackersExtended toolkitICMP flood, SYN flood, traffic analysis, PDF reports; targets DoS

Requirements: Python 3 + Scapy; Linux attacker (Windows blocks raw IPv6 packet construction); root; configure iface, ip_addr, mac_addr.


Patch Analysis

  • Changed function: Ipv6pProcessOptions() in tcpip.sys
  • Change: Replace IppSendErrorList(param) with IppSendError(param)
  • Feature flag: Feature_2660322619__private_IsEnabledDeviceUsage_3() — if this returns 0 (flag disabled), the old vulnerable IppSendErrorList path is executed. Flag controllable via registry/Group Policy = Known Issue Rollback mechanism.
  • Risk: Vulnerable code path is never removed, only gated. If the flag is disabled (e.g., by admin for “compatibility”), vulnerability re-emerges.

Workaround (if patching is not immediately possible): Disable IPv6 via registry or netsh interface ipv6 set global:

netsh interface ipv6 set global defaultcurhoplimit=0  # Not a real fix; patch is required
# Real workaround: Disable IPv6 on external-facing interfaces

References

  • Xiao Wei / Kunlun Lab — discovery (credited by MSRC)
  • Marcus Hutchins, “CVE-2024-38063 - Remotely Exploiting The Kernel Via IPv6”, malwaretech.com, August 2024
  • Kerutt et al., “Critical Analysis of CVE-2024-38063: The Microsoft IPv6-Vulnerability”, HAW Hamburg / Bavarian LSI, 2025
  • OPSWAT Fellowship, “Comprehensive Breakdown of CVE-2024-38063”, opswat.com, April 2025
  • @ynwarcs, PoC, github.com/ynwarcs/CVE-2024-38063, 2024
  • MSRC, “CVE-2024-38063 Security Update Guide”, 2024