Lo que sigue es un caso ficticio. El nombre de host, los hashes y el operador son inventados. La forma de la intrusión no. He construido líneas de tiempo muy parecidas a esta a partir de directorios Prefetch en encargos reales, y los patrones se repiten.
El sentido del recorrido es mostrar cómo se lee Prefetch cuando tienes una intrusión real entre manos y las ocho marcas temporales de ejecución son lo más fiable que tienes. Empareja cada paso con los artefactos que lo corroboran o lo amplían.
El planteamiento
Una pequeña firma de servicios profesionales. Sesenta estaciones y cuatro servidores. Viernes por la tarde, los recursos compartidos en FS01 se vuelven inaccesibles. Aparece una nota de rescate en \\FS01\Shared\!!READ-ME!!.txt. Para el lunes por la mañana, el responsable de TI ha adquirido datos de triage de FS01, el jump host JH01 y tres estaciones, entre ellas el paciente cero, WS-ACCT-04.
Recibo los directorios Prefetch de los cinco hosts el martes. Los canales EVTX de Security y Sysmon están incompletos. Algunos fueron borrados, otros nunca tuvieron Sysmon. Prefetch está mayoritariamente intacto. Es lo típico.
Lo que tiene que decir WS-ACCT-04
Empieza donde empezó el atacante.
Parsear C:\Windows\Prefetch\ en WS-ACCT-04 con PECmd arroja 412 archivos .pf. La mayoría son ruido: binarios de Office, navegadores, componentes antivirus, utilidades de Windows. Los interesantes afloran cuando filtro por rutas de ejecutable fuera de \Windows\ y \Program Files\, ordeno por NTFS Created descendente y miro las primeras treinta filas.
Los principales hits, en orden de hora de creación (redondeado para el recorrido):
| Created | Filename | Exec path | Runs |
|---|---|---|---|
| Wed 14:02 | WINWORD.EXE-00B41B71.pf | C:\Program Files\Microsoft Office\Office16\WINWORD.EXE | 47 |
| Wed 14:03 | EQNEDT32.EXE-1F2E0AB2.pf | C:\Program Files\Common Files\Microsoft Shared\Equation\EQNEDT32.EXE | 1 |
| Wed 14:03 | MSHTA.EXE-2A1D9904.pf | C:\Windows\System32\mshta.exe | 1 |
| Wed 14:04 | POWERSHELL.EXE-3DD11E22.pf | C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe | 8 |
| Wed 14:05 | WMIPRVSE.EXE-XXXXXXXX.pf | C:\Windows\System32\wbem\WmiPrvSE.exe | (muchas) |
| Wed 14:06 | CMD.EXE-XXXXXXXX.pf | C:\Windows\System32\cmd.exe | (muchas) |
| Wed 14:11 | RUNDLL32.EXE-XXXXXXXX.pf | C:\Windows\System32\rundll32.exe | (muchas) |
| Wed 14:12 | UPDATE.EXE-77AAFF12.pf | C:\Users\Public\update.exe | 1 |
| Wed 14:14 | NLTEST.EXE-XXXXXXXX.pf | C:\Windows\System32\nltest.exe | 1 |
| Wed 14:14 | WHOAMI.EXE-XXXXXXXX.pf | C:\Windows\System32\whoami.exe | 1 |
| Wed 14:15 | PSEXEC.EXE-A1A1A1A1.pf | C:\Users\Public\psexec.exe | 3 |
| Wed 14:23 | 7Z.EXE-B2B2B2B2.pf | C:\Users\Public\7z.exe | 1 |
Esa es una cadena de intrusión completa en unos veinte minutos, reconstruida desde el directorio Prefetch de un solo host.
Leída en lenguaje sencillo:
- 14:02: Word abre. (Ejecución 47 de 47, uso normal de Word en este host.)
- 14:03:
EQNEDT32.EXEcorre por primera vez en este host. Equation Editor. Vector de exploit de 2017 para DOCX maliciosos. El.pfdeWINWORD.EXEse actualizó a las 14:02, justo antes. Empareja con archivos LNK y artefactos del cliente de correo. El usuario abrió un documento malicioso. - 14:03:
MSHTA.EXEcorre por primera vez. La lista de carga (más abajo) muestra un script en un directorio temp. El exploit de Equation Editor dejó un payload HTA. - 14:04: PowerShell arranca. La primera de ocho ejecuciones.
- 14:05: Actividad de
WmiPrvSE.exe. Posiblemente llamadas WMI remotas; comprueba la lista de carga y el EVTX correspondiente. - 14:11:
rundll32.execorre. A menudo un vector de ejecución de DLL. - 14:12: Un binario llamado
update.execorre desdeC:\Users\Public\. Primera y única ejecución. No es unupdate.exelegítimo; la ruta es incorrecta. Los bytes de hash77AAFF12no colisionarán con nada benigno. - 14:14:
nltest.exeywhoami.execorren, ambos por primera vez. Reconocimiento de dominio. - 14:15:
psexec.execorre desdeC:\Users\Public\. Tres ejecuciones, lo que sugiere tres objetivos de movimiento lateral. - 14:23:
7z.execorre desdeC:\Users\Public\. Archivado para staging o exfiltración.
Ese orden vino directamente de las marcas Created de Prefetch más el campo Last run de cada .pf. No es una conjetura.
Lo que confirman las listas de carga
Las entradas Prefetch me dicen qué se ejecutó. Las listas de carga me dicen qué hizo cada binario.
Lista de carga de MSHTA.EXE-2A1D9904.pf, filtrada a rutas no-sistema:
\DEVICE\HARDDISKVOLUME2\USERS\ALICE\APPDATA\LOCAL\TEMP\BACK.HTA
\DEVICE\HARDDISKVOLUME2\USERS\ALICE\APPDATA\LOCAL\TEMP\STG1.PS1
Eso sitúa el payload HTA (entregado por el exploit de Equation Editor) en C:\Users\Alice\AppData\Local\Temp\back.hta, y un script PowerShell de seguimiento en stg1.ps1 en el mismo directorio.
Lista de carga de POWERSHELL.EXE-3DD11E22.pf, filtrada:
\DEVICE\HARDDISKVOLUME2\USERS\ALICE\APPDATA\LOCAL\TEMP\STG1.PS1
\DEVICE\HARDDISKVOLUME2\USERS\ALICE\APPDATA\LOCAL\TEMP\STG2.DLL
\DEVICE\HARDDISKVOLUME2\USERS\PUBLIC\UPDATE.EXE
\DEVICE\HARDDISKVOLUME2\USERS\PUBLIC\PSEXEC.EXE
\DEVICE\HARDDISKVOLUME2\USERS\PUBLIC\7Z.EXE
PowerShell cargó el script de stage 1, cargó una DLL de stage 2, y luego o stageó o invocó las herramientas de movimiento lateral bajo \Users\Public\. Prefetch no me dice qué hizo PowerShell con esos archivos (leer, ejecutar, copiar) pero la presencia de esas rutas en la lista de carga dice que PowerShell los tocó.
Lista de carga de UPDATE.EXE-77AAFF12.pf:
\DEVICE\HARDDISKVOLUME2\USERS\PUBLIC\UPDATE.EXE
\DEVICE\HARDDISKVOLUME2\PROGRAMDATA\STG\KEY.BIN
\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\BCRYPT.DLL
\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\BCRYPTPRIMITIVES.DLL
\DEVICE\HARDDISKVOLUME2\USERS\ALICE\DOCUMENTS\<muchas rutas .docx, .xlsx, .pdf>
update.exe es el cifrador. Cargó un archivo de clave de \ProgramData\stg\key.bin. Cargó las primitivas criptográficas de Windows. Y abrió cada documento en el directorio Documents de Alice.
El tope de la lista de carga ronda las 1000 entradas. En un host con muchos documentos llegarás al tope. El conjunto de rutas que ves es una enumeración parcial de lo que se tocó.
Lista de carga de PSEXEC.EXE-A1A1A1A1.pf:
\DEVICE\HARDDISKVOLUME2\USERS\PUBLIC\PSEXEC.EXE
\DEVICE\HARDDISKVOLUME2\USERS\PUBLIC\UPDATE.EXE
\DEVICE\HARDDISKVOLUME2\USERS\PUBLIC\PSEXEC.SYS
PsExec se cargó a sí mismo, al cifrador (sugiriendo que se usó psexec para empujar update.exe a otros hosts) y su propio driver de kernel. El contador de ejecuciones de tres combinado con la lista de carga sugiere fuertemente tres empujes laterales del cifrador.
Las ocho marcas temporales me dan el ritmo
Para PSEXEC.EXE-A1A1A1A1.pf, el array de ocho marcas temporales contiene tres tiempos válidos:
14:15:22
14:16:48
14:19:01
Eso me da el ritmo del ataque: aproximadamente 90 segundos entre empujes laterales. En FS01, el servidor de archivos, espero encontrar un UPDATE.EXE-XXXXXXXX.pf cuyo primer tiempo de ejecución sea aproximadamente las 14:15:30 más unos segundos, ya que el push de psexec al arranque del cifrador es rápido.
En el directorio Prefetch de FS01, encuentro UPDATE.EXE-77AAFF12.pf (mismos bytes de hash, misma ruta C:\Users\Public\update.exe también en FS01) con primer tiempo de ejecución a las 14:15:34. Eso confirma el movimiento lateral.
El mismo update.exe aparece en otros dos hosts, con primeros tiempos de ejecución a las 14:16:55 y 14:19:08. Cada uno está a segundos del push de psexec correspondiente.
Ahora tengo, solo a partir de Prefetch, la cronología completa de movimiento lateral del cifrador a lo largo de cuatro hosts.
Lo que Prefetch no me dio
Prefetch no me dio la línea de comandos de ninguna de estas ejecuciones. Para eso necesito Sysmon EID 1, que existía en dos de los cinco hosts. De ahí recupero los argumentos a PowerShell, el proceso padre de update.exe y el contexto de usuario.
Prefetch no me dio el destino de red del canal C2. Los archivos back.hta y stg1.ps1 probablemente contienen esa información, pero no están en Prefetch, solo sus rutas. Si los archivos sobreviven en disco, los parseo. Si fueron limpiados, miro a RAM (si adquirí imagen de memoria), el pagefile, o historial del navegador buscando rastros del dominio C2.
Prefetch no me dio el contenido cifrado real ni las perspectivas de recuperación. Para eso necesito la MFT y el USN journal para entender qué archivos se tocaron, en qué orden y si sobrevivieron VSCs. La lista de carga del cifrador me dijo qué directorios fueron el objetivo; la MFT y el USN me dijeron qué pasó con los archivos en esos directorios.
Por qué Prefetch fue la columna vertebral de esta investigación
EVTX estaba incompleto. El atacante había limpiado el log de Security en FS01 (el evento 1102 de log auditado limpiado estaba presente, pero las entradas 4688 relevantes habían desaparecido). Sysmon no estaba desplegado en todas partes. AmCache tenía hashes de algunos de los binarios pero no de todos (algunos fueron renombrados antes de ejecutarse, y AmCache asocia por metadatos del binario de modos que a veces fallan).
Prefetch atravesó todo eso. Es por máquina, escribe continuamente y estaba completo en cuatro de los cinco hosts (un host se había reiniciado tantas veces que los .pf antiguos habían caducado, pero los recientes estaban ahí). El array de ocho marcas temporales en los .pf del cifrador, cruzado entre hosts, fue el único artefacto que me permitió construir la cronología de movimiento lateral con confianza por debajo del minuto.
Para el informe cité las marcas temporales directamente. La firma de IR defensora con la que trabajamos había citado una cronología solo basada en EVTX que se perdía dos de los cuatro hosts afectados (aquellos donde el cifrador corrió pero se había limpiado el log de Security y no había Sysmon). Su cronología era incompleta de formas que Prefetch corrigió.
El patrón en un párrafo
Una intrusión real produce una firma Prefetch característica: un cluster de primeras ejecuciones de utilidades de sistema (Equation Editor, MSHTA, rundll32, nltest, whoami) en una ventana de tiempo apretada, seguido por primeras ejecuciones de binarios del atacante desde rutas escribibles por el usuario (\Users\Public\, \AppData\Local\Temp\, \ProgramData\), seguido por un pequeño número de ejecuciones de herramientas de movimiento lateral (PsExec, WMIC, ocasionalmente herramientas legítimas como clientes RDP), seguido por el cifrador. La secuencia suele caber en veinte a noventa minutos. El array de ocho marcas temporales de Prefetch por host clava cada paso al segundo.
Cuando parseas el directorio Prefetch de un host comprometido y no ves esa firma, o miras un host que no fue realmente comprometido, o el atacante fue lo bastante sofisticado para limpiar Prefetch, en cuyo caso el residuo del borrado en la MFT y el USN journal es el siguiente sitio donde mirar.
Si quieres probar el workflow contra tu propio directorio Prefetch en el navegador, el parser de este sitio carga archivos .pf localmente y te da la tabla ordenable de la que depende el workflow anterior.
Lecturas adicionales
- Eric Zimmerman, PECmd: parsea un directorio entero a CSV y el workflow anterior sale solo.
- The DFIR Report, informes anuales de casos: muchos incluyen evidencia Prefetch presentada en una forma parecida.
- Microsoft, Mitigating Ransomware: contexto desde la defensa de por qué esto importa.