ASLR bypass

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 with dumpbin /headers or mona 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

Related: dep-bypass, rop-chains, kaslr-bypass, uninitialised-memory-disclosures