RecentFileCache-Manipulation erkennen
Wie Angreifer RecentFileCache.bcf unterdrücken, vergiften oder wipen — und die Event-Log-, Scheduled-Task- und Dateisystem-Signale, die sie dabei erwischen.
Wenn RecentFileCache.bcf für die Triage nützlich ist, ist es für einen Angreifer, der unauffällig bleiben will, auch wert unterdrückt zu werden. Dieser Post geht die vier realistischen Wege durch, das Artefakt zu manipulieren, und die Signale, die jeder davon hinterlässt.
Die vier Unterdrückungsstrategien
- Den Application-Experience-Dienst deaktivieren.
sc stop AeLookupSvc+sc config AeLookupSvc start= disabled. Neue Ausführungen werden nicht mehr aufgezeichnet. - Die geplante Aufgabe ProgramDataUpdater deaktivieren. Stoppt das periodische Neuschreiben. Existierende Einträge bleiben; neue können noch im Speicher anlaufen, werden aber nicht geflusht.
- Die Datei löschen.
del C:\Windows\AppCompat\Programs\RecentFileCache.bcf(Elevation nötig). Bis zum nächstenProgramDataUpdater-Lauf ist das Artefakt einfach weg. - In-Memory-Ausführung. Das Artefakt gar nicht unterdrücken — nur sicherstellen, dass der Loader dich nie sieht. Reflective DLL Injection, Process Hollowing, fileless PowerShell, Missbrauch signierter LOLBins.
Jede hinterlässt einen anderen Fingerabdruck.
Signal: Service-Control-Events
Das Stoppen oder Deaktivieren von AeLookupSvc erzeugt Service-Control-Manager-Events im System-Log:
| Event ID | Source | Was es anzeigt |
|---|---|---|
| 7036 | Service Control Manager | Dienstzustandswechsel (z.B. "stopped") |
| 7040 | Service Control Manager | Starttyp geändert (z.B. auto → disabled) |
| 7045 | Service Control Manager | Neuer Dienst installiert (selten für AppCompat) |
Jage nach AeLookupSvc im Payload-XML des Events. Auf einer gesunden Maschine startet der Dienst beim Boot und bleibt laufen; ein 7036-stopped-Event während der Geschäftszeiten ohne entsprechenden Neustart ist laut.
Get-WinEvent -LogName System -FilterXPath "*[System[(EventID=7036 or EventID=7040)]]" |
Where-Object { $_.Message -like "*AeLookup*" } |
Select-Object TimeCreated, Id, Message
Signal: Scheduled-Task-History
Das Deaktivieren von \Microsoft\Windows\Application Experience\ProgramDataUpdater schreibt ins Microsoft-Windows-TaskScheduler/Operational-Log:
| Event ID | Bedeutung |
|---|---|
| 141 | Aufgabe gelöscht |
| 142 | Aufgabe deaktiviert |
| 200 | Aktion gestartet |
| 201 | Aktion abgeschlossen |
Suche nach 141/142, die den ProgramDataUpdater-Aufgabenpfad referenzieren, oder nach einer langen Lücke zwischen 200/201-Events auf einer eingeschalteten Maschine.
Signal: Dateisystem-Zustand
Die Datei selbst verrät die Manipulation, wenn man sie aufmerksam liest:
LastWriteTimeder Datei weit in der Vergangenheit auf einer täglich genutzten Maschine. Gesunde Systeme sehen etwa alle 24 Stunden einen Schreibvorgang. Eine.bcf, die auf einer täglich benutzten Workstation seit sechs Wochen nicht mehr geschrieben wurde, ist eine Flagge.- Datei komplett fehlend auf einem Win7-Endpoint, dessen Logs zeigen, dass ProgramDataUpdater zuvor lief.
$LogFileund$UsnJrnlwerden die Löschung festhalten; achte aufJ: USN_REASON_FILE_DELETE-Events. LastWriteTimeder Datei passt exakt zu einem Angreifer-Zeit-Event (Korrelation mit Vorfallsfenster) — möglicherweise gezielter Flush.- Null oder fast null Einträge auf einer Maschine, die Monate normaler Nutzeraktivität gesehen hat. Entweder wurde die Datei kürzlich geleert, oder
AeLookupSvcist seit dem letzten Reset aus.
Signal: USN-Journal und $LogFile
Wenn RecentFileCache.bcf gelöscht oder umbenannt wurde, hält das NTFS-USN-Journal es fest. Mit usn-parser parsen:
TIMESTAMP REASON FILE
2026-05-23T14:09:11Z FILE_DELETE | CLOSE RecentFileCache.bcf
2026-05-23T14:09:12Z FILE_CREATE | CLOSE RecentFileCache.bcf
Ein eng beieinander liegendes Delete + Create auf derselben Datei ist der klassische "Clear by Replacement"-Zug.
$LogFile (geparst mit LogFileParser oder dem $LogFile-Modus von mft-parser) erfasst feiner-granuläre MFT-Operationen und überlebt in manchen Fällen kürzere Fenster als das USN-Journal.
Signal: Inter-Artefakt-Widersprüche
Das reichste Signal ist Uneinigkeit zwischen Artefakten:
- Prefetch zeigt Ausführung;
.bcfzeigt keinen entsprechenden Pfad. Entweder hat die Binary den Loader umgangen (in Memory), oder.bcfwurde manipuliert. Vergleiche dieLastWriteTimeder Datei mit der letzten Laufzeit des Prefetch. - Amcache hat Einträge für Executables, die nicht in
.bcfsind. Normal, wennProgramDataUpdatersie bereits befördert hat. Verdächtig, wenn die Zeitstempel suggerieren, dass die Beförderung noch nicht hätte stattfinden dürfen. .bcfexistiert, enthält aber genau den 20-Byte-Header ohne Records. Ein sauberer Zustand, der natürlich nur direkt nach einemProgramDataUpdater-Rewrite eintreten kann, ohne dass etwas neu lief — gegen die Datei-mtime und das System-Log prüfen.
Wie In-Memory-Ausführung aussieht (wenn es nichts zu sehen gibt)
Der Sinn von In-Memory-Tradecraft ist, dass keine Datei je die Platte auf eine Weise berührt, die der AppCompat-Hook des Loaders fangen kann. RecentFileCache wird völlig normal aussehen. Lies sein Schweigen nicht als Freispruch. Kombiniere mit:
- EDR-Telemetrie zu
CreateRemoteThread,WriteProcessMemory, ausführbaren Regionen ohne Backing. - PowerShell-
4104-Script-Block-Logging (falls aktiviert). - Sysmon-
1(Process Create) mit den Feldern Command-Line, Parent und Image-Loaded. - Memory-Akquise +
malfind,dlllist,ldrmodulesvon Volatility.
Eine kurze Hunt-Query
Detektionsregel im Tagesrhythmus, ausgedrückt in 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
Kombiniert mit einer geplanten Prüfung, dass RecentFileCache.bcf existiert und in den letzten 48 Stunden auf jedem Win7-Endpoint modifiziert wurde, fängst du die laute Hälfte der Unterdrückungsversuche. Die leise Hälfte — In-Memory-Ausführung — braucht die andere Hälfte deines Stacks.
Ende der Serie
Damit schließt der Primer. Du hast jetzt das Format, den Lebenszyklus, den Vergleichskontext, den Akquise-Workflow, die Triage-Heuristiken, die Validierungskette und die Manipulationssignale. Der Parser auf dieser Seite ist das Front-End für all das; der Rest lebt in deinem üblichen DFIR-Toolchain.