Windows.db-Forensik: SQLite, WAL und Gather-Datenbank
Windows-11-Suchindex-Forensik: wie Windows.db, Windows.db-wal und Windows-gather.db zusammenspielen, was das WAL verrät und wie man es nicht zerstört.
Kurz gesagt. Unter Windows 11 ist der Windows-Search-Index SQLite im Write-Ahead-Log-Modus. Windows.db enthält den Eigenschaftenspeicher (SystemIndex_1_PropertyStore + _Metadata). Windows.db-wal enthält bestätigte Transaktionen, die noch nicht hineingecheckpointet sind. Windows-gather.db (+ eigenes WAL) enthält die Gatherer-Tabellen SystemIndex_Gthr und SystemIndex_GthrPth. Alles zusammen sichern. Die Datenbank mit WAL für den aktuellen Stand lesen und mit der Datenbank ohne WAL vergleichen, um zu sehen, was die letzten Transaktionen hinzugefügt, geändert oder entfernt haben. Die Originale nie in einem normalen SQLite-Client öffnen: Er kann checkpointen und diese Historie löschen.
Die Dateien
| Datei | Inhalt |
|---|---|
Windows.db | SystemIndex_1_PropertyStore (WorkId, ColumnId, Value) und SystemIndex_1_PropertyStore_Metadata (ColumnId → Eigenschaftsname, Speichertyp) |
Windows.db-wal | Write-Ahead-Log von Windows.db |
Windows.db-shm | Shared-Memory-Index des WAL. Nicht nötig; wird aus dem WAL neu aufgebaut. |
Windows-gather.db | SystemIndex_Gthr (ScopeID, DocumentID, FileName, LastModified, TransactionFlags…) und SystemIndex_GthrPth (Scope, Parent, Name) |
Windows-gather.db-wal | Write-Ahead-Log der Gather-Datenbank |
Windows-usn.db und weitere | Hilfsdatenbanken |
Die Tabellen- und Spaltennamen stammen aus öffentlicher Forschung: der Arbeit von Stroz Friedberg von 2023 und Kasperskys Beitrag zu den Artefakten von Windows 11. Microsoft dokumentiert das Schema nicht. Die Bytes 18 und 19 des SQLite-Headers sind beide 2, wenn eine Datenbank im WAL-Modus ist; so lässt sich schnell bestätigen, dass die -wal-Datei gebraucht wird.
Wie das WAL funktioniert (das Relevante)
Laut WAL-Dokumentation von SQLite und Dateiformat-Spezifikation:
- Ein Schreibvorgang verändert
Windows.dbnicht. SQLite hängt die neuen Versionen geänderter Seiten als Frames anWindows.db-walan. - Eine Transaktion ist bestätigt, wenn ihr letzter Frame mit einer Commit-Markierung (der Datenbankgröße nach dem Commit) geschrieben ist.
- Ein Leser, der eine Seite sucht, nimmt den letzten bestätigten Frame dieser Seite im WAL; gibt es keinen, liest er die Seite aus der Datenbank.
- Ein Checkpoint kopiert die neueste Version jeder Seite zurück in die Datenbank. Standardmäßig, wenn das WAL 1.000 Seiten erreicht oder die letzte Verbindung geschlossen wird.
- Nach einem Checkpoint wird das WAL normalerweise nicht gekürzt. SQLite beginnt wieder am Anfang zu schreiben und ändert die Salts im Header. Frames der vorherigen Generation jenseits der neuen Schreibposition bleiben auf der Platte, bis sie überschrieben werden.
Jeder Frame hat einen 24-Byte-Header mit Seitennummer, Commit-Markierung, den beiden Salts und einer laufenden Prüfsumme. Daran erkennt ein Leser, welche Frames gültig, bestätigt und aktuell sind.
Was das für Ermittler bringt
1. Der aktuelle Stand
Datenbank plus WAL (nur bestätigte Frames) ist das, was der Dienst Windows Search selbst lesen würde. Diese Sicht gehört in den Bericht. Ohne WAL sieht man womöglich einen Index, der Minuten, Stunden oder Tage alt ist. In der Praxis kann das heißen, dass genau die während des Vorfalls erstellten Dateien fehlen.
2. Was sich kürzlich geändert hat
Die Datenbank allein mit Datenbank plus WAL vergleichen:
| Element | Deutung |
|---|---|
| In beiden, identisch | Seit dem letzten Checkpoint unverändert |
| Nur mit WAL | Durch eine jüngste Transaktion indiziert: neue Datei, neu indizierter Ort |
| In beiden, Eigenschaften verschieden | Kürzlich neu indiziert: Datei geändert, aufgerufen, umbenannt oder verschoben |
| Nur ohne WAL | Durch eine jüngste Transaktion entfernt: vermutlich gelöscht oder ausgeschlossen |
Der Windows Search Index Parser erledigt diesen Vergleich und markiert Elemente als nur im WAL und im WAL geändert. Den dritten Fall listet er noch nicht gesondert auf; ein Vergleich von Exporten mit und ohne WAL macht ihn sichtbar.
3. Ältere Seitenversionen
Ein WAL kann mehrere Frames derselben Seite aus aufeinanderfolgenden Transaktionen enthalten. Zudem können nach Checkpoint und Neustart veraltete Frames der vorherigen Generation (mit alten Salts) am Dateiende verbleiben. Beides sind mögliche Quellen älterer Versionen von Datensätzen, auch solcher, die inzwischen gelöscht wurden. Sie wiederherzustellen erfordert einen WAL-fähigen Carver. Der Parser wendet nur gültige, bestätigte Frames der aktuellen Generation an, ignoriert den Rest und nennt den Grund (Salt-Wechsel, Prüfsummenfehler, unbestätigte Frames) in seinen Warnungen.
Die Gather-Datenbank ist nicht optional
Ohne Windows-gather.db:
- fehlen die Ordnerpfade aus dem Bereichsbaum des Gatherers.
SystemIndex_GthrPthspeichert jeden Ordner als (Scope, Parent, Name); das Hochlaufen der Eltern rekonstruiert den Pfad,SystemIndex_Gthr.FileNamevervollständigt ihn. - fehlt der Abgleich zwischen Eigenschaftenspeicher und Gather-Tabelle (DocumentID = WorkId). Ein Element im Speicher, das in der Gather-Tabelle fehlt, ist einer der besten „gelöscht?“-Hinweise; siehe Spuren gelöschter Dateien.
- fehlt der eigene
LastModified-Wert des Gatherers, eine zweite Meinung zur Änderungszeit der Datei.
Die Gather-Datenbank hat ein eigenes WAL. Auch das sichern. Der Parser ordnet Windows-gather.db und ihre -wal der Windows.db aus demselben Ordner zu; bei Sicherungen von mehreren Rechnern also die Ordnerstruktur beibehalten.
Fehler, die Spuren zerstören
- Das Original in einer SQLite-Oberfläche öffnen. Lesen mag harmlos sein, aber das Schließen der letzten Verbindung löst standardmäßig einen Checkpoint aus: Das WAL wird in die Datenbank übernommen und kann gelöscht werden. Auf einer gehashten Kopie arbeiten.
Windows.dbund WAL zu verschiedenen Zeitpunkten kopieren. Man erhält Frames, die nicht zu den Datenbankseiten passen. Ein sorgfältiger Leser prüft Salts und Prüfsummen und verwirft das WAL. Der Parser prüft zusätzlich, ob der resultierende Eigenschaftenspeicher plausibel ist, und ignoriert ein WAL aus einer anderen Datenbank mit einer Warnung.- Den Dienst beenden, um die Dateien zu „entsperren“. Ein sauberer Stopp schließt die Verbindungen und checkpointet damit. Übrig bleibt eine aufgeräumte
Windows.dbohne Vorher-Nachher-Vergleich. Siehe Sicherungsoptionen. - Die
-shm-Datei in die Tools geben, als sei sie wichtig. Sie ist ein Cache. Der Parser führt sie als nicht benötigt.
Einen Parser mit sqlite3 prüfen
Auf einer Kopie des Ordners liefert die SQLite-Shell eine Referenz für Stichproben:
-- property names
SELECT Id, Name FROM SystemIndex_1_PropertyStore_Metadata WHERE Name LIKE 'System.ItemPath%';
-- every property of one item
SELECT m.Name, hex(p.Value), p.Value
FROM SystemIndex_1_PropertyStore p
JOIN SystemIndex_1_PropertyStore_Metadata m ON m.Id = p.ColumnId
WHERE p.WorkId = 532;
Da die Shell das WAL anwendet, zeigt sie den aktuellen Stand; für den gecheckpointeten Stand die Datenbank ohne WAL in einen separaten Ordner kopieren und dort abfragen. Die Shell kann beim Beenden checkpointen, was auf einer Wegwerfkopie egal ist und ein weiterer Grund, es nie am Original zu tun.
Ehrliche Grenzen des Tools an dieser Stelle
Die Windows-11-Unterstützung im Windows Search Index Parser beruht auf öffentlicher Forschung und wurde an SQLite-Datenbanken getestet, die wie die echten aufgebaut sind, einschließlich eines nicht gecheckpointeten WAL. Die genaue DDL, die Speichertyp-Codes jenseits von Text (11) und Ganzzahl / FILETIME (12), die Pfadrekonstruktion und die Bytereihenfolge von LastModified in der Gather-Tabelle sind Heuristiken, die noch an mehr echten Windows.db-Dateien validiert werden müssen. Die Wiederherstellung von Datensätzen aus Freelist-Seiten, Freeblocks oder veralteten WAL-Frames steht auf der Roadmap, nicht im Tool.
FAQ
Kann man Windows.db mit DB Browser for SQLite oder der sqlite3-Shell öffnen?
Ja, auf einer Kopie. Ein normaler SQLite-Client wendet das WAL beim Lesen an und kann es beim Schließen in die Datenbank checkpointen und zurücksetzen. Das zerstört den Vorher-Nachher-Vergleich, also nie am Original-Beweismittel.
Warum wirkt meine Windows.db fast leer?
Entweder wurde das WAL nicht gesichert und der Großteil der jüngsten Arbeit steckt noch darin, oder das verwendete Tool liest keine WITHOUT-ROWID-Tabellen bzw. pivotiert die Eigenschaftszeilen nicht. Die Größe von Windows.db-wal prüfen und einen anderen Leser versuchen.