Skip to content

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.

Veröffentlicht am 3 Min. Lesezeit

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

OffsetGrößeWertBeschreibung
040x0fffeefeSignatur. Das einzige Header-Feld, das als tragend zu behandeln ist.
440x00002211Unbekannt. Beobachtete Konstante.
840x00000003Unbekannt. Beobachtete Konstante.
1240x00000001Unbekannt. Beobachtete Konstante.
164variabelMö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:

Datensatzchar_countPfad
011C:\foo.exe
17D:\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_count größ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.

Weiterführende Literatur

Verwandte Artikel

Das BCF-Format ist ein Header, eine Liste von längen-präfixierten UTF-16LE-Pfaden, und das war's. Hier ist, was jedes Byte bedeutet und warum sich seit 2009 nichts geändert hat.
Der Lebenszyklus der BCF hängt an einer einzigen geplanten Aufgabe. Verstehen Sie, wann ProgramDataUpdater läuft, wann sie die Datei leert und wie Sie einen deaktivierten Appraiser erkennen.
Ein vom SOC markierter Win7 Endpoint, 14 Pfade in der BCF, drei einer zweiten Betrachtung wert. Eine realistische Korroborationskette und wie viel die BCF tatsächlich beigetragen hat.