Kernel stack overflow

Kernel stack overflow

TL;DR: A buffer overflow on a kernel-mode stack — same root cause as user mode, but stack canaries (/GS), small stacks (~24 KiB), CET shadow stacks, and the lack of a libc make the exploit path very different.

What it is

Kernel routines allocate local buffers on the per-thread kernel stack. If a driver copies attacker-controlled data into one of those buffers without bounds-checking, the stack frame, saved RIP, and adjacent frames are corrupted. On modern Windows the chain is gated by /GS cookies, kCFI/kCET, and HVCI — usually the bug yields a controlled crash, not direct RIP control.

Preconditions / where it applies

  • Vulnerable driver function with memcpy/RtlCopyMemory/manual loop into a stack-local of fixed size from a user-controlled source (often IOCTL Type3InputBuffer or METHOD_NEITHER).
  • Source size attacker-controlled or unchecked; or double-fetch races a checked-then-used length.
  • Driver compiled without /GS or with weak canary placement (third-party drivers, legacy kernel modules).

Technique

Find it. Reverse driver IRP dispatch (DriverEntryMajorFunction[IRP_MJ_DEVICE_CONTROL]); for each IOCTL, trace user-buffer copies into stack locals. BinExport + BinDiff against patched versions narrows fixes quickly.

Trigger.

1
2
3
DeviceIoControl(hDev, IOCTL_VULN,
                payload, payload_len,
                NULL, 0, &cbRet, NULL);

What the corruption gives you.

  • Saved RIP overwrite → without kCET, you can chain into kernel ret-gadgets (rop-chains style, but inside ntoskrnl.exe/HAL).
  • With /GS on, the canary precedes RIP; overflow that touches both crashes in __report_gsfailure. Bypasses include: avoid reaching the cookie (overwrite an adjacent pointer used earlier), try/except registration overwrite (older builds), or use a sibling bug to leak the cookie.
  • With kCET on, even after RIP overwrite the ret mismatches the shadow stack → #CP → bug check.

Post-RIP path (where it still works):

  • Disable SMEP via cr4 toggle gadget, then jump to user-mode shellcode that calls commit_creds-equivalent token swap. SMEP defeats the most naive form (see smep-smap-overview).
  • Pure kernel ROP into a nt!HalpSetSystemInformation-style sink that calls into attacker-shaped data.

Modern reality. On HVCI+CET targets, most stack overflows are escalated by not taking RIP. Use the linear write to corrupt an adjacent struct (object pointer or IRP field) and pivot to arbitrary-read-write-primitives.

Detection and defence

  • Compile drivers with /GS, /guard:cf, /CETCOMPAT, /GUARD:EHCONT.
  • Driver Verifier (verifier /flags 0x209BB) flags many overflow patterns at test time.
  • KASLR + HVCI + kCET combination makes RIP-control extremely rare for stack overflows on current targets.

References

See also: arbitrary-read-write-primitives, double-fetch, smep-smap-overview.