ThreatHunting/Get-MITREAttackMapping.ps1
|
function Get-MITREAttackMapping { <# .SYNOPSIS Maps detected activities to MITRE ATT&CK framework techniques .DESCRIPTION Analyzes system activities and maps them to MITRE ATT&CK tactics and techniques. Provides detailed technique information with detection methods and recommendations. .PARAMETER CheckProcesses Analyze running processes for MITRE techniques .PARAMETER CheckRegistry Analyze registry for persistence techniques .PARAMETER CheckNetworkActivity Analyze network activity for C2 techniques .PARAMETER CheckEventLogs Analyze security event logs for technique indicators .PARAMETER FullAnalysis Run all checks .EXAMPLE Get-MITREAttackMapping -CheckProcesses -CheckRegistry Get-MITREAttackMapping -FullAnalysis .OUTPUTS PSCustomObject with MITRE ATT&CK technique mappings #> [CmdletBinding()] param( [Parameter()] [switch]$CheckProcesses, [Parameter()] [switch]$CheckRegistry, [Parameter()] [switch]$CheckNetworkActivity, [Parameter()] [switch]$CheckEventLogs, [Parameter()] [switch]$FullAnalysis ) begin { Write-Host "=== MITRE ATT&CK TECHNIQUE MAPPING ===" -ForegroundColor Cyan Write-Host "Start Time: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Yellow if ($FullAnalysis) { $CheckProcesses = $true $CheckRegistry = $true $CheckNetworkActivity = $true $CheckEventLogs = $true Write-Host "Full Analysis Mode: Enabled" -ForegroundColor Yellow } $results = [PSCustomObject]@{ AnalysisDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" ComputerName = $env:COMPUTERNAME DetectedTechniques = @() TacticBreakdown = @{ InitialAccess = @() Execution = @() Persistence = @() PrivilegeEscalation = @() DefenseEvasion = @() CredentialAccess = @() Discovery = @() LateralMovement = @() Collection = @() CommandAndControl = @() Exfiltration = @() Impact = @() } Summary = @{ TotalTechniques = 0 TacticsCovered = 0 RiskScore = 0 } Recommendations = @() } # Legitimate process whitelist $legitimateProcesses = @( 'svchost', 'explorer', 'dwm', 'lsass', 'csrss', 'smss', 'winlogon', 'services', 'spoolsv', 'taskhost', 'taskhostw', 'RuntimeBroker', 'SearchIndexer', 'Microsoft.Photos', 'SystemSettings', 'ShellExperienceHost', 'sihost', 'fontdrvhost', 'conhost', 'dllhost', 'SearchApp', 'StartMenuExperienceHost', 'TextInputHost', 'MoUsoCoreWorker', 'SgrmBroker', 'AutoBootInstallService', 'erlsrv', 'gamingservices', 'Xbox', 'Windows', 'Microsoft' ) # MITRE ATT&CK Technique Database - IMPROVED with context-aware detection $mitreDB = @{ 'T1059.001' = @{ Name = 'Command and Scripting Interpreter: PowerShell' Tactic = 'Execution' Description = 'Adversaries abuse PowerShell to execute commands' ProcessName = 'powershell.exe|pwsh.exe' SuspiciousArgs = @('-enc', '-encodedcommand', '-w hidden', '-windowstyle hidden', '-nop', '-noprofile', '-exec bypass', '-executionpolicy bypass') RequiresCommandLine = $true Severity = 'High' } 'T1059.003' = @{ Name = 'Command and Scripting Interpreter: Windows Command Shell' Tactic = 'Execution' Description = 'Adversaries abuse cmd.exe to execute commands' ProcessName = 'cmd.exe' SuspiciousArgs = @('/c whoami', '/c net user', '/c net localgroup', '/c tasklist', '/c ipconfig /all') RequiresCommandLine = $true Severity = 'Medium' } 'T1547.001' = @{ Name = 'Boot or Logon Autostart Execution: Registry Run Keys' Tactic = 'Persistence' Description = 'Adversaries achieve persistence via registry run keys' DetectionType = 'Registry' RegistryPaths = @( 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run', 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' ) Severity = 'High' } 'T1053.005' = @{ Name = 'Scheduled Task/Job: Scheduled Task' Tactic = 'Persistence' Description = 'Adversaries schedule tasks for persistence' ProcessName = 'schtasks.exe' SuspiciousArgs = @('/create', 'Register-ScheduledTask', 'New-ScheduledTask') RequiresCommandLine = $true Severity = 'High' } 'T1543.003' = @{ Name = 'Create or Modify System Process: Windows Service' Tactic = 'Persistence' Description = 'Adversaries create/modify services for persistence' ProcessName = 'sc.exe' SuspiciousArgs = @('create', 'config', 'New-Service') RequiresCommandLine = $true Severity = 'High' } 'T1055' = @{ Name = 'Process Injection' Tactic = 'DefenseEvasion' Description = 'Adversaries inject code into processes' SuspiciousArgs = @('VirtualAllocEx', 'WriteProcessMemory', 'CreateRemoteThread', 'QueueUserAPC') RequiresCommandLine = $true Severity = 'Critical' } 'T1027' = @{ Name = 'Obfuscated Files or Information' Tactic = 'DefenseEvasion' Description = 'Adversaries obfuscate files or information' SuspiciousArgs = @('-enc [A-Za-z0-9+/=]{50,}', 'FromBase64String', '[Convert]::FromBase64') RequiresCommandLine = $true Severity = 'High' } 'T1070.001' = @{ Name = 'Indicator Removal: Clear Windows Event Logs' Tactic = 'DefenseEvasion' Description = 'Adversaries clear event logs to hide activity' ProcessName = 'wevtutil.exe' SuspiciousArgs = @('clear-log', 'cl', 'Clear-EventLog') RequiresCommandLine = $true Severity = 'High' } 'T1003.001' = @{ Name = 'OS Credential Dumping: LSASS Memory' Tactic = 'CredentialAccess' Description = 'Adversaries dump credentials from LSASS' ProcessName = 'procdump|procdump64|mimikatz' SuspiciousArgs = @('lsass', 'sekurlsa', 'logonpasswords') RequiresCommandLine = $false Severity = 'Critical' } 'T1003.002' = @{ Name = 'OS Credential Dumping: Security Account Manager' Tactic = 'CredentialAccess' Description = 'Adversaries access SAM database for credentials' ProcessName = 'reg.exe' SuspiciousArgs = @('save.*HKLM\\SAM', 'save.*HKLM\\SYSTEM', 'save.*HKLM\\SECURITY') RequiresCommandLine = $true Severity = 'Critical' } 'T1087.001' = @{ Name = 'Account Discovery: Local Account' Tactic = 'Discovery' Description = 'Adversaries enumerate local accounts' ProcessName = 'net.exe|net1.exe' SuspiciousArgs = @('user', 'localgroup', 'accounts') RequiresCommandLine = $true Severity = 'Medium' } 'T1087.002' = @{ Name = 'Account Discovery: Domain Account' Tactic = 'Discovery' Description = 'Adversaries enumerate domain accounts' ProcessName = 'net.exe|dsquery.exe' SuspiciousArgs = @('user /domain', 'group /domain', 'Get-ADUser') RequiresCommandLine = $true Severity = 'Medium' } 'T1082' = @{ Name = 'System Information Discovery' Tactic = 'Discovery' Description = 'Adversaries gather system information' ProcessName = 'systeminfo.exe|wmic.exe' SuspiciousArgs = @('computersystem', 'os', 'qfe') RequiresCommandLine = $true Severity = 'Low' } 'T1071.001' = @{ Name = 'Application Layer Protocol: Web Protocols' Tactic = 'CommandAndControl' Description = 'Adversaries use HTTP/HTTPS for C2' ProcessName = 'powershell.exe|pwsh.exe' SuspiciousArgs = @('Invoke-WebRequest.*IEX', 'WebClient.*DownloadString', 'Net.WebClient.*DownloadFile') RequiresCommandLine = $true Severity = 'High' } 'T1571' = @{ Name = 'Non-Standard Port' Tactic = 'CommandAndControl' Description = 'Adversaries use non-standard ports for C2' DetectionType = 'Network' Severity = 'Medium' } 'T1486' = @{ Name = 'Data Encrypted for Impact' Tactic = 'Impact' Description = 'Adversaries encrypt data (ransomware)' SuspiciousArgs = @('\.encrypted', '\.locked', '\.crypt', 'ransom', 'YOUR_FILES') RequiresCommandLine = $true Severity = 'Critical' } } } process { try { # 1. Check Processes for Technique Indicators if ($CheckProcesses) { Write-Host "`n[1/4] Analyzing running processes..." -ForegroundColor Cyan try { # Get processes with command line using WMI $processes = Get-CimInstance Win32_Process | Select-Object Name, ProcessId, ExecutablePath, CommandLine foreach ($process in $processes) { # Skip whitelisted legitimate processes $isLegitimate = $false foreach ($legitProc in $legitimateProcesses) { if ($process.Name -like "*$legitProc*") { $isLegitimate = $true break } } if ($isLegitimate) { continue } foreach ($techId in $mitreDB.Keys) { $technique = $mitreDB[$techId] # Skip registry/network-only techniques if ($technique.ContainsKey('DetectionType') -and $technique.DetectionType -in @('Registry', 'Network')) { continue } # Techniques without a ProcessName anchor (e.g. T1055, T1027, T1486) # match any non-whitelisted process by command line $nameMatches = $true if ($technique.ContainsKey('ProcessName')) { $nameMatches = ($process.Name -match $technique.ProcessName) } $matched = $false $matchedIndicator = "" # Check if process name matches if ($nameMatches) { # If technique requires command line analysis if ($technique.RequiresCommandLine) { if ($process.CommandLine) { foreach ($arg in $technique.SuspiciousArgs) { if ($process.CommandLine -match $arg) { $matched = $true $matchedIndicator = $arg break } } } } else { # Process name alone is suspicious (e.g., mimikatz) $matched = $true $matchedIndicator = "Suspicious process name" } } if ($matched) { $detection = [PSCustomObject]@{ TechniqueID = $techId TechniqueName = $technique.Name Tactic = $technique.Tactic Severity = $technique.Severity DetectionSource = 'Process' Evidence = "Process: $($process.Name) (PID: $($process.ProcessId)) - Indicator: $matchedIndicator" CommandLine = if ($process.CommandLine) { $process.CommandLine.Substring(0, [Math]::Min(200, $process.CommandLine.Length)) } else { "N/A" } Description = $technique.Description Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" } $results.DetectedTechniques += $detection $results.TacticBreakdown[$technique.Tactic] += $detection Write-Host " [!] Detected: $techId - $($technique.Name)" -ForegroundColor Yellow Write-Host " Evidence: $matchedIndicator" -ForegroundColor Gray } } } if ($results.DetectedTechniques.Count -eq 0) { Write-Host " No suspicious process activity detected" -ForegroundColor Green } } catch { Write-Warning "Error analyzing processes: $_" } } # 2. Check Registry for Persistence Techniques if ($CheckRegistry) { Write-Host "`n[2/4] Analyzing registry keys..." -ForegroundColor Cyan try { $runKeys = @( 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run', 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run', 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce' ) $suspiciousEntries = @() foreach ($key in $runKeys) { if (Test-Path $key) { $values = Get-ItemProperty -Path $key -ErrorAction SilentlyContinue if ($values) { # Count non-PS properties $entryCount = 0 foreach ($prop in $values.PSObject.Properties) { if ($prop.Name -notmatch "^PS") { $entryCount++ # Check for suspicious patterns $value = $prop.Value if ($value -match "temp|appdata\\local\\temp|public|programdata|script|\.vbs|\.js|\.bat|http|download") { $suspiciousEntries += " - $($prop.Name): $value" } } } if ($entryCount -gt 0) { # T1547.001 - Registry Run Keys detected $detection = [PSCustomObject]@{ TechniqueID = 'T1547.001' TechniqueName = $mitreDB['T1547.001'].Name Tactic = 'Persistence' Severity = 'Medium' # Medium unless suspicious DetectionSource = 'Registry' Evidence = "Registry Run Key found: $key ($entryCount entries)" CommandLine = "N/A" Description = $mitreDB['T1547.001'].Description Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" } # Check if already detected for this key $alreadyDetected = $results.DetectedTechniques | Where-Object { $_.TechniqueID -eq 'T1547.001' -and $_.Evidence -match [regex]::Escape($key) } if (-not $alreadyDetected) { $results.DetectedTechniques += $detection $results.TacticBreakdown.Persistence += $detection Write-Host " [!] Detected: T1547.001 - Registry Run Keys ($entryCount entries in $key)" -ForegroundColor Yellow } } } } } if ($suspiciousEntries.Count -gt 0) { Write-Host " Suspicious entries found:" -ForegroundColor Red $suspiciousEntries | Select-Object -First 3 | ForEach-Object { Write-Host $_ -ForegroundColor Red } } } catch { Write-Warning "Error analyzing registry: $_" } } # 3. Check Network Activity for C2 Techniques if ($CheckNetworkActivity) { Write-Host "`n[3/4] Analyzing network activity..." -ForegroundColor Cyan try { $connections = Get-NetTCPConnection -State Established -ErrorAction SilentlyContinue $suspiciousConnections = 0 foreach ($conn in $connections) { # Check for non-standard ports (T1571) $nonStandardPorts = @(4444, 5555, 31337, 1337, 6666, 7777) if ($conn.RemotePort -in $nonStandardPorts) { $process = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue $processName = if ($process) { $process.Name } else { "PID $($conn.OwningProcess)" } # Skip if it's a known legitimate process $isLegitimate = $false foreach ($legitProc in $legitimateProcesses) { if ($processName -like "*$legitProc*") { $isLegitimate = $true break } } if (-not $isLegitimate) { $detection = [PSCustomObject]@{ TechniqueID = 'T1571' TechniqueName = $mitreDB['T1571'].Name Tactic = 'CommandAndControl' Severity = 'High' DetectionSource = 'Network' Evidence = "Non-standard port $($conn.RemotePort) used by $processName -> $($conn.RemoteAddress)" CommandLine = "N/A" Description = $mitreDB['T1571'].Description Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" } $results.DetectedTechniques += $detection $results.TacticBreakdown.CommandAndControl += $detection $suspiciousConnections++ Write-Host " [!] Detected: T1571 - Non-Standard Port ($($conn.RemotePort))" -ForegroundColor Yellow } } } if ($suspiciousConnections -eq 0) { Write-Host " No suspicious network activity detected" -ForegroundColor Green } } catch { Write-Warning "Error analyzing network activity: $_" } } # 4. Check Event Logs for Technique Indicators if ($CheckEventLogs) { Write-Host "`n[4/4] Analyzing security event logs..." -ForegroundColor Cyan try { # Check for log clearing (T1070.001) - High severity event $logCleared = Get-WinEvent -FilterHashtable @{ LogName = 'Security' ID = 1102 } -MaxEvents 10 -ErrorAction SilentlyContinue if ($logCleared) { foreach ($event in $logCleared) { $detection = [PSCustomObject]@{ TechniqueID = 'T1070.001' TechniqueName = $mitreDB['T1070.001'].Name Tactic = 'DefenseEvasion' Severity = 'High' DetectionSource = 'EventLog' Evidence = "Security log cleared at $($event.TimeCreated)" CommandLine = "N/A" Description = $mitreDB['T1070.001'].Description Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" } $results.DetectedTechniques += $detection $results.TacticBreakdown.DefenseEvasion += $detection } Write-Host " [!] Detected: T1070.001 - Event Log Clearing ($(@($logCleared).Count) events)" -ForegroundColor Red } else { Write-Host " No suspicious event log activity detected" -ForegroundColor Green } } catch { Write-Warning "Error analyzing event logs: $_" } } # Calculate summary statistics $uniqueTechniques = @($results.DetectedTechniques | Select-Object -Unique -Property TechniqueID) $results.Summary.TotalTechniques = $uniqueTechniques.Count # Count tactics with detections $tacticCount = 0 foreach ($tactic in $results.TacticBreakdown.Keys) { if ($results.TacticBreakdown[$tactic].Count -gt 0) { $tacticCount++ } } $results.Summary.TacticsCovered = $tacticCount # Calculate risk score foreach ($technique in $results.DetectedTechniques) { $riskScore = switch ($technique.Severity) { 'Critical' { 10 } 'High' { 7 } 'Medium' { 4 } 'Low' { 2 } default { 1 } } $results.Summary.RiskScore += $riskScore } # Generate recommendations if ($results.Summary.TotalTechniques -gt 0) { $results.Recommendations += "Review detected MITRE ATT&CK techniques immediately" $results.Recommendations += "Investigate command lines and process chains" $results.Recommendations += "Enable advanced audit logging for covered tactics" # Severity-based recommendations $criticalCount = @($results.DetectedTechniques | Where-Object { $_.Severity -eq 'Critical' }).Count if ($criticalCount -gt 0) { $results.Recommendations += "CRITICAL: $criticalCount critical techniques detected - immediate response required" } } # Tactic-specific recommendations if ($results.TacticBreakdown.Persistence.Count -gt 0) { $results.Recommendations += "Review and harden persistence mechanisms" } if ($results.TacticBreakdown.CredentialAccess.Count -gt 0) { $results.Recommendations += "CRITICAL: Investigate credential access attempts immediately" } if ($results.TacticBreakdown.DefenseEvasion.Count -gt 0) { $results.Recommendations += "Strengthen security controls and monitoring" } } catch { Write-Error "Error during MITRE ATT&CK mapping: $_" throw } } end { Write-Host "`n=== ANALYSIS COMPLETE ===" -ForegroundColor Green Write-Host "`nMITRE ATT&CK Coverage:" -ForegroundColor Cyan Write-Host " Unique Techniques Detected: $($results.Summary.TotalTechniques)" -ForegroundColor White Write-Host " Tactics Covered: $($results.Summary.TacticsCovered)/12" -ForegroundColor White Write-Host " Risk Score: $($results.Summary.RiskScore)" -ForegroundColor $( if ($results.Summary.RiskScore -ge 50) { 'Red' } elseif ($results.Summary.RiskScore -ge 20) { 'Yellow' } else { 'Green' } ) if ($results.Summary.TotalTechniques -gt 0) { Write-Host "`nDetected Techniques by Tactic:" -ForegroundColor Cyan foreach ($tactic in $results.TacticBreakdown.Keys | Sort-Object) { $count = $results.TacticBreakdown[$tactic].Count if ($count -gt 0) { Write-Host " $tactic : $count technique(s)" -ForegroundColor Yellow } } Write-Host "`nTop Detected Techniques:" -ForegroundColor Cyan $results.DetectedTechniques | Group-Object TechniqueID | Sort-Object Count -Descending | Select-Object -First 5 | ForEach-Object { $tech = $_.Group[0] Write-Host " $($tech.TechniqueID) - $($tech.TechniqueName) [$($tech.Severity)]" -ForegroundColor White } } else { Write-Host "`nNo suspicious MITRE ATT&CK techniques detected" -ForegroundColor Green } if ($results.Recommendations.Count -gt 0) { Write-Host "`nRecommendations:" -ForegroundColor Cyan $results.Recommendations | Select-Object -Unique | ForEach-Object { Write-Host " ! $_" -ForegroundColor Yellow } } Write-Host "`nMITRE ATT&CK Navigator:" -ForegroundColor Cyan Write-Host " https://mitre-attack.github.io/attack-navigator/" -ForegroundColor Gray return $results } } |