welpwn

Hello,

As the first exploitation challenge for RCTF event, the exploit requires information leak some ROP programming and ret2libc techniques.

➜  rctf  checksec welpwn_932a4428ea8d4581431502ab7e66ea4b
    Arch:          amd64-64-little
    RELRO:         Partial RELRO
    Stack Canary:  No canary found
    NX:            NX enabled
    PIE:           No PIE

Main function looks like this:

mainfunc

So we have a read() that takes in 0x400 bytes which is not enough to overwrite the RET of main. The echo() function looks like this:

echofunc

Seems like the vulnerability is here. We see a local buffer of 0x20 bytes and a loop that copies bytes one by one from the buffer of main() to the local buffer of echo(). The loop copies bytes until it sees a null byte, obviously we can overwrite the RET of echo() here.

By executing the binary and passing a single newline to read(), we can cause a print of a leak in libc. No overwrites here, a single leak to confirm whether ASLR is enabled or not.

➜  rctf  ./welpwn_932a4428ea8d4581431502ab7e66ea4b| xxd
0000000: 5765 6c63 6f6d 6520 746f 2052 4354 460a  Welcome to RCTF.

0000010: 0a2d 5a4a e47f                           .-ZJ..
➜  rctf  ./welpwn_932a4428ea8d4581431502ab7e66ea4b| xxd
0000000: 5765 6c63 6f6d 6520 746f 2052 4354 460a  Welcome to RCTF.

0000010: 0a7d 3853 f67f                           .}8S..
➜  rctf  ./welpwn_932a4428ea8d4581431502ab7e66ea4b| xxd
0000000: 5765 6c63 6f6d 6520 746f 2052 4354 460a  Welcome to RCTF.

0000010: 0aad b093 e77f                           ......
➜  rctf  ./welpwn_932a4428ea8d4581431502ab7e66ea4b| xxd
0000000: 5765 6c63 6f6d 6520 746f 2052 4354 460a  Welcome to RCTF.

0000010: 0a9d 64e6 ad7f                           ..d...
➜  rctf  ./welpwn_932a4428ea8d4581431502ab7e66ea4b| xxd
0000000: 5765 6c63 6f6d 6520 746f 2052 4354 460a  Welcome to RCTF.

0000010: 0a9d 33ba f37f                           ..3...

Yes, I’m executing it locally and I see that ASLR is enabled (on my system) however, I did the same to the remote box by doing something like:

#!/usr/bin/env python

from pwn import *

r = remote('180.76.178.48', 6666)
print r.recv()
r.send("\n")
print r.recv().encode('hex')

and I got randomized leak just like in my local tests… meaning ASLR is enabled. With ASLR enabled and PIE disabled we will have everything but the .text segment of the binary randomized… nothing new here, let’s continue.

By looking for ROP gadgets in the binary, there was not a single syscall gadget, making exploitation by ROP from the binary only impossible… We either need syscall from a library or we need ret2libc. I’m going with ret2libc, so next I needed to find their version of libc.

Let’s construct a payload to overwrite RET of echo(), put the address we would like to leak in RDI and jump to 0x4007b0 which is the call to puts.

I used http://libcdb.com/ to find the libc version, I used the address of __libc_start_main and fflush, in the run above we get 0x00007fb98b74bdd0 and 0x00007fb98b797ee0. The search brings us here the following libraries http://libcdb.com/search?symbolA=__libc_start_main&addressA=0x00007fb98b74bdd0&symbolB=fflush&addressB=0x00007fb98b797ee0. Now we can download libc or we can just use the website to calculate the offset of “/bin/sh\x00” string in libc and the offset of system() from the base of libc.

findlibc

Next step is to get a leak from libc load address, calculate the offset to “/bin/sh\x00” string and system() while we loop again to overwrite the RET.

  • Thank you for watching :)