Forensique des bases ESE : les bases pour enquêteurs
Comment est construite une base ESE (JET Blue) comme Windows.edb : en-tête, pages, arbres B+, catalogue, colonnes tagged, valeurs longues et suppressions.
En bref. ESE, aussi appelé JET Blue, est le moteur de base de données embarqué derrière Windows.edb, SRUDB.dat, WebCacheV01.dat, le ntds.dit d'Active Directory et Exchange. Un fichier ESE, c'est un en-tête (avec sa copie de secours), puis des pages de taille fixe organisées en arbres B+. Le catalogue MSysObjects décrit chaque table et chaque colonne. Les lignes mélangent colonnes fixes, variables et « tagged » (éparses). Les grosses valeurs vivent dans un arbre de valeurs longues séparé. Le texte est souvent compressé. Les modifications passent d'abord par des journaux de transactions, d'où l'état « dirty » d'une copie à chaud. Les lignes supprimées sont marquées « defunct » et nettoyées plus tard : c'est dans cet intervalle que le carving trouve des preuves. Connaître tout cela vous aide à juger la sortie de n'importe quel parseur ESE, y compris celui-ci.
Pourquoi un analyste forensique devrait s'y intéresser
Vous n'avez pas besoin d'écrire un parseur ESE. Vous devez en savoir assez pour répondre à des questions comme : pourquoi l'outil A affiche-t-il 41 000 lignes et l'outil B 40 212 ? Pourquoi cette colonne est-elle vide dans une visionneuse et pas dans l'autre ? Peut-on rapporter sur une base « dirty » ? Les réponses viennent du format.
Microsoft décrit ESE comme un moteur ISAM (méthode d'accès séquentielle indexée) avec transactions, récupération après incident via un journal d'écriture anticipée, et prise en charge de tables très larges avec de nombreuses colonnes éparses et multivaluées. Ce dernier point correspond exactement au besoin de Windows Search : des centaines de propriétés possibles, une poignée renseignées par élément. Microsoft a publié le code source du moteur sous licence MIT en 2021. La référence la plus utile pour la forensique reste la documentation du format libesedb de Joachim Metz.
Autres bases ESE que vous croiserez dans la même affaire :
| Fichier | Contenu | Outil de la même famille |
|---|---|---|
Windows.edb | Index Windows Search (Windows 10 et antérieurs) | Windows Search Index Parser |
SRUDB.dat | System Resource Usage Monitor | parseur SRUM |
WebCacheV01.dat | Historique, cookies et cache d'IE / ancien Edge | forensique des navigateurs |
ntds.dit | Base Active Directory | — |
L'en-tête du fichier
La première page du fichier est l'en-tête. Une seconde copie, l'en-tête de secours (shadow header), la suit. Les champs qui comptent :
| Champ (selon libesedb) | Offset | Pourquoi c'est utile |
|---|---|---|
Signature 0x89ABCDEF | 4 | Identifie un fichier ESE quelle que soit son extension |
| Version / révision du format | 8 / 232 | Génération du moteur. Les révisions récentes ajoutent la structure des grandes pages. |
| État de la base | 52 | 2 = dirty shutdown, 3 = clean shutdown |
| Taille de page | 236 | De 2 à 32 Kio. Les pages de 16 et 32 Kio utilisent une structure de page différente. |
L'état de la base est la première chose à vérifier. esentutl /mh Windows.edb l'affiche (State: Dirty Shutdown), comme le montre le billet archivé de Microsoft sur esentutl et VSS. Un dirty shutdown signifie que des modifications validées peuvent n'exister que dans les journaux. Voir réparer un Windows.edb en dirty shutdown.
Si l'en-tête principal est endommagé, un parseur peut se rabattre sur la copie de secours. Le Windows Search Index Parser le fait et l'indique dans ses avertissements.
Pages et arbres B+
Après les deux pages d'en-tête, le fichier est un tableau de pages de la taille déclarée. Chaque page a un en-tête (40 octets ; 80 octets dans la structure étendue utilisée par les pages de 16 et 32 Kio depuis Windows 7) et un tableau de tags en fin de page qui pointe vers les entrées qu'elle contient.
Les pages forment des arbres B+. Les données d'une table forment un arbre ; chaque index en est un autre ; les valeurs longues un troisième. Les pages de branche pointent vers des pages filles ; les pages feuilles contiennent les enregistrements. Les entrées d'une page peuvent partager un préfixe de clé commun avec la première entrée de la page, une petite astuce de compression que les parseurs doivent défaire pour reconstruire les clés.
Deux détails au niveau des pages comptent en forensique :
- Les entrées « defunct ». Un enregistrement supprimé est d'abord marqué dans son tag et laissé en place. Il disparaît quand la page est nettoyée ou réorganisée.
- L'espace libre. L'espace libéré par les suppressions et les fusions de pages est réutilisé plus tard, pas effacé immédiatement. D'anciens enregistrements peuvent y survivre.
Le catalogue : MSysObjects
MSysObjects est une table comme les autres, à un emplacement connu (sa racine est la page 4). Elle liste chaque table, colonne, index et arbre de valeurs longues, avec leurs identifiants, types, pages de code et pages racines. Un parseur lit d'abord le catalogue, puis parcourt l'arbre de chaque table. Parmi les tables Windows Search qu'on y trouve : SystemIndex_PropertyStore, SystemIndex_Gthr et SystemIndex_GthrPth.
Enregistrements : colonnes fixes, variables et tagged
Un enregistrement ESE a trois parties :
| Partie | Identifiants de colonne | Usage |
|---|---|---|
| Colonnes fixes | 1–127 | Entiers, dates, GUID de taille fixe |
| Colonnes variables | 128–255 | Texte court et binaire de taille variable |
| Colonnes tagged | 256+ | Valeurs éparses : présentes seulement si renseignées ; peuvent être multivaluées |
SystemIndex_PropertyStore s'appuie massivement sur les colonnes tagged : l'élément a un WorkID et seulement les propriétés effectivement renseignées. Les colonnes tagged multivaluées contiennent des listes, comme System.Kind = program; executable. Un parseur qui ignore les valeurs multiples perd des données sans le dire.
Les valeurs longues
Une valeur trop grande pour l'enregistrement, comme un long extrait de contenu ou une grosse propriété binaire, est stockée dans l'arbre de valeurs longues de la table ; l'enregistrement ne garde qu'une référence (un identifiant de valeur longue sur 4 ou 8 octets selon la version du moteur). Un parseur qui ne suit pas ces références affiche la propriété vide ou sous forme d'un court blob binaire. Quand deux outils ne s'accordent pas sur l'existence d'un extrait, c'est le premier suspect.
La compression
ESE peut compresser les données des colonnes. La documentation libesedb décrit :
- La compression 7 bits pour du texte ASCII ou Unicode court : les caractères sont empaquetés sur 7 bits.
- XPRESS (LZ77) pour les valeurs plus grandes, identifiée par un octet de tête.
- Des schémas plus récents dans les versions récentes du moteur, que tous les parseurs n'implémentent pas.
Un parseur qui ne gère pas un schéma donné affiche du charabia ou rien. Le Windows Search Index Parser gère la compression 7 bits et XPRESS (LZ77 simple) et signale les valeurs qu'il n'a pas pu décoder au lieu de les masquer. XPRESS9 / XPRESS10 / LZ4 ne sont pas encore pris en charge.
Journaux de transactions et checkpoint
ESE écrit les modifications dans des fichiers journaux séquentiels (pour Windows Search : MSS.log, MSS00001.log…), et MSS.chk enregistre jusqu'où ils ont été appliqués. Le fichier de base est mis à jour plus tard. Conséquences :
- Une copie d'une base en fonctionnement ne contient que ce qui a été vidé sur disque. Le reste est dans les journaux.
esentutl /r MSSrejoue les journaux dans la base (récupération douce, « soft recovery »). Toujours sur une copie.- Les journaux sont eux-mêmes des traces de modifications récentes. Des outils spécialisés savent les parser, ce qui dépasse ce que font la plupart des parseurs.
Où se cachent les enregistrements Windows Search supprimés dans ESE
| Emplacement | Récupérable avec |
|---|---|
| Entrées « defunct » encore présentes dans les pages feuilles | Un parseur qui lit les tags defunct, ou un outil de carving |
| Pages libres / inutilisées | Un outil de carving d'enregistrements (par exemple WinSearchDBAnalyzer, ou l'approche wdsCarve de Chivers et Hargreaves, 2011) |
| Journaux de transactions pas encore rejoués | Rejeu sur une copie, puis parsing ; ou un parseur de journaux |
Le Windows Search Index Parser compte actuellement les entrées « defunct » des tables qu'il parcourt et en indique le nombre, sans les récupérer. Plus de détails dans les traces de fichiers supprimés dans l'index Windows Search.
Un mot sur la validation
ESE est un format vaste et les détails varient selon les versions du moteur. Le lecteur ESE du Windows Search Index Parser suit la documentation libesedb et le code source de Microsoft, et il est testé contre un écrivain ESE synthétique. Cela prouve la cohérence interne, pas l'exactitude sur chaque Windows.edb réel. À ce jour, il n'a pas été validé sur des bases réelles, et l'interface le dit. Quand une constatation compte, comparez avec esedbexport, ESEDatabaseView ou SIDR, comme expliqué dans la comparaison des parseurs.