Le format de base ESE derrière SRUDB.dat
17/05/2026
ESE en un paragraphe
L’Extensible Storage Engine est la base ISAM embarquée de Microsoft. Chaque fichier est une série de pages de taille fixe (4 ou 8 Ko) qui organisent les données en B-trees, un par table. Les écritures passent d’abord par un journal de transactions pour permettre la récupération après crash en plein flush. Le moteur est mono-processus — seul le service propriétaire a un handle sur le fichier à un moment donné.
Anatomie sur disque
- Pages — 4 ou 8 Ko, identifiées par un numéro de page 4 octets. La première page contient l’en-tête de la base (signature, taille de page, signature du log).
- B-trees — un par table. Une page feuille contient les données de ligne ; les pages internes contiennent les plages de clés et pointeurs vers enfants.
- Catalog — un B-tree spécial (table id 0) qui décrit chaque autre table : son nom, numéro de page racine, et définitions de colonnes.
- Long values — données de taille variable trop grosses pour tenir en ligne, stockées dans un arbre « long-value » séparé, la ligne ne portant qu’une référence.
- Journaux de transactions — fichiers
.logqui contiennent les écritures non commit. Le fichier checkpoint (.chk) enregistre jusqu’où le moteur a flushé.
Types de colonnes rencontrés
ESE a 19 types de colonnes. Les plus courants dans SRUDB.dat :
| ID | Nom | Encodage |
|---|---|---|
| 1 | Bit | 1 octet (0/1) |
| 4 | Long | int signé 32-bit |
| 7 | IEEEDouble | float 8 octets (utilisé pour dates OLE) |
| 8 | DateTime | OLE variant date 8 octets |
| 11 | LongBinary | octets variables (souvent compressés XPRESS) |
| 12 | LongText | texte UTF-16 / cp1252 variable |
| 14 | UnsignedLong | int non-signé 32-bit |
| 15 | LongLong | int signé 64-bit (souvent FILETIME) |
| 16 | GUID | 16 octets bruts (endian mixte) |
À noter : la colonne TimeStamp de SRUM est de type 8 (date OLE en
f64) tandis que les colonnes événementielles comme ConnectStartTime
sont de type 15 (FILETIME en i64). Un parseur doit gérer les deux.
Pourquoi un nouvel outil pour le web
Les lecteurs ESE existants — libesedb en C, strozfriedberg/ese_parser en Rust, Velocidex/go-ese en Go — sont excellents mais ciblent le desktop/serveur.
Pour tourner dans un navigateur via WebAssembly :
- Le crate Rust
ese_parsercompile sans accroc surwasm32-unknown-unknown. - Il expose une API
Read + Seek, donc unCursor<Vec<u8>>sur les octets du fichier fonctionne sans couche FS virtuelle. - Retirer les features inutilisées (
filepathetnt_comparison) amène le payload WASM à ~160 Ko — assez petit pour servir en asset statique.
C’est exactement ce qui alimente l’analyseur SRUM de ce site.
Récupérer une base dirty
Si vous copiez SRUDB.dat pendant que le service SRUM écrit, le fichier est « dirty » — l’en-tête le marque incohérent. Un parseur read-only refusera ou ignorera silencieusement les pages nécessitant un replay du log.
La meilleure parade à l’acquisition est de prendre tout le répertoire
sru\ y compris les .log. Une bibliothèque ESE complète (libesedb,
esentutl) peut rejouer les logs contre la base dirty et produire une
copie cohérente.
Pour aller plus loin
Questions fréquentes
- Que signifie ESE ?
- Extensible Storage Engine. Microsoft l’appelle aussi Jet Blue en interne. C’est une base ISAM embarquée, transactionnelle, avec pages B-tree.
- Où ESE est-il utilisé en dehors de SRUM ?
- Active Directory (NTDS.dit), Microsoft Exchange (boîtes mail), le cache Edge / Internet Explorer (WebCacheV01.dat), Windows Search (Windows.edb), et DHCP.
- Puis-je ouvrir SRUDB.dat dans Microsoft Access ?
- Non. Access utilise Jet Red, un moteur différent. ESE/Jet Blue a son propre format on-disk et requiert un lecteur dédié comme libesedb, ese_parser, ou cet outil navigateur.
- Le format ESE est-il documenté ?
- Partiellement. Microsoft a open-sourcé le moteur ESE en 2021. Le projet libyal de Joachim Metz maintient la spécification communautaire la plus complète.
- Pourquoi les lignes SRUM sont compressées ?
- ESE supporte la compression XPRESS par colonne. SRUM l’utilise sur ses payloads variables (l’IdBlob dans SruDbIdMapTable, par exemple) pour garder la base compacte.