# Hacking Tube

## CSAW CTF 2015 -- autobots

Category: Exploitable
Points: 350

I hear bots are playing ctfs now.
nc 52.20.10.244 8888

Once we connect to the service, it will send us a 64 bit ELF binary.

We can see that this binary was another socket server program, which has a simple stack overflow vulnerability in it. But after I reversed the binary, got the port number and connected to the service, it gave me nothing.

At first I thought this was such a crap, but then I found out that each time I connected to the original service, it'll gave me a different binary. It's still a socket server program, which wait for our connection, read the input and output our input, but it has a different port number, different buffer location & different reading size.

After having some discussion with my teammates, we figure out that maybe the challenge want us to exploit the service like a bot, which means that we'll have to figure out the port number, buffer size and try to exploit the service -- all done fully automatically.

So the first thing we'll have to do is to retrieve some informations in the binary, such as port number, buffer's location and reading size. By using objdump, we can analyze the assembly and retrieve those informations:

Now we figure out the port number, we can connect to the service immediately after we get the binary. This time, it actually wait for me to input a string and send it back to me.

So we're on the right track, time to exploit the service. Notice that sometimes the binary's not exploitable, because its reading size might be smaller than the buffer's offset from the rbp. Anyway, once we know that the service is exploitable, we can send our payload and try to do the ROP attack ( the binary has enable the DEP protection ).

But before that, there're few things we need to beware of:
1. It's a socket server, so if we want to spawn a shell and execute our own command, we'll have to use dup2() to copy stdin & stdout to our socket fd.
2. Our socket fd is 6, we can leak it with the help of the write function
3. The socket fd is also on stack, so while overwriting the return address, the socket fd should remain the same.

Consider that the reading size might not be big enough to read the whole ROP chain, I decide to use the stack migration trick:
1. After overwriting the return address in main function, the first thing we do is to read the 2nd ROP chain to a data segment (buffer1) , and change the stack to buffer1 ( by using the pop rbp; ret and leave; ret gadget )
2. The 2nd ROP chain is to leak the address in libc, read the 3rd ROP chain to buffer2, and change the stack to buffer2
3. Finally the 3rd ROP chain will do dup2(6, 0), dup2(6, 1) and system("/bin/sh")

We can use ROPgadget to find some useful gadgets, such as pop rdi; ret and pop rsi; pop r15; ret for setting the function parameters. Notice that although we can't find a gadget to control rdx (storing the 3rd function parameter), but since only read and write function need the third parameter, we can leverage the fact that the program has already set the rdx for us in the main function (for writing our output).

So to sum it up:
1. Use objdump to get the port number, buffer location and reading size
2. Use ROPgadget to find some useful gadgets (for setting parameters & stack migration)
3. Overwrite the return address, notice that the socket fd should not be modified
4. First ROP chain: read the 2nd ROP chain to buffer1 and change the stack
5. Second ROP chain: leak libc's base address, read the 3rd ROP chain to buffer2 and change the stack
6. Third ROP chain: do dup2(6, 0), dup2(6, 1) and system("/bin/sh")

For finding the libc version, here's an useful tool: libc database

And finally we get the flag: flag{c4nt_w4it_f0r_cgc_7h15_y34r}

CGC huh, well...I'm not sure about that :/ but anyway this is a pretty good challenge :)