vshadow 0.1.0

Pure Rust parser for Windows Volume Shadow Copy (VSS) snapshots. Read-only access to VSS stores from forensic disk images without Windows APIs.
Documentation

vshadow-rs

License Rust Platform


Read-only access to Windows Volume Shadow Copy (VSS) snapshots from any Read + Seek source — forensic disk images (E01, dd), raw partitions, or mounted volumes. No Windows APIs required. Works on Linux, macOS, and Windows.

Why?

During incident response, attackers frequently clear Windows event logs. But if Volume Shadow Copies exist, the old logs are still there — frozen in time inside the shadow copy snapshots. Tools like vshadowmount require FUSE and only work on Linux. EVTXECmd's --vss flag requires the Windows VSS COM API and only works on live systems.

vshadow-rs reads the VSS on-disk format directly, giving you cross-platform access to shadow copy data from forensic images.

Usage

use std::fs::File;
use std::io::BufReader;
use vshadow::VssVolume;

// Open any Read+Seek source (raw partition, E01 via ewf crate, etc.)
let f = File::open("partition.raw")?;
let mut reader = BufReader::new(f);

// Parse VSS structures
let volume = VssVolume::new(&mut reader)?;
println!("Found {} VSS snapshots", volume.store_count());

for i in 0..volume.store_count() {
    let info = volume.store_info(i)?;
    println!("Store {}: {} changed blocks", i, info.volume_size);

    // Get a reader for this snapshot — implements Read + Seek
    let mut store_reader = volume.store_reader(&mut reader, i)?;

    // Pass store_reader to any filesystem parser (e.g., ntfs crate)
    // let ntfs = ntfs::Ntfs::new(&mut store_reader)?;
}

How it works

VSS stores data using a copy-on-write mechanism:

  1. When a snapshot is created, the current state of every block is recorded
  2. When a block is later modified, the old data is copied to a store area
  3. To reconstruct the snapshot, read from the store area for changed blocks and from the current volume for unchanged blocks

vshadow-rs parses the on-disk structures:

  • Volume header at offset 0x1E00 — identifies VSS presence
  • Catalog — linked list of 16 KiB blocks containing store metadata and locations
  • Block descriptors — map of which blocks changed and where the old data is stored
  • Store reader — combines block descriptors with the base volume to present the snapshot view

Integration with forensic tools

vshadow-rs is designed to integrate with other Rust forensic crates:

// E01 image → NTFS partition → VSS stores → NTFS filesystem → files
let ewf_reader = ewf::EwfReader::open("evidence.E01")?;
let mut partition = OffsetReader::new(ewf_reader, partition_offset);

let vss = VssVolume::new(&mut partition)?;
for i in 0..vss.store_count() {
    let mut store = vss.store_reader(&mut partition, i)?;
    let ntfs = ntfs::Ntfs::new(&mut store)?;
    // Extract files from the snapshot...
}

VSS Format Reference

Based on the libvshadow documentation by Joachim Metz.

Structure Offset Size Description
Volume Header 0x1E00 128 bytes VSS signature, catalog offset, volume GUID
Catalog Block variable 16 KiB Linked list of store metadata + locations
Block Descriptor variable 32 bytes Maps original_offset to store_data_offset
Store Data variable 16 KiB blocks Copy-on-write data for changed blocks

Supported Windows versions

  • Windows Vista / Server 2008 (VSS v1)
  • Windows 7 / Server 2008 R2 (VSS v1)
  • Windows 8 / Server 2012 (VSS v2)
  • Windows 10 / 11 / Server 2016-2022 (VSS v2)

Part of the WIA project

vshadow-rs is part of the We Investigate Anything (WIA) project and is used by masstin for forensic image analysis with VSS support.

License

Dual-licensed under MIT and Apache 2.0.