Recuperar notificaciones borradas de Windows
Por qué los toasts descartados y caducados sobreviven en wpndatabase.db, dónde los deja SQLite y cómo recuperarlos sin llevarse sorpresas.
En resumen. Al borrar una fila en SQLite, su espacio se marca como libre; los bytes permanecen hasta que se reutilizan (salvo que secure_delete esté activado). En wpndatabase.db, eso significa que las notificaciones descartadas y caducadas, incluidas las vistas previas de chats, a menudo pueden recuperarse del espacio libre de las páginas, de la freelist y de las imágenes antiguas de las páginas en el archivo y en el WAL. Trata cada fila recuperada como una pista, no como un registro.
Dónde se esconden las filas borradas
El formato de archivo de SQLite ofrece cuatro lugares:
- Freeblocks. El espacio de una celda borrada se convierte en un freeblock dentro de la misma página del árbol B. Solo se sobrescriben sus cuatro primeros bytes (el puntero al siguiente freeblock y el tamaño del bloque); el resto del registro, incluida la carga útil, queda intacto.
- La freelist. Cuando una página ya no contiene ninguna fila, pasa a la freelist con todo su contenido, hasta que SQLite vuelve a necesitar una página.
- Páginas obsoletas en el archivo de la base de datos. Cuando existe el WAL, el archivo contiene la página tal como estaba en el último checkpoint. Si una transacción posterior borró una fila, la imagen antigua de la página todavía la contiene.
- Tramas del WAL. El WAL guarda versiones sucesivas de las páginas. Las tramas más antiguas, y las de una generación anterior del WAL, pueden contener filas que las versiones más recientes ya no tienen.
Una base de datos de notificaciones es un buen candidato: las cargas útiles son unos cientos de bytes de XML muy característico, las filas cambian constantemente y el archivo rara vez se compacta con VACUUM.
Cómo las recupera el parser
Windows Notification Parser utiliza dos métodos:
- Borradas por el WAL. Las filas presentes en la base de datos consolidada que desaparecen al aplicar el WAL son exactas: el parser las lee con el decodificador de registros normal y las marca como «borrada por una transacción del WAL».
- Carving anclado en la carga útil. Cada
<toast,<tile,<badgeo<?xmlencontrado en cualquier página o trama del WAL es un posible inicio de un valorPayload. Para cada uno, el parser busca hacia atrás una cabecera de registro cuyos tipos serie coincidan con el esquema activo deNotificationy sitúen la carga útil exactamente en ese desplazamiento. Además, deben cuadrar los tipos de columna, un FILETIME plausible y unTypeen ASCII. Las cargas útiles que se desbordaron a páginas de overflow se reconstruyen a partir de la cadena si todavía existe; si no, la fila se marca como parcial.
Las filas idénticas a una fila activa se descartan. Una fila obtenida por carving con el mismo Id que una activa pero con distinto contenido se muestra como versión anterior.
Cómo interpretar una fila recuperada
Cada notificación recuperada indica su procedencia, por ejemplo free space in page 4, freelist page 12 o WAL frame 3 (page 5). Comprueba tres cosas antes de utilizarla:
- ¿Está completa? Una fila parcial tiene la carga útil cortada o le faltan campos.
- ¿Sigue existiendo su gestor?
HandlerIdse resuelve contra la tabla de gestores activa; es posible que el gestor ya no exista. - ¿Encaja en la cronología? Una hora de llegada en mitad de otra actividad es buena señal; una hora muy alejada del resto de los datos merece desconfianza.
Limitaciones
- El espacio se reutiliza a medida que llegan notificaciones nuevas: cuanto más tiempo pasa desde el borrado, peor es la recuperación.
VACUUMreescribe el archivo y elimina el espacio libre.- Si una compilación activó
secure_delete, el contenido liberado se pone a cero. No está documentado si alguna compilación de Windows lo hace; un resultado vacío no demuestra ausencia. - Un registro cuya cabecera se sobrescribió no puede recuperarse con este método. Existen otros enfoques de carving; este prioriza tener pocos falsos positivos.
Preguntas frecuentes
¿Se pueden recuperar las notificaciones borradas de Windows?
A menudo sí, hasta que SQLite reutiliza el espacio. Una fila borrada permanece en la página como freeblock, las páginas completas pasan a la freelist y las imágenes antiguas de las páginas siguen en el archivo de la base de datos y en el WAL. Las filas recuperadas son evidencias de mejor esfuerzo y deben identificarse como tales.
¿Abrir la base de datos destruye los registros borrados?
Puede hacerlo. Abrir con SQLite una base de datos en modo WAL y cerrarla puede provocar un checkpoint y reiniciar el WAL, y escribir en ella reutiliza el espacio libre. Trabaja siempre sobre copias con hash.