Arbitrary R/W primitives
TL;DR: Modern kernel exploitation is mostly primitive engineering — turning a tiny bug (single out-of-bounds qword, freed object, wrong sized write) into reliable “read 8 bytes from address X” and “write 8 bytes to address Y” calls.
What it is
A primitive is a reusable function callable from user mode that performs a memory operation in kernel context. Once you have arbitrary read (AR) + arbitrary write (AW), the exploit is mechanical: leak structures, walk lists, patch tokens, restore state, return cleanly. Without primitives, you have a crash. The art is shaping whatever the bug gives you into AR + AW with as few syscalls as possible.
Preconditions / where it applies
- Initial bug provides any of: linear OOB read/write, type confusion, UAF, integer underflow on a size, partial pointer overwrite.
- A “victim object” exists in the same SLAB cache/pool whose fields are read back to user mode (read) or used as a length/pointer (write).
- Spray is feasible — i.e. the cache is not isolated/randstruct’d to the point of denying placement.
Technique
Common victim objects on Windows:
_PIPE_QUEUE_ENTRY/_PIPE_ATTRIBUTE— variable-size, sprayable viaNtFsControlFileon named pipes; field read back viaNtFsControlFile(FSCTL_PIPE_QUERY_ATTRIBUTE).- I/O ring entries (Win11) —
_IORING_OBJECTfields including a kernel pointer. _WNF_NAME_INSTANCE/ WNF state data — sprayable, readable viaNtQueryWnfStateData.
Pattern: AR.
- Overwrite a length field in the victim with a controlled large value.
- Issue the read syscall; kernel copies
lengthbytes starting at the (still-original) data pointer → adjacent objects leak.
Pattern: AW.
- Overwrite the data pointer of a victim (e.g. pipe attribute value pointer) with the target kernel address.
- Issue the set/write syscall; kernel copies attacker bytes into the chosen address.
Pattern: data-only escalation. With AR + AW, no ROP needed: locate current EPROCESS, walk ActiveProcessLinks to find the System process, copy its Token over your EPROCESS.Token → instant SYSTEM. Or flip Previous Mode to 0 inside KTHREAD, then use NtReadVirtualMemory/NtWriteVirtualMemory against the kernel directly.
Cleanup. Restore overwritten lengths and pointers before returning; an unstable victim object that the kernel later frees with the wrong size or wrong pool produces a BSOD on a timer.
Detection and defence
- Pool/freelist hardening, segment heap pool, kernel CFI (cfg-cet-kernel) and hvci-vbs limit what AR/AW can do (e.g. read-only PTEs for kernel code).
- EDR sensors watching
NtFsControlFileflood patterns and inconsistentTokenreferences can flag this. - VBS-protected token / Credential Guard isolation makes some classic “copy System token” patterns less universal on 11/2022+.
References
- pipe attribute primitive write-up — modern AR/AW shape
- Microsoft: kernel primitive mitigations — pool defences and randomisation
- HackTricks Windows kernel — adjacent techniques
See also: type-confusion-kernel, use-after-free-kernel, token-stealing-payloads.