ret instruction, which pops the next address off the stack and transfers control there, enabling arbitrary gadget chains.
How ROP works
Control the stack
Exploit a stack overflow (or equivalent) to overwrite the saved return address with the address of the first gadget.
Chain gadgets
Place gadget addresses and their associated data values sequentially on the stack. When each gadget’s
ret fires, it pops the next gadget address into the instruction pointer.Finding gadgets
- ROPgadget
- ropper
- pwntools ROP
x86 (32-bit) ROP chain
On 32-bit x86, function arguments are passed on the stack. Asystem("/bin/sh") call needs /bin/sh’s address on the stack directly after the return address.
x64 (64-bit) ROP chain
On x86-64 (System V ABI), the first six integer arguments go in registersRDI, RSI, RDX, RCX, R8, R9. A pop rdi; ret gadget is the most important building block.
Common ROP sub-techniques
ret2lib — call libc functions
ret2lib — call libc functions
Set up registers/stack for a libc function (commonly
system("/bin/sh")) and jump to it. Requires knowing the libc base address (defeat ASLR via an info leak first).ret2syscall — direct syscall
ret2syscall — direct syscall
Load
rax = 59 (execve), rdi -> "/bin/sh", rsi = 0, rdx = 0, then reach a syscall gadget. Useful when libc addresses are unknown.ret2csu — universal gadgets
ret2csu — universal gadgets
__libc_csu_init contains a reliable gadget pair that lets you control RBX, RBP, R12, R13, R14, R15, and call [r12 + rbx*8]. Available in nearly every dynamically linked x86-64 binary.SROP — sigreturn-oriented programming
SROP — sigreturn-oriented programming
A single
sigreturn syscall restores all registers from a crafted sigreturn frame on the stack. One gadget can set every register simultaneously, avoiding the need to find individual pop reg; ret gadgets.BROP — blind ROP
BROP — blind ROP
Used when you have a stack overflow but no binary to analyse. Exploits a remote service that stays alive (e.g., a forking server) and probes for gadgets by observing whether the process crashes or continues.
JOP — Jump-Oriented Programming
JOP replacesret at the end of each gadget with an indirect jmp or call. This is common on ARM where ret is less universal.
- An overwritten function pointer in the heap points to a gadget:
ldr x0, [x0, #0x20]; ldr x2, [x0, #0x30]; br x2 - Set
x0 + 0x20→ pointer to/bin/shstring - Set
x0 + 0x30→ address ofsystem
Stack pivoting
When the stack is too small for a full chain, pivot the stack pointer (RSP/SP) to a controlled region (heap, BSS, or a large input buffer).
Protections against ROP
| Protection | Effect on ROP |
|---|---|
| ASLR + PIE | Randomises gadget addresses — requires info leak |
| Stack canaries | Detects overflow before ret — must be bypassed separately |
| CET / Shadow Stack | Hardware enforces that ret targets match the call stack |
| Lack of gadgets | Small or heavily stripped binaries may not have enough useful gadgets |