This weekend, I participated briefly in the CSAW 2020 CTF. I solved a number of challenges, and below are the writeups for two (fairly straightforward, unfortunately) challenges, and one I missed because I did something incredibly dumb in the exploitation process.
roppity
This challenge was presented as a 64-bit Linux binary, which you can download here.
Initial reverse engineering showed this to be a straightforward two-stage ROP challenge – leaking the location of something in libc, then directly calling one_gadget. A puts call at 0x4005F5 can be exploited, leaking the GOT – and then helpfully, this continues onto a gets call at 0x400606.
We can use ropper and one_gadget to help us construct the rop chain, and moments later, we have a working exploit:
slithery
This challenge was presented as a host / port combination, which hosted a listening service, purporting to be a Python sandbox, with source code provided. The sandbox can be found here.
Initial exploration showed that we actually have a working exec primitive, but didn’t consistently work. That said, I could print items, and the blacklist didn’t cover itself (i.e. didn’t cover “blacklist”).
The following silly trick worked to get us out of the sandbox, by deleting the blacklist, importing the “os” module then system’ing bash:
It looks like the intended solution was something different, triggering some kind of exception and hitting a second sandbox (not provided):
Thankfully, we never had to deal with this.
grid
This challenge was presented as a 64-bit Linux binary, which you can download here.
Initial reverse engineering showed that this was a mess of C++. The application seemed to allow manipulation of a “grid”, which appeared to be implemented as a linked list, and then “copied” to the stack when the “d” command was used to display the grid:
Using this as an exploit primitive, we can write arbitrary (within reason: cin dies on some characters) content to the stack, including ROP gadgets (here: a call to cout trying to point to the GOT, but notice I can’t enter the full address of the GOT onto the stack):
I spent a little while searching for a GOT leak, but I didn’t realize: you could leak libc content simply by hitting “d” without overwriting anything.
FML.
With something in libc, it’s trivial to then overwrite a return address to hit a one_gadget special and get a shell. No flag this time, better luck next time 🙂
Thanks to the CSAW team for putting together this CTF – I look forward to playing again next year.