Skip to content

Detectando tampering de RecentFileCache

Cómo los atacantes suprimen, envenenan o limpian RecentFileCache.bcf — y las señales en event log, tareas programadas y sistema de archivos que los pillan en el acto.

Publicado el 5 min de lectura

Si RecentFileCache.bcf es útil para triaje, también vale la pena suprimirlo para un atacante que quiere mantenerse silencioso. Este post recorre las cuatro formas realistas de tamper el artefacto y las señales que cada una deja.

Las cuatro estrategias de supresión

  1. Deshabilitar el servicio Application Experience. sc stop AeLookupSvc + sc config AeLookupSvc start= disabled. Nuevas ejecuciones dejan de registrarse.
  2. Deshabilitar la tarea programada ProgramDataUpdater. Detiene la reescritura periódica. Las entradas existentes permanecen; las nuevas pueden seguir acumulándose en memoria pero no se flushearán.
  3. Borrar el archivo. del C:\Windows\AppCompat\Programs\RecentFileCache.bcf (requiere elevación). Hasta el próximo ciclo de ProgramDataUpdater, el artefacto simplemente desaparece.
  4. Ejecución en memoria. No suprimas el artefacto en absoluto — solo asegúrate de que el loader nunca te vea. Inyección reflectiva de DLL, process hollowing, PowerShell sin archivo, abuso de LOLBins firmados.

Cada uno deja una huella diferente.

Señal: eventos de control de servicio

Detener o deshabilitar AeLookupSvc emite eventos de Service Control Manager en el log System:

Event IDFuenteQué indica
7036Service Control ManagerCambio de estado del servicio (e.g. "stopped")
7040Service Control ManagerTipo de inicio cambiado (e.g. auto → disabled)
7045Service Control ManagerNuevo servicio instalado (raro para AppCompat)

Caza AeLookupSvc en el XML de payload del evento. En una máquina sana el servicio arranca al boot y se mantiene corriendo; un evento 7036-stopped en horario laboral, sin reinicio correspondiente, es ruidoso.

Get-WinEvent -LogName System -FilterXPath "*[System[(EventID=7036 or EventID=7040)]]" |
  Where-Object { $_.Message -like "*AeLookup*" } |
  Select-Object TimeCreated, Id, Message

Señal: historial de tareas programadas

Deshabilitar \Microsoft\Windows\Application Experience\ProgramDataUpdater escribe en el log Microsoft-Windows-TaskScheduler/Operational:

Event IDSignificado
141Tarea borrada
142Tarea deshabilitada
200Acción iniciada
201Acción completada

Busca 141/142 referenciando la ruta de la tarea ProgramDataUpdater, o un hueco largo entre eventos 200/201 en una máquina encendida.

Señal: estado del sistema de archivos

El archivo mismo delata el tampering cuando se lee con atención:

  • LastWriteTime del archivo muy en el pasado en una máquina de uso diario. Sistemas sanos ven una escritura aproximadamente cada 24 horas. Un .bcf modificado por última vez hace seis semanas en una workstation usada a diario es una bandera.
  • Archivo enteramente ausente en un endpoint Win7 donde los logs muestran que ProgramDataUpdater corrió antes. El $LogFile y el $UsnJrnl registrarán el borrado; busca eventos J: USN_REASON_FILE_DELETE.
  • LastWriteTime del archivo que coincide exactamente con un evento atacante-tiempo (correlación con la ventana del incidente) — posible flush deliberado.
  • Cero o casi cero entradas en una máquina con meses de actividad de usuario normal. O el archivo se limpió recientemente, o AeLookupSvc ha estado apagado desde el último reset.

Señal: journal USN y $LogFile

Si RecentFileCache.bcf fue borrado o renombrado, el journal USN de NTFS lo registra. Parsea con usn-parser:

TIMESTAMP                 REASON                              FILE
2026-05-23T14:09:11Z      FILE_DELETE | CLOSE                 RecentFileCache.bcf
2026-05-23T14:09:12Z      FILE_CREATE | CLOSE                 RecentFileCache.bcf

Una pareja apretada delete + create sobre el mismo archivo es el clásico "clear by replacement".

$LogFile (parseado con LogFileParser o el modo $LogFile de mft-parser) captura operaciones MFT de grano más fino y sobrevive a ventanas más cortas que el journal USN en algunos casos.

Señal: contradicciones entre artefactos

La señal más rica es el desacuerdo entre artefactos:

  • Prefetch muestra ejecución; .bcf no muestra ninguna ruta correspondiente. O el binario evitó el loader (en memoria), o .bcf fue tampered. Verifica el LastWriteTime del archivo vs el último run del prefetch.
  • Amcache tiene entradas para ejecutables que no están en .bcf. Normal si ProgramDataUpdater ya los promovió. Sospechoso si los timestamps sugieren que la promoción aún no debería haber ocurrido.
  • .bcf existe pero contiene exactamente la cabecera de 20 bytes sin registros. Un estado limpio que solo puede ocurrir naturalmente justo después de que ProgramDataUpdater reescribió y nada ha vuelto a ejecutarse — verifica contra el mtime del archivo y el log System.

Cómo se ve la ejecución en memoria (cuando no hay nada que ver)

El punto del tradecraft en memoria es que ningún archivo toca el disco de manera que el hook AppCompat del loader pueda atrapar. RecentFileCache se verá totalmente normal. No leas su silencio como exoneración. Combina con:

  • Telemetría EDR sobre CreateRemoteThread, WriteProcessMemory, regiones ejecutables sin backing.
  • Logging de script blocks de PowerShell 4104 (si está habilitado).
  • Sysmon 1 (process create) con los campos command-line, parent e image-loaded.
  • Adquisición de memoria + malfind, dlllist, ldrmodules de Volatility.

Una pequeña query de caza

Regla de detección a cadencia diaria, expresada en pseudo-XQL:

service = "AeLookupSvc" AND
event_id IN (7036, 7040) AND
NOT (event_id = 7036 AND state = "running")
| stats count by host, event_id, _time
| where count > 0

Combinada con una comprobación programada de que RecentFileCache.bcf existe y ha sido modificado en las últimas 48 horas en cada endpoint Win7, atraparás la mitad ruidosa de los intentos de supresión. La mitad silenciosa — ejecución en memoria — necesita la otra mitad de tu stack.

Fin de la serie

Eso cierra el primer. Ahora tienes el formato, el ciclo de vida, el contexto de comparación, el workflow de adquisición, las heurísticas de triaje, la cadena de validación y las señales de tampering. El parser de este sitio es el front-end de todo eso; el resto vive en tu toolchain DFIR habitual.

Artículos relacionados

El ciclo de vida del BCF depende de una única tarea programada. Entiende cuándo se ejecuta ProgramDataUpdater, cuándo vacía el archivo y cómo detectar un appraiser deshabilitado.
El formato BCF es una cabecera, una lista de rutas UTF-16LE con prefijo de longitud, y se acabó. Aquí está lo que significa cada byte y por qué nada ha cambiado desde 2009.
Un endpoint Win7 marcado por el SOC, 14 rutas en el BCF, tres dignas de una segunda mirada. Una cadena de corroboración realista y cuánto contribuyó realmente el BCF.