What happens when Windows Defender Quarantines Stuff...

Recently a colleague of mine asked me what happens in the file system when a malicious file is "quarantined". The answer varies widely and as this is the "secret sauce" for many antivirus vendors, most of the time it is not overly documented how they do the voodoo they do. Seems like something that might make for a good blog or two so I sat down and did a few tests.

This post is going to cover what happened on my Windows 8 VM when I turned Windows Defender against a vicious EICAR.TXT file!

Windows Defender is a software product that attempts to detect and remove malware. Initially released as an antispyware program, it was first released as a free download for Windows XP, shipped with Windows Vista by default, and currently ships with antivirus capabilities as part of Windows 10. --Wikipedia

I chose to beat up on Windows Defender mostly because it is free and has a huge market share. Nothing personal.

So first things first: I grabbed the EICAR file and saved it to C:\temp.
Then I grabbed a copy of the $MFT to take a look at the this file's record. Looks like this:
2015-11-02 23_26_38-Document - WordPad
There is a lot going on in there but I just wanted to focus on a few things. If you are lost, read this.

NEXT, I turned on Windows Defender real-time protection. It was recommended.

Then a whole bunch of stuff happened.

Let's start with $MFT record number 27152. So I quickly dumped the $MFT again and here's what I got:

2015-11-03 00_52_57-Document.rtf - WordPad

So what changed? Pretty much everything accept the $MFT record number.

The sequence number is increment by 4, indicating that there were numerous changes to the file. Specifically the rename and move to a new parent folder.
Lets take a closer look at the USNJrnl-$J to get an idea what happened:

###When I created the EICAR File and Added the EICAR string to it.###
2015-11-03 03:03:23.186	ref_num = 27152-96	eicar.txt	File_Create,Close
2015-11-03 03:03:23.231	ref_num = 27152-97	eicar.txt	File_Create,Data_Extend,Close
2015-11-03 03:06:48.274	ref_num = 27152-97	eicar.txt	Data_Extend,Data_Truncation,Close

### This is Windows Defender Deleting the File. ###
2015-11-03 03:07:20.379	ref_num = 27152-97	eicar.txt	Object_ID_Change,Close
2015-11-03 03:09:43.529	ref_num = 27152-97	eicar.txt	Basic_Info_Change,Data_Overwrite,File_Delete,Close

###Since this Record Number is up for grabs, it is reused for a different file ###
2015-11-03 03:09:43.534	ref_num = 27152-98	5A7D7B64F11FF203E09434276A974A97	File_Create,Data_Extend,Close

So in short Windows Defender deleted the original file. The MFT record number was up for grabs so it was picked up by a newly created file C:\ProgramData\Microsoft\Windows Defender\Scans\History\RemCheck\5A7D7B64F11FF203E09434276A974A97

So where did my EICAR file go? Windows Defender puts quarantined files C:\ProgramData\Microsoft\Windows Defender\Quarantine\ResourceData\. Mine was saved C:\ProgramData\Microsoft\Windows Defender\Quarantine\ResourceData\50\50761523FA79FDF68E04707959836D1F6DBA9969.
Let's take a look at that:
2015-11-05 19_55_39-Document.rtf - WordPad
For those that don't know, Windows Defender and Microsoft Security Essentials Quarantine files have a magic number of 0B AD 00. Clever.

Looking at the histogram of the data, it is pretty obvious that it was stored using some kind of encryption.
Screen Shot 2015-11-04 at 10.40.52 AM
After doing a bit more digging, it turns out that Windows Defender uses a hard coded RC4 key to encrypt quarantine files.
A colleague of my pointed me at the this cool script from Cuckoo
Here is the relevant chuck of their code that I bastardized for this blog post:

# Copyright (C) 2015 KillerInstinct, Optiv, Inc. (brad.spengler@optiv.com)
# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
# See the file 'docs/LICENSE' for copying permission.

import os
import struct
import hashlib
from binascii import crc32

def mse_ksa():
    # hardcoded key obtained from mpengine.dll
    key = [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
    sbox = range(256)
    j = 0
    for i in range(256):
        j = (j + sbox[i] + key[i]) % 256
        tmp = sbox[i]
        sbox[i] = sbox[j]
        sbox[j] = tmp
    return sbox

def rc4_decrypt(sbox, data):
    out = bytearray(len(data))
    i = 0
    j = 0
    for k in range(len(data)):
        i = (i + 1) % 256
        j = (j + sbox[i]) % 256
        tmp = sbox[i]
        sbox[i] = sbox[j]
        sbox[j] = tmp
        val = sbox[(sbox[i] + sbox[j]) % 256]
        out[k] = val ^ data[k]

    return out

def mse_unquarantine(f):
    with open(f, "rb") as quarfile:
        data = bytearray(quarfile.read())

    fsize = len(data)
    if fsize < 12 or data[0] != 0x0B or data[1] != 0xad or data[2] != 0x00:
        return None

    sbox = mse_ksa()
    outdata = rc4_decrypt(sbox, data)
    with open("unquar-with-meta.bin", "wb") as f:

    # MSE stores metadata like the original filename in a separate file,
    # so due to our existing interface, we can't restore the original name
    # from just the ResourceData file.  Later we may allow uploading pairs
    # of files, match them up by name, and then associate that data here
    # for the final submission

    headerlen = 0x28 + struct.unpack("<I", outdata[8:12])[0]
    origlen = struct.unpack("<I", outdata[headerlen-12:headerlen-8])[0]

    if origlen + headerlen = fsize:
        with open("unquar.bin", "wb") as f:

The RC4 cipher can be found twice in each of these files:
c:\ProgramData\Microsoft\Windows Defender\Definition Updates\Backup\mpengine.dll
c:\ProgramData\Microsoft\Windows Defender\Definition Updates\Default\MpEngine.dll
c:\ProgramData\Microsoft\Windows Defender\Definition Updates\{D45C13C3-59B3-4726-B82F-03461072F006}\mpengine.dll
c:\Users\All Users\Microsoft\Windows Defender\Definition Updates\Backup\mpengine.dll
c:\Users\All Users\Microsoft\Windows Defender\Definition Updates\Default\MpEngine.dll
c:\Users\All Users\Microsoft\Windows Defender\Definition Updates\{D45C13C3-59B3-4726-B82F-03461072F006}\mpengine.dll

Looks like this:
I might dig a little deeper on this but this is all for now. Hope this helps.