Forense de Windows.db: SQLite, WAL y base gather
El índice de Windows 11 en forense: cómo encajan Windows.db, Windows.db-wal y Windows-gather.db, qué revela el WAL y cómo no destruirlo durante el análisis.
En resumen. En Windows 11, el índice de Windows Search es SQLite en modo de registro de escritura anticipada (WAL). Windows.db contiene el almacén de propiedades (SystemIndex_1_PropertyStore + _Metadata). Windows.db-wal contiene las transacciones confirmadas aún no consolidadas en ella. Windows-gather.db (+ su propio WAL) contiene las tablas del rastreador, SystemIndex_Gthr y SystemIndex_GthrPth. Adquiérelas todas juntas. Lee la base con el WAL para el estado actual, y compárala con la base sin él para ver qué añadieron, cambiaron o eliminaron las últimas transacciones. No abras nunca los originales en un cliente SQLite normal: puede consolidar y borrar ese historial.
Los archivos
| Archivo | Contenido |
|---|---|
Windows.db | SystemIndex_1_PropertyStore (WorkId, ColumnId, Value) y SystemIndex_1_PropertyStore_Metadata (ColumnId → nombre de propiedad, tipo de almacenamiento) |
Windows.db-wal | Registro WAL de Windows.db |
Windows.db-shm | Índice en memoria compartida del WAL. No hace falta; se reconstruye a partir del WAL. |
Windows-gather.db | SystemIndex_Gthr (ScopeID, DocumentID, FileName, LastModified, TransactionFlags…) y SystemIndex_GthrPth (Scope, Parent, Name) |
Windows-gather.db-wal | Registro WAL de la base gather |
Windows-usn.db y otros | Bases auxiliares |
Los nombres de tablas y columnas proceden de investigación pública: el trabajo de Stroz Friedberg de 2023 y el artículo de Kaspersky sobre artefactos de Windows 11. Microsoft no documenta el esquema. Los bytes 18 y 19 de la cabecera SQLite valen ambos 2 cuando una base está en modo WAL, una forma rápida de confirmar que necesitas el archivo -wal.
Cómo funciona el WAL (lo que importa)
Según la documentación WAL de SQLite y la especificación del formato de archivo:
- Una escritura no modifica
Windows.db. SQLite añade las nuevas versiones de las páginas cambiadas aWindows.db-wal, como tramas (frames). - Una transacción queda confirmada cuando su última trama se escribe con un marcador de commit (el tamaño de la base tras la confirmación).
- Un lector que busca una página toma la última trama confirmada de esa página en el WAL; si no hay ninguna, lee la página de la base.
- Un checkpoint copia la última versión de cada página de vuelta a la base. Por defecto ocurre cuando el WAL alcanza 1000 páginas o cuando se cierra la última conexión.
- Tras un checkpoint, el WAL normalmente no se trunca. SQLite vuelve a escribir desde el principio y cambia las sales (salts) de la cabecera. Las tramas de la generación anterior que quedan más allá de la nueva posición de escritura permanecen en disco hasta que se sobrescriben.
Cada trama tiene una cabecera de 24 bytes con el número de página, el marcador de commit, las dos sales y una suma de comprobación acumulada. Así sabe un lector qué tramas son válidas, confirmadas y actuales.
Qué obtiene el investigador
1. El estado actual
La base más el WAL (solo tramas confirmadas) es lo que leería el propio servicio Windows Search. Es la vista sobre la que informar. Sin el WAL puedes estar mirando un índice con minutos, horas o días de antigüedad. En la práctica, eso puede significar que faltan justo los archivos creados durante el incidente.
2. Qué cambió recientemente
Compara la base sola con la base más el WAL:
| Elemento | Lectura |
|---|---|
| En ambas, idéntico | Sin cambios desde el último checkpoint |
| Solo con el WAL | Indexado por una transacción reciente: archivo nuevo, ubicación recién indexada |
| En ambas, propiedades distintas | Reindexado recientemente: archivo modificado, accedido, renombrado o movido |
| Solo sin el WAL | Eliminado por una transacción reciente: probablemente borrado o excluido |
El Windows Search Index Parser hace esta comparación por ti y marca los elementos solo en el WAL y modificados en el WAL. Todavía no enumera el tercer caso por separado; comparar exportaciones con y sin el WAL lo muestra.
3. Versiones antiguas de páginas
Un mismo WAL puede contener varias tramas para la misma página, de transacciones sucesivas. Además, tras un checkpoint y un reinicio, pueden quedar al final del archivo tramas obsoletas de la generación anterior (con sales antiguas). Ambas son fuentes potenciales de versiones antiguas de registros, incluidos registros borrados después. Recuperarlas requiere una herramienta de carving que entienda el WAL. El analizador solo aplica tramas válidas y confirmadas de la generación actual e ignora el resto, indicando el motivo (cambio de sal, suma de comprobación incorrecta, tramas sin confirmar) en sus avisos.
La base gather no es opcional
Sin Windows-gather.db:
- Pierdes las rutas de carpetas del árbol de ámbitos del rastreador.
SystemIndex_GthrPthguarda cada carpeta como (Scope, Parent, Name); subir por los padres reconstruye la ruta ySystemIndex_Gthr.FileNamela completa. - Pierdes la comprobación cruzada entre el almacén de propiedades y la tabla gather (DocumentID = WorkId). Un elemento presente en el almacén pero ausente en la tabla gather es uno de los mejores indicadores de «¿borrado?»; ver rastros de archivos borrados.
- Pierdes el valor
LastModifieddel propio rastreador, una segunda opinión sobre la fecha de modificación del archivo.
La base gather tiene su propio WAL. Adquiérelo también. El analizador empareja Windows-gather.db y su -wal con el Windows.db de la misma carpeta, así que conserva la estructura de carpetas cuando adquieras de varias máquinas.
Errores que destruyen evidencias
- Abrir el original en una interfaz de SQLite. Leer puede ser inofensivo, pero cerrar la última conexión dispara por defecto un checkpoint: el WAL se fusiona con la base y puede eliminarse. Trabaja sobre una copia con hash.
- Copiar
Windows.dby el WAL en momentos distintos. Obtienes tramas que no encajan con las páginas de la base. Un lector cuidadoso valida sales y sumas de comprobación y descarta el WAL. El analizador también comprueba que el almacén de propiedades resultante sea verosímil e ignora, con un aviso, un WAL de otra base. - Detener el servicio para «desbloquear» los archivos. Una parada limpia cierra las conexiones, lo que provoca un checkpoint. Acabas con un
Windows.dbordenado y sin comparación antes/después. Ver opciones de adquisición. - Pasar el archivo
-shma tus herramientas como si importara. Es una caché. El analizador lo indica como innecesario.
Verificar un analizador con sqlite3
Sobre una copia de la carpeta, el shell de SQLite te da la verdad de referencia para comprobaciones puntuales:
-- 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;
Como el shell aplica el WAL, muestra el estado actual; copia la base sin su WAL a una carpeta aparte para consultar el estado consolidado. El shell puede consolidar al salir, lo cual no importa en una copia desechable y es una razón más para no hacerlo nunca sobre el original.
Límites honestos de la herramienta en este punto
El soporte de Windows 11 del Windows Search Index Parser se basa en investigación pública y se ha probado con bases SQLite construidas como las reales, incluido un WAL sin consolidar. El DDL exacto, los códigos de tipo de almacenamiento más allá del texto (11) y el entero / FILETIME (12), la reconstrucción de rutas y el orden de bytes del LastModified de gather son heurísticas que aún deben validarse con más archivos Windows.db reales. La recuperación de registros desde páginas de la freelist, freeblocks o tramas WAL obsoletas está en la hoja de ruta, no en la herramienta.
Preguntas frecuentes
¿Puedo abrir Windows.db con DB Browser for SQLite o el shell sqlite3?
Sí, sobre una copia. Un cliente SQLite normal aplica el WAL al leer y puede consolidarlo en la base y reiniciarlo al cerrar. Eso destruye la comparación antes/después, así que no lo hagas nunca con la evidencia original.
¿Por qué mi Windows.db parece casi vacío?
O no se adquirió el WAL y la mayor parte del trabajo reciente sigue en él, o la herramienta que usaste no lee tablas WITHOUT ROWID o no pivota las filas de propiedades. Comprueba el tamaño de Windows.db-wal y prueba otro lector.