XWorm, a popular and actively distributed remote access trojan (RAT), has steadily evolved into a versatile tool in the cybercriminal toolkit. Known for its robust feature set, ranging from keylogging and remote desktop access to data exfiltration and command execution, XWorm continues to attract threat actors due to its ease of use, modularity, and frequent updates by its developers.
XWorm (RAT) is leveraged by various threat actors who frequently target organizations within the software supply chain and the gaming industry. In a notable campaign, attackers deployed AsyncRAT and XWorm as initial-stage malware to establish footholds within victim environments. These tools were then used to deliver ransomware payloads created with the leaked LockBit Black builder, linking the operation to tactics commonly associated with the LockBit ransomware group.
Aside from that, One of the more interesting aspects of recent XWorm campaigns is the use of varied stagers and loaders tailored to bypass detection and improve delivery efficiency. Unlike traditional malware that often relies on a fixed infection chain, XWorm leverages a dynamic approach, cycling through multiple file formats and scripting languages such as PowerShell, VBS, .NET executables, java script, batch script, .hta, .lnk, .iso, .vhd, .img and even Office macros to stage and load its payload. This adaptability not only complicates detection but also suggests a deliberate strategy to evade endpoint defenses and sandboxing tools.
In this blog, the Splunk Threat Research Team (STRT) takes a closer look at recent XWorm malware samples spotted in the wild. We’ll dive into how this threat uses a mix of different stagers and loaders to sneak past defenses and carry out its attacks. XWorm doesn’t rely on just one method to get in, it constantly changes its delivery tactics, making it tricky to detect and stop. Along the way, we’ll also share Splunk detections you can use to spot signs of XWorm activity in your environment and strengthen your defenses against this threat.
XWorm is known for using a wide variety of droppers, stagers and loaders throughout its infection chain. To get a better understanding of the different file formats XWorm relies on for these components, STRT pulled data from 1,000 XWorm-tagged samples hosted on Malware Bazaar. We specifically looked beyond the usual .exe and .dll files to focus on the more diverse file types used for initial access and payload delivery.
Figure 01 shows a bubble chart visualizing the distribution of these file types. As seen in the chart, some of the most commonly used formats include batch scripts, VBS files, JavaScript, PowerShell scripts, and ZIP archives—many of which are delivered as email attachments or embedded in lure documents.
Figure 01: XWorm Stager and Loader Sampling Statistics
By analyzing metadata from the top 1,000 XWorm samples in Malware Bazaar, we were able to uncover some of the most common and interesting filenames used for its downloaders, stagers and loaders. These filenames often give clues about the social engineering tactics behind each campaign.
Figure 02 highlights a snippet of filenames tied to different XWorm campaigns, revealing how the malware tries to trick users into executing malicious files. We observed recurring themes like invoices, receipts, delivery and shipping notifications, classic phishing lures designed to appear urgent or business-related. These naming tactics are meant to entice unsuspecting users into opening the files, unknowingly triggering the infection chain.
Figure 02: Interesting XWorm Phishing File Name
Some XWorm script components are designed to directly download the main XWorm payload from the command and control (C2) server. As shown in Figure 03 to Figure 05, there are several variants of these components that perform this behavior. During our analysis, we identified both .hta files and PowerShell-based stagers that act as the initial stage and retrieve the next-stage payload directly from the C2.
Figure 03: XWorm .hta Downloader
Figure 04: XWorm .ps1 Downloader
Figure 05: XWorm .ps1 Downloader
XWorm also employs obfuscation techniques to hinder analysis and evade detection, particularly within its stager and loader components. As shown in Figure 06 and Figure 07, the .vbs and batch script stagers are obfuscated to make static code analysis more difficult and conceal their true functionality.
Figure 06: XWorm .vbs Stager Component
Figure 07: XWorm .bat Stager Component
The obfuscated .vbs and batch scripts shown in Figure 06 and Figure 07 Base64 decode and decrypt two executable files that are encrypted using AES algorithm in memory before executing them. These files act as the next stager and loader that helps deliver other defense evasion components, and the actual XWorm malware that compromised the system.
The first decrypted file is specifically designed to bypass AMSI (Antimalware Scan Interface), a Windows security feature that allows antivirus software to scan scripts and other content in memory before they run. To achieve this, the payload attempts to patch the AmsiScanBuffer() function within the amsi.dll library. By modifying this function in memory, the malware prevents AMSI from properly scanning or detecting malicious code, allowing its execution to continue without being flagged by security tools.
Figure 08: Evading Windows AMSI Feature
The second decrypted file also attempts to tamper with Windows Event Tracing for Windows (ETW) by patching the EtwEventWrite() function. ETW is a built-in logging framework used by the operating system and security tools to monitor and collect detailed runtime information about system and application behavior. By patching EtwEventWrite() in memory, the malware effectively disables or suppresses ETW logging, allowing its malicious activities to proceed without being recorded or detected by event monitoring tools.
Figure 09: Evading Windows ETW Audit Logs
This stager also establishes persistence and attempts privilege escalation by creating registry run keys for a .vbs script dropped in the %appdata% directory. These keys execute a copy of the stager. Additionally, it sets up scheduled tasks that reference a .bat file, also dropped in %appdata% which points to the same executable stager copy.
Figure 10: XWorm Stager Persistence and Privilege Escalation Mechanism
This stager attempts to decompress GZIP-compressed data from its resource sections labeled “UAC” and “Stager.” It also decrypts an AES-encrypted file named “payload.exe”, which is the XWorm payload. Figure 11 shows the three resource data entries embedded in the stager that are executed at a later stage.
Figure 11: XWorm Stager Decrypt Payloads
The stager sets an environment variable named “phantombp” with a value derived from the Console.Title of its running process. It then decompresses the “UAC” resource directory entry, which contains a DLL module designed to execute the value stored in the “phantombp” variable. This module is saved as version.dll in the fake directory C:\\Windows \System32 (note the trailing space), and is automatically loaded via DLL side-loading through msconfig.exe. However, this DLL side-loading attempt might fail, because Windows does not permit directory names with trailing spaces. This might result in an error, such as "Access Denied" or "File exists."
Figure 12: XWorm “UAC” Module DLL Side Loading Technique
The resource directory entry named “Stager” contains shellcode that is injected into a target process whose name matches either Taskmgr, explorer, or svchost. Figure 13 shows a code snippet demonstrating how the stager performs process injection into these selected processes.
Figure 13: ShellCode Process Injection
Figure 14 shows a code snippet from the DLL module decrypted and loaded by the “Stager” shellcode. This module hooks several Windows APIs to hide a process and a named pipe, both identified as “phantom”.
Figure 14: Hooking API for Stealth Mode
Once decrypted, payload.exe reveals the actual XWorm payload. Below are the tactics, techniques, and procedures (TTPs) observed in this XWorm variant:
As part of its software discovery phase, XWorm queries Windows Management Instrumentation (WMI). As shown in Figure 15, XWorm gathers information about antivirus products installed and registered with the Windows Security Center WMI namespace.
Figure 15: AV Software Discovery
Figure 16 shows the code snippet of XWorm that retrieves a description of a video capture driver based on its index (0-based) using capGetDriverDescriptionA() API. This function identifies available webcam or capture devices on the compromised host.
Figure 16: Video Capture Driver Discovery
The Win32_VideoController() WMI class is used by XWorm to retrieve detailed information about the GPU(s) on a Windows system. It can provide properties such as the GPU name, driver version, adapter RAM, and video processor.
Figure 17: GPU Information Discovery
Like many remote access trojans (RATs), XWorm attempts to evade detection by Microsoft Defender through the abuse of Defender's exclusion settings. Specifically, it modifies the ExclusionPath and ExclusionProcess registry entries to exclude its own directory and process from being scanned. This allows the malware to operate with reduced risk of detection or removal by the built-in antivirus.
Figure 18: XWorm Evading Microsoft Defender
In this XWorm variant, a function named RunDisk() is responsible for executing a PowerShell component with a modified execution policy, as shown in Figure 19. Specifically, it runs the command: powershell -ExecutionPolicy Bypass -File <obj>, which allows the script to bypass standard execution restrictions.
Figure 19: Function for Powershell Execution
As part of its persistence mechanism, this XWorm variant attempts to maintain execution across system reboots by either creating a .lnk shortcut file pointing to its executable in the %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup folder or by adding a registry Run key referencing the malware's file path. These techniques ensure the malware is automatically executed each time the system starts.
Figure 20: XWorm Persistence Mechanism
XWorm also attempts to spread via removable drives by dropping a copy of itself along with a .lnk shortcut that points to the malicious executable. The shortcut is designed to entice users into clicking it, thereby manually triggering execution of the payload.
Figure 21: XWorm Spread In Removable Drives
Similar to one of its stager components, XWorm also creates a scheduled task that references its own executable to establish persistence and potentially achieve privilege escalation. By configuring the task to run under a specific user account, often one with elevated privileges, the malware ensures its execution with higher permissions during system startup or at predefined intervals.
Figure 22: XWorm Scheduled Task Entry
XWorm includes a function that processes backdoor commands received from its command-and-control (C2) server, as shown in Figure 23. These commands include actions such as shutting down or restarting the system, downloading files, opening URLs, initiating DDoS attacks, and more.
Figure 23: XWorm BackDoor Command
Figure 24 illustrates the HTTP POST connection and data transmission setup initiated by XWorm to communicate with its C2 server, which includes the use of a specific User-Agent string. Figure 25 also highlights the exact User-Agent used by this particular XWorm variant.
Figure 24: XWorm HTTP Post Connection
Figure 25: XWorm User Agent
This analytic identifies a suspicious spawned process by WScript or CScript process.
| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where Processes.parent_process_name IN ("cscript.exe", "wscript.exe") Processes.process_name IN ("regsvr32.exe", "rundll32.exe","winhlp32.exe","certutil.exe","msbuild.exe","cmd.exe","powershell*","pwsh.exe","wmic.exe","mshta.exe") by Processes.action Processes.dest Processes.original_file_name Processes.parent_process Processes.parent_process_exec Processes.parent_process_guid Processes.parent_process_id Processes.parent_process_name Processes.parent_process_path Processes.process Processes.process_exec Processes.process_guid Processes.process_hash Processes.process_id Processes.process_integrity_level Processes.process_name Processes.process_path Processes.user Processes.user_id Processes.vendor_product | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `wscript_or_cscript_suspicious_child_process_filter`
Figure 26: Wscript Or Cscript Suspicious Child Process Detection
The following analytic detects PowerShell processes initiated with parameters that bypass the local execution policy for scripts.
| tstats `security_content_summariesonly` values(Processes.process_id) as process_id, values(Processes.parent_process_id) as parent_process_id values(Processes.process) as process min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where `process_powershell` (Processes.process="* -ex*" AND Processes.process="* bypass *") by Processes.action Processes.dest Processes.original_file_name Processes.parent_process Processes.parent_process_exec Processes.parent_process_guid Processes.parent_process_id Processes.parent_process_name Processes.parent_process_path Processes.process Processes.process_exec Processes.process_guid Processes.process_hash Processes.process_id Processes.process_integrity_level Processes.process_name Processes.process_path Processes.user Processes.user_id Processes.vendor_product | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `malicious_powershell_process___execution_policy_bypass_filter`
Figure 27: Malicious PowerShell Process - Execution Policy Bypass Detection
The following analytic detects suspicious PowerShell script execution involving the cryptography namespace via EventCode 4104.
`powershell` EventCode=4104 ScriptBlockText = "*System.Security.Cryptography*" AND NOT(ScriptBlockText IN ("*SHA*", "*MD5*", "*DeriveBytes*")) | fillnull | stats count min(_time) as firstTime max(_time) as lastTime by dest signature signature_id user_id vendor_product EventID Guid Opcode Name Path ProcessID ScriptBlockId ScriptBlockText | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `windows_powershell_cryptography_namespace_filter`
Figure 28: Windows Powershell Cryptography Namespace Detection
The following analytic detects the use of PowerShell scripts to load .NET assemblies into memory via reflection, a technique often used in malicious activities such as those by Empire and Cobalt Strike.
| `powershell` EventCode=4104 ScriptBlockText IN ("*Reflection.Assembly]::Load*", "*Reflection.Assembly.Load*", "*UnsafeLoadFrom*", "*.LoadFrom(*", "*.LoadModule(*", "*.LoadWithPartialName*", "*ReflectionOnlyLoad*", "*Reflection.Assembly]::('daoL'[-1..-4] -join '')*") | fillnull | stats count min(_time) as firstTime max(_time) as lastTime by dest signature signature_id user_id vendor_product EventID Guid Opcode Name Path ProcessID ScriptBlockId ScriptBlockText | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `powershell_loading_dotnet_into_memory_via_reflection_filter`
Figure 29: PowerShell Loading DotNET into Memory via Reflection Detection
The following analytic detects the creation of files in the Windows %startup% folder, a common persistence technique.
|tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Filesystem where Filesystem.file_path = "*\Microsoft\Windows\Start Menu\Programs\Startup\*" by Filesystem.action Filesystem.dest Filesystem.file_access_time Filesystem.file_create_time Filesystem.file_hash Filesystem.file_modify_time Filesystem.file_name Filesystem.file_path Filesystem.file_acl Filesystem.file_size Filesystem.process_guid Filesystem.process_id Filesystem.user Filesystem.vendor_product | `drop_dm_object_name(Filesystem)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `windows_boot_or_logon_autostart_execution_in_startup_folder_filter`
Figure 30: Windows Boot or Logon Autostart Execution In Startup Folder Detection
The following analytic identifies instances where `ipconfig.exe`, `systeminfo.exe`, or similar tools are executed by a non-standard shell parent process, excluding CMD, PowerShell, or Explorer.
| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where Processes.process_name IN ("ipconfig.exe", "systeminfo.exe", "net1.exe", "arp.exe", "nslookup.exe", "route.exe", "netstat.exe", "hostname.exe", "whoami.exe") AND NOT Processes.parent_process_name IN ("cmd.exe", "powershell.exe", "powershell_ise.exe", "pwsh.exe", "explorer.exe", "-", "unknown") by Processes.action Processes.dest Processes.original_file_name Processes.parent_process Processes.parent_process_exec Processes.parent_process_guid Processes.parent_process_id Processes.parent_process_name Processes.parent_process_path Processes.process Processes.process_exec Processes.process_guid Processes.process_hash Processes.process_id Processes.process_integrity_level Processes.process_name Processes.process_path Processes.user Processes.user_id Processes.vendor_product | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `windows_cmdline_tool_execution_from_non_shell_process_filter`
Figure 31: Windows Cmdline Tool Execution From Non-Shell Process Detection
The following analytic identifies instances where the PowerShell executable has been renamed and executed under an alternate filename.
| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where Processes.process_name!=powershell.exe AND Processes.process_name!=pwsh.exe AND Processes.original_file_name=powershell.EXE by Processes.action Processes.dest Processes.original_file_name Processes.parent_process Processes.parent_process_exec Processes.parent_process_guid Processes.parent_process_id Processes.parent_process_name Processes.parent_process_path Processes.process Processes.process_exec Processes.process_guid Processes.process_hash Processes.process_id Processes.process_integrity_level Processes.process_name Processes.process_path Processes.user Processes.user_id Processes.vendor_product | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `windows_renamed_powershell_filter`
Figure 32: Windows Renamed Powershell Detection
XWorm Analytic Story consists of 31 detections to identify this threat.
SHA256 | description |
---|---|
78b15b9b54925120b713a52a09c66674463bd689e3b01395801ef58c77651127 | Bat loader |
0f10d6cbaf195a7b0c9f708b7f0a225e2de29beb769bdf8d1652b682b1c4679f | Powershell script |
28859e4387fefb9d1f36fdf711d1b058df5effe21d726cfe6a9a285f96db1c98 | Batch script |
327a98bd948262a10e37e7d0692c95e30ba41ace15fe01d8e614a9813ad9d5cf | Vb script |
354d082858bfc5e24133854ff14bb2e89bc16e1b010b9d3372c8370d3144cdb9 | hta |
4a885cec3833f3872e1e38f9149936fe6bcda2181e0df163556497d42383cffa | Cmd script |
665e41e416954d5ff623a37c7bce17d409c11e003c29ae9ddeb25fc736e533c7 | Vb script |
8044220d34e77501df4a9831ac27802261ea2309f104bb49ac00301df36dee72 | Java script |
9db47f709898b79c9ac07e6352de9be05d6b2b91902c146272e47c17c6b8d5b2 | Powershell script |
This blog is designed to assist security analysts, blue teamers, and Splunk customers in identifying XWorm malware including its stager and loader components. It empowers the community to uncover related Tactics, Techniques, and Procedures (TTPs) employed by threat actors and adversaries. You can implement the detections in this blog using the Enterprise Security Content Updates app or the Splunk Security Essentials app. To view the Splunk Threat Research Team's complete security content repository, visit research.splunk.com.
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 Teoderick Contreras for authoring this post and the entire Splunk Threat Research Team for their contributions: Michael Haag, Jose Hernandez, Lou Stella, Bhavin Patel, Rod Soto, Eric McGinnis, Patrick Bareiss, and Nasreddine Bencherchali.
The world’s leading organizations rely on Splunk, a Cisco company, to continuously strengthen digital resilience with our unified security and observability platform, powered by industry-leading AI.
Our customers trust Splunk’s award-winning security and observability solutions to secure and improve the reliability of their complex digital environments, at any scale.