So I don't really have much time for playing CTFs right now, but yesterday I took it for the "th3jackers" CTF. I solved the Reversing 100 and Crypto 300 challenges.
Crypto 300
For the Crypto 300 challenge, there were two files given, a wat.png that was no valid PNG file and a key.txt that said:
the key is : aniesse
Looking at wat.png in a hex editor, I saw the string "ssea" somewhere near the end so I suspected the file was just XORed with the (repeated) key. Undoing that gave in fact a valid PNG file:
That looks like a scrambled QR code, but exactly how is it scrambled? I was
scratching my head for a while until I threw strings
at it to find the
following text in it:
----- IMAGE ORDER ----------
MTIzNzg5NDU5
Nzg5NDU2MTIz
NDU2MTIzNzg5
MTIzNzg5NDU5
Nzg5NDU2MTIz
NDU2MTIzNzg5
MTIzNzg5NDU5
Nzg5NDU2MTIz
NDU2MTIzNzg5
These lines are encoded with Base64, so undoing that gives us:
123789459
789456123
456123789
123789459
789456123
456123789
123789459
789456123
456123789
So apparently the original QR code was split into 9x9 small images and then those images were scrambled around in the order given above. Note that every 3rd line has two 9s instead of a 6, so some information went missing.
So I wrote a script to do the unscrambling and the QR code had lost too much information to decode. I refined my script a bit - my first version split the image in a 3x9 pattern which left quite some artifacts due to rounding differences - but that didn't solve the problem. So I thought maybe instead of leaving whatever image data is at the position of those 6s, I should gray them out so that I don't give any wrong black/white information to the QR decoder. The result is an image like this, that still doesn't decode:
If you look closely at the edges of the 2nd and 3rd gray box, you can see that the gray boxes don't align with the 15x15 pixel sized boxes that make up the QR code. For example, below the box in the middle we can see a small stripe of black. So we know there should be 3 black 15x15 boxes in the lower third of that gray box. Applying the same technique all around the 2nd and 3rd gray box gave me this image:
And feeding this into zbarimg
successfully decodes to the string
8d54e284d4668bbed5dc391b27kc7fc05
:). I didn't really know what to do with
this. It looks like a hex string, but there's a "k" in there so it can't really
be. Even if it were, it can't be ASCII because there's a bunch of characters >
127. It's no Base64 either and Google doesn't know the string either. So that's
where I finally went to bed, thinking I'd continue the next day. Turns out the
CTF actually already ended after 12 hours, not 48 hours as it said on
CTFTime.
Luckily, my teammate Tim had the glorious idea of just ignoring the "k" and to treat the string as a hex encoded md5 sum. So he went to MD5DB to paste the data and voila - we had the flag "beprepared".
For reference, this is the script I hacked together to descramble the QR code:
Reversing 100
This was a rather small task. It was a 32bit Linux binary. Static analysis
showed that it first computed some kind of checksum over some memory area then
use that (with some bit rotation) as the XOR key to a static memory buffer.
Lazy as I am, I didn't want to write a program to compute the checksum, so I ran
the program in GDB, set a breakpoint after the checksum was computed and printed
it. But it wasn't as easy as that - the checksummed memory area was actually the
main
function and setting a breakpoint changes the first byte of a instruction
to 0xcc
. So that means you have to use a hardware breakpoint (hbreak
) in
GDB.
Besides that, everything was straight-forward and the following script gave me
the correct flag flag{$O_mUcH_FuN_w1tH_r3v3R$iNg}
: