Return-Oriented Programming (ROP)

If you've read the memory visualizer's buffer overflow walk-through, it ended with "you can hijack the return address, but NX prevents you from running shellcode on the stack". This is the answer to that. ROP is how attackers get arbitrary code execution when they can't put their own code anywhere executable: they build a "program" out of pieces of the target's own legitimate, already-executable code.

1. The Problem: NX Killed Shellcode

Before NX (mid-2000s), buffer overflow exploits worked by writing CPU instructions ("shellcode") into the buffer, then redirecting RIP to that shellcode. NX killed this. Now what?

2. What's a "Gadget"?

A gadget is a tiny snippet of code (1 to about 5 instructions) ending in ret, that exists somewhere in legitimate executable memory. libc has thousands of them. Your binary has hundreds. The attacker scans for them with tools like ROPgadget or Ropper.

3. The Chain: Stack-as-Program

The key insight: when a function executes ret, it pops the next 8 bytes off the stack into RIP and jumps there. If those 8 bytes are the address of another gadget that also ends in ret, the gadgets chain automatically.

4. A Real 3-Gadget Chain: Call system("/bin/sh")

The classic. The goal is to call system("/bin/sh") from libc to get a shell. system\'s first argument has to be in RDI (System V x86_64 ABI). We need a gadget that puts our string\'s address into RDI, then a way to jump into system. Step through it.

5. ASLR: What (Mostly) Stops This

ROP needs the attacker to know exact addresses of gadgets. ASLR randomizes those addresses every time the program (and libc) loads. Without the addresses, the chain can\'t be built. This is the modern defense, and it works, until the attacker finds an "info leak".