jscript-environment-variable-staging

Overview

A defense-evasion and payload-delivery technique in which a JScript/WScript carrier encodes a binary payload (typically a PE or .NET assembly) as a series of strings, assigns each string to a unique process-scoped environment variable via WScript.Shell.Environment("Process"), and then spawns a PowerShell child process that reads the variables back and reconstructs the payload in-memory. This breaks the payload across the process environment block, making memory-dump analysis and string-based detection harder.

Observed Variants

Variant Payload Encoding Staging Count Inner Stage Sample
CJK steganography CJK characters (byte = charcode - 0x3400) 384 env vars PowerShell → .NET reflective load 0de6482c
Hangul steganography Hangul Syllables (byte = charcode - 0xAC00) 347 env vars + fallback CJK stream cipher PowerShell → .NET reflective load 7129076f
CJK Unified Ideographs CJK characters (byte = charcode - 0x4E00) 381 env vars XSLT JScript extension → conhost --headless powershell → .NET reflective load eba13078

Technique Details

  1. Encode the raw payload into a series of strings (e.g., CJK characters, Base64, hex).
  2. Assign each string to a process-scoped environment variable via WScript.Shell.Environment("Process").Item(var_name) = payload_chunk.
  3. Spawn a PowerShell process that iterates over the variable names, concatenates the chunks, decodes them, and either writes to disk or loads reflectively.
  4. Cleanup may include unsetting variables or self-deletion of the JScript carrier.

Detection Opportunities

  • Sigma rule: ImageLoaded contains wscript.exe with unusually large command-line arguments, followed by powershell.exe with -EncodedCommand or inline script reading $env: variables.
  • Memory forensics: scan process environment blocks for high counts of variables containing Base64, CJK characters, or long alphanumeric strings.
  • EDR: flag WScript.Shell creating more than N environment variables in rapid succession.

References