Yesterday, I participated in the Nuit Du Hack Quals. In hindsight, I should’ve played this all day – this was a good CTF quality-wise, with a good variety of challenges and infrastructure which seemed to remain online.
I will present two writeups below, for posterity.
So_Stealthy
This challenge was presented as a PCAP file, which you can download here. The objective was to reverse engineer some malware included in the pcap. At a glance in wireshark, most data is HTTP or HTTPS traffic: so we start by extracting all the HTTP/HTTPS objects:
I don’t have an consistent way to attempt these “needle-in-a-haystack” style problems (is there one?), so I went with a manual approach, running “strings” across each of the extracted objects.
Eventually, I identified an odd-looking favicon(1).ico, comprised of obfuscated JS:
I quickly extracted the base64, which turned out to be a binary file, containing a .NET executable at a non-zero offset. We then extract the file and pop it into ILSpy to determine what it does:
It looks like this is a reasonably simple XOR cipher, but I couldn’t find the key initialization anywhere. Going back to the JS, we find our culprit:
We can then match this up with our disassembly, to note that the “Aa6b…” function takes the last 22 characters of it’s argument as the xor key:
Knowing this, a quick python script gives us the flag:
Rescue Shell
This challenge was presented as a Linux binary, which you can download here. This was ostensibly a shell in itself, but was disabled (and infact, did not import any shell-executing functions).
Popping this into IDA pro, I quickly got the sense that this was a classic stack overflow vulnerability, conveniently using read (so null bytes were safe).
A quick test later, and this is confirmed, with the return address from check_passphrase being controlled:
Controlling the stack to this extent makes the rest of the challenge trivial: we then wrangle a rop chain to leak the address of one of the elements in the GOT (using 0x40099a as a “leak” gadget, taking an argument from the stack) and then from there, bounce to a libc magic gadget to give us shell:
You can download the python script I used here.
As always, thanks to the NDH organisers for putting together another quality CTF event. There’s quite a number of CTF events next weeked to participate in, so I’ll likely see you all in UIUCTF next weekend.
Nice writeup, i have a noob question, why do they provide the libc.so.6 ? Its for local testing purpose? How can i set the ELF to run with that libc? Thanks!!
It’s not – libc is provided so you can take one address from libc, leaked from the GOT, and calculate the location of something else in libc, and have that work on the target system.
You might be able to run it against the remote libc with LD_LIBRARY_PATH=/path/to/libc /path/to/libc/libc.so.6 /path/to/chal/chal, but ymmv (see https://unix.stackexchange.com/questions/195505/run-a-program-with-a-newer-libc for more info).
Thank you! Very clear!
Hi, i am quite confuse with the exploit here. So basically you are leaking the GOT of fread 0x601210 and calculate the base address with GOTfread – 0x6A460. After that may i know which libc function you are returning to? Because i dont see any function with offset 0x41320. I am guessing you might return to system but if it is the case, we still need the arguement of /bin/sh
This is a magic libc gadget. In libc there’s a few places where if you return, AND some conditions are met (in this case – from memory, RAX had to be zero), it’s the equivalent of a complete execve /bin/sh.
Take a look at one_gadget for more information.
Thanks. It is very clear for me. However i still have one more question that might seems dump. May i know why you choose fread GOT to leak? I try other GOT for example strncmp and i realize the base address is not correct after minus the offset. Do we have a clue on which GOT to choose?
There isn’t a specific reason beyond strncmp (the first logical choice) didn’t seem to work when I initially tried it, getting directed to some other variant strncmp when I tested locally.