typetechniqueconfidencehighcreated2026-08-04updated2026-08-04powershellobfuscationtoken-cipherreflectiondotnet

PowerShell Token Substitution Loader

A PowerShell anti-static technique in which the script source is encoded with a single-character token-substitution cipher, then fragmented across multiple SET variable assignments in a parent batch file. The tokens are replaced at runtime by batch variable-expansion or by PowerShell string replacement, producing a fully functional reflective .NET assembly loader.

Pipeline

Stage 1 — Token mapping

The attacker defines a fixed mapping of multi-character tokens to single PowerShell characters:

Token Replacement
#O (
#Q )
#R $
#W newline (\n)
#X [
#E ]
#D .
#U -
#I (deleted / no-op)

Stage 2 — Fragmentation across batch variables

The encoded payload is split across dozens of batch SET variables, each holding a fragment of the encoded string. For example:

set "_xzg=$ErrorActionPreference=#O#ISt#I#U#Iop#I#Q#W$_iv=#O#IInv#I#U#Ioke#I#Q"
set "_vmg=$_tspm=#O#O#Is#I#U#Iyst#I#Q#U#O#I{0}{1}#I-f#Iem#I,#I.nume#I#Q"

^[/intel/analyses/c96b83fa0b190f3e09f92507e04b821b98eeed9f51a866a75c188ff08baa3b36.html]

Stage 3 — Assembly and decode

The batch script concatenates the variables into a single PowerShell command line, or passes them as an -EncodedCommand / -Command argument. The resulting PowerShell script then performs string replacement to restore the original tokens:

$script = $script.Replace('#O','(').Replace('#Q',')').Replace('#R','$').Replace('#W','`n')

Stage 4 — Reflective execution

The decoded PowerShell:

  1. Validates ExecutionContext.SessionState.LanguageMode is FullLanguage
  2. Forces TLS 1.2 via System.Net.ServicePointManager
  3. Loads System.Net.Http for HttpClient
  4. Reads the parent batch file from disk
  5. Extracts Base64-encoded .NET assembly from REM lines
  6. Loads the assembly via [Reflection.Assembly]::Load
  7. Invokes the entry point via reflection (GetMethod + Invoke) ^[/intel/analyses/c96b83fa0b190f3e09f92507e04b821b98eeed9f51a866a75c188ff08baa3b36.html]

Detection / Triage

  • Batch variables with # tokens: grep -E 'set.*#[OQRWXEUDI]' in a batch file is a strong signal.
  • Long SET lines: awk 'length > 500 && /^set/' will surface the encoded fragments.
  • PowerShell language-mode gate: FullLanguage check is a reliable behavioural indicator.
  • Reflection assembly load: [Reflection.Assembly]::Load inside a batch-launched PowerShell is always suspicious.

Related