The ESE database format that powers SRUDB.dat
5/17/2026
The Extensible Storage Engine is Microsoft's embedded ISAM database
engine — Jet Blue if you ever read internal docs. It is the storage
layer for SRUM, Active Directory's NTDS.dit, Exchange mailbox stores,
the old IE/Edge WebCacheV01.dat, Windows Search's Windows.edb, and
DHCP. Once you can read one ESE file you can read all of them, so it is
worth knowing how it ticks before you try to parse SRUDB.dat.
ESE in one paragraph
A series of fixed-size pages (4 KB or 8 KB) organised into B-trees, one per table. Writes go through a write-ahead log first, so recovery is possible after a crash. The engine is single-process — only the owning service has the file handle. Tables are described by a catalog B-tree (table id 0).
On-disk anatomy
- Pages. 4 or 8 KB. The first page contains the database header
(signature
EFCDAB89, page size, log signature, state). Theesentutl /mhoutput reads this header. - B-trees. One per table. Internal pages hold key ranges and child pointers; leaf pages hold rows.
- Catalog. A special B-tree (table id 0) describing every other table: name, root page number, column definitions.
- Long values. Variable-length data too big to fit inline lives in a separate long-value tree; the row holds a reference key.
- Transaction logs.
.logfiles holding committed but un-flushed writes..chkis the checkpoint — how far the engine has flushed.
Column types you will meet in SRUDB.dat
ESE has 19 column types. The ones SRUM uses:
| Type ID | Name | Encoding |
|---|---|---|
| 1 | Bit | 1 byte (0/1) |
| 4 | Long | 32-bit signed int |
| 7 | IEEEDouble | 8-byte float (used for OLE date times) |
| 8 | DateTime | 8-byte OLE variant date |
| 11 | LongBinary | variable bytes (often XPRESS-compressed) |
| 12 | LongText | variable UTF-16 / cp1252 text |
| 14 | UnsignedLong | 32-bit unsigned int |
| 15 | LongLong | 64-bit signed int (often FILETIME) |
| 16 | GUID | 16 raw bytes (mixed-endian) |
Two gotchas you will hit on SRUM:
- The
TimeStampcolumn on Application Resource Use is type 8 (OLE date, 8-byte float). A bucket boundary at midnight UTC is44986.0, not a FILETIME. Tools that assume FILETIME for every timestamp column produce dates in the year 4,000,000. - Event-style columns like
ConnectStartTimeon Network Connectivity andEventTimestampon Energy Usage are type 15 FILETIMEs. A parser must handle both.
The same divergence catches people on NTDS.dit and Exchange. Type
matters.
Recovering from a dirty database
ESE marks the database "dirty shutdown" whenever the engine did not
write its clean-shutdown record. Copying SRUDB.dat from a live host
almost guarantees this state — DPS held the handle and was actively
writing.
A read-only parser will either refuse the dirty header or quietly skip
pages that need log replay. The fix is soft recovery: replay the .log
files against the database with esentutl /r. The
dirty-database recovery post
walks the command line.
Always work on a copy. esentutl /p (hard repair) is destructive — it
can discard rows. Reserve it for cases where logs are gone entirely.
XPRESS compression on variable columns
SRUM uses XPRESS compression on variable-length payloads. The
SruDbIdMapTable.IdBlob column is the obvious example — the UTF-16
application paths often compress 3:1. A parser that does not decompress
returns garbage strings. The compressed payload is prefixed by a
magic byte (0x10 for XPRESS, 0x18 for XPRESS Huffman).
Reading ESE in 2026
Real-world choices for parsing ESE:
- libesedb (Joachim Metz, C). The reference open-source library. Powers everything that does not write its own parser.
- ese_parser (Stroz Friedberg, Rust). Compiles cleanly to
wasm32-unknown-unknown, which is how the in-browser SRUM parser works. - go-ese (Velocidex, Go). Used by Velociraptor.
- esentutl.exe. Ships with Windows. Useful for recovery, not for programmatic reads.
Further reading
Frequently asked questions
What does ESE stand for?
Extensible Storage Engine. Microsoft also calls it Jet Blue internally. It is an embedded, transactional, ISAM database with B-tree pages.
Where else is ESE used besides SRUM?
Active Directory (NTDS.dit), Microsoft Exchange (mailbox stores), the Edge / Internet Explorer cache (WebCacheV01.dat), Windows Search (Windows.edb), and DHCP.
Can I open SRUDB.dat in Microsoft Access?
No. Access uses Jet Red, a different engine. ESE/Jet Blue has its own on-disk format and requires a dedicated reader like libesedb, ese_parser, or this browser-based tool.
Is the ESE format documented?
Partially. Microsoft open-sourced the ESE engine in 2021. Joachim Metz' libyal project maintains the most complete community reverse-engineered specification.
Why are SRUM rows compressed?
ESE supports per-column XPRESS compression. SRUM uses it on its variable-length payloads (the IdBlob in SruDbIdMapTable, for example) to keep the database small.