Unfortunately I didn’t have much time to play this CTF, but this challenge caught my eyes and I decided to look at it at the last few hours of the tournament. I didn’t manage to do it in time for the CTF due to the lack of time and some bone-headed mistake, but I went on with it anyways the day after.
Note: All the files related to this challenge can be found here
Reconnaissance (and failures)
So we were given showmethemoney.zip with the description:
Not very helpful, but we check out the contents and we find 3 files
readme.txt simply stated
Show me the money to decrypt it.
Not very informative yet, but seems highly likely that we’re looking at some hypothetical ransomware situation. We need to dig deeper.
A quick look at
showmethemoney.exe reveals that it is a .NET executable. Neat. So I fired up .NET Reflector to check it out. The application is relatively simple, just a couple of classes.
AesCryptoHelper is a rather peculiar wrapper class around .NET’s
AESCryptoServiceProvider, and it seems like a red herring because it’s never referenced in the code that actually gets run. Let’s dig a little deeper then.
There are some interesting things going on here, but for a quick rundown of how things happen starting with
IDis generated using
keyis generated using some combination of
RijndaelManaged(AES in this case) is used to encrypt the contents of
keyand overwrite it with the base64 encoding of the ciphertext. Note that the
ECBmode is used and the key size is 256 bits. I considered this more evidence that the
AesCryptoHelperclass is a red herring since it uses
CFBmode, but I could still be mistaken at this point.
- Both the generated
keyare sent to a process listening on port 9999 on some server. The format of the message is
With this in mind, I started looking at how could I possibly replicate the state of the
System.Random PRNG to hopefully manage to recover the key. I frantically searched for any bugs or information leaks from GUIDs only to learn that this specific GUID implementation is a UUID version 4, as indicated by the character
4 at the beginning of the third part in the given ID
09ce12e1-b775-4bda-af37-8abd886478ee. Those do not leak information (allegedly) like previous versions of UUID and are well, for all purposes of this challenge, a dead end. And this would be the reason why I couldn’t finish this challenge during the CTF as I went on looking down this - incorrect - path wasting a good hour and a half before calling it quits for the day.
Fast forward a day later, I decided to list the information that I currently posses:
- How the data was encrypted.
- Which server the data was sent to.
After listing the 2nd item, I already knew what I missed. So I fired up nmap and decided to take a look at this server, which luckily was and is still running at the time of writing of this post. There were 3 open ports:
22 (ssh), and
We know that
9999 is the port that the ransomware sends the keys to, but why is
Oh look, what is this? vvss?
It turns out to be an ELF. IDA is fired up and after some quick messing around, we learn that this application uses 2 sqlite databases, namely
keysbak.db, the latter seemingly a backup of the former. It also accepts input of the forms:
(2), it forms a query that it executes on
(1) adds a new row to the table
keys with columns
len=length(plain). This is clearly the routine used to store keys and their respective IDs that the ransomware sends.
(2) reads the row with
qid=string1 and deletes it from the table afterwards. It’s very likely that neither of these are of any help given what they do.
(3) runs a
select * from keys; query on
keysbak.db. Yep, there it is.
Attack vector (Very Very Secure System)
So now that we know what we need to do, it’s very easy to write a python script that will send our query to the process. This is the output from the script:
> python attack.py Sent 4 bytes Received: 5 bytes ID:1 Received: 87 bytes PLAIN:58897d583d888978b62469889d584472 QID:09ce12e1-b775-4bda-af37-8abd886478ee LEN:32
QID matches the
ID in the given readme! Hence, our key is
It’s just as simple then to write another script to decrypt the contents of
flag.txt, and indeed we get the flag we’re looking for:
Moral of this writeup: do your reconnaissance well before going down rabbit holes.