vmspect 0.3.1

Blazing-fast static inspection, forensic analysis and information extraction library for virtual machine disk images (VMDK, RAW, QCOW2, VHD, VHDX, VDI).
docs.rs failed to build vmspect-0.3.1
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

vmspect

Crates.io License Rust

vmspect is a Rust library and CLI tool for ultra-fast static inspection, forensic analysis and information extraction of virtual machine disk images (VMDK, RAW, QCOW2, VHD, VHDX, VDI, etc.).

It can examine partition-table structures (MBR/GPT), identify the guest operating system (Windows/Linux), extract complete lists of installed software and detect integration tools (Guest Tools) in a non-invasive way (without booting the virtual machine or requiring mount privileges on the host) in less than 70 ms even for virtual disks larger than 80 GiB.


🚀 Key Features

  • Extreme performance and lightweight streaming (<70 ms for 80 GiB images):
    • Native Rust parser: Direct, ultra-low-latency reading for RAW and VMDK images (monolithicSparse, monolithicFlat, twoGbMaxExtentFlat/Sparse, etc.) without external dependencies or child processes.
    • Integrated qemu-nbd server: For complex formats (QCOW2, VHDX, VDI, compressed/streamOptimized VMDK), connects over a local TCP socket (127.0.0.1) or UNIX sockets using the standard NBD protocol, with direct block streaming and no temporary files on disk.
  • Resilience against dirty registries and NTFS fallback (Graceful Degradation):
    • Permissive Windows Registry reading: Tolerance for dirty or damaged registry hives (SequenceNumberMismatch caused by abrupt shutdowns or hot snapshots) using Hive::without_validation and isolating internal panics from third-party libraries via catch_unwind.
    • NTFS fallback inspection: If the Registry hives are totally inaccessible, vmspect gracefully degrades by inspecting the PE header of \Windows\System32\ntoskrnl.exe directly to extract the OS build and version, and scans \Program Files, tagging applications as source: Some("FallbackFS").
    • Non-fatal warnings list: Reports issues in the warnings field of the report without aborting the inspection pipeline.
  • Multi-hypervisor, hypervisor-agnostic Guest Tools detection:
    • Full and typed support in the GuestTools struct to identify and extract the version of:
      • VMware Tools / open-vm-tools
      • VirtualBox Guest Additions
      • QEMU Guest Agent
      • Hyper-V Integration Services
  • Supported guest operating systems:
    • Windows (NTFS): Extracts Registry hives (SOFTWARE and SYSTEM) by parsing uninstall keys (32 and 64-bit), operating system version, build number, Service Pack and Guest Tools.
    • Linux (ext2 / ext3 / ext4): Reads /etc/os-release, /etc/hostname and analyzes the /var/lib/dpkg/status package database along with virtualization agents.
  • Scheme and file-system detection:
    • Partition schemes: MBR, GPT and Volumes without a partition table.
    • Signature recognition: NTFS, FAT12/16/32, ext2/3/4, XFS, Btrfs, LVM2 PV, Linux Swap.
  • Agnostic and complete extraction:
    • Default, complete collection of all applications and system information without noise filters or proprietary categorizations.
    • Support for --no-apps (disables application collection) and --no-system (disables OS metadata collection) flags.
  • Designed for UI and CLI:
    • Emits progress events in structured percentages (0% to 100%) ideal for Tauri, egui or Electron.
    • Cancellation support via atomic tokens (Arc<AtomicBool> / CancellationToken) while preserving partial results.

📂 Crate Structure

The project follows the standard Rust library package convention:

vmspect/
├── Cargo.toml               # Crate configuration, metadata and dependencies
├── readme.md                # Main documentation
├── LICENSE                  # MIT / Apache-2.0 license
├── src/
│   ├── lib.rs               # Library entry point (public API and re-exports)
│   ├── models/              # Domain types (InspectionReport, GuestInfo, Partition, etc.)
│   │   ├── image.rs
│   │   ├── options.rs       # Inspection options, progress and cancellation
│   │   ├── partition.rs
│   │   ├── software.rs      # Program and GuestInfo models
│   │   └── traits.rs        # Abstract traits (OsInspector, VmDriver, MemoryMapper)
│   ├── parsers/             # Per-OS analyzers
│   │   ├── mod.rs           # OsInspector trait and polymorphic factory
│   │   ├── windows.rs       # NTFS extraction and Registry parsing (nt-hive)
│   │   ├── linux.rs         # ext4 superblock reading and DPKG database
│   │   └── desconocido.rs   # Handling of unrecognized operating systems
│   └── vms/                 # Disk access and virtualization layer
│       ├── mod.rs           # Disk access module
│       ├── detector.rs       # MBR/GPT detection and FS signatures
│       ├── nbd.rs           # Native NBD client and qemu-nbd connector
│       ├── stream.rs        # DiskReader facade and VirtualDisk view (Read + Seek)
│       └── vmdk.rs          # Native VMDK parser (sparse and descriptors)
├── tests/                   # Integration tests
│   └── integration_test.rs
└── examples/                # Ready-to-run usage examples
    └── basic_inspection.rs

📦 Installation

Add vmspect to your Cargo.toml:

[dependencies]

vmspect = "0.3.0"


💡 Examples as a Library

1. Full Inspection with Guest Tools, Warnings and Progress

use std::path::Path;
use vmspect::{inspect_with_progress, Options, InspectionProgressEvent};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let path = Path::new("virtual_disk.vmdk");
    
    // Options configuration (e.g. full OS and application analysis)
    let options = Options::default();

    let report = inspect_with_progress(path, &options, |p: InspectionProgressEvent| {
        println!("[{:>3}%] {} - {}", p.percentage, p.stage, p.detail.unwrap_or_default());
    })?;

    println!("Disk format: {}", report.image.format);
    println!("Operating system: {:?}", report.operating_system);
    println!("OS details: {}", report.guest_info.formatted_os_string());
    
    // Hypervisor-agnostic Guest Tools detection (VMware, VirtualBox, QEMU, Hyper-V)
    if let Some(ref tools) = report.guest_info.guest_tools {
        if tools.present {
            println!("Guest tools: {} (version: {})", tools.kind, tools.version.as_deref().unwrap_or("N/A"));
        }
    }

    // Non-fatal warnings (graceful Registry/FS degradation)
    if !report.warnings.is_empty() {
        println!("Inspection warnings:");
        for w in &report.warnings {
            println!("  [!] {}", w);
        }
    }

    println!("Partitions detected: {}", report.partitions.len());
    println!("Installed software found: {}", report.installed_programs.len());

    for prog in report.installed_programs.iter().take(10) {
        let source = prog.source.as_deref().map(|s| format!(" [{}]", s)).unwrap_or_default();
        println!(
            " - {} (v{}) [Publisher: {}]{}",
            prog.name,
            prog.version.as_deref().unwrap_or("N/A"),
            prog.publisher.as_deref().unwrap_or("N/A"),
            source
        );
    }

    Ok(())
}

2. Advanced Extraction Options

use vmspect::Options;

// Disable application or system extraction depending on performance needs:
let light_options = Options {
    no_apps: true,           // Skip installed-software scan
    no_system: false,        // Keep OS detection and Guest Tools
    force_nbd: false,        // Use the ultra-fast native parser when available
    ..Options::default()
};

assert!(!light_options.should_analyze_apps());
assert!(light_options.should_analyze_system());

3. Concurrent Processing and Result Preservation on Cancellation

ConcurrentProcessor and InspectionEngine provide clean shutdown (Graceful Shutdown) with partial-result preservation. When the cancellation token is triggered, worker threads do not accept new images, safely finish the in-progress analysis and return all successfully processed reports:

use std::path::PathBuf;
use vmspect::prelude::*;

fn main() -> Result<()> {
    let paths = vec![
        PathBuf::from("srv1.vmdk"),
        PathBuf::from("srv2.raw"),
        PathBuf::from("srv3.qcow2"),
        PathBuf::from("srv4.vhdx"),
    ];

    let cancel = CancellationToken::new();
    let options = Options::default()
        .with_cancellation_token(&cancel);

    let engine = InspectionEngine::new(options);

    // Cancel at any time from another thread or callback:
    // cancel.cancel();

    // Returns all reports completed before and during cancellation:
    let completed_reports = engine.inspect_batch(paths, 4)?;

    println!("Total reports recovered: {}", completed_reports.len());
    for r in &completed_reports {
        println!(" - {} (OS: {:?})", r.image.path.display(), r.operating_system);
    }

    Ok(())
}

4. Tauri / Async Runtime Integration

use tauri::Emitter;
use vmspect::{inspect_with_progress, InspectionReport, InspectionProgressEvent, Options};

#[tauri::command]
async fn inspect_vm(app_handle: tauri::AppHandle, path: String) -> Result<InspectionReport, String> {
    let path = std::path::PathBuf::from(path);
    let options = Options::default();

    tauri::async_runtime::spawn_blocking(move || {
        inspect_with_progress(&path, &options, |p: InspectionProgressEvent| {
            let _ = app_handle.emit("inspection_progress", p);
        })
        .map_err(|e| e.to_string())
    })
    .await
    .map_err(|e| e.to_string())?
}

🖥️ Command-Line Interface (CLI) Usage

vmspect ships a high-performance terminal binary:

# Standard inspection with human-formatted output:

vmspect /path/to/disk.vmdk


# Structured JSON output (ideal for scripts, CI/CD pipelines and forensic analysis):

vmspect /path/to/disk.qcow2 --json


# Concurrent recursive scan of a full VM directory:

vmspect /var/lib/libvirt/images/ --concurrent --recursive --workers 8


# Fast inspection skipping application extraction:

vmspect /path/to/disk.vhdx --no-apps


# Inspection skipping OS metadata:

vmspect /path/to/disk.raw --no-system


🛠️ Running Tests and Examples

Run Unit and Integration Tests:

cargo test

Run Example with a Real Disk:

cargo run --example basic_inspection -- /path/to/your/disk.vmdk


📄 License

This project is licensed under the MIT or Apache-2.0 license at your option.