ASLR bypass
TL;DR: Defeat user-mode address randomisation by leaking a pointer (info-disclosure bug) or by chaining gadgets out of a module compiled without
/DYNAMICBASE.
What it is
Address Space Layout Randomisation (ASLR) on Windows randomises the base address of every PE that opts in with the IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag, plus stack, heap, and PEB/TEB locations. Without a leak, an attacker cannot hard-code addresses for ROP gadgets, shellcode, or import targets. Bypass strategies fall into two buckets: leak a runtime pointer, or chain off a module the developer forgot to mark /DYNAMICBASE.
Preconditions / where it applies
- Win Vista+ for OS support, but enforcement depends on per-image opt-in until Force-ASLR / Mandatory ASLR is enabled
- Either an info-leak primitive (format string, OOB read, uninitialised disclosure) or a non-ASLR module loaded into the target process
- High-entropy ASLR (HEASLR) on x64 needs ≥ 19 bits of leak to be useful
Technique
Path A — info leak. Common sources:
- Format-string reads on legacy services
- OOB reads in parsers (JPEG/TTF/PDF chunks)
- Exception-record disclosure (e.g. server returns a stack-trace style structure)
- Browser/renderer JIT type confusion exposing object pointers
Convert the leak into a module base by subtracting the known offset of the leaked symbol (base = leaked - RVA(symbol)).
Path B — non-ASLR module. Use rp++, ROPgadget, or mona.py modules to find a DLL loaded into the target with ASLR: False:
1
2
!mona modules
!mona rop -m non_aslr_module.dll -cp nonull
Build the ROP chain entirely out of that module’s static gadgets — the rest of the process can be randomised.
Path C — partial overwrite. Overwrite only the low bytes of a saved return address or vtable pointer when ASLR randomises only the high bits — works against page-aligned (12-bit) low-entropy targets.
Path D — heap-spray + JIT spray. Browsers without modern JITless modes still let a sprayed payload survive at a predictable VA (NaN-boxing or RWX JIT pages).
Detection and defence
- Enforce system-wide Force-ASLR / Mandatory ASLR via Exploit Protection (Windows Security → App & browser control → Exploit protection settings)
- Build every binary with
/DYNAMICBASE /HIGHENTROPYVA; audit third-party DLLs withdumpbin /headersormona modules - CFG + CET further raise the cost of pointer reuse even after a leak — see control-flow-guard and cet-shadow-stack
- EMET/Defender Exploit Guard flags non-ASLR DLL loads via Address Filtering policies
References
- Microsoft: Exploit Protection — ASLR enforcement settings
- Corelan: Exploit writing — bypassing ASLR — practical bypass patterns
- HackTricks: ASLR bypass — short cookbook
Related: dep-bypass, rop-chains, kaslr-bypass, uninitialised-memory-disclosures