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 version 2 (VHDX) image format

The Virtual Hard Disk version 2 (VHDX) 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

A VHDX image file consist of:

  • file header
  • 2x image headers
  • 2x region tables
  • log or metadata journal
  • block allocation table (BAT) region
  • metadata region
    • metadata table
    • metadata items
  • image (content) data

The elements are stored in 64 KiB (65536 bytes) aligned blocks

Characteristics

CharacteristicsDescription
Byte orderlittle-endian
Date and time valuesN/A
Character stringsUCS-2 little-endian, which allows for unpaired Unicode surrogates such as "U+d800" and "U+dc00"

The number of bytes per sector is 512 or 4096 depending on the logical sector size.

File hader

The file header of (file type identifier) is 64 KiB (65536 bytes) in size and consists of:

OffsetSizeValueDescription
08"vhdxfile"Signature
8512Creator application and version, with contains an UCS-2 little-endian string with end-of-string character
52065016Unknown (reserved)

Image header

The image header is 4 KiB (4096 bytes) in size and consists of:

OffsetSizeValueDescription
04"head"Signature
44Checksum
88Sequence number
1616File write identifier, which contains a GUID
3216Data write identifier, which contains a GUID
4816Log identifier, which contains a GUID
642Log format version
6621Format version
684Log size, which according to MS-VHDX this value must be a multitude of 1 MiB
728Log offset, which according to MS-VHDX this value must be a multitude of 1 MiB and greater than or equal to 1 MiB
8040160Unknown (reserved), which according to MS-VHDX this value must be set to 0

Checksum calculation

The CRC32-C algorithm with the Castagnoli polynomial (0x1edc6f41) and initial value of 0 is used to calculate the checksum.

The checksum is calculated over the 4 KiB bytes of data of the image header, where the image header checkum value is considered to be 0 during calculation.

Region table

The region table is stored in a block of 64 KiB (65536 bytes) and consists of:

  • region table header
  • 0 or more region table entries
  • Unknown (reserved)

TODO: determine if 0 entries is actually supported

Region table header

The region table header is 16 bytes in size and consists of:

OffsetSizeValueDescription
04"regi"Signature
44Checksum
84Number of table entries, which according to MS-VHDX this value must be less than or equal to 2047
1240Unknown (reserved), which according to MS-VHDX this value must be set to 0

The CRC32-C algorithm with the Castagnoli polynomial (0x1edc6f41) and initial value of 0 is used to calculate the checksum.

The checksum is calculated over the 64 KiB bytes of data of the region table where the image header checkum value is considered to be 0 during calculation.

Region table entry

The region table entry is 32 bytes in size and consists of:

OffsetSizeValueDescription
016Region type identifier, which contains a GUID
168Region data offset, which contains an offset relative to the start of the file. According to MS-VHDX this value must be a multitude of 1 MiB and greater than or equal to 1 MiB
244Region data size, which according to MS-VHDX this value must be a multitude of 1 MiB
284Is required flag, which contains 1 to indicate the region type needs to be supported

Region type identifiers

ValueIdentifierDescription
2dc27766-f623-4200-9d64-115e9bfd4a08Block allocation table (BAT) region
8b7ca206-4790-4b9a-b8fe-575f050f886eMetadata region

Metadata region

The metadata region contains:

  • metadata table
  • metadata items

Metadata table

The metadata table is stored in a block of 64 KiB (65536 bytes) and consists of:

  • metadata table header
  • 0 or more metadata table entries
  • Unknown (reserved)

TODO: determine if 0 entries is actually supported

Metadata table header

The metadata table header is 32 bytes in size and consists of:

OffsetSizeValueDescription
08"metadata"Signature
820Unknown (reserved), which according to MS-VHDX this value must be set to 0
102Number of table entries, which according to MS-VHDX this value must be less than or equal to 2047
12200Unknown (reserved), which according to MS-VHDX this value must be set to 0

Metadata table entry

The metdata table entry is 32 bytes in size and consists of:

OffsetSizeValueDescription
016Metadata item identifier, which contains a GUID
164Metadata item offset, which contains an offset relative to the start of the metadata region. According to MS-VHDX this value must be greater than 64 KiB
204Metadata item size
248Unknown

TODO: describe last 8 bytes

ValueIdentifierDescription
0x00000001IsUser
0x00000002IsVirtualDisk
0x00000004IsRequired

Metadata items

Metadata item identifiers

ValueIdentifierDescription
2fa54224-cd1b-4876-b211-5dbed83bf4b8Virtual disk size
8141bf1d-a96f-4709-ba47-f233a8faab5fLogical sector size
a8d35f2d-b30b-454d-abf7-d3d84834ab0cParent locator
beca12ab-b2e6-4523-93ef-c309e000c746Virtual disk identifier
caa16737-fa36-4d43-b3b6-33f0aa44e76bFile parameters
cda348c7-445d-4471-9cc9-e9885251c556Physical sector size

File parameters metadata item

The file parameters metadata item is 8 bytes in size and consists of:

OffsetSizeValueDescription
04Block size, which according to MS-VHDX this value must be a power of 2 and greater than or equal to 1 MiB and not greater than 256 MiB
4.01 bitBlocks remain allocated flag, which is used to indicate the file is a fixed-size image
4.11 bitHas parent flag, which indicates if the VHDX file contains a differential image that has a parent image
4.230 bits0Unknown (reserved), which according to MS-VHDX this value must be set to 0

Logical sector size metadata item

The logical sector size metadata item is 4 bytes in size and consists of:

OffsetSizeValueDescription
04Logical sector size, which according to MS-VHDX this value must be either 512 or 4096

Parent locator metadata item

The parent locator metadata item is of variable size and consits of:

  • parent locator header
  • 0 or more parent locator entry
  • parent locator key and value data

TODO: determine if 0 entries is actually supported

Parent locator header

The parent locator header is 20 bytes in size and consists of:

OffsetSizeValueDescription
016Parent locator type indicator, which contains the GUID: b04aefb7-d19e-4a81-b789-25b8e9445913
1620Unknown (reserved), which according to MS-VHDX this value must be set to 0
182Number of entries (or key-value pairs)
Parent locator entry

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

OffsetSizeValueDescription
04Key data offset, which contains the offset relative from the start of the parent locator header
44Value data offset, which contains the offset relative from the start of the parent locator header
82Key data size
102Value data size
Parent locator key and value data

A parent locator key or value is stored as UCS-2 little-endian string without end-of-string character.

Known keys are:

ValueDescription
absolute_win32_pathThe value contains an absolute drive Windows path "\?\c:\file.vhdx"
parent_linkageThe value contains a string of a GUID. This GUID should correspond to the data write identifier of the parent image
parent_linkage2The value contains a string of a GUID
relative_pathThe value contains a relative Windows path "..\file.vhdx"
volume_pathThe value contains an absolute volume Windows path with "\?\Volume{%GUID%}\file.vhdx"

Physical sector size metadata item

The physical sector size metadata item is 4 bytes in size and consists of:

OffsetSizeValueDescription
04Physical sector size, which according to MS-VHDX this value must be either 512 or 4096

Virtual disk identifier metadata item

The virtual disk identifier metadata item is 16 bytes in size and consists of:

OffsetSizeValueDescription
016Virtual disk identifier, which contains a GUID

Note that in contrast to VHD (version 1) the virtual disk identifier does not change between a differential image and its parent. The data write identifier seems to be used instead.

Virtual disk size metadata item

The virtual disk size metadata item is 8 bytes in size and consists of:

OffsetSizeValueDescription
08Virtual disk size

Block allocation table (BAT) region

The block allocation table (BAT) region contains the block allocation table. The entries of this table describe the location of either blocks containing image content data (or payload blocks) or blocks containing a sector bitmap.

The size of an individual sector bitmap block is 1 MiB which allows for 2^23 sectors to be represented by the bitmap.

Block allocation table (BAT) entries are grouped in chunks. The size of a chunk can be calculated as following:

number_of_entries_per_chunk = (2^23 * logical_sector_size) / block_size

The block allocation table (BAT) consists of:

  • one or more chunks containing:
    • number of entries per chunk x BAT entry describing image content data
    • 1 x BAT entry describing the a sector bitmap

Unused BAT entries are filled with 0-byte values.

The block allocation table (BAT) of:

  • a fixed-size image does not contain sector bitmap entries;
  • a dynamic-size image does contain sector bitmap entries, although according to MS-VHDX are not used;
  • a differential image does contain sector bitmap entries.

Block allocation table (BAT) entry

The block allocation table (BAT) entry is 64 bits in size and consists of:

OffsetSizeValueDescription
0.03 bitsBlock state
0.317 bits0Unknown (reserved), which according to MS-VHDX this value must be set to 0
2.444 bitsBlock offset, which contains the offset relative from the start of the file as a multitude of 1 MiB

Block states

Payload block states

ValueIdentifierDescription
0PAYLOAD_BLOCK_NOT_PRESENTBlock is new and therefore not (yet) stored in the file
1PAYLOAD_BLOCK_UNDEFINEDBlock is not stored in the file
2PAYLOAD_BLOCK_ZEROBlock is sparse and therefore filled with 0-byte values
3PAYLOAD_BLOCK_UNMAPPEDBlock has been unmapped
6PAYLOAD_BLOCK_FULLY_PRESENTBlock is stored in the file
7PAYLOAD_BLOCK_PARTIALLY_PRESENTBlock is stored in the parent

Sector bitmap block states

ValueIdentifierDescription
0SB_BLOCK_NOT_PRESENTBlock is new and therefore not (yet) stored in the file
6SB_BLOCK_PRESENTBlock is stored in the file

Sector bitmap

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 stored in a 1 MiB block.

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

Log (metadata journal)

TODO: complete section

The log serves as metadata journal is of variable size and consist of contiguous circular (ring) buffer that contains log entries.

Log entry

TODO: complete section

4 KiB (4096 bytes) in size

Log entry header

TODO: complete section

Zero descriptor

TODO: complete section

Data descriptor

TODO: complete section

Data sector

TODO: complete section

References