In my quest to learn forensics, I took on the annual French cybersecurity challenge organized by ANSSI. It was my first time participating in it, so I approached it calmly, focusing on solving the tasks that would help me learn the most.
Being entirely new to the field of forensics, I learned on the fly through this challenge, and I thought it would be good to share the challenge that I enjoyed solving the most.
Challenge Objective
You were looking at your beautiful cat photos when suddenly your super-secret file on your desktop changes its extension and becomes unreadable…
You capture memory to understand what happened in order to recover this precious file.
According to the description, it appears that we are dealing with ransomware that has encrypted a specific file on the desktop.
Using the provided memory capture, we will follow this trail and find a way to recover the file.
Finding the Malware
The first step is to locate the malware in the memory capture. We will analyze it using the volatility3 memory analysis tool.
I started with the more complex part. I analyzed the handles to the desktop using the windows.handles
option. In Windows programming, a handle is an object returned by a function that allows interaction with Windows objects (programs, files, registry keys, etc.). When a process interacts with one of these objects, it first obtains a handle to it.
Since we know that the process is acting on the desktop, it is natural to think that a handle to the desktop must be associated with a specific process:
|
|
The only “non-system” process with a handle on the desktop is svchost.exe with a PID of 5540.
Now, the simpler method:
|
|
It can be noted that svchost.exe was created from a user process (VboxTray) descending from explorer.exe, which is suspicious.
Malware Analysis
Once this process is identified, it should be extracted from memory for analysis. In fact, most running processes during a memory capture keep their executable file inside it:
|
|
This first function generates 64 random bytes and writes them to a file each time it is executed. The file containing these bytes will be located at “C:\Windows\Temp\MsCmdRun%d.log” where %d will be replaced by the corresponding execution number.
|
|
This function snippet is responsible for file encryption. This is where we understand the encryption logic of this malware. It is simple: randomly generated bytes are used to XOR the bytes of the original file, along with the execution number.
The program scans the desktop in search of any file with the .fcsc extension. If it doesnt find one, it increments a counter and generates new random bytes.
We know that XOR is a reversible operation. So, having the execution counter, the file with random bytes, and the encrypted file, we can recover the original file.
Now, we just need to recover these files..
File Recovery
Volatility3 contains a command to list files present in memory:
|
|
These are the random byte files present in memory. However, it’s not enough because we don’t know which one was used to encrypt our file. Additionally, memory doesn’t contain the encrypted file on the desktop.
This is where the Master File Table (MFT) comes into play. In simple terms, in an NTFS file system, there is a file that records information about each file on the disk (size, last modification, address on the disk), making it easier for Windows to find it. This table also stores the content of small files, and much of it is available in memory.
Volatility3 doesn’t provide in-depth analysis of the MFT, so we have to resort to volatility2:
|
|
I found the encrypted file in the MFT table. We know that a file with random bytes named MsCmdRun is created before altering the flag file. So, I searched in this table for an MsCmdRun file with the creation/modification date closest to that of the flag:
|
|
With these two files, all that remained was to create a script to decrypt the flag.
At first, I thought the execution counter incremented with each encrypted file. Since it was the only encrypted file, I assumed the counter corresponded to 0. XORing by 0 is trivial, so I omitted this operation:
|
|
However, the flag was still encrypted. I noticed that the beginning of the flag was still recognizable, as the flags in this competition started with FCSC. I saw the presence of 2 M’s corresponding to the two C’s in the flag header. So, I needed to find the value that, when XORed with M multiple times, would yield C. This is the weakness of XOR algorithms when part of the initial string is known; it can be brute-forced to obtain the final string.
The value 14 allowed me to reveal the flag. This is how I realized the importance of the execution counter, and that it was recorded in the random byte file (MsCmdRun14):
|
|
Conclusion
And so, this forensics challenge comes to an end. It was very interesting and taught me a lot about memory analysis and other Windows internals. My reverse engineering skills allowed me to easily pass the malware analysis task, where others may have failed due to a lack of expertise.