Recently, I got an incident related to Windows Defender detected & quarantined file related to some backdoor. The MDE alert details show something like this:
Usually, we go with the easiest way; by contacting user & ask the million dollar question (like details of the file, the purpose, etc.)
So I was thinking, since the file has been quarantined by MDE, can’t we just retrieve it remotely from user host machine for further analysis?
Initially, my teammate already remoted to the host machine; to check whether the file still exist or not on user Desktop folder. Unfortunately, the file seems already gone – which we thought the user already deleted the file.
But after a careful look on the MDE alert details, we notice that it mentioned the file been quarantined – not deleted by Defender (it means that the file still exist! yeay!).
This is where came an idea to look on Defender quarantine folder on user host machine – to see if the detected file still available to be fetch for further analysis.
File Structure
Windows Defender stores all of its quarantine related files inside this folder:
C:\ProgramData\Microsoft\Windows Defender\Quarantine
The contents of this folder has the following structure:
C:\ProgramData\Microsoft\Windows Defender\Quarantine
├── Entries
│ └─ {RANDOM_GUID}
├── ResourceData
│ └─ <RANDOM-CHAR>
│ └─ <RANDOM_ID>
└── Resources
└─ <RANDOM-CHAR>
└─ <RANDOM_ID>
Entries folder
Files contained in this folder have a unique GUID as their filename – e.g. {80039D6E-0000-0000-A208-04AFAAF7C4DF}. This file contains information:
- Full path of the original file
- Signature
- Timestamp
- Unique Hash
ResourceData folder
This is where the actual quarantined files are stored. The filenames are composed of a custom hash, uniquely identifying each sample. Every sample is also grouped into a subfolder, where subfolder name is obtained from the first two characters of a hash.
To decrypt files in this folder, we simply apply the RC4 to the whole file.
Go Get ‘Em
Let’s go check the mentioned path on user machine via our favorite EDR:
[123456789] C:\WINDOWS\Temp\> ls C:\ProgramData\Microsoft\Windows Defender\Quarantine\
Directory of C:\ProgramData\Microsoft\Windows Defender\Quarantine\
11/06/2023 06:16 AM GMT <DIR> .
11/07/2023 12:39 AM GMT <DIR> ..
11/06/2023 06:16 AM GMT <DIR> Entries
11/06/2023 06:16 AM GMT <DIR> ResourceData
11/06/2023 06:16 AM GMT <DIR> Resources
[123456789] C:\WINDOWS\Temp\> ls C:\ProgramData\Microsoft\Windows Defender\Quarantine\ResourceData
Directory of C:\ProgramData\Microsoft\Windows Defender\Quarantine\ResourceData\
11/06/2023 06:16 AM GMT <DIR> .
11/06/2023 06:16 AM GMT <DIR> ..
11/06/2023 06:16 AM GMT <DIR> 1F
[123456789] C:\WINDOWS\Temp\> ls C:\ProgramData\Microsoft\Windows Defender\Quarantine\ResourceData\1F
Directory of C:\ProgramData\Microsoft\Windows Defender\Quarantine\ResourceData\1F\
11/06/2023 06:16 AM GMT <DIR> .
11/06/2023 06:16 AM GMT <DIR> ..
11/06/2023 06:16 AM GMT 2391097024 1F4C9AA31FEECD648D6F148A0B74C65EA665BA56
Seems this is the only file inside here. Lets fetch the file:
[123456789] C:\WINDOWS\Temp\> get C:\ProgramData\Microsoft\Windows Defender\Quarantine\ResourceData\1F\1F4C9AA31FEECD648D6F148A0B74C65EA665BA56
File ready for download
Open ‘Em Up
Now we have downloaded the file. Let’s open it:
Hmm. Unable to open it. I thought its a .tgz (compressed archive file). Let’s see what kind of file is this:
Filetype: data? Hmm.. Something is not right here. If we open the file via WinHex, view the file entropy histogram, seems like its been encrypted:
The Saviors
After Googling for a while, I found these 2 article:
- https://reversingfun.com/posts/how-to-extract-quarantine-files-from-windows-defender/
- https://jon.glass/blog/quarantines-junk/
Based on article above, it seems like the Defender take file that it detect as malicious and put it into folder mentioned earlier; and apply encryption to the file using RC4 cipher.
The article above also mentioned that Defender uses a hard-coded static key to obfuscate the quarantine files.
The RC4 key as follow:
0x1E, 0x87, 0x78, 0x1B, 0x8D, 0xBA, 0xA8, 0x44, 0xCE, 0x69,
0x70, 0x2C, 0x0C, 0x78, 0xB7, 0x86, 0xA3, 0xF6, 0x23, 0xB7,
0x38, 0xF5, 0xED, 0xF9, 0xAF, 0x83, 0x53, 0x0F, 0xB3, 0xFC,
0x54, 0xFA, 0xA2, 0x1E, 0xB9, 0xCF, 0x13, 0x31, 0xFD, 0x0F,
0x0D, 0xA9, 0x54, 0xF6, 0x87, 0xCB, 0x9E, 0x18, 0x27, 0x96,
0x97, 0x90, 0x0E, 0x53, 0xFB, 0x31, 0x7C, 0x9C, 0xBC, 0xE4,
0x8E, 0x23, 0xD0, 0x53, 0x71, 0xEC, 0xC1, 0x59, 0x51, 0xB8,
0xF3, 0x64, 0x9D, 0x7C, 0xA3, 0x3E, 0xD6, 0x8D, 0xC9, 0x04,
0x7E, 0x82, 0xC9, 0xBA, 0xAD, 0x97, 0x99, 0xD0, 0xD4, 0x58,
0xCB, 0x84, 0x7C, 0xA9, 0xFF, 0xBE, 0x3C, 0x8A, 0x77, 0x52,
0x33, 0x55, 0x7D, 0xDE, 0x13, 0xA8, 0xB1, 0x40, 0x87, 0xCC,
0x1B, 0xC8, 0xF1, 0x0F, 0x6E, 0xCD, 0xD0, 0x83, 0xA9, 0x59,
0xCF, 0xF8, 0x4A, 0x9D, 0x1D, 0x50, 0x75, 0x5E, 0x3E, 0x19,
0x18, 0x18, 0xAF, 0x23, 0xE2, 0x29, 0x35, 0x58, 0x76, 0x6D,
0x2C, 0x07, 0xE2, 0x57, 0x12, 0xB2, 0xCA, 0x0B, 0x53, 0x5E,
0xD8, 0xF6, 0xC5, 0x6C, 0xE7, 0x3D, 0x24, 0xBD, 0xD0, 0x29,
0x17, 0x71, 0x86, 0x1A, 0x54, 0xB4, 0xC2, 0x85, 0xA9, 0xA3,
0xDB, 0x7A, 0xCA, 0x6D, 0x22, 0x4A, 0xEA, 0xCD, 0x62, 0x1D,
0xB9, 0xF2, 0xA2, 0x2E, 0xD1, 0xE9, 0xE1, 0x1D, 0x75, 0xBE,
0xD7, 0xDC, 0x0E, 0xCB, 0x0A, 0x8E, 0x68, 0xA2, 0xFF, 0x12,
0x63, 0x40, 0x8D, 0xC8, 0x08, 0xDF, 0xFD, 0x16, 0x4B, 0x11,
0x67, 0x74, 0xCD, 0x0B, 0x9B, 0x8D, 0x05, 0x41, 0x1E, 0xD6,
0x26, 0x2E, 0x42, 0x9B, 0xA4, 0x95, 0x67, 0x6B, 0x83, 0x98,
0xDB, 0x2F, 0x35, 0xD3, 0xC1, 0xB9, 0xCE, 0xD5, 0x26, 0x36,
0xF2, 0x76, 0x5E, 0x1A, 0x95, 0xCB, 0x7C, 0xA4, 0xC3, 0xDD,
0xAB, 0xDD, 0xBF, 0xF3, 0x82, 0x53
I use Python script from Jon.Glass blog (modified a bit to fit my needs). After the file successfully decrypted, you should be able to open the file:
Random check the file content, seems like its an application log file (sort of I guess).
I’m thinking, why this logs detected by Defender as backdoor?
So, I randomly pick content from “[REDACTED]/varlog.tar->log/apache2/webui_httpd_access.log”, save it into new text file & scan it with Defender.
After several trial & error, I found this line below that appear to be detected by Defender:
2023-07-18T15:51:59.532008+08:00 <19.6> [REDACTED](REDACTED) httpd[4365]: REDACTED - - [18/Jul/2023:15:51:59 +0800] "GET /index.php HTTP/1.1" 404 196 "-" "}__test|O:21:\"JDatabaseDriverMysqli\":3:{s:2:\"fc\";O:17:\"JSimplepieFactory\":0:{}s:21:\"\\0\\0\\0disconnectHandlers\";a:1:{i:0;a:2:{i:0;O:9:\"SimplePie\":5:{s:8:\"sanitize\";O:20:\"JDatabaseDriverMysql\":0:{}s:8:\"feed_url\";s:63:\"eval(base64_decode($_POST[123456]));JFactory::getConfig();exit;\";s:19:\"cache_name_function\";s:6:\"assert\";s:5:\"cache\";b:1;s:11:\"cache_class\";O:20:\"JDatabaseDriverMysql\":0:{}}i:1;s:4:\"init\";}}s:13:\"\\0\\0\\0connection\";b:1;}\xf0\xfd\xfd\xfd"
Here’s the Defender scan result:
Based on Google, this seems related to some kind of Joomla exploit.
So, we can safely mark this as False Positive; as the detection is related to content from a log files – not a truly backdoor file detection.
Side Quest – Rust vs Python
Couple days later, I saw a Tweet/X post related to Rust vs Python performance. In that post, it shows that Rust use less resources & executes faster.
I’m thinking, since the Python script from reference site require your machine installed with Python (I know you can also convert it into exe using pyinstaller/auto-py-to-exe), why not try to create script in Rust & compare against Python & compiled Python. Therefore, we can see if the Rust is truly king or not :p
Size
In term of size comparison, the Rust code is just 327 KB whereby the compiled Python code is around 7 MB. That’s a huge difference:
327 KB - defender_file_decryptor.exe (Rust)
7.0 MB - MDE_Decode.exe (AutoPy)
3.8 KB - MDE_Decode.py (Python)
Resource & Performance
To measure the resource that each code use & its performance, I’ve created a Powershell script to measure CPU, Memory (RAM) usage & time taken to complete decrypting 2 GB file. The result as below:
C:\>.\Code_Benchmark.ps1
Rust - defender_file_decryptor.exe
Monitoring results:
CPU Usage Percentage (Avg): 7.82%
Memory Usage: Min = 2283 MB, Max = 4502 MB, Avg = 3017 MB
Total Execution Time: 0 Days, 0 Hours, 0 Minutes, 21 Seconds
C:\>.\Code_Benchmark.ps1
Python - MDE_Decode.py
Monitoring results:
CPU Usage Percentage (Avg): 12.35%
Memory Usage: Min = 2 MB, Max = 5457 MB, Avg = 4549 MB
Total Execution Time: 0 Days, 0 Hours, 14 Minutes, 25 Seconds
C:\>.\Code_Benchmark.ps1
AutoPy - MDE_Decode.exe
Monitoring results:
CPU Usage Percentage (Avg): 0.00%
Memory Usage: Min = 5 MB, Max = 5 MB, Avg = 5 MB
Total Execution Time: 0 Days, 0 Hours, 14 Minutes, 5 Seconds
As you see, the Rust executed & finished the task very fast – decrypting 2 GB file in 21 seconds with CPU usage of 7.82%; while both Python script & compiled Python code takes around 14 minutes to complete decrypting.
The Python script uses 12.35% of CPU resources, but it shows 0% of CPU & only 5 MB of RAM usage for compiled Python. I’m not sure why.
The End
If you interested to see & test the code, I’ve published all the necessary code at my Github:
So yeah. Hope you enjoy my journey learning on how to decrypt Defender quarantine file & learning little bit about Rust. 🙂
Great write-up and informative, thank you!
I was wondering, there are quite some straightforward methods to retrieve quarantined files (like the ‘download file’ button in the alert view of a quarantined file), is there any reason you went this way to retrieve files while it can be collected through the Defender GUI?
If yes, did you notice any difference in collecting the quarantined file through Defender versus your method?