Windows Defender Exploit Guard ASR VBScript/JS Rule

Microsoft has been adding to Windows 10 the features of the Enhanced Mitigation Experience Toolkit (EMET) in to the OS. On the 1709 release they added more features and expanded on them as part of Windows Defender Exploit Guard One of the features of great interest for me is Attack Surface Reduction. I have used this feature in EMET with great success as a mitigation to many techniques that abuse built in functionality in Windows. One of the rules of great interest to me is the "Block JavaScript or VBScript from launching downloaded executable content" rule. With the greater visibility now in Windows PowerShell many of us as going back to the old and tested Windows Scripting Host languages and old techniques that have worked for so long. 

The description of the rule as per Microsoft documentations says:

Rule: Block JavaScript ok VBScript From launching downloaded executable content

JavaScript and VBScript scripts can be used by malware to launch other malicious apps.
This rule prevents these scripts from being allowed to launch apps, thus preventing malicious use of the scripts to spread malware and infect machines.

The Rule title mentions to prevent the execution of a downloaded executable. The description mentions the prevention of Javascript and VBScript running applications. So we have 2 different scenarios there. 

The rule can be controlled via GPO, PowerShell cmdlets or via MDM (Mobile Device Management). For the purpose of this blog post I will use the PowerShell cmdlet. I will start by looking at the current setting for the rule using the Get-MpPreference cmdlet. The ASR information is in 2 properties one has the rule GUIDs and the other in order their setting. 

PS C:\Windows\system32> Get-MpPreference | Select-Object -ExpandProperty AttackSurfaceReductionRules_Ids
3B576869-A4EC-4529-8536-B80A7769E899
5BEB7EFE-FD9A-4556-801D-275E5FFC04CC
75668C1F-73B5-4CF0-BB93-3ECF5CB7CC84
92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B
BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550
D3E037E1-3EB8-44C8-A917-57927947596D
D4F940AB-401B-4EfC-AADC-AD5F3C50688A
PS C:\Windows\system32> Get-MpPreference | Select-Object -ExpandProperty AttackSurfaceReductionRules_Actions
2
2
2
2
2
2
2

The Rule GUIDs are as follows:

  • BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550 - Block executable content from email client and webmail
  • D4F940AB-401B-4EFC-AADC-AD5F3C50688A - Block Office applications from creating child processes
  • 3B576869-A4EC-4529-8536-B80A7769E899 - Block Office applications from creating executable content
  • 75668C1F-73B5-4CF0-BB93-3ECF5CB7CC84 - Block Office applications from injecting code into other processes
  • D3E037E1-3EB8-44C8-A917-57927947596D - Block JavaScript or VBScript from launching downloaded executable content
  • 5BEB7EFE-FD9A-4556-801D-275E5FFC04CC - Block execution of potentially obfuscated scripts
  • 92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B - Block Win32 API calls from Office macro

The setting for each are:

  • 0 - Disabled
  • 1 - Enabled (Blocking)
  • 2 - Audit Mode

Not the most useful way to show this details. This would be better handled by a ASR specific cmdlet that showed each rule and its information as its own object instead of lumping all the settings in to a single cmdlet with GUIDs that need one to reference a table in docs to match what they do. 

I want to test a collection of execution methods one can do with VBScript:

'https://ss64.com/vb/shell.html
Dim obj0
Set obj0 = CreateObject("Wscript.Shell")
obj0.Run "powershell.exe", 0

Dim obj1
Set obj1 = GetObject("new:72C24DD5-D70A-438B-8A42-98424B88AFB8")
obj1.Run "powershell.exe", 0

'https://msdn.microsoft.com/en-us/library/windows/desktop/gg537745(v=vs.85).aspx
'Operation paramter supports an undocumented option called runas that will ask the user permission
'to elevate via UAC if enabled.
Dim obj2
Set obj2 = CreateObject("Shell.Application")
obj2.ShellExecute "PowerShell.exe","","","runas",0

Dim obj3
Set obj3 = GetObject("new:13709620-C279-11CE-A49E-444553540000")
obj3.ShellExecute "PowerShell.exe","","","runas",0

'requires to run in a high priviledge. Shell.Application with RunAs could be use.
'https://msdn.microsoft.com/en-us/library/aa815396(v=vs.85).aspx
Set objMMC = CreateObject("MMC20.Application")
Set objDoc = objMMC.Document.ActiveView
objDoc.ExecuteShellCommand "powershell.exe","","",7

Set objMMC1 = CreateObject("new:49B2791A-B1AE-4C90-9B8E-E860BA07F889")
Set objDoc1 = objMMC1.Document.ActiveView
objDoc1.ExecuteShellCommand "powershell.exe","","",7

'Using WMI Win32_Process
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set objStartup = objWMIService.Get("Win32_ProcessStartup")
Set objConfig = objStartup.SpawnInstance_
objConfig.ShowWindow = 0
set process = GetObject("winmgmts:Win32_Process")
result = process.Create ("powershell.exe",null,objConfig,processid)

' Short WMi Method with win32_process
set process = GetObject("winmgmts:Win32_Process")
set startup = GetObject("winmgmts:Win32_ProcessStartup")
startup.ShowWindow = 0
process.Create "notepad.exe",null,startup,processid

Each one uses the COM object and also has a reference to the GUID of the COM. I found out via long hours of testing that ASR will not block or audit any of this execution methods by themselves but that the script must perform a request. 

There are multiple ways to perform a request using VBScript/Jscript. We can leverage any of the COM objects in the table bellow.  

com_download.JPG

The Windows Defender Exploit Guard evaluation package Uses the following scripts to test settings:

Jscript

// SCPT:xmlHttpRequest
var xmlHttp = WScript.CreateObject("MSXML2.XMLHTTP");
xmlHttp.open("GET", "https://www.bing.com", false);
xmlHttp.send();

// SCPT:JSRunsFile
var shell = WScript.CreateObject("WScript.Shell");
shell.Run("notepad.exe");

VBScript

' SCPT:xmlHttpRequest
set xmlHttp = CreateObject("MSXML2.XMLHTTP")
xmlHttp.Open "GET", "https://www.bing.com", False
xmlHttp.Send

' SCPT:JSRunsFile
set shell = CreateObject("WScript.Shell")
shell.run("notepad.exe")

If we remove any of the 2 components the script will not be blocked. 

Lets configure the ASR rule for blocking using the Add0MpPreference cmdlet by providing the rule GUID and the Action for it.

Add-MpPreference -AttackSurfaceReductionRules_Ids D3E037E1-3EB8-44C8-A917-57927947596D -AttackSurfaceReductionRules_Actions Enabled

Once that is set we should see an entry in the eventlog indicating that the settings of Windows Defender where modified. The event Id should 5007 and it the data is structured so as to make it easy to parse

eventid.PNG

The vent will include the old and new value information. 

When a script is ran and blocked it is logged under Event Id 1121 and under EventData the ID attribute will reference the ASR rule GUID

block_eventid.PNG

For testing I tested each of the execution methods and tested each as a standard VBS/Js script, HTA and as a Scriptlet using the MS2XML COM object for the download segment. 

execmatrix.JPG

If we look at the COM objects we can use as the download part of a cradle the results are bellow:

download_matrix.JPG

We now know as of the version tested that we have some ways to bypass the rules. Would not be surprised if Microsoft updated the engine to also catch these.  I did try to also encode the scripts but those that where caught where still caught after being encoded. 

One thing I noticed during testing is that when a HTA and a Scriptlet (SCT) was blocked the path to the script was empty. Thankfully the event also includes the Process ID that can be used to match what process was using the specified engine when it was blocked as you can see bellow.

nopath.PNG

Do remember that Process ID numbers are re-used so the time stamp is of great value in the correlation.

Conclusion

The solution covers some techniques an attacker/Red Team may use but it does not cover all, the fact that both download and execution have to be in the same script is a limiting factor of the ASR rule since some other program may have placed a file on disk or the script may simply execute PowerShell with the payload in the command line. Both red and blue teams should set some automated way to test the rules as Microsoft releases new versions so as to keep they playbooks updated. Blue should work on XPath filters for the rule ID and EventID to aid in their threat hunting action, like the filter bellow to find all actions for blocked events for this specific rule.

$Filter=@{
    ID=1121
    LogName='Microsoft-Windows-Windows Defender/Operational'
    Data='D3E037E1-3EB8-44C8-A917-57927947596D'}
    
Get-WinEvent -FilterHashtable $filter 

Blue should start by setting the rule in audit mode, collect logs and build a whitelist if false positives are experienced and then build exclusions for those. 

As always I hope you found the blog post useful.