Return-Oriented Programming (ROP)

Return-Oriented Programming (ROP) is an exploitation technique that bypasses non-executable memory protections by chaining together small code sequences (gadgets) ending in return instructions, already present in the program or libraries.

How ROP Works

Instead of injecting shellcode, the attacker controls the stack to chain addresses of existing code snippets (gadgets). Each gadget performs a small operation and returns, jumping to the next gadget's address on the stack.

ROP Chain Concept

Stack Layout:
┌─────────────────┐
│ gadget1 address │ → pop rdi; ret
├─────────────────┤
│ "/bin/sh" addr  │ → value for rdi
├─────────────────┤
│ gadget2 address │ → pop rax; ret
├─────────────────┤
│ 0x3b (execve)   │ → syscall number
├─────────────────┤
│ gadget3 address │ → syscall; ret
└─────────────────┘

Result: execve("/bin/sh", 0, 0)

Finding Gadgets

# Using ROPgadget
ROPgadget --binary ./vulnerable_app

# Using ropper
ropper --file ./vulnerable_app --search "pop rdi"

# Common useful gadgets:
pop rdi; ret        # Load argument 1
pop rsi; ret        # Load argument 2
pop rax; ret        # Load syscall number
syscall; ret        # Trigger syscall

Bypassed Protections

  • NX/DEP: No code injection needed - uses existing code
  • Stack canaries: May need info leak or separate bypass
  • ASLR: Requires address leak or brute forcing

See Also