KASLR bypass
TL;DR: Kernel ASLR randomises
ntoskrnland HAL load addresses per boot — bypass via low-integrity NT-side syscalls that still leak kernel pointers, uninitialised pool disclosures, or side channels that survive HVCI.
What it is
KASLR randomises the load address of every kernel module by a per-boot offset. Without a leak, an attacker holding a kernel write/call primitive does not know where nt!PsInitialSystemProcess or nt!HalDispatchTable live, so token-swap and ROP chains cannot be constructed. KASLR bypass is therefore the gating step for nearly every modern Windows LPE.
Preconditions / where it applies
- Windows 8+ with KASLR enabled by default
- Process at any integrity level — many leaks were closed for low/medium IL but remain in admin/high IL contexts (and a kernel exploit running from admin is still useful — services LPE, sandbox escape)
- Bypasses split by whether HVCI is on; HVCI changes only what you can do with the leak, not the leak itself
Technique
Common leak primitives:
- NT system information classes. Historically
NtQuerySystemInformation(SystemModuleInformation)returnedImageBasefor every kernel module to all callers. Win 10 1607+ requires Medium IL; Win 11 22H2 returns zero for non-admin. From admin, it still works — useful for service LPE. SystemBigPoolInformation,SystemHandleInformation. Leak pool/object addresses; admin-only on modern builds.- Uninitialised kernel memory disclosures. Drivers that copy a partially initialised struct back to user mode leak heap/stack KVA — see uninitialised-memory-disclosures. Survives HVCI because HVCI does not zero memory.
- GDI / Win32k objects.
gSharedInfo,HMValidateHandle,tagWNDhad years of leak primitives via shared sections. - Side channels. Meltdown closed by KPTI; Spectre v1/v2/L1TF variants leaked the
KVA_SHADOWdirectory base. EntryBleed (2022) revealed kernel function offsets via prefetch on KPTI hosts. - Bring-your-own-driver read. A signed-vulnerable driver providing physical-memory read trivially defeats KASLR.
Workflow:
1
2
3
4
5
// Admin-only legacy approach
NTSTATUS s = NtQuerySystemInformation(
SystemModuleInformation, buf, len, &ret);
// Walk buf as RTL_PROCESS_MODULE_INFORMATION array;
// the first entry is ntoskrnl, .ImageBase is the leak.
After leak: combine with arbitrary write primitive to corrupt nt!HalDispatchTable[1] (legacy) or nt!PsInitialSystemProcess.Token (token steal) — see token-stealing-payloads.
Detection and defence
- Microsoft has progressively gated info classes behind SeDebug or admin; track changes via
nt!ExGetPreviousModeaudits - HVCI (hvci-vbs) does not stop the leak but blocks the typical follow-up of marking sprayed pool RX
- Microsoft Vulnerable Driver Blocklist closes BYOVD leak primitives
- Enable Kernel CET (cfg-cet-kernel) and SMEP/SMAP (smep-smap-overview) so post-leak chains face additional CFI
References
- Connor McGarr: KASLR bypass writeups — recurring series with current primitives
- j00ru: Windows kernel leaks — long-running catalogue of disclosure bugs
- EntryBleed (CVE-2022-4543) — KPTI-side-channel KASLR break
Related: aslr-bypass, uninitialised-memory-disclosures, kpti-meltdown-implications, token-stealing-payloads