Splunk is committed to using inclusive and unbiased language. This blog post might contain terminology that we no longer use. For more information on our updated terminology and our stance on biased language, please visit our blog post. We appreciate your understanding as we work towards making our community more inclusive for everyone.
In 2007 we saw the initial beginnings and rise of QakBot, the same year when Windows XP and Windows Server 2003 were still the primary operating systems in the enterprise. QakBot, or QuackBot, made its presence known as a banking trojan and a loader. Over time, it continually developed and became a standard in malicious software circles. Today, we see QakBot used by a varied group of adversaries in a variety of ways, such as deploying ransomware, persistence, and stealing credentials. Before an adversary has access to an endpoint or the ability to move laterally, they have to gain initial access. That initial access vector continues to evolve and keep pace with operating systems, browsers, and antivirus vendors to ensure the deliverability of malicious payloads.
In this blog, the Splunk Threat Research Team (STRT) showcases a year's evolution of QakBot. We also dive into a recent change in tradecraft meant to evade security controls. Last, we reverse engineered the QakBot loader to showcase some of its functions.
In February 2022 Microsoft pushed an update to disable macros by default in Office products. A huge win within the industry is to prevent the vast amount of initial access vectors into an organization. It wasn’t long before adversaries began to update their tradecraft to use everything except macros. Similar to what was mentioned by Bleeping Computer in February, DarkReading mentioned in this article, the change went to HTML Applications (.hta) and was very successful. Over time, we began to hear of Mark-of-the-Web (MOTW) bypasses. Windows MOTW is a simple feature in the OS that labels items and scrutinizes them as they are downloaded. As outlined by Outflank in 2020, the role of MOTW in security measures is used by Windows SmartScreen, and Protected view sandbox in Excel and Word, to name a few. How does an adversary bypass these controls? Some downloaded files do not get scrutinized, therefore evading MOTW and allowing for process execution. One popular format that we see today includes the delivery of ISO files within an HTML file. Most containers, like ISO or VHDX, are not scrutinized by MOTW.
Want to simulate Mark of the Web Bypasses? Check out Atomic Red Team T1553.005.
Below is a timeline of changes from June to October. Proxylife monitors and tracks QakBot campaigns and daily shares the indicators for each campaign. We began looking at how QakBot operated in June, four months after Microsoft disabled macros, and we can see the pattern of using .html files with embedded zip, and img files.
The simple flow chart below shows the basic infection flow of this QakBot sample.
To follow this evolution we monitor Proxylife as well as other sources (Proxylife monitors Qakbot’s evolution and shares campaign indicators).
Based on this and other sources, below is a timeline of changes from June to October captured by Proxylife updates. We began looking at how QakBot operated in June, four months after Microsoft disabled macros, and we can see the pattern of using .html files with embedded zip and img files.
Immediately following, we see that on June 13, 2022 the campaign changed to using HTML smuggling with an embedded ZIP+.LNK file. Adversaries change their tradecraft frequently when attempting to see what sticks as far as evasion goes, and this is a great view into that.
Reference tweet
Jumping forward three months, we can see the more widespread use of HTML smuggling with ZIP and ISO attachments. In this particular sample, the .LNK will execute a javascript file that loads the .cmd (batch script) to continue on.
Reference tweet
While reviewing the QakBot samples outlined above, we found a particularly distinct sample that was being utilized. Once we began digging into the HTML we noticed that it had evasive techniques built in that piqued our interest. We found that ProxyLife had shared this sample on Twitter, along with the other campaigns that utilized HTML smuggling, along with a password-protected zip that contained the ISO.
Reference tweet
What we don’t see here is the functionality being used to evade controls. It’s easy to say “HTML smuggling” or “ISO containers”, but what is the core behavior underneath it all that is making each of these different?
We will explore this sample and showcase everything in more detail.
This has become the de facto standard for the delivery of malicious payloads as of late. What is HTML smuggling? As defined by MITRE ATT&CK T1027.006, “HTML documents can store large binary objects known as JavaScript blobs (immutable data that represents raw bytes) that can later be constructed into file-like objects. Data may also be stored in Data URLs, which enable embedding media type or MIME files inline of HTML documents.”
Below we showcase two ways to view these campaigns, one from the victim perspective and the other from within the code.
Victim Perspective
For the end user, this particular sample requires the downloading and opening of the HTML file. Once opened, the attachment.zip saves to disk, and the end user must now enter the password to decrypt the contents. Once decrypted, mount the ISO (by double-clicking) and finally click the A.LNK file.
View Within Code
(For a larger resolution of this diagram visit this link)
Stage 1 HTML
This HTML file contains a reversed base64 encoded string initialized in div id = “MS860aTc” which contains the stage 2 javascript. To be able to execute this stage 2 javascript, it creates an HTML element with the tag “embed” that will be appended to the code body of this HTML using “document.body.appendChild(element)”. The width and height frame properties of the “embed” element are also hidden (value = 1) to hide the stage 2 javascript execution from the user.
Figure 1 is the screenshot of the main code of the stage 1 HTML file with annotations
Figure 1
Stage2 HTML File
The stage 2 HTML contains javascript that will decode a base64 encoded (password protected) zip file initialized in variable “gdhpoIyu”. After decoding, it will try to convert the decoded base64 data into an unsigned integer byte array that will be used to create a blob file object as a ZIP file. Then it will use a javascript static method URL.CreateObjectURL with the new blob file object as a parameter that will be loaded using the windows.location.assign() method.
Figure 2 shows the stage 2 HTML javascript code and the portion of the base64 encoded zip file that contains the malicious ISO file.
Figure 2
Figure 3 shows the effect of the stage 2 HTML file as you run the main HTML (stage 1). Notice that it automatically dropped the zip file in the compromised host.
Figure 3
ISO File
Once the ZIP is extracted and decrypted using the password “PG1”, we will be able to get the “A7490.iso” that contains an A.LNK file and a hidden tools folder.
Hidden Folder Contents
Within the hidden tools folder is protracted.cmd (bat file) and the malicious bucketfuls.dat (.dll) that will be loaded.
To the victim, the .LNK will be the only thing inside the ISO as the tools directory is hidden.
Below is the breakdown of the two files which showcases how the adversary attempts to evade detection.
LNK
Within the LNK it gives away the .cmd file that will run from within the hidden tools directory -
C:\Windows\System32\cmd.exe /c tools\protracted.cmd re gs v |
Note the re gs and v arguments, at first glance it doesn’t make sense and seems out of place until we look at the .cmd file.
Figure 4
The .cmd file uses a few tricks to evade controls. First, lines 4-7 are using set, which will _set_ environment variables for the different strings. On line 6 we see the % symbols, which are passed in from the LNK file (re gs v) to complete the regsvr32.exe process name.
Line 9 will set “copy” as a variable. The final call on line 16 will now look like this:
copy %systemroot%\system32\regsvr32.exe %temp%\envelopingConcussion.com |
This will copy regsvr32.exe from system32 to the \appdata\local\temp directory and rename regsvr32.exe to envelopingConcussion.com.
Now, envelopingConcussion.com will run tools\bucketfuls.dat.
In Splunk:
Figure 5
Now we will switch gears and dive into the different QakBot capabilities found within the DLL that gets loaded.
Figure 6 is a screenshot of QakBot code that will execute several Windows commands to collect system and network information that will be sent to the remote C2 server.
Figure 6
The table below is the complete list of the Windows commands that it will execute on the compromised host.
Command | Description |
---|---|
ipconfig /all |
List all TCP/IP network configuration |
nslookup -querytype=ALL -timeout=12 _ldap._tcp.dc._msdcs.%s | Query SRV records of the domain from the main DNS record of the compromised host (%s is the domain name) |
nltest /domain_trusts /all_trusts |
Enumerate domain trusts |
net localgroup |
Get local groups information |
qwinsta | Displays information about sessions on a Remote Desktop Session Host server. |
route print |
Get route information |
arp -a |
Get ARP information |
cmd /c set |
Get environment variables |
whoami /all |
Get user, group, and privilege information of the compromised host |
netstat -nao |
Get the active network connections in the compromised host |
net view |
Displays a list of domains, computers, or resources that are being shared by the specified computer. |
net share |
Displays information about all of the resources that are shared on the local computer |
This event can be seen using the Sysmon event logs in Splunk. Figure 7 shows how the QakBot malware injected in the wermgr.exe process executes the following Windows native commands that we’ve listed in the above table.
Figure 7
As part of this Tactic, it will also execute several WMI query commands to gain more system information about the compromised host. Table 2 shows the list of WMI classes it uses in its WMI query to collect more information.
WMI Class | Description |
---|---|
Win32_ComputerSystem |
System Information (AdminPasswordStatus, Model, Name, Manufacturer and many more) |
Win32_Bios |
BIOS information (e.g BIOSVersion, PrimaryBIOS, serialNumber) |
Win32_Product |
Product and software information |
Win32_PhysicalMemory |
Physical RAM information |
Win32_DiskDrive |
Hard disk information like the partition, free size, model. |
Win32_Processor |
CPU processor information |
Win32_OperatingSystem | OS information |
SELECT * FROM antivirusProduct | List all antivirus Products Installed in Windows OS.
|
Additionally, it will also make Windows API calls to get the computer name, system metrics, Active Directory domain status, system info, all processes and its modules, windows architecture (x32/x64), and OS version.
Figure 8 shows a code snippet of how it gets the computer name and the volume information of the compromised host.
Figure 8
Figure 9 shows the short code snippet of how it sets up and executes the WMI command listed in the table above to perform system discovery on the compromised host.
Figure 9
QakBot will also create a registry run key entry or Scheduled Task to execute itself upon the reboot of the compromised host. Figure 10 shows the code snippet of this sample that creates scheduled tasks or creates registry run keys.
Figure 10
We also saw a function in its code capable of creating services for its malicious code to gain privileges or persist on the target host machine. Unfortunately, this TTP was not triggered during our testing. Figure 11 is a screenshot of how it registers a service control handler for its file.
Figure 11
This QakBot sample can execute the dropped .DLL copy of itself or a .DLL plugin downloaded from its Command and Control (C2) server using several techniques available in Windows Operating System such as Living on The Land Application (LOLBIN) or through scripts.
Figure 12 shows how it uses the WMI command in .VBScript to copy files.
Figure 12
Below is a short table of commands we saw during our analysis for its Execution Tactics
Command | Description |
---|---|
Regsvr32.exe <dll_file_path> |
Execute dropped randomly generated DLL file name using regsvr32.exe. |
Rundll32.exe <dll_file_path> |
Execute dropped randomly generated DLL file name using rundll32.exe. |
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\%coot\cimv2") Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process") errReturn = objProcess.Create("%s", null, nul, nul) |
Execute a process using a WMI object in VBScript. |
“runas” |
Shellexecute a command line with “runas “ parameter to gain admin privileges in its execution |
Powershell.exe -encodedCommand |
Execute a base64 encoded PowerShell script |
Wmic process call create expand <lolbin> <dll_file_path> |
Execute its dropped DLL copy of itself or .dll component using WMIC in a batch script. E.g Wmic process call creates expand regsvr32.exe <dll_file_path> |
When The .DLL stager or the .DLL loader is executed by the .batch script inside the .ISO file using regsvr32.exe, It will inject its malicious code to a legitimate Windows OS process to perform defense evasion.
Figure 13 shows the code and how it creates a suspended process (the wermgr.exe) as the first step of the process hollowing technique.
Figure 13
After creating a suspended process, it will create a new section on that process that can fit its QakBot .DLL code. Then, it will map and allocate memory pages on that section and write its malicious code on that mapped section using WriteProcessMemory() API. Figure 13.1 is the code snippet of this process.
Figure 13.1
Below is the list of possible processes where it can inject the QakBot core .DLL during its executions:
Aside from Process Injections, it also has several functions that check if it is being debugged, being run in a sandbox, or being analyzed in a research lab.
This QakBot variant has 2 conditions that serve as a killswitch for its execution.
Figure 14 shows the screenshots of its code that checks the following killswitch
Figure 14
Figure 15 shows its code snippet and how it checks if its code is being debugged using the Process Environment Block Structure. If the BeingDebugged flag is True, it will xor encrypt the 2 decryption key tables in addresses 0x1001E16B0 and 0x1001E050 then exit its process.
Figure 15
It also enumerates all the running processes on the compromised host and checks if one of those processes is on the list below (Table 4) which is related to security, malware analysis tools, and sandbox.
|
|
|
It also has a list of processes it checks (Table 5) related to antivirus products such as AVG, Dr. Web, Fortinet, TrendMicro, F-Secure, ByteFence Anti-Malware, BitDefender, Avast, Windows Defender, Comodo Internet Security and ESET.
|
|
It also checks antivirus .DLL’s component if it is loaded on the compromised host. Figure 16 shows the function that checks if the Avast module (awshooka.dll and aswhookx.dll) is installed or running on the compromised host.
Figure 16
This malware is capable of communicating to its C2 server to send the collected data in the compromised Windows OS and also to download configuration files, plugins, or other malware.
Figure 17 shows the code snippet that contains a function renamed as “mw_internet_crack_send_request” that will send a request to its C2 using HttpSendRequestA() API. Then it will be followed by another function that will read the reply from the HTTP Request and save it to a file that could be either a configuration file or other malware to be executed in the target or compromised host.
Figure 17
This malware also uses a named pipe to communicate to its other process running on the compromised host. Figure 18 is a code snippet showing how it creates named pipes and reads data or files sent or transferred on that randomly generated named pipe.
Figure 18
Figure 19 shows how Sysmon Event=17, 18 (CreateNamedPipe And ConnectNamedPipe) captured the creation and connection of the injected QakBot in legitimate wermgr.exe process to its randomly generated named pipe.
`sysmon` EventCode IN (17, 18) Image= "*\\wermgr.exe" EventType IN ( "CreatePipe", "ConnectPipe") | stats min(_time) as firstTime max(_time) as lastTime count by Image EventType ProcessGuid ProcessId PipeName SecurityID EventCode Computer UserID | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
Figure 19
In addition to all this, we are also sharing the decrypted data section of this QakBot variant that contains more TTPs.
https://gist.github.com/tccontre/360dbda059562b67b983d58ae70ac371
As defenders, it doesn’t end here. QakBot and other frameworks will continue to improve, evading next-generation controls in place. We must continue to dissolve these loaders into their smallest form and share with the greater security community their tradecraft to help everyone defend their organization.
All of the previously listed detections create entries in the risk index by default, and can be used seamlessly with risk notables and the Risk Notable Playbook Pack. The community Splunk SOAR playbooks below can be used in conjunction with some of the previously described analytics:
Playbook | Description |
---|---|
This playbook performs a general investigation on key aspects of a windows device using windows remote management. Important files related to the endpoint are generated, bundled into a zip, and copied to the container vault. |
|
This playbook retrieves IP addresses, domains, and file hashes, blocks them on various services, and adds them to specific blocklists as custom lists. |
|
This playbook accepts a list of hosts and filenames to remediate on the endpoint. If filenames are provided, the endpoints will be searched and then the user can approve deletion. Then the user is prompted to quarantine the endpoint. |
Splunk Threat Research Team has curated new and old analytics and tagged them to the QakBot Analytic Story to help security analysts detect adversaries leveraging the QakBot malware. This analytic story introduces 43 detections across MITRE ATT&CK techniques.
For this release, we used and considered the relevant data endpoint telemetry sources such as:
With this article the Splunk Threat Research Team (STRT) enables security analysts, blue teamers and Splunk customers to identify one of the CISA TOP malware strains . This article helps the community discover QakBot tactics, techniques and procedures. By understanding QakBot behaviors, we were able to generate telemetry and datasets to develop and test Splunk detection analytics designed to defend and respond against this threat.
You can find the latest content about security analytic stories on GitHub and in Splunkbase. Splunk Security Essentials also has all of these detections available now.
For a full list of security content, check out the release notes on Splunk Docs.
Any feedback or requests? Feel free to put in an issue on GitHub and we’ll follow up. Alternatively, join us on the Slack channel #security-research. Follow these instructions if you need an invitation to our Splunk user groups on Slack.
We would like to thank the authors Teoderick Contreras, Michael Haag and collaborators Lou Stella, Mauricio Velazco, Rod Soto, Jose Hernandez, Patrick Bareiss, Bhavin Patel, and Eric McGinnis for their contributions to this post.
We would like to extend a huge thank you to @proxylife for sharing his research and this malware sample that helped the STRT produce this analysis.
The Splunk platform removes the barriers between data and action, empowering observability, IT and security teams to ensure their organizations are secure, resilient and innovative.
Founded in 2003, Splunk is a global company — with over 7,500 employees, Splunkers have received over 1,020 patents to date and availability in 21 regions around the world — and offers an open, extensible data platform that supports shared data across any environment so that all teams in an organization can get end-to-end visibility, with context, for every interaction and business process. Build a strong data foundation with Splunk.