typeanalysisfamilyunclassified-js-dropperconfidencemediumcreated2026-06-02scriptdropperpersistencec2anti-vmanti-debugevasiondefense-evasionmitre-attck
SHA-256: 0e4141aac553fa9b2e3a224ad54ce65ba61ddbf9c1e856d363b59cad111ef0d4

unclassified-js-dropper: 0e4141aa — WScript→PowerShell→.NET assembly loader with debugger/sandbox gate

Executive Summary

A Portuguese-language WScript dropper (ykqtogmy.js) designed to run from the user's Temp/Downloads directory. It self-copies to C:\Users\Public\nswls.js, launches via wscript.exe, and emits a layered PowerShell payload that: checks internet connectivity, enumerates debugger/sandbox processes, downloads a .NET assembly byte array from a Brazilian HostGator domain, reflectively loads it via System.Reflection.Assembly, and invokes method ClassLibrary3.Class1::prFVI with C2 arguments including a secondary download URL. ^[strings.txt:39;^strings.txt:52;^strings.txt:55]

What It Is

  • Type: UTF-16LE Windows Script Host (WScript) .js file (not PE) ^[file.txt]
  • Size: 41,218 bytes (41 KB) ^[metadata.json]
  • Origin: Labeled ykqtogmy.js by MalwareBazaar / OpenCTI. Artifact ID cb212459-9a29-4924-8903-9301e0f27779 ^[metadata.json]
  • Language / Platform: JScript for Windows Script Host (WScript), targeting Windows environments
  • Packer / Obfuscator: Manual obfuscation — dead functions (ZaYEL, CTQLO, RGrIv, WehKV, PuoEh, fcUyb, etc.), Unicode garbage strings (CJK, Arabic, emoji, Cyrillic), repeated no-op assignments, semicolon noise. No commercial packer (e.g., JScript-Obfuscator, ConfuserEx) observed. ^[sample_utf8.js:1-470]

How It Works

Stage 1 — Environment Relocation

At top-level, the script checks WScript.ScriptFullName for "Temp" or "Downloads" in the path. ^[sample_utf8.js:41]

If matched, it:

  1. Copies itself to C:\Users\Public\nswls.js using Scripting.FileSystemObject.CopyFile. ^[sample_utf8.js:52-53]
  2. Launches the copy via Shell.Application.ShellExecute("wscript.exe", "//nologo \"...nswls.js\"", "", "open", 0). ^[sample_utf8.js:56]
  3. Calls WScript.Quit() to end the original process. ^[sample_utf8.js:58]

This ensures the active copy is staged outside of the browser-download quarantine directories.

Stage 2 — PowerShell String Generation

The payload string PoQct is built across multiple concatenated double-quoted fragments (~7,400 chars total). ^[sample_utf8.js:342]

Obfuscation layers:

  • Fragment concatenation: Single characters and short strings joined via + inside the JS string literal. ^[sample_utf8.js:342]
  • Noise insertion: Characters 'A' and '9' are replaced with expanded patterns " + A + " / " + 9 + ", then later stripped by PowerShell replace statements. ^[sample_utf8.js:426-427;^sample_utf8.js:441-443]
  • Quote stripping: PowerShell script removes all single quotes (''), + , and spaces at runtime before base64-decoding. ^[sample_utf8.js:441-443]

The cleaned string is valid Base64 and decodes to a self-contained PowerShell script (~3,000 chars). ^[decoded_final.txt:1]

Stage 3 — PowerShell Gate + Downloader

Decoded PS script performs three gates before proceeding:

  1. Internet-connectivity gate: Test-Connection 'www.google.com' -ErrorAction SilentlyContinue. If $null (no connectivity), calls irRkH which runs Restart-Computer -Force. ^[decoded_final.txt:4-12]
  2. Debugger/sandbox process gate: Get-Process enumerates handle, autorunsc, Dbgview, tcpvcon, any.run, sandbox, tcpview, OLLYDBG, ImmunityDebugger, Wireshark, apateDNS, analyze. If any found, also triggers Restart-Computer -Force. ^[decoded_final.txt:16-22]

If gates pass, it forces TLS 1.2, constructs a C2 URL via Base64 decoding:

  • Primary C2 (stage-2 payload text file): https://andrefelipedonascime1775471117328.2082219.meusitehostgator.com.br/FVTwhWzaQj_06_04_Meus_ArquivosDeTexto/03.txt ^[decoded_final.txt]
  • Secondary C2 (.NET assembly DLL or PE): https://catalogo.castrou2la.com/a9f88b/pr.txt ^[decoded_final.txt]

It downloads 03.txt, strips a %x% prefix, saves the cleaned content to C:\Users\Public\pfvzx.txt, splits the file on commas into a [byte[]] array, reflectively loads it via System.Reflection.Assembly::Load($cplhq), invokes type ClassLibrary3.Class1 with method prFVI, passing a 5-argument object array containing the secondary C2 URL, %vVlGz% (script path), msbuild path, $true, and the assembly byte array itself. ^[decoded_final.txt]

Stage 4 — Second-Stage Drop

The same PowerShell script writes a second PS file (sqzch_01.ps1) to C:\Users\Public\ and immediately re-launches PowerShell with -ExecutionPolicy Bypass -File pointing to it. ^[decoded_final.txt]

Build / RE

  • Toolchain: Hand-written JScript — no compiler, no packer, no framework.
  • Obfuscation: Manual — dead functions, repeated no-op variable assignments, Unicode garbage, semicolon spam. No string-array obfuscation (unlike spamita). No control-flow flattening. ^[sample_utf8.js:1-470]
  • Anti-analysis: Process-name debugger/sandbox enumeration (PowerShell get-process), connectivity check to www.google.com, conditional computer restart on detection. No anti-VM (CPUID, WMI), no timing delays. ^[decoded_final.txt]
  • Code quality: Low — verbose, repetitive, easily cleaned with simple string concatenation and regex. The author appears to have copy-pasted the same junk-function block dozens of times. Comments in Portuguese (Linha 5: "..." para ZaYEL). ^[sample_utf8.js:181;^sample_utf8.js:293]

Deploy / ATT&CK

Tactic Technique Implementation
Execution T1059.005 — Visual Basic / JScript WScript hosts .js file; native Windows feature. ^[sample_utf8.js:1]
Execution T1059.001 — PowerShell PowerShell invoked with -ExecutionPolicy Bypass -File via ShellExecute. ^[decoded_final.txt]
Defense Evasion T1497 — Virtualization/Sandbox Evasion Process-name check for debuggers / sandboxes; restart-on-detection. ^[decoded_final.txt:16]
Defense Evasion T1218 — System Binary Proxy Execution wscript.exe used to proxy execution of JScript payload. ^[sample_utf8.js:56]
Persistence T1547.001 — Registry Run Keys Suspected (not observed in this sample but common in Troldesh cluster); the nswls.js copy path is Public, a known Troldesh persistence directory. ^[sample_utf8.js:52-53]
Discovery T1012 — Query Registry / T1082 — System Information WScript.ScriptFullName path introspection to detect Temp/Downloads origin. ^[sample_utf8.js:41]
Command & Control T1071.001 — Web Protocols HTTP(S) to HostGator domain for second-stage payload; secondary C2 on catalogo.castrou2la.com. ^[decoded_final.txt]
Exfil T1041 — Exfiltration Over C2 Channel Inferred from Troldesh pattern; not observed in static.

C2 Infrastructure

Indicator Type Note
andrefelipedonascime1775471117328.2082219.meusitehostgator.com.br Domain Brazilian HostGator subdomain; serves stage-2 text payload (03.txt). Pattern: *.meusitehostgator.com.br is a known cheap reseller host abused by Brazilian malware. ^[decoded_final.txt]
catalogo.castrou2la.com Domain Secondary C2; catalogo path suggests masquerade as an e-commerce store. ^[decoded_final.txt]
https://catalogo.castrou2la.com/a9f88b/pr.txt URL Likely reflectively-loaded .NET assembly or packed PE delivered as comma-separated decimal bytes. ^[decoded_final.txt]
C:\Users\Public\nswls.js File path Relocated copy of the JScript payload. ^[sample_utf8.js:50]
C:\Users\Public\ntkzl.ps1 File path First-stage PowerShell script generated by JS. ^[decoded_final.txt]
C:\Users\Public\hhsqh.txt File path C2 URL holder file created by the PS payload. ^[decoded_final.txt]
C:\Users\Public\pfvzx.txt File path Second-stage payload text file (cleaned). ^[decoded_final.txt]
C:\Users\Public\sqzch_01.ps1 File path Second-stage PowerShell script generated at runtime. ^[decoded_final.txt]

Interesting Tidbits

  • Portuguese fingerprints: Comments read para RGrIv dois and para verificar se um, and the HostGator domain is a Brazilian reseller (meusitehostgator.com.br). This aligns with Brazilian crimeware clusters such as Troldesh/Xorist and generic stealers/droppers. No Portuguese-language ransom notes observed (static only). ^[sample_utf8.js:293;^sample_utf8.js:342]
  • Reused C2 infrastructure: The numeric subdomain 1775471117328.2082219.meusitehostgator.com.br follows a pattern of numeric tokens, possibly derived from victim ID or campaign metadata.
  • No YARA hits: Triaged with zero YARA matches, confirming the sample has no known family label in our current rule sets. ^[yara.txt]
  • CAPE skipped: Not a supported binary class for detonation. All behavioral claims are static inferences. ^[dynamic-analysis.md]
  • Attribution confidence: medium. Pattern (WScript→PS→.NET reflector, Brazilian HostGator, C:\Users\Public staging, process-name sandbox gate) is strongly consistent with Troldesh / Xorist / generic Brazilian stealer chains. However, without the second-stage payload or a ransom note, no definitive family label is assigned.

Detection Signatures

IOC List

IOC Type
0e4141aac553fa9b2e3a224ad54ce65ba61ddbf9c1e856d363b59cad111ef0d4 SHA-256 (this sample)
ykqtogmy.js Filename (observed)
C:\Users\Public\nswls.js File path (persistence/copy)
C:\Users\Public\ntkzl.ps1 File path (generated PS)
C:\Users\Public\sqzch_01.ps1 File path (second-stage PS)
C:\Users\Public\hhsqh.txt File path (C2 URL holder)
C:\Users\Public\pfvzx.txt File path (second-stage payload)
andrefelipedonascime1775471117328.2082219.meusitehostgator.com.br Domain
catalogo.castrou2la.com Domain

Sigma Rule — WScript PowerShell Chain with Public Path

title: WScript-to-PowerShell Chain with Public Directory Staging
id: c7a3f2e1-8b44-4c90-a3d2-0e4141aa-
status: experimental
description: Detects WScript spawning PowerShell with ExecutionPolicy Bypass targeting files in C:\Users\Public\, consistent with JS dropper staging.
logsource:
  category: process_creation
  product: windows
detection:
  selection_main:
    ParentImage|endswith: '\wscript.exe'
    CommandLine|contains:
      - 'ExecutionPolicy Bypass'
      - 'C:\\Users\\Public\\'
  selection_child:
    Image|endswith: '\powershell.exe'
  condition: selection_main and selection_child
falsepositives:
  - Legitimate administrative scripts
level: high

YARA Rule — Troldesh-Style JS Dropper Signature

rule troldesh_js_dropper_heuristic
{
    meta:
        description = "Heuristic for Troldesh-style WScript→PowerShell dropper JS"
        author = "pp-hermes"
        date = "2026-06-02"
        sha256 = "0e4141aac553fa9b2e3a224ad54ce65ba61ddbf9c1e856d363b59cad111ef0d4"
    strings:
        $wscript_fullname = "WScript.ScriptFullName" ascii wide
        $temp_check = "Temp" ascii wide
        $downloads_check = "Downloads" ascii wide
        $shell_app = "Shell.Application" ascii wide
        $shell_exec = "ShellExecute" ascii wide
        $fso = "Scripting.FileSystemObject" ascii wide
        $powershell_chain = "power" + "rsh" + "ell" ascii wide
        $base64_decode = "FromBase64String" ascii wide
        $reflection_load = "System.Reflection.Assembly" ascii wide
    condition:
        filesize < 100KB and
        all of ($wscript_fullname, $fso, $shell_app) and
        any of ($temp_check, $downloads_check) and
        any of ($powershell_chain, $base64_decode, $reflection_load)
}

How To Mess With It (Homelab Replication)

  1. Write a minimal JScript that checks WScript.ScriptFullName.indexOf("Temp"), copies to C:\Users\Public\, and launches itself.
  2. Build the PowerShell downloader inside a Base64-encoded string; concatenate with + 'A' + noise.
  3. Add a sandbox gate (get-process handle, wireshark, any.run -SilentlyContinue).
  4. Reflectively load a small .NET assembly from a comma-delimited text file via System.Reflection.Assembly::Load([byte[]]).
  5. Compare capa output — N/A for script; instead verify with manual string extraction and YARA rule above.

This is an exercise in persistence staging and PowerShell obfuscation, not in PE reverse engineering.

References

  • Sample: 0e4141aac553fa9b2e3a224ad54ce65ba61ddbf9c1e856d363b59cad111ef0d4
  • Artifact ID: cb212459-9a29-4924-8903-9301e0f27779
  • Source: OpenCTI / MalwareBazaar
  • Related wiki page: spamita — another JScript family with comparable three-stage obfuscation, though this sample uses manual dead-code injection rather than RC4 encryption.

Provenance

Analysis derived from UTF-16LE JScript source (sample_utf8.js, lines 1–470) decoded via iconv -f UTF-16LE -t UTF-8; Base64 payload reconstructed with string concatenation stripping noise characters (', + , spaces) matching the PowerShell replace operations defined at lines 426–443 of the JS source. Decoded PowerShell saved to /tmp/decoded_final.txt. Dynamic analysis absent (CAPE skipped — unsupported file type). File-type: Unicode text UTF-16LE ^[file.txt]. No PE sections; not a binary.