Lion Cipher Lab
Pivot the stack to fit a longer ROP chain (when the overflow is too small) — ROP Emporium 'pivot'
- Penetration Testing / Red Team
- Advanced
- ~90 min
- Free · no account required
Why it matters
Every ROP lab before this one quietly assumed the overflow gave you ROOM: enough bytes past the saved return address to lay down a whole chain of gadgets and addresses. Real bugs are stingier. Very often the buffer you can overflow past RIP is tiny — space for one or two 8-byte words, nowhere near enough for a leak stage plus a ret2libc plus alignment. A short overflow like that looks like a dead end, and this is the technique that turns it back into a win: the STACK PIVOT. The insight is that the stack is just wherever rsp (the stack pointer register) happens to point, and `ret` blindly…
What you'll learn
- understanding WHEN you need a stack pivot: the overflow past the saved return address is too SHORT to hold your whole ROP chain (room for only a gadget or two), so a full ret2libc/ret2csu chain simply does not fit on the stack
- the core idea of a pivot: STAGE the real ROP chain in a large writable buffer the program hands you the address of (in the ROP Emporium 'pivot' challenge, a heap/mmap region whose address it prints), then redirect rsp to point at that buffer so the CPU 'returns' through your staged chain
- the pivot-gadget families and what each does to rsp: `pop rsp ; ret` (pops your address straight into rsp), `xchg <reg>, rsp ; ret` (swaps a register you loaded with rsp), `leave ; ret` (mov rsp,rbp ; pop rbp — pivot via a controlled rbp), and `add rsp, N ; ret` (a short local hop)
- finding a pivot gadget the pro way — grepping ROPgadget and ropper output for `pop rsp`, `xchg`, `leave` and `: ret` — and reasoning about which one the situation allows
- driving the two-write interaction with pwntools: write the staged chain into the leaked buffer first, then send the short overflow that loads the buffer address and executes the pivot gadget
- the concrete goal in 'pivot': call foothold_function() once to resolve its real address into the GOT, read that runtime address, add the published offset to reach ret2win(), and call it — all from the staged chain running after the pivot
- the judgment: when a pivot is the missing piece versus when you have room for a normal chain, why .bss / a leaked heap buffer / an mmap region make good pivot destinations, and how ASLR/PIE change whether you can even know where to pivot to
Steps in this lab
- Read this first: a downloaded challenge binary, run only on your own machine
- Where the arc left you — and the exact problem a pivot solves
- What a stack pivot actually is (rsp is the whole game)
- The pivot-gadget families: pop rsp, xchg, leave, add rsp
- Get the Linux toolchain, pwntools, and the 'pivot' challenge binary
- Read the challenge: it HANDS you the buffer address and a short overflow
- Find the offset and the pivot gadget
- Decide what the staged chain will DO: foothold_function -> ret2win
- Build it with pwntools: stage the chain, then send the pivot
- When you reach for a pivot — and how ASLR/PIE decide if you can