Das .bcf-Format, Byte für Byte
Eine praxisnahe Lektüre des binären RecentFileCache.bcf-Formats mit einem Hex-Dump, einem decodierten Datensatz und den Sonderfällen, die ein Parser handhaben muss.
Das RecentFileCache.bcf-Format ist klein genug, um es bei einem Kaffee zu lernen. Die maßgebliche Referenz ist libyal/dtformats. Dieser Beitrag geht dieselbe Spec mit einem echten Hex-Dump und den Sonderfällen durch, die Parser tatsächlich stolpern lassen.
Endianness und Encoding
- Alle Integer sind Little-Endian.
- Strings sind UTF-16LE, NUL-terminiert.
- Kein Footer, kein längenpräfixierter Body. Datensätze laufen bis EOF.
Wenn Sie jemals einen Parser für eines der Windows-AppCompat-Ära-Binärformate geschrieben haben, wird Sie nichts davon überraschen.
Der 20-Byte-Header
| Offset | Größe | Wert | Beschreibung |
|---|---|---|---|
| 0 | 4 | 0x0fffeefe | Signatur. Das einzige Header-Feld, das als tragend zu behandeln ist. |
| 4 | 4 | 0x00002211 | Unbekannt. Beobachtete Konstante. |
| 8 | 4 | 0x00000003 | Unbekannt. Beobachtete Konstante. |
| 12 | 4 | 0x00000001 | Unbekannt. Beobachtete Konstante. |
| 16 | 4 | variabel | Möglicherweise eine Prüfsumme. Kein öffentlicher Parser verifiziert sie. |
Validieren Sie die Signatur. Wenn die Bytes an Offset 0 nicht fe ef ff 0f Little-Endian sind, sehen Sie keine RecentFileCache.bcf an. Brechen Sie ab und warnen. Die anderen drei Konstanten waren auf jedem Sample, das ich über ein Jahrzehnt Win7-Hosts gesehen habe, derselbe Wert. Behandeln Sie sie als Konstanten für Sanity-Checks; gaten Sie das Parsen nicht an ihnen.
Ein Datensatz
offset size field
0 4 char_count ; Anzahl der UTF-16-Code-Units, INKL. abschließendem NUL
4 var path ; UTF-16LE, NUL-terminiert
Ein char_count von 5 bedeutet 4 Code-Units Pfad plus das NUL, was 10 Byte Payload plus 4 für den Count ergibt.
Ein char_count von 0 ist kein legitimer leerer Datensatz. Jeder Parser, den ich gesehen habe, behandelt ihn entweder als Korruption oder als Terminator und stoppt. Tun Sie dasselbe. Versuchen Sie nicht, 0 Bytes zu lesen und ewig zu schleifen.
Ein gearbeiteter Hex-Dump
Minimale Datei mit C:\foo.exe und D:\bar:
00000000 fe ef ff 0f 11 22 00 00 03 00 00 00 01 00 00 00 header (Sig + 3 Unbekannte)
00000010 00 00 00 00 mögliche Prüfsumme (genullt)
00000014 0b 00 00 00 char_count = 11 (10 Zeichen + NUL)
00000018 43 00 3a 00 5c 00 66 00 6f 00 6f 00 2e 00 65 00 "C:\foo.e"
00000028 78 00 65 00 00 00 "xe" + NUL
0000002e 07 00 00 00 char_count = 7 (6 Zeichen + NUL)
00000032 44 00 3a 00 5c 00 62 00 61 00 72 00 00 00 "D:\bar" + NUL
Decodiert:
| Datensatz | char_count | Pfad |
|---|---|---|
| 0 | 11 | C:\foo.exe |
| 1 | 7 | D:\bar |
Gesamtdateigröße: 64 Byte.
Beachten Sie, dass die aufgezeichneten Pfade in echten Samples fast immer das \??\-NT-Präfix tragen (z. B. \??\C:\Users\bob\AppData\Local\Temp\setup.exe). Das ist die DOS-Pfad-Notation des NT-Object-Managers. Strippen Sie sie während der Normalisierung. Versuchen Sie nicht, sie zu „reparieren", bevor Sie die Signatur validieren.
Sonderfälle, die ein echter Parser handhaben muss
Ein robuster Parser vertraut der Datei nicht. Echte .bcf-Dateien in freier Wildbahn kommen mit all diesen Problemen.
- Falsche Signatur. Forensische Kopien werden gepaddet, mit Erfassungsheadern präfixiert oder aus einer falsch ausgerichteten Region gezogen. Validieren Sie die Signatur; warnen Sie, aber fahren Sie fort, wenn Sie nachsichtiges Verhalten wollen.
char_count = 0. Als Terminator behandeln. Stop.char_countgrößer als die verbleibenden Bytes. Abgeschnittene Datei oder korrupter Datensatz. Stop und Warnung. Nicht über EOF hinaus lesen.- Trailing-Bytes nach dem letzten wohlgeformten Datensatz. Üblich, besonders bei Dateien, die mitten in einem Rewrite erfasst wurden. Geben Sie eine Warnung aus, damit der Analyst weiß, dass es unerklärte Tail-Daten gibt.
- Leerer String-Body (
char_count = 1). Nur das NUL. Technisch gültig. Geben Sie einen leeren Pfad aus; stürzen Sie nicht ab. - UTF-16-Surrogatpaare. Das Format erlaubt sie. Decodieren Sie nachsichtig mit Ersatz bei schlechten Sequenzen. Lassen Sie nicht die ganze Datei wegen eines hässlichen Code-Points scheitern.
Die Referenzimplementierung in diesem Repo tut all das oben und gibt ein strukturiertes Warnungs-Array neben den Datensätzen aus.
Was das Format Ihnen nicht sagt
Nach all diesem sorgfältigen Parsen haben Sie eine Liste von Pfaden. Es gibt keine:
- Per-Eintrag-Zeitstempel,
- Dateigrößen,
- Hashes,
- Signierer,
- PE-Metadaten,
- noch irgendeine Angabe, wann ein Eintrag relativ zum letzten
ProgramDataUpdater-Lauf hinzugefügt wurde.
Wenn Sie „wann" oder „was war diese Binärdatei" beantworten möchten, paaren Sie jeden interessanten BCF-Treffer mit Amcache.hve für dieselbe Ära (oder Prefetch, oder die On-Disk-Datei selbst, oder den MFT-Datensatz) und triangulieren. Die BCF gibt Ihnen eine Liste von Spuren. Die Metadaten leben anderswo.