Lab 8.2: AMSI and PowerShell Detection
Learning Objectives
By the end of this lab, you will be able to:
- Understand how AMSI (Antimalware Scan Interface) works
- Identify how malicious scripts are detected
- Know bypass techniques (for defensive purposes)
- Implement effective detection
Estimated Duration
45 minutes
Prerequisites
- Windows 10/11 VM
- Active Windows Defender
- PowerShell 5.1+
- Administrator rights
Professional Context
AMSI is a critical interface for:
- Detecting malicious scripts
- Protecting against fileless malware
- Integrating antivirus with PowerShell
- Securing enterprise environments
WARNING
This lab explains concepts for defensive purposes.
- Bypass techniques are presented to understand threats
- DO NOT use these techniques maliciously
- Execute only on isolated test VMs
Part 1: Understanding AMSI
Step 1.1: What is AMSI?
AMSI (Antimalware Scan Interface) is a Windows interface that allows antivirus software to inspect the content of scripts before execution.
Execution flow:
PowerShell Script --> AMSI --> Antivirus --> Allow/Block
Applications supporting AMSI:
- PowerShell
- Windows Script Host (wscript, cscript)
- JavaScript
- VBScript
- Office VBA macros
- .NET assemblies
Step 1.2: Verify AMSI is active
# AMSI is active if Windows Defender is active
Get-MpComputerStatus | Select-Object AMServiceEnabled, AntivirusEnabled, RealTimeProtectionEnabled
Step 1.3: Test AMSI
Windows Defender detects the standard AMSI test string:
# This command SHOULD be blocked by AMSI
# It contains the official test string
# Try this (will be blocked):
"AM" + "SI" + "Test"
Note: Simply mentioning certain terms triggers AMSI.
Question 1: Was the AMSI test detected?
Part 2: How AMSI Detects Threats
Step 2.1: Signature-based detection
AMSI scans for known patterns:
# Examples of detected patterns (do not execute):
# - "Invoke-Mimikatz"
# - "Invoke-Empire"
# - Certain Base64 encoded commands
# - Shellcode patterns
Step 2.2: Encoded scripts
Attackers often use Base64 encoding:
# Simple command
$cmd = "whoami"
# Encoded in Base64
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmd)
$encoded = [Convert]::ToBase64String($bytes)
Write-Host "Encoded command: $encoded"
# Decode
$decoded = [System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($encoded))
Write-Host "Decoded: $decoded"
AMSI analyzes content AFTER decoding, so encoding alone is not sufficient.
Step 2.3: Observe AMSI in action
# This script shows how AMSI intercepts commands
# Execution with logging
# Enable PowerShell logging (requires admin)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1 -ErrorAction SilentlyContinue
# Verify
Get-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -ErrorAction SilentlyContinue
Part 3: Bypass Techniques (Defensive Knowledge)
Step 3.1: Why know the bypasses?
As a defender, you need to know attackers' techniques to:
- Improve detection
- Test your defenses
- Understand security alerts
- Train SOC teams
Step 3.2: Categories of bypass
| Technique | Description | Detection |
|---|---|---|
| Memory Patching | Modify AMSI in memory | Event ID 4104, suspicious behavior |
| Reflection | Use .NET reflection | Script Block Logging |
| Obfuscation | Obfuscate code | Behavioral analysis |
| COM Hijacking | Hijack COM interface | Registry monitoring |
Step 3.3: Detecting bypass attempts
# Script to detect AMSI bypass attempts
# Search in PowerShell logs
Write-Host "=== AMSI BYPASS DETECTION ===" -ForegroundColor Cyan
# Search for suspicious terms in logs
$suspectTerms = @(
"amsi",
"AmsiInitFailed",
"AmsiContext",
"amsiSession",
"SetValue.*amsi"
)
$events = Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -MaxEvents 100 -ErrorAction SilentlyContinue
$suspicious = @()
foreach ($event in $events) {
foreach ($term in $suspectTerms) {
if ($event.Message -match $term) {
$suspicious += [PSCustomObject]@{
Time = $event.TimeCreated
EventId = $event.Id
Match = $term
Message = $event.Message.Substring(0, [Math]::Min(200, $event.Message.Length))
}
}
}
}
if ($suspicious.Count -gt 0) {
Write-Host "`n[ALERT] Suspicious activity detected:" -ForegroundColor Red
$suspicious | Format-Table -AutoSize
} else {
Write-Host "`n[OK] No bypass attempts detected" -ForegroundColor Green
}
Question 2: Were any bypass attempts detected?
Part 4: Strengthening Protection
Step 4.1: Enable Script Block Logging
# Configure full logging (requires admin)
# Create keys if necessary
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell" -Force -ErrorAction SilentlyContinue | Out-Null
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Force -ErrorAction SilentlyContinue | Out-Null
# Enable logging
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" `
-Name "EnableScriptBlockLogging" -Value 1 -Type DWord
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" `
-Name "EnableScriptBlockInvocationLogging" -Value 1 -Type DWord
Write-Host "Script Block Logging enabled" -ForegroundColor Green
Step 4.2: Enable Module Logging
# Enable module logging
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging" -Force -ErrorAction SilentlyContinue | Out-Null
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging" `
-Name "EnableModuleLogging" -Value 1 -Type DWord
# Log all modules
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames" -Force -ErrorAction SilentlyContinue | Out-Null
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames" `
-Name "*" -Value "*" -Type String
Write-Host "Module Logging enabled" -ForegroundColor Green
Step 4.3: Configure Constrained Language Mode
# Check current language mode
$ExecutionContext.SessionState.LanguageMode
# To enforce constrained mode (via GPO or):
# [Environment]::SetEnvironmentVariable('__PSLockdownPolicy', '4', 'Machine')
# Requires reboot
# Note: Constrained mode limits PowerShell features
# Use with caution in production
Step 4.4: Verify configuration
# PowerShell security configuration verification script
Write-Host "=== POWERSHELL SECURITY CONFIGURATION ===" -ForegroundColor Cyan
# AMSI
Write-Host "`n[AMSI]" -ForegroundColor Yellow
$defender = Get-MpComputerStatus -ErrorAction SilentlyContinue
if ($defender) {
Write-Host " AMSI Service: $($defender.AMServiceEnabled)"
Write-Host " Real-Time Protection: $($defender.RealTimeProtectionEnabled)"
}
# Language Mode
Write-Host "`n[Language Mode]" -ForegroundColor Yellow
Write-Host " Current mode: $($ExecutionContext.SessionState.LanguageMode)"
# Execution Policy
Write-Host "`n[Execution Policy]" -ForegroundColor Yellow
Get-ExecutionPolicy -List | Format-Table
# Script Block Logging
Write-Host "[Script Block Logging]" -ForegroundColor Yellow
$sbl = Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -ErrorAction SilentlyContinue
if ($sbl.EnableScriptBlockLogging -eq 1) {
Write-Host " Status: Enabled" -ForegroundColor Green
} else {
Write-Host " Status: Disabled" -ForegroundColor Red
}
# Module Logging
Write-Host "`n[Module Logging]" -ForegroundColor Yellow
$ml = Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging" -ErrorAction SilentlyContinue
if ($ml.EnableModuleLogging -eq 1) {
Write-Host " Status: Enabled" -ForegroundColor Green
} else {
Write-Host " Status: Disabled" -ForegroundColor Red
}
Part 5: Monitoring and Alerts
Step 5.1: Key events to monitor
| Event ID | Log | Description |
|---|---|---|
| 4103 | PowerShell/Operational | Module logging |
| 4104 | PowerShell/Operational | Script block logging |
| 1116 | Microsoft-Windows-Windows Defender | Malware detected |
| 1117 | Microsoft-Windows-Windows Defender | Malware action |
Step 5.2: Monitoring script
# Monitoring suspicious PowerShell events
Write-Host "=== POWERSHELL MONITORING ===" -ForegroundColor Cyan
$suspectKeywords = @(
"bypass",
"encoded",
"downloadstring",
"invoke-expression",
"iex",
"reflection",
"assembly",
"shellcode",
"mimikatz"
)
# Script Block Logs (4104)
$events = Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 50 -ErrorAction SilentlyContinue
Write-Host "`nAnalyzing the last 50 Script Block Logs..." -ForegroundColor Yellow
$alerts = @()
foreach ($event in $events) {
foreach ($keyword in $suspectKeywords) {
if ($event.Message -match $keyword) {
$alerts += [PSCustomObject]@{
Time = $event.TimeCreated
Keyword = $keyword
Preview = $event.Message.Substring(0, [Math]::Min(100, $event.Message.Length))
}
break
}
}
}
if ($alerts.Count -gt 0) {
Write-Host "`n[ALERTS] Suspicious content detected:" -ForegroundColor Red
$alerts | Format-Table -AutoSize
} else {
Write-Host "`n[OK] No suspicious activity detected" -ForegroundColor Green
}
Deliverables
-
Answers to the 2 questions
-
Screenshots:
- AMSI test (detection)
- Security configuration
- Monitoring script execution
-
Report (1-2 pages):
- Explanation of AMSI functionality
- Importance of PowerShell logging
- Recommendations for your environment
Evaluation Criteria
| Criterion | Points |
|---|---|
| AMSI Understanding | 25% |
| Logging Configuration | 30% |
| Detection Script | 25% |
| Report and Analysis | 20% |
Resources
Lab developed as part of the Operating Systems course - MODULE 8