CVE-2022-34718 — EvilESP: Windows TCP/IP IPsec ESP OOB Write RCE
Last updated: 2026-04-19
Severity: Critical (CVSS 9.8)
Component: tcpip.sys
Bug Class: OOB Write (single byte, remote, kernel-mode)
Privilege Escalation: Remote Unauthenticated → SYSTEM (RCE theoretical; DoS demonstrated)
Patch: September 2022 Patch Tuesday (KB5017315 and related)
Related: Tcpip Stack, Pool Internals, Primitives, Reversing
Vulnerability Summary
CVE-2022-34718 (“EvilESP”) is a critical zero-click remote kernel vulnerability in tcpip.sys. An unauthenticated attacker with an established IPsec Security Association can send a crafted IPv6 packet containing a Fragment Extension Header embedded inside an IPsec ESP payload to trigger a single-byte out-of-bounds write into the NetIoProtocolHeader2 kernel pool object. The written offset is > 0x38 and the written value (0x2c) is controlled via the ESP tail’s Next Header field. Reliable remote DoS was demonstrated; RCE paths were outlined but not publicly completed at time of disclosure.
Prerequisites:
- Target has IPv6 enabled (default on Windows 7+)
- Target has IPsec configured and a Security Association established with the attacker
- SA can be established via: domain environment with group policy, pre-shared key (PSK), or certificate-based auth — requires two IP security policies with mutual authentication
Root Cause Analysis
Two patched functions in tcpip.sys
BinDiff analysis of sequential pre/post-patch builds revealed two modified functions:
1. Ipv6pReassembleDatagram — incorrect memory offset calculation
When reassembling an IPv6 fragmented datagram that was delivered through an IPsec ESP payload, the offset into the NetIoProtocolHeader2 pool object is computed as:
offset = sizeof(Payload Data) + sizeof(Padding) + sizeof(Padding Length)
Due to a missing bounds check, this offset can be larger than the object’s size (> 0x38), placing the write past the end of the allocated object into adjacent pool memory.
2. ESP extension header type gate — patch discards malformed packets early
The patch adds a check: if the IPv6 extension header type embedded in the ESP tail structure is ≤ 0x2c, discard the packet before reassembly. This blocks the three extension headers that exploit the bug:
| Extension Header | Next Header Value |
|---|---|
| Hop-by-Hop Options | 0x00 |
| Routing Header | 0x2b |
| Fragment Header | 0x2c ← exploit vector |
The OOB Write Primitive
Target object: NetIoProtocolHeader2 (kernel paged pool)
Write offset: > 0x38 (controllable via packet crafting)
Write value: 0x2c (IPv6 Fragment Header type — Next Header field value)
Write size: 1 byte
The value 0x2c (= IPv6 Fragment Extension Header type) comes from the Next Header field in the ESP tail structure. Corrupting even one byte of the NetIoProtocolHeader2 object at a random offset > 0x38 does not cause an immediate crash, but reliable BSOD is achievable by:
- Additional headers in fragmented message — insert extra extension headers to push the offset further and corrupt more critical bytes of adjacent objects
- Repeated pings after initial corruption — spray the pool and trigger crash through accumulated corruption
IPsec ESP Protocol Background
ESP (Encapsulating Security Payload, RFC 4303) is an IPsec protocol that encrypts/authenticates network traffic between two hosts sharing a Security Association (SA). An SA is a unidirectional set of cryptographic parameters (algorithm, key, SPI) negotiated via IKEv1/IKEv2 or manual configuration. The SA requirement is the main exploitation prerequisite: without it, tcpip.sys drops ESP packets before any parsing occurs.
ESP packet structure relevant to the bug:
ESP Header:
[SPI (4)] [Seq# (4)]
ESP Payload:
[Payload Data — contains embedded IPv6 packet with Fragment Header]
ESP Trailer:
[Padding (0-255 bytes)] [Padding Length (1)] [Next Header (1)] ← 0x2c here
ICV (optional):
[Integrity Check Value — aligned on 4-byte boundary per RFC]
The padding requirement (ICV must be 4-byte aligned per RFC) means the Padding Length field can be crafted to control the offset calculation.
Exploitation Technique
Stage 1: Establish Security Association
Attacker configures IPsec SA with the target using PSK or domain policy. Both endpoints need matching IP security policies with mutual authentication.
Stage 2: Send Malicious ESP Packet
Craft an IPv6 ESP packet containing:
- An IPv6 Fragment Header (type 0x2c) embedded in the payload
- ESP tail Next Header = 0x2c
- Padding tuned to control
sizeof(Payload Data) + sizeof(Padding) + sizeof(Padding Length)> 0x38
Send to target. tcpip.sys decrypts the ESP payload, then processes the embedded IPv6 extension headers including the Fragment Header, triggering Ipv6pReassembleDatagram with the corrupted offset calculation.
Stage 3: NetIoProtocolHeader2 Corruption
The 1-byte OOB write at offset > 0x38 lands in NetIoProtocolHeader2 or an adjacent pool object. Immediate crash is not guaranteed — the byte at that position may be padding. Reliability techniques:
# Conceptual: additional extension headers increase offset
# Each extension header adds to sizeof(Payload Data) path
# Craft: Fragment Header + N×RoutingHeaders inside ESP payload
# → offset grows to corrupt critical fields of adjacent object
Exploit Primitives (Theoretical RCE Paths)
IBM X-Force outlined two paths from OOB write to RCE:
Path 1: NetIoProtocolHeader2 → AAR/AAW
Study the NetIoProtocolHeader2 structure layout. If the 1-byte write at offset > 0x38 can land on a length field, pointer low byte, or function pointer, it can be converted into an arbitrary read/write primitive.
Path 2: Adjacent object corruption
Use pool grooming to place a controlled kernel object adjacent to NetIoProtocolHeader2 in the paged pool. Corrupt a single critical byte (e.g., a refcount, size field, or pointer LSB) in that adjacent object to gain a stronger primitive. See Pool Internals for grooming strategies.
PoC Implementation Approach
IBM X-Force used an NDIS protocol driver to construct and send raw IPv6+ESP packets with full control over all header fields — bypassing the socket API’s inability to craft raw IPsec payloads. Scapy with raw socket mode is a secondary approach for crafting the outer packet structure.
Key Primitives Used
- OOB write: 1 byte at controllable offset > 0x38, value = 0x2c, into
NetIoProtocolHeader2pool object - Pool position control: Adjacent object grooming via paged pool spray (path to RCE)
- Remote vector: No local access required — exploitable over network
Mitigations Bypassed
- No authentication required: Exploitable pre-auth (SA establishment is a network operation, not OS login)
- Windows Firewall: tcpip.sys processes ESP packets below the firewall layer — firewall cannot filter this
- KASLR: Not bypassed in DoS demo; required for full RCE — would need kernel leak or predictable pool layout
Proof-of-Concept Notes
- chompie1337 (@chompie1337) demonstrated remote DoS via crafted IPv6/ESP packet
- PoC video: https://twitter.com/chompie1337/status/1583666434668101637
- Numen Cyber Labs published independent PoC restoration: https://www.numencyber.com/tcp-ip-vulnerability-cve-2022-34718-poc-restoration-and-analysis/
- PoC requires: NDIS driver or low-level raw packet sender; established IPsec SA with PSK; IPv6 reachability
- Full RCE PoC: not publicly released as of 2026-04
Patch Analysis
Methodology (IBM X-Force):
- Obtained pre-patch and post-patch
tcpip.sysfrom Winbindex (https://winbindex.m417z.com/?file=tcpip.sys) — sequential builds to minimize noise - Loaded both binaries in Ghidra; applied PDB files from Microsoft Symbol Server → all functions named
- Exported both binaries in BinExport format using the BinExport Ghidra extension
- Loaded into BinDiff → matched functions by name (symbol info available) → identified two modified functions
Key insight from patch diff:
The patch prohibits ESP from carrying IPv6 extension headers with type ≤ 0x2c. This is the minimal fix — the check is added at the ESP parsing layer before reassembly is triggered. The underlying offset calculation bug in Ipv6pReassembleDatagram is also fixed independently.
Patch analysis workflow note:
Using Ghidra+BinExport+BinDiff is a valid alternative to the IDA-based workflow (see Reversing). When PDB symbols are available, all functions match by name and BinDiff’s structural algorithms are less important — focus directly on the matched-but-changed function list.
References
- chompie1337 (IBM X-Force), “Dissecting and Exploiting TCP/IP RCE Vulnerability ‘EvilESP’”, IBM Security Intelligence / IBM Think, 2023 — https://www.ibm.com/think/x-force/dissecting-exploiting-tcp-ip-rce-vulnerability-evilesp
- chompie1337, Twitter PoC demo: https://twitter.com/chompie1337/status/1583666434668101637
- Numen Cyber Labs, “TCP/IP Vulnerability CVE-2022-34718 PoC Restoration and Analysis”, 2022 — https://www.numencyber.com/tcp-ip-vulnerability-cve-2022-34718-poc-restoration-and-analysis/
- Microsoft MSRC Advisory: https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2022-34718
- RFC 4303 — IP Encapsulating Security Payload (ESP)
