Lion Cipher Lab
Defeat ASLR with no leak: forge the dynamic linker's resolver structures (ret2dlresolve) in your own lab
- Penetration Testing / Red Team
- Advanced
- ~120 min
- Free · no account required
Why it matters
The ret2libc lab defeated ASLR (Address Space Layout Randomisation — the OS defense that loads libc, the stack and the heap at a different random base every run) by LEAKING a runtime address and doing arithmetic. But that assumed you had a leak primitive at all — a puts() you could point at the GOT, a format string, something. Plenty of real targets give you a clean stack overflow and nothing else: no output you can steer, no second bug to leak with. ret2dlresolve is the answer to exactly that dead end. Instead of leaking libc, you turn the dynamic linker — the loader that normally resolves…
What you'll learn
- understanding the ELF lazy-binding pipeline end to end: how a first call to an imported function walks PLT stub -> GOT slot -> _dl_runtime_resolve, and how the resolver uses .rela.plt, .dynsym and .dynstr to find the real address and patch the GOT
- seeing WHY this gives an ASLR defeat with NO leak: the resolver itself computes libc addresses for you at runtime, so you never need to know or print one
- forging the three structures by hand-understanding: a fake Elf64_Rel (relocation), a fake Elf64_Sym (symbol), and a fake symbol string "system", staged in a writable, statically-known, non-PIE region (.bss/.data)
- driving _dl_runtime_resolve with an attacker-chosen relocation INDEX that points at your forged Rel, so the loader resolves and jumps to system("/bin/sh") on your behalf
- doing it the practical, reliable way with pwntools' Ret2dlresolvePayload and ROP -- while being able to explain every field the payload contains
- the judgment: ret2dlresolve is the right tool when you have NO leak, NO PIE, and a known writable address -- and it FAILS under Full RELRO (resolver path is read-only) or PIE-without-a-leak (its fixed addresses move)
- verifying the forged structures and the resolver call in gdb rather than trusting the payload blindly -- the way a pro actually ships one of these
Steps in this lab
- Read this first: your own machine, your own binary, authorized-only
- Where the ret2libc lab left you — and the case it could not solve
- The machinery: PLT, GOT, lazy binding, and _dl_runtime_resolve
- The idea: forge the structures and let the loader resolve system() for you
- Why this needs a writable, non-PIE region — meet .bss
- Get Linux and the exploit tooling
- Pick a target: your own binary, or a ROP Emporium challenge
- Compile it into the exact vulnerable profile — and confirm it
- Find the offset and a way to control the first argument
- Build the payload with Ret2dlresolvePayload — and know every field
- The way a pro does it: verify the forgery in gdb
- The judgment: when ret2dlresolve is right — and exactly when it fails
- Prove the limits yourself, then clean up