Eventos de Windows
Windows lleva un diario de lo que pasa en el equipo: quién entra, quién falla al intentarlo, qué se instala y quién toca las cuentas. Casi nadie lo lee, pero está ahí. Y si alguien lo borra, el borrado también queda apuntado.
El caso
Un lunes por la mañana todo parece normal: nadie ha notado nada raro y los equipos funcionan. Pero el registro de seguridad de uno de ellos cuenta otra historia. Durante la madrugada del domingo hay cientos de intentos de inicio de sesión fallidos, todos desde la misma dirección, probando nombres de usuario uno detrás de otro. Y luego, a las 3:14, uno que no falló: una sesión de escritorio remoto que nadie de la empresa abrió.
Nadie lo vio en su momento porque nadie estaba mirando. El rastro, sin embargo, estaba escrito con hora, usuario, tipo de acceso y origen. Este capítulo va de aprender a leer ese diario: los intentos, el acceso que sí prosperó y lo que pasó después.
La herramienta
El registro de eventos de Windows es el sistema que usa el propio sistema operativo, sus servicios y muchas aplicaciones para dejar constancia de lo que ocurre. Cada anotación es un evento con un identificador numérico (el Event ID), una fecha, un origen y un bloque de datos con los detalles.
Los eventos se agrupan en registros o canales. Para forense y defensa, los que más importan son estos:
| Registro | Qué guarda |
|---|---|
Security | Inicios y cierres de sesión, cambios en cuentas y grupos, uso de privilegios, borrado del propio registro. Es el más valioso. |
System | Servicios que se instalan, arrancan o paran, errores de controladores, apagados. |
Application | Lo que escriben las aplicaciones: errores, bloqueos, instalaciones. |
Microsoft-Windows-PowerShell/Operational | Bloques de código de PowerShell ejecutados, si está activado su registro. |
Microsoft-Windows-TerminalServices-LocalSessionManager/Operational | Sesiones de escritorio remoto (RDP): inicio, reconexión y desconexión, con el usuario y la IP de origen. |
Físicamente son archivos .evtx que viven en C:\Windows\System32\winevt\Logs\. Se pueden copiar y analizar en otro equipo, que es justo lo que se hace en una investigación.
Cómo se usa
Con el Visor de eventos
Pulsa Win + R, escribe eventvwr.msc y entra en Registros de Windows → Seguridad. Para no ahogarte en miles de líneas, usa Filtrar registro actual en el panel derecho y escribe los ID que buscas, por ejemplo 4625. En la pestaña Detalles de cada evento, la vista XML muestra todos los campos con su nombre.
Para el registro de seguridad necesitas abrirlo como administrador.
Qué revela
No hace falta memorizar cientos de ID. Con este puñado se reconstruye buena parte de lo que pasa en un equipo:
| ID | Registro | Qué significa |
|---|---|---|
4624 | Security | Inicio de sesión correcto. |
4625 | Security | Inicio de sesión fallido. |
4634 / 4647 | Security | Cierre de sesión (el 4647 es el que inicia el propio usuario). |
4648 | Security | Inicio de sesión con credenciales explícitas, por ejemplo con runas. |
4672 | Security | Sesión con privilegios especiales: alguien entró como administrador. |
4688 | Security | Se creó un proceso. Solo si la auditoría está activada. |
4720 | Security | Se creó una cuenta de usuario. |
4732 | Security | Se añadió un miembro a un grupo local, como Administradores. |
1102 | Security | Se borró el registro de seguridad. |
1100 | Security | El servicio de registro de eventos se detuvo. |
7045 | System | Se instaló un servicio nuevo. Clásico en persistencia y movimiento lateral. |
104 | System | Se borró un registro distinto al de seguridad. |
4104 | PowerShell/Operational | Bloque de código de PowerShell ejecutado. |
21 / 25 | TerminalServices-LocalSessionManager | Inicio (21) o reconexión (25) de una sesión de escritorio remoto, con el usuario y la IP de origen. |
41 | System | El equipo se apagó sin cerrar bien: corte de luz, cuelgue o apagado forzado (Kernel-Power). |
6008 | System | El apagado anterior fue inesperado. Confirma lo que sugiere el 41. |
El tipo de inicio de sesión
Un 4624 solo dice que alguien entró. El campo LogonType dice cómo, y ahí está la mitad de la historia:
| Tipo | Significado |
|---|---|
2 | Interactivo: alguien delante del teclado. |
3 | Red: acceso a una carpeta compartida o a un recurso remoto. |
4 / 5 | Tarea programada / servicio. |
7 | Desbloqueo de la sesión. |
10 | Escritorio remoto (RDP). |
11 | Credenciales en caché, sin contactar con el controlador de dominio. |
Por qué falló
En un 4625, el campo SubStatus distingue entre alguien que se equivoca y alguien que está probando:
| Código | Motivo | Lectura |
|---|---|---|
0xC000006A | Contraseña incorrecta | El usuario existe. Si se repite mucho, fuerza bruta sobre una cuenta. |
0xC0000064 | El usuario no existe | Alguien está adivinando nombres de cuenta. |
0xC0000234 | Cuenta bloqueada | Los intentos ya dispararon la política de bloqueo. |
0xC0000072 | Cuenta deshabilitada | Alguien intenta usar una cuenta dada de baja. |
El detalle que da nombre a la serie
Borrar el registro de seguridad no borra el rastro: genera un 1102 nuevo, con la hora y la cuenta que lo hizo. Y si el registro aparece vacío salvo ese evento, eso ya es una pregunta que responder. Quien intenta ocultar lo que hizo deja otra huella al hacerlo.
Con PowerShell
Toda esta lectura del diario se puede automatizar. Los comandos son largos, así que van plegados: ábrelos cuando los necesites.
Ver comandos de PowerShell
Consultas útiles
Abre PowerShell como administrador y carga primero esta pequeña función, que convierte los datos de cada evento en campos con nombre. Así no dependes de posiciones numéricas que cambian entre versiones de Windows:
# Convierte el bloque EventData de un evento en campos con nombre
function Get-EventData {
param([Parameter(ValueFromPipeline)]$Evento)
process {
$xml = [xml]$Evento.ToXml()
$datos = [ordered]@{ Hora = $Evento.TimeCreated; Id = $Evento.Id }
foreach ($d in $xml.Event.EventData.Data) { $datos[$d.Name] = $d.'#text' }
[pscustomobject]$datos
}
}
Inicios de sesión fallidos de las últimas 24 horas:
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=(Get-Date).AddDays(-1)} -ErrorAction SilentlyContinue |
Get-EventData |
Select-Object Hora, TargetUserName, LogonType, IpAddress, SubStatus |
Format-Table -AutoSize
¿Desde dónde vienen? Agrupa por origen y por usuario intentado:
$fallos = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -ErrorAction SilentlyContinue | Get-EventData
$fallos | Group-Object IpAddress | Sort-Object Count -Descending | Select-Object Count, Name
$fallos | Group-Object TargetUserName | Sort-Object Count -Descending | Select-Object Count, Name
Inicios de sesión correctos por escritorio remoto (tipo 10):
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624} -ErrorAction SilentlyContinue |
Get-EventData |
Where-Object LogonType -eq '10' |
Select-Object Hora, TargetUserName, IpAddress |
Format-Table -AutoSize
El registro de Seguridad da el 4624, pero el escritorio remoto tiene además su propio canal, con el usuario y la IP de origen en cada sesión:
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-TerminalServices-LocalSessionManager/Operational'; Id=21,25} -ErrorAction SilentlyContinue |
Get-EventData |
Select-Object Hora, Id, User, 'Address' |
Format-Table -AutoSize
Apagados inesperados: cortes de luz, cuelgues o apagados forzados. El 41 y el 6008 se apoyan entre sí.
Get-WinEvent -FilterHashtable @{LogName='System'; Id=41,6008} -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, Message | Format-List
¿Alguien ha borrado registros?
# 1102: se borró el registro de seguridad
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=1102} -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, Message | Format-List
# 104: se borró otro registro (System, Application...)
Get-WinEvent -FilterHashtable @{LogName='System'; Id=104} -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, Message | Format-List
Sacar una copia para analizarla fuera
En una investigación no se trabaja sobre el equipo vivo. Exporta los registros y analiza la copia:
New-Item -ItemType Directory -Path C:\evidencia -Force | Out-Null
wevtutil epl Security C:\evidencia\Security.evtx
wevtutil epl System C:\evidencia\System.evtx
wevtutil epl "Microsoft-Windows-PowerShell/Operational" C:\evidencia\PowerShell-Operational.evtx
wevtutil epl "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" C:\evidencia\RDP-LocalSessionManager.evtx
# Leer una copia exportada
Get-WinEvent -Path C:\evidencia\Security.evtx -FilterXPath "*[System[EventID=4625]]" | Get-EventData
Activar lo que Windows no registra de fábrica
Un Windows recién instalado apunta los inicios de sesión, pero no registra qué programas se ejecutan ni el código de PowerShell completo, y su registro de seguridad es pequeño. Si quieres que el diario sirva cuando haga falta, hay que prepararlo antes:
# Ver la política de auditoría actual
auditpol /get /category:*
# Auditar la creación de procesos (evento 4688).
# Se usa el GUID porque el nombre de la subcategoría cambia con el idioma de Windows.
auditpol /set /subcategory:"{0CCE922B-69AE-11D9-BED3-505054503030}" /success:enable
# Incluir la línea de comandos completa en el 4688
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" /v ProcessCreationIncludeCmdLine_Enabled /t REG_DWORD /d 1 /f
# Registrar los bloques de código de PowerShell (evento 4104)
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v EnableScriptBlockLogging /t REG_DWORD /d 1 /f
# Ver el tamaño del registro de seguridad y subirlo a 1 GB
Get-WinEvent -ListLog Security | Select-Object LogName, MaximumSizeInBytes, RecordCount
wevtutil sl Security /ms:1073741824
En una empresa con dominio, esto se configura por GPO y no equipo a equipo. Lo de arriba sirve para tu equipo o tu laboratorio.
Practica
La mejor forma de aprender a leer el diario es escribir en él y luego buscarte. Haz estos ejercicios en una máquina virtual, nunca en un equipo de trabajo.
Ver los 4 ejercicios
Provoca inicios de sesión fallidos y encuéntralos.
# Tres intentos contra una cuenta que no existe
1..3 | ForEach-Object { net use \\localhost\IPC$ /user:usuario_falso ClaveFalsa123 2>$null }
# Búscalos
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -MaxEvents 5 |
Get-EventData | Select-Object Hora, TargetUserName, LogonType, SubStatus
¿Qué tipo de inicio de sesión aparece y por qué? ¿Qué SubStatus ves? Repite con tu usuario real y una contraseña equivocada y compara.
Simula la persistencia más básica: una cuenta nueva con privilegios.
net user soporte_it P4ssw0rd!Lab /add
net localgroup Administrators soporte_it /add # en Windows en español: Administradores
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4720,4732} -MaxEvents 5 |
Get-EventData | Format-List
# Limpieza
net user soporte_it /delete
¿Qué cuenta aparece como autora del cambio? Al borrarla, ¿qué evento nuevo se genera?
Haz lo que haría un intruso y comprueba qué queda.
# SOLO EN LA MÁQUINA VIRTUAL
wevtutil cl Security
Get-WinEvent -LogName Security -MaxEvents 5 | Select-Object TimeCreated, Id, Message | Format-List
¿Cuántos eventos quedan? ¿Qué te dice el 1102 sobre quién lo hizo?
Descarga registros .evtx de ataques documentados y analízalos como si llegaran de un cliente. El repositorio EVTX-ATTACK-SAMPLES los tiene clasificados por técnica.
# Con Hayabusa: línea de tiempo con las detecciones de sus reglas
hayabusa.exe csv-timeline -d .\EVTX-ATTACK-SAMPLES -o timeline.csv
# Con EvtxECmd: todos los eventos normalizados a CSV
EvtxECmd.exe -d .\EVTX-ATTACK-SAMPLES --csv .\salida
Elige una carpeta, por ejemplo la de movimiento lateral, e intenta contar qué pasó solo con los eventos antes de leer su nombre.