ese-parser
Pure-Rust parser for the Microsoft Extensible Storage Engine (ESE / "Jet Blue") database format. Read-only, forensic-focused, no C-library FFI — everything is in-tree Rust.
ESE is the on-disk B-tree Windows uses for:
ntds.dit— Active DirectoryWebCacheV*.dat— Edge / IE browsing historyWindows.edb— Search index- Legacy Exchange
Mail.dat - Event Tracing Logs (some flavors)
Part of the icedracon forensics / offensive-AD ecosystem.
Status
0.1.0 — skeleton. Header validation + random-access page reads with parsed page-header fields. B-tree walk, catalog decode, and row iteration are on the roadmap for v0.2.
What v0.1 does
EseFile::open(path)— read + validate the 668-byte database header (magic0x89ABCDEF, format-version, format-revision, page-size, file-type, backup log-generation numbers so a caller can check DB consistency).EseFile::page(page_number)— random-access read of a specific page. Returns a [RawPage] with parsed header fields: page number, previous/next sibling in the B-tree chain, father data page, object ID, available data size, tag count, page flags (leaf / root / parent / long-value / etc.).- Full page bytes are retained on the [
RawPage] so a downstream B-tree walker can decode tags on top.
What v0.1 does not do (roadmap)
- B-tree walk — root → branch → leaf, following child page pointers. Needed to iterate a table.
- Catalog decode — the
MSysObjectstable lists every user table + its column definitions (ATTs → ATTx numeric IDs, column offsets, long-value / multi-value flags). - Row / tag decode — each leaf page has N tag entries pointing at record bytes; each record needs column-defined slicing + long-value chunk reassembly.
- Encryption — Windows database encryption (per-page XOR with a table key) is not v0.1.
- Recovery — dirty-shutdown recovery from transaction logs is out of scope; use Microsoft's own
esentutl /p /d /rto bring a dirty DB to consistent state before feeding it to this crate.
Once these land, ntds-parse v0.3 will consume ese-parser as its EseBackend.
Usage
use ;
let mut db = open?;
println!;
// Walk pages 2..100 (page 0 = header, page 1 = shadow header) looking for leaf pages
for pn in 2..100u32
# Ok::
Verification
- Header offsets validated against libesedb's ESE spec doc.
- Page header layout matches Joachim Metz's reverse-engineering notes.
- Format-version + page-size accepted values match what libesedb + Windows itself produce for
ntds.dit,Windows.edb,WebCacheV*.dat.
Related icedracon crates
ntds-parse— NTDS.dit crypto + attribute decoders (will consumeese-parserin v0.3)lsass-parse— LSASS minidump sibling (different file format, same DFIR / offensive-security scope)
License
MIT © 2026 zevs