Skip to content

Open an E01 disk image in your browser

Browse an Expert Witness Format (E01) image without FTK Imager or a local install. How EWF segments, compression and hashing actually work.

Published on 5 min read
Open an E01 disk image in your browser

E01 is the format you get handed and the format nobody enjoys parsing. Expert Witness Format, sometimes called EWF, came out of EnCase and became the de facto container for forensic disk images because it does three things raw dd doesn't: it compresses, it stores metadata about the acquisition, and it carries a hash so you can prove the image didn't change since it was captured.

The cost is that you can't just dd if=image.E01 your way into it. The bytes on disk are not the bytes of the original drive. They're chunked, optionally compressed with zlib, indexed by an offset table, and wrapped in a section structure. To read sector 0 of the original media you have to walk that structure first.

What's actually inside an E01

An EWF file is a sequence of sections, each with a 76-byte header that names the section type and points at the next one. The ones that matter:

  • header / header2 — acquisition metadata. Examiner name, case number, acquisition date, the tool and version that made the image. This is free intelligence about provenance and it's the first thing worth reading.
  • volume / disk — geometry. Sector size, sector count, chunk size (number of sectors per compressed chunk, classically 64 sectors = 32 KiB).
  • table / table2 / sectors — the actual data. sectors holds the compressed chunks; table is the offset index that says where each chunk lives. table2 is a backup copy of the table, which matters more than it sounds like when the primary table is damaged.
  • digest / hash — the stored MD5 and, in EWF2/Ex01, SHA-1 or SHA-256.
  • done — end marker.

The high bit of each table offset is a flag: set means the chunk is zlib-compressed, clear means it's stored raw (EWF skips compression when a chunk doesn't shrink, which is common for already-compressed or high-entropy regions). Miss that flag and you'll hand a raw chunk to the decompressor and get garbage, or hand a compressed chunk straight to the caller and get garbage a different way.

Reading a sector is a four-step lookup

To answer "give me byte offset N of the original media," you do this:

  1. Divide N by the chunk size in bytes to find which chunk holds it.
  2. Look up that chunk's entry in the table to get its file offset and its compressed-or-not flag.
  3. Read the chunk bytes, decompress if the flag is set.
  4. Index into the decompressed chunk at N mod chunk_size.

None of this is hard. What makes it annoying in practice is that the data spans multiple physical files. A 500 GB image isn't one .E01 — it's .E01 through .E0n, often capped at 640 MB or 2 GB per segment because of old FAT32 and CD-R limits that nobody needs anymore but everybody still defaults to. The offset in the table can point into segment 14, so your reader has to treat the whole set as one logical byte stream and keep all the file handles open. Select only the first file and any read past the first segment fails.

Why doing this in the browser is the interesting part

The obvious objection: forensic images are huge, browsers are sandboxed, surely you upload it somewhere and let a server do the work. No. That's exactly what you don't want.

The File System Access API hands you a FileSystemFileHandle that you can read in ranges without pulling the whole file into memory. Combined with WebAssembly for the decompression and structure parsing, you get a reader that opens a 500 GB E01 by reading kilobytes — the section headers and the offset table — and then fetches individual 32 KiB chunks lazily as you browse the partition tree. The image never moves. For evidence you're not authorized to copy off the acquisition host, that's not a nice-to-have, it's the whole point. No upload, no temp file on a server you don't control, no second copy to account for in your custody log.

The constraint you feel is memory, not transfer. You cannot decompress the whole image into a buffer. You decompress the chunk you need, use it, and let it go. Cache a small LRU window of recently-touched chunks because filesystem walks have strong locality — reading the MFT touches the same neighborhood repeatedly — but keep the cap low. The moment you try to hold the whole thing you're back to needing a server.

The corruption you'll meet, and what to do about it

Real E01s come off failing drives, and the acquisition tool faithfully records every read error. A bad chunk is usually a chunk that won't decompress or whose CRC doesn't match. Don't abort the whole image because one chunk is dead. Zero-fill the unreadable region, flag it in your output, and keep going — the rest of the filesystem is almost always fine and the analyst needs to know exactly which sectors are untrustworthy, not be told the image is unopenable.

The table2 backup exists precisely for the case where the primary offset table is corrupt. If a table read looks wrong — offsets that point past the end of the segment set, a chunk count that doesn't match the volume section — fall back to table2 before giving up.

And verify the hash when you can. EWF stores an MD5 (and SHA-1/256 in the newer Ex01 variant) computed over the media data at acquisition time. Recompute it from the chunks you decompress and compare. If it matches, you can state in a report that the image is intact. If it doesn't, that's a finding: either the image is damaged or someone touched it after capture, and either way you want to know before you build a case on it.

E01 isn't elegant. But once you've internalized that it's just sections, a chunk table with a compression bit, and data possibly scattered across a dozen files, it stops being a black box and becomes something you can open anywhere — including a browser tab, with nothing installed and nothing uploaded.

Related articles

A practitioner's checklist for disk images that refuse to mount: format mismatches, split sets, truncated acquisitions, wrong sector size and corruption.
Detect filesystems from the superblock instead of trusting the partition type byte. Magic numbers, the offsets that trip people up, and faking it.
Walk the partition table of a disk image yourself: MBR's 64 bytes, the EBR chain, GPT headers, CRCs, and the offset bugs that read the wrong sector.