Type: CTF task

Platform: Windows x86

Category: Reverse

Idea: ransomware encrypted one file, need to decrypt file

It was a simple reverse-engineering task. But there was a mistake in the first version of this task. I will analyze both versions of this task.

Let’s look at description.

So, we have something of ransomware on Windows and encrypted file.

If we load this binary in IDA, then we will see that it not packed. This already makes the task easier. In the beginning, we may notice some useless checks (language and time) that prevent it from starting on the machine. We can just remove them.

There is also a whole function with testing various analysis and debugging tools. But we can also patch it so that it always returns 0. Part of this function in the image below.

Patch is simple.

Now we need to find encryption function. I just trying to find some crypto constants, and found AES sbox in memory.

Now you can find where the encryption takes place by cross-referencing (xrefs).

Using the links, we find such a code (picture above) and it is very similar to the AES-CFB mode. Now we need to figure out how the key and the initialization vector are formed.

The function in which the encryption function is called initially checks if we have found the right folder. If so, then we calculate some checksum from the name of the file in the folder, after which this value is used as an initializer of some random generator.

Next, using this generator, we get the values of the key and the initialization vector.

And it was in this place that a mistake was made. The fact is that AES 256 was chosen and the key size was 32 bytes, and the size of the initialization vector was 16 bytes. But if you look closely at how much memory is allocated for the key and the vector (56-59 lines), then you can understand that there are only 8 bytes, which means that the remaining bytes will be taken from the heap, where any bytes can be located. As a result, the file cannot be decrypted.

This bug was fixed in the second version (After 17 hours from the start of the task).

Fix in the image below.

And now we have 32 bytes for key and 32 bytes for iv (Although in fact the second 16 bytes are not processed). After the fix, all the solutions to the task came down to set a breakpoint in one place and dumping the key and the IV.

And just dump key and IV from heap.

Key: 2D91949EA0C067B0BCF4F47F066D2B39B0A54F78FBF5DB2BA021A1F10DE50FC2

IV: 7925CFE7133F19A8C6A14D3868B8E1BC

Now you just need to decrypt the file. Although I had some problems with the CFB mode (it only decoded the first 16 bytes correctly), I used the OPENPGP mode, which was almost the same and got everything except the first two blocks, but that was enough to unpack the file and get the flag.

Code to decrypt:

from Crypto.Cipher import AES
from binascii import unhexlify

key =
unhexlify("2D91949EA0C067B0BCF4F47F066D2B39B0A54F78FBF5DB2BA021A1F10DE50FC2")
iv = unhexlify("7925CFE7133F19A8C6A14D3868B8E1BC")
data = open("plan_important.docx",'rb').read()

ctx = AES.new(key, AES.MODE_OPENPGP, iv=iv)
out = ctx.decrypt(data)

fd = open("out.docx", 'wb')
fd.write(out)
fd.close()

After decryption I got this file.

And I unpacked it with a zip. In word/document.xml I found the flag.

Flag: ZN_ HOHrTOPUu6fmFTdWJ67W_ nUwHpcPS12b9gqp9W6oa

Summary: It seemed to me that the task was too easy for such a cool hack quest. Also, the mistakes made by the developer look very childish and it is not clear why it was written that the error was in the library. Obviously, the error was in the custom code and not in the AES implementation.