Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Virtual Hard Disk (VHD) image format

The Virtual Hard Disk (VHD) format is used by Microsoft vitualization products as one of its image formats. It is both used the store hard disk images and snapshots.

Overview

There are multiple types of VHD images, namely:

  • Fixed-size VHD image
  • Dynamic-size (or sparse) VHD image
  • Differential (or differencing) VHD image

Fixed-size hard disk image

A fixed-size VHD image consists of:

  • data
  • file footer

Note that a fixed-size VHD image is equivalent to a raw storage media image with an additional footer.

Dynamic-size (or sparse) hard disk image

A dynamic-size (or sparse) VHD image consists of:

  • copy of file footer
  • dynamic disk header
  • block allocation table
  • data in blocks
  • file footer

Differential hard disk image

A differential (or differencing) VHD image consists of:

  • copy of file footer
  • dynamic disk header
  • block allocation table
  • data in blocks
  • file footer

Characteristics

CharacteristicsDescription
Byte orderbig-endian
Date and time valuesNumber of seconds since January 1, 2000 00:00:00 UTC
Character stringsUCS-2 big-endian, which allows for unpaired Unicode surrogates such as "U+d800" and "U+dc00"

The number of bytes per sector is 512.

Undo disk image

Virtual PC has a feature to create “Undo Disks”. This undo disk feature stores a differential hard disk image in files named something similar like:

VirtualPCUndo_<name>_0_0_hhmmssMMDDYYYY.vud

Where the date and time seems to be stored in UTC and <name> represents the name of the parent image.

The file footer is 512 bytes in size and consists of:

OffsetSizeValueDescription
08"conectix"Signature (also referred to as cookie)
84Features
1240x00010000Format version, where the upper 16-bit are the major version and the lower 16-bit the minor version
168Next offset, which contains the offset to the next (metadata) structure. The offset is relative from the start of the file. It should only be set in dynamic and differential disk images. In fixed disk images it should be set to 0xffffffffffffffff (-1)
244Modification time, which contains the number of seconds since January 1, 2000 00:00:00 UTC
284Creator application
324Creator version, where the upper 16-bit are the major version and the lower 16-bit the minor version
364Creator (host) operating system
408Disk size, which contains the size of the disk in bytes
488Data size, which contains the size of the data in bytes
564Disk geometry
604Disk type
644Checksum, which contains a one's complement of the sum of the file footer excluding the checksum itself
6816Identifier, which contains a big-endian UUID
841Saved state, which contains a flag to indicate the image is in saved state
854270Unknown (Reserved should contain 0-byte values)

Features

OffsetSizeValueDescription
0.01 bitIs temporary disk, which indicates that this disk is a candidate for deletion on shutdown
0.11 bitUnknown (Reserved, must be set to 1)
0.230 bitsUnknown (Reserved, must be set to 0)

A value of 0 represents no features are enabled.

Creator application

ValueIdentifierDescription
"d2v\x00"Disk2vhd
"qemu"Qemu
"vpc\x20"Virtual PC
"vs\x20\x20"Virtual Server
"win\x20"Windows (Disk Management)

Creator host operating system

ValueIdentifierDescription
"Mac\x20"Macintosh
"Wi2k"Windows

Disk geometry

The disk geometry is 4 bytes in size and consists of:

OffsetSizeValueDescription
02Number of cylinders
21Number of heads
31Number of sectors per track (cylinder)

Disk type

ValueIdentifierDescription
0None
1Unknown (Deprecated)
2Fixed hard disk
3Dynamic hard disk
4Differential hard disk
5Unknown (Deprecated)
6Unknown (Deprecated)

Dynamic disk header

The dynamic disk header is 1024 bytes in size and consists of:

OffsetSizeValueDescription
08"cxsparse"Signature (Cookie)
88Next offset, which contains the offset to the next (metadata) structure. The offset is relative from the start of the file. Currently this is unused and should be set to 0xffffffffffffffff (-1)
168Block allocation table offset, whic contains the offset to the block allocation table structure. The offset is relative from the start of the file
2440x00010000Format version, where the upper 16-bit are the major version and the lower 16-bit the minor version
284Number of blocks, which is equivalent to the number of block allocation table entries
324Block size. The block size must be a power-of-two multitude of the sector size and does not include the size of the sector bitmap. The default block size is 4096 x 512-byte sectors (2 MiB)
364Checksum, which contains a one's complement of the sum of the dynamic disk header excluding the checksum itself
4016Parent identifier, which contains a big-endian UUID that identifies the parent image. Only used by differential hard disk images
564Parent last modification time, which contains the number of seconds since January 1, 2000 00:00:00 UTC. Only used by differential hard disk images
6040Unknown (Reserved should contain 0-byte values)
64512Parent name, which contains an UCS-2 big-endian string. Only used by differential hard disk images
5768 x 24 = 192Array of parent locator entries. Only used by differential hard disk images
7682560Unknown (Reserved should contain 0-byte values)

The maximum number of block allocation table entries should match the maximum possible number of blocks in the disk.

Note that the parent name can also contain a full path, e.g. in .avhd files. The part segments are separated by the \ character.

Parent locator entry

The parent locator entry is 24 bytes in size and consists of:

OffsetSizeValueDescription
04Locator platform code
44Platform data space, which contains the number of 512-byte sectors needed to store the parent hard disk locator
84Locator data size
1240Unknown (Reserved should contain 0-byte values)
168Locator data offset, which contains the offset to the locator data. The offset is relative from the start of the file

Locator platform code

ValueIdentifierDescription
0None
"Mac\x20"Mac OS alias stored as a blob
"MacX"File URL with UTF-8 encoding conforming to RFC 2396
"W2ku"Absolute Windows path, which contains an UCS-2 big-endian string
"W2ru"Windows path relative to the differential image, which contains an UCS-2 big-endian string
"Wi2k"Unknown (Deprecated)
"Wi2r"Unknown (Deprecated)

Block allocation table

The block allocation table is only used in dynamic and differential disk images.

The block allocation table consists of 32-bit entries. An entry contains the sector number where the data block starts or is set to 0xffffffff (-1) if the block is sparse or stored in the parent disk image.

if block_allocation_table_entry == 0xffffffff:
    block is sparse or stored in parent
else:
    file_offset = (block_allocation_table_entry * 512 ) + sector_bitmap_size

Unused block in a dynamic disk are sparse and should be filled with zero byte values. In a differential disk the block is stored in the parent disk image.

Data blocks

Data blocks are only used in dynamic and differential disk images.

A data block consists of:

  • sector bitmap
  • sector data
size_of_bitmap (in bytes) = block_size / (512 * 8)

The size of the bitmap is rounded up to the next multitude of the sector size.

Sector bitmap

In dynamic disk images the sector bitmap indicates which sectors contain data (bit set to 1) or are sparse (bit set to 0).

In differential disk images the sector bitmap indicates which sectors are stored within the image (bit set to 1) or in the parent (bit set to 0).

The bitmap is padded to a 512-byte sector boundary.

The bitmap is stored on a per-byte basis with the MSB represents the first bit in the bitmap.

References