Files
sbousseaden-EDRUnChoker/Get-EdrChokerDefenseStatus.ps1
T
Samirbous 9d28f642d9 Fix ActiveStore QoS policy detection via WbemContext PolicyStore.
Plain WMI ExecQuery missed ActiveStore policies from New-NetQosPolicy and EDRChoker; enumerate ActiveStore and GPO:localhost with SWbemNamedValueSet and align status checks with Get-NetQosPolicy.
2026-06-08 16:54:41 +01:00

143 lines
5.4 KiB
PowerShell

#Requires -Version 5.1
<#
.SYNOPSIS
Reports fileless EDRChoker WMI defense subscription status.
#>
[CmdletBinding()]
param(
[string]$FilterName = 'EDRChokerDefense_QoSFilter',
[string]$ConsumerName = 'EDRChokerDefense_QoSConsumer',
[string]$TimerId = 'EDRChokerDefense_Timer'
)
$WmiNs = 'root\subscription'
$MaxThrottleBps = 1048576
$ExactTargets = @(
'amsvc', 'cb', 'cbdefense', 'cetasevc', 'cntaosmgr', 'cramtray', 'crsvc',
'cylancesvc', 'cybereasonav', 'cyserver', 'cyveraservice', 'cyvrfsflt',
'eiconnector', 'ekrn', 'elastic-agent', 'elastic-defend', 'elastic-endpoint', 'endpointbasecamp',
'executionpreventionsvc', 'filebeat', 'fortiedr', 'hurukai', 'logprocessorservice',
'mpdefendercoreservice', 'msmpeng', 'mssense', 'ntrtscan', 'pccntmon', 'qualysagent',
'sensecncproxy', 'senseir', 'sensendr', 'sensesampleuploader', 'sentinelagent',
'sentinelagentworker', 'sentinelbrowsernativehost', 'sentinelhelperservice',
'sentinelservicehost', 'sentinelstaticengine', 'sentinelstaticenginescanner',
'sfc', 'taniumclient', 'taniumcx', 'taniumdetectengine', 'tmccsf', 'tmlisten',
'tmbmsrv', 'tmwscsvc', 'traps', 'winlogbeat', 'wscommunicator', 'xagt'
)
$VendorPatterns = @(
'elastic', 'sentinel', 'cybereason', 'carbonblack', 'carbon\', 'crowdstrike',
'cylance', 'defender', 'msmpeng', 'mssense', 'windows defender', 'senseir',
'tanium', 'qualys', 'fortiedr', 'mcafee', 'symantec', 'broadcom', 'trend micro',
'eset', 'kaspersky', 'bitdefender', 'sophos', 'fireeye', 'mandiant', 'traps',
'cbdefense', 'cyvera', 'hurukai', 'xagt', 'filebeat', 'winlogbeat', 'elastic-endpoint'
)
function Get-AppBaseName {
param([string]$Path)
$p = $Path.Trim().ToLowerInvariant()
if ($p.EndsWith('.exe')) { $p = $p.Substring(0, $p.Length - 4) }
$segments = $p -split '[\\/]'
return $segments[-1]
}
function Test-KnownSecurityTarget {
param([string]$AppPath)
if ([string]::IsNullOrWhiteSpace($AppPath)) { return $false }
$lower = $AppPath.ToLowerInvariant()
$base = Get-AppBaseName -Path $lower
foreach ($t in $ExactTargets) {
if ($base -eq $t -or $base.EndsWith($t)) { return $true }
}
foreach ($p in $VendorPatterns) {
if ($lower.Contains($p)) { return $true }
}
return $false
}
function Get-PolicyAppPath {
param($Policy)
$p = [string]$Policy.AppPathNameMatchCondition
if ([string]::IsNullOrWhiteSpace($p)) { $p = [string]$Policy.AppPathName }
return $p
}
function Get-PolicyThrottle {
param($Policy)
foreach ($name in @('ThrottleRateAction', 'ThrottleRateActionBitsPerSecond')) {
if ($null -ne $Policy.$name -and [uint64]$Policy.$name -gt 0) {
return [uint64]$Policy.$name
}
}
$formatted = [string]$Policy.ThrottleRate
if ($formatted -match '^(\d+)') {
return [uint64]$Matches[1]
}
return [uint64]0
}
function Test-MaliciousQosPolicy {
param($Policy)
$appPath = Get-PolicyAppPath -Policy $Policy
if ([string]::IsNullOrWhiteSpace($appPath)) { return $false }
$throttle = Get-PolicyThrottle -Policy $Policy
if ($throttle -eq 0) { return $false }
if (Test-KnownSecurityTarget -AppPath $appPath) { return $true }
if ($throttle -le $MaxThrottleBps) { return $true }
return $false
}
function Get-AllNetQosPolicies {
$all = @()
foreach ($store in @('ActiveStore', 'GPO:localhost')) {
$all += @(Get-NetQosPolicy -PolicyStore $store -ErrorAction SilentlyContinue)
}
return $all
}
Write-Host '=== WMI subscription (root\subscription) ===' -ForegroundColor Cyan
Get-WmiObject -Namespace $WmiNs -Class __IntervalTimerInstruction -ErrorAction SilentlyContinue |
Where-Object { $_.TimerId -eq $TimerId } |
Format-List TimerId, IntervalBetweenEvents
Get-WmiObject -Namespace $WmiNs -Class __EventFilter -ErrorAction SilentlyContinue |
Where-Object { $_.Name -eq $filterName } |
Format-List Name, Query, EventNamespace
Get-WmiObject -Namespace $WmiNs -Class CommandLineEventConsumer -ErrorAction SilentlyContinue |
Where-Object { $_.Name -eq $consumerName } |
Format-List Name, CommandLineTemplate
Get-WmiObject -Namespace $WmiNs -Class ActiveScriptEventConsumer -ErrorAction SilentlyContinue |
Where-Object { $_.Name -eq $consumerName } |
Format-List Name, ScriptingEngine, KillTimeout
Get-WmiObject -Namespace $WmiNs -Class __FilterToConsumerBinding -ErrorAction SilentlyContinue |
Where-Object { $_.Filter -match [regex]::Escape($filterName) } |
Format-List Filter, Consumer
Write-Host '=== Policies matching hardened detection rules ===' -ForegroundColor Cyan
$all = @(Get-AllNetQosPolicies)
$malicious = @($all | Where-Object { Test-MaliciousQosPolicy -Policy $_ })
Write-Host "Count: $($malicious.Count) / $($all.Count) total QoS policies"
if ($malicious.Count -gt 0) {
$malicious | ForEach-Object {
[PSCustomObject]@{
Name = $_.Name
AppPath = (Get-PolicyAppPath -Policy $_)
Throttle = (Get-PolicyThrottle -Policy $_)
Owner = $_.Owner
}
} | Format-Table -AutoSize
}
Write-Host '=== Recent remediation events (Application / EDRChokerDefense) ===' -ForegroundColor Cyan
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
ProviderName = 'EDRChokerDefense'
} -MaxEvents 15 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, LevelDisplayName, Message |
Format-Table -Wrap -AutoSize