Forensique de Windows.db : SQLite, WAL et base gather
L'index de Windows 11 en forensique : comment s'articulent Windows.db, Windows.db-wal et Windows-gather.db, ce que révèle le WAL et comment le préserver.
En bref. Sous Windows 11, l'index Windows Search est une base SQLite en mode WAL (journal d'écriture anticipée). Windows.db contient le magasin de propriétés (SystemIndex_1_PropertyStore + _Metadata). Windows.db-wal contient les transactions validées pas encore checkpointées dans la base. Windows-gather.db (+ son propre WAL) contient les tables du gatherer, SystemIndex_Gthr et SystemIndex_GthrPth. Collectez-les ensemble. Lisez la base avec le WAL pour l'état actuel, et comparez avec la base sans le WAL pour voir ce que les dernières transactions ont ajouté, modifié ou retiré. N'ouvrez jamais les originaux dans un client SQLite classique : il peut checkpointer et effacer cet historique.
Les fichiers
| Fichier | Contenu |
|---|---|
Windows.db | SystemIndex_1_PropertyStore (WorkId, ColumnId, Value) et SystemIndex_1_PropertyStore_Metadata (ColumnId → nom de propriété, type de stockage) |
Windows.db-wal | Journal WAL de Windows.db |
Windows.db-shm | Index en mémoire partagée du WAL. Inutile ; reconstruit à partir du WAL. |
Windows-gather.db | SystemIndex_Gthr (ScopeID, DocumentID, FileName, LastModified, TransactionFlags…) et SystemIndex_GthrPth (Scope, Parent, Name) |
Windows-gather.db-wal | Journal WAL de la base gather |
Windows-usn.db et autres | Bases annexes |
Les noms de tables et de colonnes proviennent de recherches publiques : l'article de Stroz Friedberg de 2023 et l'article de Kaspersky sur les artefacts de Windows 11. Microsoft ne documente pas le schéma. Les octets 18 et 19 de l'en-tête SQLite valent tous deux 2 quand une base est en mode WAL : un moyen rapide de confirmer qu'il vous faut le fichier -wal.
Comment fonctionne le WAL (ce qui compte)
D'après la documentation WAL de SQLite et la spécification du format de fichier :
- Une écriture ne modifie pas
Windows.db. SQLite ajoute les nouvelles versions des pages modifiées àWindows.db-wal, sous forme de trames (frames). - Une transaction est validée quand sa dernière trame est écrite avec un marqueur de commit (la taille de la base après validation).
- Un lecteur qui cherche une page prend la dernière trame validée de cette page dans le WAL ; s'il n'y en a pas, il lit la page dans la base.
- Un checkpoint recopie la dernière version de chaque page dans la base. Par défaut, il a lieu quand le WAL atteint 1 000 pages, ou quand la dernière connexion se ferme.
- Après un checkpoint, le WAL n'est normalement pas tronqué. SQLite recommence à écrire depuis le début et change les sels (salts) de l'en-tête. Les trames de la génération précédente situées au-delà de la nouvelle position d'écriture restent sur le disque jusqu'à être écrasées.
Chaque trame a un en-tête de 24 octets avec le numéro de page, le marqueur de commit, les deux sels et une somme de contrôle cumulative. C'est ainsi qu'un lecteur sait quelles trames sont valides, validées et actuelles.
Ce que cela apporte à l'enquêteur
1. L'état actuel
La base plus le WAL (trames validées uniquement), c'est ce que lirait le service Windows Search lui-même. C'est la vue sur laquelle rapporter. Sans le WAL, vous regardez peut-être un index vieux de quelques minutes, heures ou jours. En pratique, cela peut signifier que justement les fichiers créés pendant l'incident manquent.
2. Ce qui a changé récemment
Comparez la base seule avec la base plus le WAL :
| Élément | Lecture |
|---|---|
| Dans les deux, identique | Inchangé depuis le dernier checkpoint |
| Seulement avec le WAL | Indexé par une transaction récente : nouveau fichier, emplacement nouvellement indexé |
| Dans les deux, propriétés différentes | Réindexé récemment : fichier modifié, consulté, renommé ou déplacé |
| Seulement sans le WAL | Retiré par une transaction récente : probablement supprimé ou exclu |
Le Windows Search Index Parser fait cette comparaison pour vous et marque les éléments uniquement dans le WAL et modifiés dans le WAL. Il ne liste pas encore le troisième cas séparément ; comparer des exports avec et sans le WAL le fait apparaître.
3. Les anciennes versions de pages
Un même WAL peut contenir plusieurs trames pour la même page, issues de transactions successives. De plus, après un checkpoint et un redémarrage du WAL, des trames périmées de la génération précédente (avec d'anciens sels) peuvent subsister en fin de fichier. Les deux sont des sources potentielles de versions anciennes d'enregistrements, y compris d'enregistrements supprimés depuis. Les récupérer exige un outil de carving qui comprend le WAL. Le parseur n'applique que les trames valides et validées de la génération courante et ignore le reste, en indiquant pourquoi (changement de sel, somme de contrôle incorrecte, trames non validées) dans ses avertissements.
La base gather n'est pas optionnelle
Sans Windows-gather.db :
- Vous perdez les chemins de dossiers issus de l'arbre d'étendues du gatherer.
SystemIndex_GthrPthstocke chaque dossier sous la forme (Scope, Parent, Name) ; remonter les parents reconstruit le chemin, etSystemIndex_Gthr.FileNamele complète. - Vous perdez le contrôle croisé entre magasin de propriétés et table gather (DocumentID = WorkId). Un élément présent dans le magasin mais absent de la table gather est l'un des meilleurs indicateurs « supprimé ? » ; voir les traces de fichiers supprimés.
- Vous perdez la valeur
LastModifiedpropre au gatherer, un second avis sur la date de modification du fichier.
La base gather a son propre WAL. Collectez-le aussi. Le parseur associe Windows-gather.db et son -wal au Windows.db du même dossier : conservez l'arborescence quand vous collectez sur plusieurs machines.
Les erreurs qui détruisent la preuve
- Ouvrir l'original dans une interface SQLite. La lecture peut être anodine, mais la fermeture de la dernière connexion déclenche par défaut un checkpoint : le WAL est fusionné dans la base et peut être supprimé. Travaillez sur une copie hachée.
- Copier
Windows.dbet le WAL à des moments différents. Vous obtenez des trames qui ne correspondent pas aux pages de la base. Un lecteur rigoureux valide sels et sommes de contrôle et écarte le WAL. Le parseur vérifie aussi que le magasin de propriétés obtenu est vraisemblable et ignore, avec un avertissement, un WAL provenant d'une autre base. - Arrêter le service pour « déverrouiller » les fichiers. Un arrêt propre ferme les connexions, donc checkpointe. Vous obtenez un
Windows.dbbien rangé et plus de comparaison avant/après. Voir les options d'acquisition. - Donner le fichier
-shmà vos outils comme s'il comptait. C'est un cache. Le parseur l'indique comme inutile.
Vérifier un parseur avec sqlite3
Sur une copie du dossier, le shell SQLite vous donne une vérité de référence pour des contrôles ponctuels :
-- 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;
Comme le shell applique le WAL, il montre l'état actuel ; copiez la base sans son WAL dans un dossier séparé pour interroger l'état checkpointé. Le shell peut checkpointer en sortant : sans importance sur une copie jetable, et une raison de plus de ne jamais le faire sur l'original.
Les limites honnêtes de l'outil sur ce point
La prise en charge de Windows 11 dans le Windows Search Index Parser repose sur des recherches publiques et a été testée sur des bases SQLite construites comme les vraies, y compris un WAL laissé non checkpointé. Le DDL exact, les codes de type de stockage au-delà du texte (11) et de l'entier / FILETIME (12), la reconstruction des chemins et l'ordre des octets du LastModified gather sont des heuristiques qui doivent encore être validées sur davantage de fichiers Windows.db réels. La récupération d'enregistrements depuis les pages de la freelist, les freeblocks ou les trames WAL périmées est sur la feuille de route, pas dans l'outil.
FAQ
Peut-on ouvrir Windows.db avec DB Browser for SQLite ou le shell sqlite3 ?
Oui, sur une copie. Un client SQLite classique applique le WAL à la lecture et peut le checkpointer dans la base puis le réinitialiser à la fermeture. Cela détruit la comparaison avant/après : ne le faites jamais sur la preuve originale.
Pourquoi mon Windows.db paraît-il presque vide ?
Soit le WAL n'a pas été collecté et l'essentiel du travail récent s'y trouve encore, soit l'outil utilisé ne lit pas les tables WITHOUT ROWID ou ne pivote pas les lignes de propriétés. Vérifiez la taille de Windows.db-wal et essayez un autre lecteur.