# HITCON CTF start pwnable

This pwnable task with the description “Have you tried pwntools-ruby?” was a challenge that was served on: 54.65.72.116 31337 The task contained two files, the first was a ruby script called server.rb

and another binary called start which reveals to be a x64 binary statically linked.

So the task is already pretty clear. it seems as we have to connect to the server and then give our exploit in ruby code and then exploit the local binary serving at 127.0.0.1:31338

As we can see that they are forcing us to use pwntools in ruby we simply write our exploit in python and then port it later on and debug it on their machines so we don’t have to install it ;)

The first thing we do is check the security enabled on the binary. We do that by opening the binary in gdb-peda and run checksec

Stack canary and NX bit enabled. With that in mind we will now look at the binary.

The binary is rather simple. We can see that it sets an alarm with the timer 0xA(10 seconds) alarm img

Then a little further down we see the call to read with 3 arguments. from man: read(int fd, void *buf, size_t count); The first argument is placed in RDI and is the filedescripter 0 which is STDIN The second argument is the buffer and placed in RSI and is a pointer to the buffer The third is the buffer size and is placed in RDX and is a buf size of 0xD9 as also commented in the screenshot.

Then the binary calls strncmp and looks for the string exit\n in the first 5 bytes of the buffer we put data into. If it does contain exit\n we jump down to the stack cookie check and then if the stack is not smashed we exit cleanly. If exit\n is not in buffer we simply print the buffer to STDOUT and run the loop again.

With this in mind we now want to see what the stack layout looks like to see if the buffer is the proper size.

as we can see above the stack is only 24 bytes long. We are allowed to write 0xD9(217) bytes to the stack and the buffer overflow is pretty clear. Our problem is here that if we overwrite our buffer we will smash our stack cookie and the binary will crash.

So the payload would look like this after the cookie is leaked: "A"*24 + LEAKED_STACKCOOKIE + "B"*8 + NEW_RETURNADDR

We now have EIP control over the binary. Onwards to a working exploit!

So as the binary is statically linked we looked for usefull functions in the binary. We ended up taking the long road and ran mprotect on the stack in order to make it executable again and then simply just jmp to our shellcode with a jmp rsp gadget.

As mprotect takes 3 arguments mprotect(void *addr, size_t len, int prot); we needed to set the 3 registers RDI, RSI and RDX To do this we made a ropchain that looked like this:

In order to do this however we needed to know what to put in as the RDI register(*addr) as this should be a stack address which is page aligned.

To do this we needed to go back and use the trick we did to leak the stack cookie. The thing is that further down the stack there is a stack address, which we can leak(64 bytes down the stack). This address points to a higher address on the stack and we therefore substact 0x300 to get below our buffer and page align it

After we had the leaked stack address, leaked stack cookie and everything else we needed we simply had to put all the bits together and have a working exploit.

This made us end up with the final exploit:

from here we simply had to port our exploit to ruby(which made it quite ugly). So to sum up what this does. We have the ruby exploit in a string. It has to be under 1024 bytes. We send this to the server and they run it and it then exploits the local binary and runs a command that cats the flag.