Return-Oriented Programming
What is Return-Oriented Programming?
Return-Oriented ProgrammingReturn-Oriented Programming (ROP) is a code-reuse exploit technique that chains short instruction sequences ending in RET to execute arbitrary computation without injecting new code.
Hovav Shacham introduced ROP in his 2007 paper "The Geometry of Innocent Flesh on the Bone," proving that return-into-libc could be generalised into Turing-complete computation and thereby defeat DEP/W^X. The attacker corrupts the stack and writes a chain of addresses, each pointing to a short gadget — a handful of instructions ending in RET. After each gadget executes, RET pops the next address, so control flows through existing executable bytes (libc, the program, loaded libraries) with no injected code for DEP to catch.
Because every gadget address is absolute, ROP depends on knowing where code sits in memory, which is exactly what ASLR randomises; real exploits therefore pair ROP with an information leak. Variants generalise the primitive: JOP (jump-oriented) and COP (call-oriented) chain indirect jumps/calls instead of returns, and SROP (sigreturn-oriented) abuses the kernel's signal-frame restore to set every register at once. Blind ROP (Bittau et al., 2014) even builds a chain against a remote service with no binary, by observing crashes.
ROP is the principal reason a generation of mitigations exists. Defences attack one of three surfaces: gadget availability, control-flow integrity, or memory safety at the source. Intel CET (shipping since Tiger Lake, 2020) enforces a hardware shadow stack that detects mismatched return addresses and Indirect Branch Tracking (endbr64) against JOP/COP; ARM offers Pointer Authentication and BTI. Memory-safe languages such as Rust remove the corruption bug that starts the chain.
flowchart TD A["Memory-corruption bug<br/>stack overflow"] --> B["Overwrite saved return address"] B --> C["Stack now holds<br/>gadget address chain"] C --> G1["Gadget 1: pop rdi, ret"] G1 --> G2["Gadget 2: pop rsi, ret"] G2 --> G3["Gadget 3: syscall, ret"] G3 --> X["execve /bin/sh"] D1["DEP: stack non-exec"] -. bypassed by reuse .-> C D2["ASLR"] -. needs info leak .-> C D3["Intel CET shadow stack"] -. blocks bad RET .-> G1
● Examples
- 01
An exploit chaining pop-rdi/syscall gadgets in glibc to call execve("/bin/sh").
- 02
A kernel exploit using kASLR-leak plus ROP into commit_creds(prepare_kernel_cred(0)).
● Frequently asked questions
What is Return-Oriented Programming?
Return-Oriented Programming (ROP) is a code-reuse exploit technique that chains short instruction sequences ending in RET to execute arbitrary computation without injecting new code. It belongs to the Application Security category of cybersecurity.
What does Return-Oriented Programming mean?
Return-Oriented Programming (ROP) is a code-reuse exploit technique that chains short instruction sequences ending in RET to execute arbitrary computation without injecting new code.
How do you defend against Return-Oriented Programming?
Defences for Return-Oriented Programming typically combine technical controls and operational practices, as detailed in the full definition above.
What are other names for Return-Oriented Programming?
Common alternative names include: ROP, Code reuse attack, Return-to-libc.