# CVE-2026-41108 — Windows DNS Client `dnsapi.dll` Length-Prefix Write Past Packet Buffer → Heap Buffer Overflow

---

## Summary

| | |
|---|---|
| **Product** | Windows — `dnsapi.dll` (Windows DNS Client / DNS API) |
| **CVE ID** | CVE-2026-41108 |
| **Impact** | Elevation of Privilege (to SYSTEM) |
| **MSRC severity** | Important |
| **CVSS** | 7.0 / 6.1 — `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C` |
| **CWE** | CWE-122: Heap-based Buffer Overflow (race-triggered) |
| **Delivery** | Local — winning a race on the DNS packet-buffer bounds |
| **KB / Fixed build** | KB5094126 — `dnsapi.dll` 10.0.26100.8655 (Win11 24H2 x64) |
| **Patch Date** | June 9, 2026 (2026-Jun) |
| **Pre-patch binary** | `dnsapi.dll` 10.0.26100.8521 — SHA256 `d7f46b666ac7bb0559f0f074b31263121b8ea324ad8de86ca954cfcc1a666c23` |
| **Post-patch binary** | `dnsapi.dll` 10.0.26100.8655 — SHA256 `55f028f320563f04d456682850d47d0e67d4dba89cc62711fbf3653a648bba43` |
| **Feature flag** | `Feature_3831740731` — **the fix is CFR-gated** |
| **Exploitability** | Exploitation Unlikely; not publicly disclosed; not exploited (per MSRC) |

---

## Product Description

`dnsapi.dll` is the Windows DNS Client library. When it assembles a DNS message,
`Dns_WriteStringToPacket` serialises a name/label into the packet buffer as a
**length-prefixed string**: it writes a one-byte length prefix at the current write
pointer and then copies the string bytes after it, checking the result against the
end-of-buffer pointer as it goes.

---

## Vulnerability Summary

`Dns_WriteStringToPacket(write_ptr, end_ptr, string, flag)` writes the one-byte
length prefix `*write_ptr = (char)len` **before** it has verified that `write_ptr`
is still inside the buffer (`write_ptr < end_ptr`). When the write pointer has
reached the end of the packet buffer, that length-prefix store lands **one byte
past the heap-allocated packet buffer** — a heap-based buffer overflow (CWE-122).
The condition is reached by racing the buffer state (MSRC: `AC:H` — "requires an
attacker to win a race condition"), and because the DNS client work runs in a
service context, a successful overflow yields **SYSTEM** (per the MSRC FAQ).

---

## Prerequisites and Constraints

- Local, low-privileged (`PR:L`, `AV:L`); `AC:H` — must win a race that drives the
  packet write pointer to the buffer boundary as `Dns_WriteStringToPacket` runs.
- Result: the length-prefix byte is written at/after `end_ptr`, one byte past the
  heap packet buffer.

---

## Vulnerability Details

### Root Cause

The length-prefix byte was written unconditionally once the string length passed the
`< 0x100` check, without first confirming the destination write pointer was still
below the end-of-buffer pointer. At the buffer boundary this is a one-byte
out-of-bounds heap write.

### The patch (confirmed — diff, .8521 → .8655)

The diff shows a single code-changed function, `Dns_WriteStringToPacket`. Gated
behind `Feature_3831740731`, the fix adds a **`write_ptr < end_ptr` precondition**
around the entire prefix-write-and-copy block, so the length byte and the string
copy only proceed when there is room in the buffer:

```c
// Dns_WriteStringToPacket (10.0.26100.8655) — PATCHED (from the diff)
iVar3 = Dns_GetBufferLengthForStringCopy(string, 0, 2 - (flag != 0), 2);
uVar1 = iVar3 - 1;
if (uVar1 < 0x100) {
    uVar4 = Feature_3831740731__private_IsEnabled();
    if ((uVar4 == 0) || (write_ptr < end_ptr)) {          // *** NEW bounds precondition ***
        _Dst = write_ptr + 1;
        *write_ptr = (char)uVar1;                          // length prefix — now only when write_ptr < end_ptr
        puVar2 = (uchar*)((ulonglong)uVar1 + (longlong)_Dst);
        if (puVar2 <= end_ptr) {
            if (flag == 0) { memcpy(_Dst, string, uVar1); return puVar2; }
            if (puVar2 + 1 <= end_ptr) {
                local_38[0] = (int)end_ptr - (int)_Dst;
                Dns_StringCopy(_Dst, local_38, string, uVar1, 1, 2);
                return puVar2;
            }
        }
    }
    dwErrCode = 0xea;                                       // ERROR_BUFFER_OVERFLOW
}
```

Pre-patch, `*write_ptr = (char)uVar1` executed whenever `uVar1 < 0x100`, regardless
of whether `write_ptr` had already reached `end_ptr`. With the added
`write_ptr < end_ptr` guard, the length-prefix store can no longer land at or past
the end of the packet buffer, closing the one-byte heap overflow; the boundary case
now falls through to `ERROR_BUFFER_OVERFLOW` (`0xea`).

### Patch Completeness Assessment

**CFR-gated behind `Feature_3831740731`.** The bounds precondition runs only when the
flag is enabled; the original unconditional length-prefix write still ships when
disabled. Verify `Feature_3831740731` is enabled to confirm the fix is live.

---

## Detection Guidance

**Behavioural.** Heap corruption / one-byte-overwrite crashes in
`dnsapi!Dns_WriteStringToPacket` (and its callers building DNS packets) on
unpatched/flag-disabled builds, particularly under concurrent DNS activity that
stresses packet-buffer boundaries.

**Config.** The fix is CFR-gated — confirm `Feature_3831740731` is enabled.

---

## References

- MSRC advisory — CVE-2026-41108 (Windows DNS Client Elevation of Privilege), released 2026-06-09, KB5094126.
- Full binary diff: `/data/patch_diffs/dnsapi_dll-cve-2026-41108-ghidriff.md`
