Pure-Rust read-only VMware VMDK disk image reader — Read + Seek over the virtual sector stream.
cargo install vmdk-cli[dependencies]
vmdk = "0.1"vmdk info disk.vmdk # Format, virtual disk size, sector sizeuse vmdk::VmdkReader;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
// Single-file VMDKs (monolithicSparse, streamOptimized)
let file = File::open("disk.vmdk")?;
let mut reader = VmdkReader::open(file)?;
println!("Disk type: {}", reader.disk_type()); // "monolithicSparse"
println!("Virtual disk size: {}", reader.virtual_disk_size()); // bytes
// Read the first sector
let mut sector = [0u8; 512];
reader.read_exact(&mut sector)?;
// Seek anywhere — O(1) via two-level grain table
reader.seek(SeekFrom::Start(1_048_576))?;VmdkReader<R> is generic over any R: Read + Seek, so it works with File,
Cursor<Vec<u8>>, network streams, or any custom reader:
// In-memory (tests, embedded use)
use std::io::Cursor;
let reader = VmdkReader::open(Cursor::new(bytes))?;Multi-file VMDKs (flat extents) require a filesystem path:
// twoGbMaxExtentFlat — descriptor + companion extent files
let reader = VmdkReader::open_path(std::path::Path::new("disk.vmdk"))?;VmdkReader implements Read + Seek, so it plugs directly into filesystem crates:
// e.g. ext4::Filesystem::open(reader)?;
// e.g. ntfs::Ntfs::new(&mut reader)?;- monolithicSparse — VMware Workstation / Fusion / ESXi sparse images; two-level GD/GT grain lookup
- streamOptimized — sparse and compressed (zlib / RFC 1950) grains;
GrainMarkerdecoded at read time - twoGbMaxExtentFlat / monolithicFlat — multi-file flat extent descriptors; opens via
open_path - twoGbMaxExtentSparse — multi-file sparse extent descriptors; each extent is an independent binary VMDK with its own GD/GT
- O(1) virtual offset resolution — GD loaded at open, one GT read + one seek per grain access
- Graceful rejection — unknown formats and bad magic return
Err, never panic - Fuzz-hardened — proptest + cargo-fuzz; all corpus inputs verified not to panic
- Zero unsafe code —
#![forbid(unsafe_code)] - MIT licensed — no GPL, safe for proprietary DFIR tooling
| Format | Status |
|---|---|
monolithicSparse (v1) |
✓ |
streamOptimized (v3, all-sparse) |
✓ |
streamOptimized (v3, compressed grains) |
✓ |
twoGbMaxExtentFlat |
✓ (open_path only) |
monolithicFlat |
✓ (open_path only) |
twoGbMaxExtentSparse |
✓ (open_path only) |
VmdkReader::open and open_path return Err (never panic) on unrecognised inputs.
byte 0 SparseExtentHeader (512 bytes) — magic, version, geometry, GD offset
sector 1–20 embedded text descriptor — createType, CID, extent map
sector 21–25 redundant grain directory (ignored)
sector 26 primary grain directory — one u32 per grain table
sector 27+ grain tables — one u32 (file sector offset) per grain
sector 128+ grain data — raw 64 KiB blocks
Virtual offset resolution is O(1): one GD lookup (in-memory Vec<u32>) + one GT read
(4 bytes from file) + one grain data seek.
- 59 tests across unit, integration real-images, and integration synthetic suites
- Validated against real VMware-generated images from the dfvfs and plaso forensics test corpora
- External validation against pWnOS v2.0 (VulnHub, VMware Workstation 7, 40 GiB sparse image)
and Metasploitable3 Windows 2008 (Rapid7, VMware Workstation 13,
twoGbMaxExtentSparse)
See docs/validation.md for detailed results and reproduction steps.
| Crate | Format | Notes |
|---|---|---|
ewf |
E01 / EWF / Ex01 | Dominant professional forensic acquisition format |
aff4 |
AFF4 v1 | Evimetry / aff4-imager forensic disk images with Map streams |
vhdx |
Microsoft VHDX | Hyper-V, Windows 8+, WSL2, Azure disk container |
vhd |
Legacy VHD | Virtual PC / Hyper-V Generation-1 fixed and dynamic disk images |
qcow2 |
QCOW2 v2/v3 | QEMU / KVM / libvirt disk images |
ufed |
Cellebrite UFED | Physical mobile device dumps with UFD XML segment mapping |
dd |
Raw / flat / gz | dd, dcfldd, and gzip-wrapped raw images |
iso9660-forensic |
ISO 9660 | Optical disc images: multi-session, UDF bridge, Rock Ridge, Joliet, El Torito |
dmg |
Apple DMG / UDIF | macOS disk images with koly trailer, mish block tables, zlib decompression |
dar |
DAR archive | Disk ARchiver archives with catalog index and CRC32 validation |
| Crate | Format | Notes |
|---|---|---|
ewf-forensic |
E01 | Structural integrity audit, Adler-32 / MD5 hash verification, and in-memory repair |
vhdx-forensic |
VHDX | Forensic integrity analyser and in-memory repair tool for VHDX containers |
Privacy Policy · Terms of Service · © 2026 Security Ronin Ltd