Skip to content

Détecter le tampering de RecentFileCache

Comment les attaquants suppriment, empoisonnent ou wipent RecentFileCache.bcf — et les signaux d’event log, de tâche planifiée et de système de fichiers qui les attrapent.

Publié le 5 min de lecture

Si RecentFileCache.bcf est utile pour le triage, il vaut aussi le coup d’être supprimé pour un attaquant qui veut rester discret. Ce post parcourt les quatre façons réalistes de tamper l’artefact et les signaux que chacune laisse.

Les quatre stratégies de suppression

  1. Désactiver le service Application Experience. sc stop AeLookupSvc + sc config AeLookupSvc start= disabled. Les nouvelles exécutions cessent d’être enregistrées.
  2. Désactiver la tâche planifiée ProgramDataUpdater. Stoppe la réécriture périodique. Les entrées existantes restent ; les nouvelles peuvent encore s’accumuler en mémoire mais ne seront pas flushées.
  3. Supprimer le fichier. del C:\Windows\AppCompat\Programs\RecentFileCache.bcf (élévation requise). Jusqu’au prochain run de ProgramDataUpdater, l’artefact a simplement disparu.
  4. Exécution en mémoire. Ne pas supprimer l’artefact du tout — juste s’assurer que le loader ne vous voit jamais. Injection réflective de DLL, process hollowing, PowerShell fileless, abus de LOLBins signés.

Chacune laisse une empreinte différente.

Signal : événements de contrôle de service

Arrêter ou désactiver AeLookupSvc émet des événements Service Control Manager dans le log System :

Event IDSourceCe que ça indique
7036Service Control ManagerChangement d’état du service (e.g. « stopped »)
7040Service Control ManagerType de démarrage modifié (e.g. auto → disabled)
7045Service Control ManagerNouveau service installé (rare pour AppCompat)

Chassez AeLookupSvc dans le XML de payload de l’événement. Sur une machine saine, le service démarre au boot et reste en marche ; un événement 7036-stopped pendant les heures de bureau, sans redémarrage correspondant, est bruyant.

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

Signal : historique des tâches planifiées

Désactiver \Microsoft\Windows\Application Experience\ProgramDataUpdater écrit dans le log Microsoft-Windows-TaskScheduler/Operational :

Event IDSignification
141Tâche supprimée
142Tâche désactivée
200Action démarrée
201Action terminée

Cherchez 141/142 référençant le chemin de la tâche ProgramDataUpdater, ou un long écart entre les événements 200/201 sur une machine restée allumée.

Signal : état du système de fichiers

Le fichier lui-même trahit le tampering quand vous le lisez attentivement :

  • LastWriteTime du fichier loin dans le passé sur une machine utilisée quotidiennement. Les systèmes sains voient une écriture environ toutes les 24 heures. Un .bcf modifié pour la dernière fois il y a six semaines sur un poste où l’on s’est loggé tous les jours est un drapeau.
  • Fichier entièrement absent sur un endpoint Win7 dont les logs montrent que ProgramDataUpdater a déjà tourné. Le $LogFile et le $UsnJrnl enregistreront la suppression ; cherchez les événements J: USN_REASON_FILE_DELETE.
  • LastWriteTime du fichier qui correspond exactement à un événement temps-attaquant (corrélation avec la fenêtre d’incident) — flush délibéré possible.
  • Zéro ou quasi-zéro entrée sur une machine qui a tourné des mois d’activité utilisateur normale. Soit le fichier a été récemment vidé, soit AeLookupSvc est éteint depuis le dernier reset.

Signal : journal USN et $LogFile

Si RecentFileCache.bcf a été supprimé ou renommé, le journal USN NTFS l’enregistre. Parser avec 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

Une paire serrée delete + create sur le même fichier est le « clear by replacement » classique.

$LogFile (parsé avec LogFileParser ou le mode $LogFile de mft-parser) capture des opérations MFT à grain plus fin et survit à des fenêtres plus courtes que le journal USN dans certains cas.

Signal : contradictions inter-artefacts

Le signal le plus riche est le désaccord entre artefacts :

  • Prefetch montre une exécution ; .bcf ne montre aucun chemin correspondant. Soit le binaire a contourné le loader (en mémoire), soit .bcf a été tampered. Vérifiez le LastWriteTime du fichier vs le dernier run du prefetch.
  • Amcache contient des entrées pour des exécutables absents de .bcf. Normal si ProgramDataUpdater les a déjà promus. Suspect si les timestamps suggèrent que la promotion n’aurait pas encore dû se produire.
  • .bcf existe mais ne contient exactement que l’en-tête de 20 octets sans aucun record. Un état propre qui ne peut naturellement survenir que juste après une réécriture de ProgramDataUpdater et qu’aucune nouvelle exécution n’a encore eu lieu — vérifiez contre le mtime du fichier et le log System.

À quoi ressemble l’exécution en mémoire (quand il n’y a rien à voir)

L’intérêt du tradecraft en mémoire est qu’aucun fichier ne touche le disque d’une manière que le hook AppCompat du loader puisse attraper. RecentFileCache aura l’air parfaitement normal. Ne lisez pas son silence comme une exonération. Croisez avec :

  • Télémétrie EDR sur CreateRemoteThread, WriteProcessMemory, régions exécutables non backées.
  • Logging de script blocks PowerShell 4104 (s’il est activé).
  • Sysmon 1 (process create) avec les champs command-line, parent et image-loaded.
  • Acquisition mémoire + malfind, dlllist, ldrmodules de Volatility.

Une courte requête de chasse

Règle de détection à cadence quotidienne, exprimée 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

Combinée à une vérification planifiée que RecentFileCache.bcf existe et a été modifié dans les 48 dernières heures sur chaque endpoint Win7, vous attraperez la moitié bruyante des tentatives de suppression. La moitié silencieuse — l’exécution en mémoire — a besoin de l’autre moitié de votre stack.

Fin de la série

Cela clôt le primer. Vous avez maintenant le format, le cycle de vie, le contexte de comparaison, le workflow d’acquisition, les heuristiques de triage, la chaîne de validation et les signaux de tampering. Le parser de ce site est le front-end de tout ça ; le reste vit dans votre toolchain DFIR habituel.

Articles liés

Le cycle de vie du BCF tient en une seule tâche planifiée. Comprenez quand ProgramDataUpdater s'exécute, quand il vide le fichier, et comment repérer un appraiser désactivé.
Le format BCF est un en-tête, une liste de chemins UTF-16LE préfixés de leur longueur, et c'est tout. Voici ce que signifie chaque octet et pourquoi rien n'a changé depuis 2009.
Un endpoint Win7 signalé par le SOC, 14 chemins dans le BCF, trois méritant un second regard. Une chaîne de corroboration réaliste et combien le BCF a réellement contribué.