[FCSC 2019] - 3615 Incident (3/3)
Introduction 📌
The context remains the same as in Part 1 and Part 2. Yet another victim has fallen victim to ransomware. Payment of the ransom is not an option, given the amount involved. So we’re called in to try and restore the encrypted files.
This time, the objective is to decrypt the attached data file.
(The challenge is always solved using the mem.dmp.tar.xz
file. As a reminder, this is a memory image of the victim’s computer. In concrete terms, it corresponds to the contents of volatile memory (RAM
) at the time of acquisition. We also have the data
file to decrypt.)
1. Study of the encryption algorithm 📋
In order to decrypt the data
file, we’ll need to study the encryption algorithm implemented by this ransomware. Since we have access to the source code, this greatly simplifies the process.
Zoom on ransomware.go
(again, yes)
Let’s go back to the file /cmd/ransomware/ransomware.go, line 223 this time.
|
|
We can see that the Encrypt()
encryption function comes from the file
file. It seems to take the encryption key and a temporary file name as parameters. It is therefore necessary to analyze what exactly this function does.
Zoom on file.go
The encryption algorithm used by the Encrypt()
function can be found in line 21 of the cryptofs/file.go file.
|
|
The first part of the code shows the use of the AES-256 encryption algorithm. Encryption is carried out in counter mode (CTR), as can be seen below.
The second part of the code tells us that the IV
is the first block of the encrypted file. This is good news for us. Since we have the encrypted files and the encryption key, all we need to do to decrypt them is extract the IV from them.
2. Decrypting the data
file 🔓
IV Extraction
To extract the IV
from data
, we can use xxd
to get the file contents in hexadecimal and fold
to split it into 32-character blocks (remember, the IV is a 32-character hexadecimal string). Then we can use head
to keep only the first block, using the -n 1
option.
|
|
In this way, we obtain the IV
corresponding to our data
file : b627d24fc90dfe7ce421c43312dc2f2e
Decryption with Cyberchef (lazy way)
To decrypt our file, we can use Cyberchef. To do this, we need to give it an input (input) the contents of the encrypted file (here data) in hexadecimal. To do this, we can use xxd
.
sed
tool to do this.
|
|
*As the result is too large, I will only write the characters corresponding to the beginning and end of the file here.
We then need to copy/paste this result into Cyberchef, select the AES Decrypt
recipe and enter the following parameters:
- Key (UTF-8) :
95511870061fb3a2899aa6b2dc9838aa
- IV (HEX) :
b627d24fc90dfe7ce421c43312dc2f2e
- Mode :
CTR
- Input :
HEX
- Output :
RAW
We can see that decryption seems to be effective, since we can see the header of a ZIP file 50 4b 03 04
corresponding to PK
and other strings such as :
- _rels/.rels
- docProps/core.xml
- docProps/app.xml
- word/_rels/document.xml.rels
- word/document.xml […]
These lead us to believe that we are dealing with a Word document. Our file would therefore be the equivalent of flag.docx
that we found in the first part of this test. We can then download the file to our machine. Here, we call it flag.zip
. We can now unzip it:
|
|
The content of a word file is usually found in the word/document.xml
document. We can therefore use grep
to display the flag directly without having to open it:
|
|
And that’s it! The decryption is a success. Now let’s look at another way of doing it.
Decrypting with Python (street credibility++)
To decrypt our data
file, we can also call on our programming skills (or call on our friend ChatGPT :p). Since we’re more familiar with Python, we’ll use it to decrypt our file. However, you’re free to choose another programming language for this exercise.
Here’s the decrypt.py
script in question:
|
|
The principle is simple:
- Ask the user the path to the encrypted file.
- Ask the user for the path and name of the file in which to store the decrypted content.
- Ask the user for the decryption key.
Then, this script will automatically extract the IV from the encrypted file, display it to the user and finally decrypt its contents.
*It would be interesting to modify this script so as to be able to decrypt all files with the extension .encrypted' and name them by their original name (just decode their name in
base64’).
Here’s an example:
|
|
We can check the file type using file
:
|
|
The script works, since the command correctly detects the decrypted file as a Word document. We can now unzip it and use the same grep
as before:
|
|
We’ve got our flag back. :D
3. Flag 🚩
We have therefore succeeded in helping our victim to decrypt his files.
The flag for this final challenge is: ECSC{M4ud1t3_C4mp4gn3_2_r4NC0nG1c13L}
.
This third and final challenge marks the end of the event. I’d like to thank you for reading my writeups and hope I’ve made my explanations clear enough. Don’t hesitate to give me your feedback by contacting me directly on Discord or Twitter ;)
BONUS - Find the flag without the data
file 💡
Being curious by nature, I wanted to see if it was possible to find the flag directly using the encrypted flag.docx
file (ZmxhZy5kb2N4.encrypted) from the memory dump. As a reminder, we had found its virtual address in the dump using the windows.filescan
plugin from Volatility3.
|
|
I then recovered the file using the windows.dumpfiles
plugin and the --virtaddr
option, followed by the virtual address of ZmxhZy5kb2N4.encrypted
.
|
|
I then ran my Python script on the encrypted file:
|
|
As this is indeed considered a Word document, I unzipped it and used grep
to extract the flag :
|
|
It is therefore possible to solve this last test without relying on the attached data
file.