Prefetch
Windows guarda un pequeño archivo por cada programa que se ejecuta, pensado para que arranque más rápido la próxima vez. Ese archivo apunta cuántas veces se ha abierto, las ocho últimas y desde dónde. Borrar el programa no borra su Prefetch: el rastro vive aparte del binario.
El caso
Un equipo con comportamiento raro: la red va lenta a ratos, aparecen conexiones hacia una IP que nadie reconoce. Al mirar Program Files y los procesos actuales, no hay nada sospechoso. El binario que estaba haciendo esas peticiones ya no está. El usuario jura que no ha instalado nada. Pero en C:\Windows\Prefetch hay un archivo SVCH0ST.EXE-A1B2C3D4.pf: alguien ejecutó algo que se hacía pasar por un servicio del sistema, siete veces, la última hace dos horas. El binario ya no existe. El Prefetch sí.
La herramienta
Prefetch es un mecanismo del propio Windows para acelerar el arranque de los programas. La primera vez que se ejecuta un ejecutable, el sistema analiza qué DLL y qué archivos necesita durante los primeros diez segundos, y lo apunta en un archivo .pf para precargarlo la siguiente vez.
Para el forense ese archivo es oro: cada .pf es la prueba de que un ejecutable se lanzó al menos una vez en ese equipo, con metadatos muy útiles.
| Dónde | Qué guarda |
|---|---|
C:\Windows\Prefetch\*.pf | Un archivo por ejecutable. Nombre: EJECUTABLE.EXE-<hash>.pf. |
Dentro del .pf | Nombre del binario, nº de ejecuciones, las 8 últimas fechas, lista de archivos tocados en los primeros 10 s, volumen desde el que se ejecutó. |
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters | Clave EnablePrefetcher: 0 desactivado, 3 activado (valor por defecto en Windows cliente). |
El hash del nombre no es un capricho: dos ejecutables con el mismo nombre pero en rutas distintas generan .pf distintos. Dos svchost.exe-XXXXXXXX.pf en el mismo equipo son dos binarios diferentes.
Cómo se usa
El Prefetch está activo por defecto en Windows cliente (10, 11) y desactivado en Windows Server. Para leerlo basta con listar la carpeta, pero el contenido del .pf está comprimido y hay que parsearlo con una herramienta dedicada. En la sección final están los comandos.
Qué revela
Un .pf contesta a varias preguntas de un vistazo:
| Pregunta | Dónde está la respuesta |
|---|---|
| ¿Se ha ejecutado este programa en este equipo? | Existe el .pf. Punto. |
| ¿Cuántas veces? | Campo Run count. |
| ¿Cuándo las últimas 8 veces? | Lista de Last run times. |
| ¿Desde dónde se ejecutó? | Ruta completa del binario y volumen de origen (útil para pendrives). |
| ¿Qué archivos usó al arrancar? | Lista de Files referenced: DLL, configuración, datos. |
| ¿Es un binario legítimo o un impostor? | Dos .pf con el mismo nombre y hashes distintos: hay dos binarios con el mismo nombre. |
El detalle que da nombre al capítulo
El Prefetch no está pensado para forense: es un cache de rendimiento. Pero por diseño sobrevive al borrado del binario, al reinicio del equipo, y guarda hasta ocho ejecuciones hacia atrás. Un atacante que ejecuta su herramienta, roba lo que iba a robar y la borra, deja el .pf intacto, con la hora exacta, el número de veces y los archivos que tocó. Para eliminarlo también hay que acordarse de la carpeta Prefetch y hacerlo con permisos, lo que a su vez deja otro rastro (eventos 4663 si hay auditoría de objeto, o huecos sospechosos en la carpeta).
Con PowerShell
Para listar la carpeta y las ejecuciones recientes basta PowerShell. Para abrir el contenido de un .pf hace falta PECmd (de Eric Zimmerman): abajo está todo plegado.
Ver comandos de PowerShell y PECmd
¿Está activo el Prefetch en este equipo?
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters' |
Select-Object EnablePrefetcher
# 0 = off, 1 = solo apps, 2 = solo arranque, 3 = ambos (por defecto en cliente)
Qué hay en la carpeta Prefetch
Como administrador. Ordenado por fecha de última ejecución del binario (la del propio .pf coincide):
Get-ChildItem 'C:\Windows\Prefetch\*.pf' |
Sort-Object LastWriteTime -Descending |
Select-Object -First 30 LastWriteTime, Name, Length |
Format-Table -AutoSize
Buscar un binario concreto (y sus posibles impostores)
# Todos los .pf con un nombre dado
Get-ChildItem 'C:\Windows\Prefetch\' -Filter 'POWERSHELL.EXE-*.pf'
# Dos .pf con el mismo nombre y hashes distintos = dos binarios distintos
Get-ChildItem 'C:\Windows\Prefetch\*.pf' |
Group-Object { ($_.Name -split '-')[0] } |
Where-Object Count -gt 1 |
Format-Table Count, Name
Leer el contenido de un .pf con PECmd
El .pf va comprimido; PECmd (Prefetch Explorer Command Line, de Eric Zimmerman) lo parsea y exporta a CSV con todos los campos: nº de ejecuciones, 8 últimas fechas, volumen de origen, lista de archivos tocados.
# Un archivo concreto, a pantalla
PECmd.exe -f C:\Windows\Prefetch\POWERSHELL.EXE-022A1F67.pf
# Toda la carpeta a CSV
PECmd.exe -d C:\Windows\Prefetch --csv C:\salida
Sobre una copia (investigación)
En un caso real se trabaja sobre una copia, no sobre el equipo vivo. Copia la carpeta entera y procésala en frío:
robocopy C:\Windows\Prefetch D:\evidencia\Prefetch /E /COPY:DT /DCOPY:T
PECmd.exe -d D:\evidencia\Prefetch --csv D:\salida --csvf prefetch.csv
Línea de tiempo rápida de ejecuciones
# Fechas del propio archivo .pf (coinciden con la última ejecución del binario)
Get-ChildItem 'C:\Windows\Prefetch\*.pf' |
Select-Object LastWriteTime, @{N='Binario';E={($_.Name -split '-')[0]}} |
Sort-Object LastWriteTime -Descending |
Format-Table -AutoSize
Practica
Hazlo en una máquina virtual con Windows 10 u 11; en Windows Server el Prefetch está desactivado por defecto y no verás nada.
Ver los 4 ejercicios
Antes de ejecutar nada, cuenta cuántos .pf hay. Lanza un programa que nunca hayas abierto en esa VM (Notepad desde una ruta rara, Calculadora, el certutil.exe). Vuelve a contar.
(Get-ChildItem 'C:\Windows\Prefetch\*.pf').Count
# ... ejecuta algo ...
(Get-ChildItem 'C:\Windows\Prefetch\*.pf').Count
¿Cuánto tarda Windows en escribir el .pf? ¿Aparece justo tras cerrar el programa o antes?
Copia C:\Windows\System32\calc.exe a C:\temp\miapp.exe, ejecútalo tres o cuatro veces, y bórralo.
Copy-Item C:\Windows\System32\calc.exe C:\temp\miapp.exe
1..4 | ForEach-Object { Start-Process C:\temp\miapp.exe; Start-Sleep 2 }
Remove-Item C:\temp\miapp.exe
Get-ChildItem 'C:\Windows\Prefetch\MIAPP.EXE-*.pf'
PECmd.exe -f (Get-ChildItem 'C:\Windows\Prefetch\MIAPP.EXE-*.pf').FullName
¿Cuántas ejecuciones aparecen? ¿Qué ruta del binario queda apuntada en el .pf?
Copia calc.exe a dos rutas distintas con el mismo nombre y ejecútalos.
Copy-Item C:\Windows\System32\calc.exe C:\temp\a\svchost.exe
Copy-Item C:\Windows\System32\calc.exe C:\temp\b\svchost.exe
Start-Process C:\temp\a\svchost.exe
Start-Process C:\temp\b\svchost.exe
Get-ChildItem 'C:\Windows\Prefetch\SVCHOST.EXE-*.pf' | Select-Object Name, LastWriteTime
¿Cuántos .pf con el mismo nombre tienes? Compara con los SVCHOST.EXE-*.pf normales del sistema. ¿Cuál es sospechoso y por qué?
Lanza PECmd sobre un .pf y mira la lista de archivos a los que accedió el binario en los primeros diez segundos.
PECmd.exe -f C:\Windows\Prefetch\POWERSHELL.EXE-*.pf --json C:\salida
¿Aparecen DLL que no esperarías? ¿Hay rutas en \Users\...\AppData\Local\Temp o similares que delaten de dónde se lanzó?