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

Volume Shadow Snapshot (volsnap) format

As of Windows Vista the Volume Shadow Snapshot (VSS) stores persistent shadow copies on the local NTFS volume.

Overview

According to “Shadow Copies and Shadow Copy Sets” a shadow copy is a snapshot of a volume. A shadow copy can be part of a set which contains a collection of shadow copies of various volumes, taken at the same time.

Volume Shadow Snapshot (VSS) can use different providers to store shadow copies, this document focuses on the “Microsoft Software Shadow Copy provider 1.0” (GUID: b5946137-7b9f-4925-af80-51abd60b20d5) and will refer to it as volsnap. The volsnap provider stores the copies on the local volume using 16 KiB blocks.

Volsnap uses the GUID 3808876b-c176-4e48-b7ae-04046e6cc752 to identify its data or metadata files. It leverages several metadata files in “\System Volume Information” directory:

  • Volsnap catalog; stored in the metadata file named {%VOLSNAPGUID%}
  • Volsnap store; stored in the metadata file named {%GUID%}{%VOLSNAPGUID%}

Where %VOLSNAPGUID% (_VSP_DIFF_AREA_FILE_GUID) contains the volsnap identifier and %GUID% contains a time/MAC based GUID.

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

Volume header

The volsnap volume header is part of the NTFS volume header (or $Boot metadata file). The volsnap volume header data is stored at offset 7680 (0x1e00) of the volume and is at least 100 bytes in size, but presumably 512 bytes, and consists of:

OffsetSizeValueDescription
016volsnap identifier, which contains a GUID
164Format version
2040x01Record type
2480x1e00Current offset, which is relative to the start of the volume
3280x1e00Unknown (Next offset?), which is relative to the start of the volume
408Unknown (empty value)
488Catalog offset, which is relative to the start of the volume or contains 0 if there is no catalog
568Maximum size, in number of bytes or contains 0 if unbounded
6416Volume identifierwhich contains a GUID
8016Shadow copy storage volume identifier, which contains a GUID
964Unknown
100412Unknown (empty values)

Version

ValueIdentifierDescription
1Windows Vista, Windows 7
2Windows 8

Catalog

The catalog contains information about the individual stores. The catalog consists of one or more catalog blocks. Each catalog block is 16384 (0x4000) bytes in size and consists of:

  • catalog block header
  • an array of catalog entries

The volsnap catalog metadata files contains the catalog blocks stored directly after one-and-other.

If the volume does not contain a catalog when there are no snapshots (stored) but volsnap is enabled.

Catalog block header

The catalog block header is 128 bytes in size and consists of:

OffsetSizeValueDescription
016volsnap identifier, which contains a GUID
1640x01Version
2040x02Record type
248Relative (catalog block) offset, which is relative to the start of the first catalog block
328Current (catalog block) offset, which is relative to the start of the volume
408Next (catalog block) offset, which is relative to the start of the volume or contains 0 if this is the last block
4880Unknown (empty values)

Catalog entry

Each catalog entry consists of a catalog entry type 0x02. A corresponding type 0x03 is required if the shadow copy is stored in a store, which is the case as of Windows Vista.

Note that a Windows 2003 R2 catalog does not contain catalog entry type 0x03.

TODO: Determine how Windows 2003 R2 volumes store the snapshot data

The type 0x02 and type 0x03 entries are not necessarily stored directly after one-and-other and can be scattered over the catalog. For now it is assumed that entry type 0x02 must be defined before entry type 0x03.

Also these entries are not necessarily stored in order of age.

There can be unused catalog entries (of type 0x01) as well. Empty catalog entries seem to consist entirely of 0-bytes.

Unused catalog entry (type 0x01)

An unused catalog entry (type 0x01) is 128 bytes in size and consists of:

OffsetSizeValueDescription
080x01Catalog entry type
8120Unknown (empty values)

Catalog entry type 0x02

A catalog entry type 0x02 is 128 bytes in size and consists of:

OffsetSizeValueDescription
080x02Catalog entry type
88Volume size
1616Store identifier, which contains a GUID that is used in the store filename
328Unknown (Sequence number)
408Unknown (Flags?), seen 0x40 in Windows in Vista and 7 and 0x440 in Windows 8 (file backup?)
488Shadow copy creation time, which contains a FILETIME
5672Unknown (empty values)

Catalog entry type 0x03

A catalog entry type 0x03 is 128 bytes in size and consists of:

OffsetSizeValueDescription
080x03Catalog entry type
88Store block list offset, which is relative to the start of the volume
1616Store identifier, which contains a GUID, that is used in the store filename
328Store header offset, which is relative to the start of the volume
408Store block range list offset, which is relative to the start of the volume
488Store (current) bitmap offset, which is relative to the start of the volume
568NTFS (metadata) file reference
648Unknown (Allocated size)
728Store previous bitmap offset, which is relative to the start of the volume or contains 0 if not used
808Unknown (store index?)
8840Unknown (empty)

Store

The store contains information about the shadow volume; it actually contains copies of previous versions of data blocks on the volume.

The stores must be applied starting with the most recent on top of the current volume. E.g. if there are 3 stores and we want to access the state of the oldest (number 1) we must first apply the changes in store 3 over the current volume, the changes in store 2 over the resulting volume, and finally the changes in store 1 over the resulting volume.

The store consists of:

  • store header
  • store block list
  • store block range list
  • store bitmaps
  • data blocks

Store block header

The store block header is 128 bytes in size and consists of:

OffsetSizeValueDescription
016volsnap identifier, which contains a GUID
1640x01Version
204Record type
248Relative (block) offset, which is relative to the start of the store
328Current (block) offset, which is relative to the start of the volume
408Next (block) offset, which is relative to the start of the volume or contains 0 if this is the last block
488Size of store information, whichis only used in first block header and should be 0 in successive block headers
5672Unknown (empty value)

Store block record types

ValueIdentifierDescription
0x0000Unknown
0x0001Volume header
0x0002Catalog block header
0x0003Block descriptor list (Diff area table)
0x0004Store header
0x0005Unknown (Store block ranges list)
0x0006Store bitmap

Store information

The store information is stored directly after the store header.

The store information is of variable size and consists of:

OffsetSizeValueDescription
016Unknown (identifier?), which contains a GUID
1616Shadow copy identifier, which contains a GUID
3216Shadow copy set identifier, which contains a GUID
484Snapshot context
524Unknown (Provider?)
564Attribute flags
604Unknown (empty values)
642Operating machine string size, in number of bytes
66(size)Operating machine string, which contains an UCS-2 little-endian string without end-of-string character
...2Service machine string size, in number of bytes
...(size)Service machine string, which contains an UCS-2 little-endian string without end-of-string character
......Unknown (empty value)

Note that the difference between the operating machine and the service machine is currently unknown.

Store snapshot context

ValueIdentifierDescription
0x00000000VSS_CTX_BACKUP (or Backup)Standard backup context
0x00000009VSS_CTX_APP_ROLLBACK (or ApplicationRollback)Persistent shadow copy
0x0000000dVSS_CTX_CLIENT_ACCESSIBLE_WRITERS (or ClientAccessibleWriters)Read-only shadow copy created with writer involvement
0x00000010VSS_CTX_FILE_SHARE_BACKUPNon-persistent shadow copy created
0x00000019VSS_CTX_NAS_ROLLBACKPersistent shadow copy of a NAS volume
0x0000001dVSS_CTX_CLIENT_ACCESSIBLERead-only shadow copy for Shared Folders
0xffffffffVSS_CTX_ALLAll types of shadow copy are available for administrative operations

Note that the store snapshot context value is a combination of (some of the) store attribute flags.

Store attribute flags

“VSS_VOLUME_SNAPSHOT_ATTRIBUTES enumeration (vss.h)” refers to the store attribute flags as _VSS_VOLUME_SNAPSHOT_ATTRIBUTES.

ValueIdentifierDescription
0x00000001VSS_VOLSNAP_ATTR_PERSISTENTThe shadow copy is persistent across reboots
0x00000002VSS_VOLSNAP_ATTR_NO_AUTORECOVERY (or VSS_VOLSNAP_ATTR_READ_WRITE)Auto-recovery is disabled, which appears to not be shown by vssadmin
0x00000004VSS_VOLSNAP_ATTR_CLIENT_ACCESSIBLEThe specified shadow copy is a client-accessible
0x00000008VSS_VOLSNAP_ATTR_NO_AUTO_RELEASEThe shadow copy is not automatically deleted when the shadow copy requester process ends (no auto release)
0x00000010VSS_VOLSNAP_ATTR_NO_WRITERSNo writers are involved in creating the shadow copy
0x00000020VSS_VOLSNAP_ATTR_TRANSPORTABLEThe shadow copy is to be transported and therefore should not be exposed locally
0x00000040VSS_VOLSNAP_ATTR_NOT_SURFACEDThe shadow copy is not currently exposed (surfaced)
0x00000080VSS_VOLSNAP_ATTR_NOT_TRANSACTEDNot transacted, which appears to not be shown by vssadmin
0x00010000VSS_VOLSNAP_ATTR_HARDWARE_ASSISTEDIndicates that a given provider is a hardware provider
0x00020000VSS_VOLSNAP_ATTR_DIFFERENTIALIndicates that a given provider uses differential data or a copy-on-write mechanism to implement shadow copies
0x00040000VSS_VOLSNAP_ATTR_PLEXIndicates that a given provider uses a PLEX or mirrored split mechanism to implement shadow copies
0x00080000VSS_VOLSNAP_ATTR_IMPORTEDThe shadow copy of the volume was imported onto this machine
0x00100000VSS_VOLSNAP_ATTR_EXPOSED_LOCALLYThe shadow copy is locally exposed
0x00200000VSS_VOLSNAP_ATTR_EXPOSED_REMOTELYThe shadow copy is remotely exposed
0x00400000VSS_VOLSNAP_ATTR_AUTORECOVERIndicates that the writer will need to auto-recover the on post snapshot
0x00800000VSS_VOLSNAP_ATTR_ROLLBACK_RECOVERYIndicates that the writer will need to auto-recover the on post snapshot if the snapshot is used for rollback
0x01000000VSS_VOLSNAP_ATTR_DELAYED_POSTSNAPSHOTDelayed post snapshot, which is reserved for system use and appears to not be shown by vssadmin
0x02000000VSS_VOLSNAP_ATTR_TXF_RECOVERYIndicates that Transactional NTFS (TxF) recovery should be enforced during shadow copy creation, which appears to be not shown by vssadmin

Store block list

The store block list contains information about the data block ranges used by the snapshot.

The store block list is stored in blocks of 16384 (0x4000) bytes. Each store block list block consists of:

  • a store block header of type 3
  • an array of store block descriptors

Block descriptor

The block descriptor is 32 bytes in size and consists of:

OffsetSizeValueDescription
08Original data block offset, which is relative to the start of the volume
88Relative store data block offset, which is relative to the start of the store. TODO: determine if the lower bits are used for different purpose
168Store data block offset, which is relative to the start of the volume
244Flags
284Allocation bitmap, which is used if flag 0x02 is set, otherwise is should contain a value of 0

Store block descriptor flags

ValueIdentifierDescription
0x00000001Is forwarder. The absolute offset is set to 0 and the relative offset maps to the original offset of the next block
0x00000002Overlay. The block descriptor is an overlay. The allocation bitmap value contains information about the block fill
0x00000004Not used. If set, the block is ignored
0x00000008Unknown
0x00000010Unknown
0x00000020Unknown
0x00000040Unknown
0x00000080Unknown

Successive block descriptors

Note that this section is not complete yet, since the meaning of several flags is unknown.

Successive block descriptors with the same original offset are be handled differently based on their flags and position in the block list. The block list is scanned front to back.

For the new block descriptor:

* If the not used flag is set (0x04):
    * Ignore the new block descriptor

* If the overlay flag (0x02) is not set:
    * If there is a corresponding block descriptor in the reverse block list:
      Meaning that the original offset (of the new block descriptor) matches
      the relative offset of a forwarder block descriptor in the reverse block
      list.
        * Replace the original offset with that of the forwarder block
          descriptor in the reverse block list.
        * Remove the forwarder block descriptor from the reverse block list.
        * If the forwarder flag (0x01) (of the new block descriptor) is set:
            * If the original offset (of the new block descriptor) is the same
              as the relative offset:
                * Ignore the new block descriptor

* If no previous block descriptor was found:
    * Add the new block descriptor to the block list.
* Else:
    * If the overlay flag (0x02) is set:
      The new block descriptor contains an overlay. The allocation bitmap
      contains information about which part of the block is used. Every bit
      in the allocation bitmap signifies a block of 512 bytes. The LSB in
      the allocation bitmap represent the first 512 bytes in the block.
      Normally the relative offset is should not be 1, but this seems to be
      ignored if it is.

        * If an existing overlay block descriptor was defined:
            * Extended the existing overlay.
              Normally the relative offset should be 1 and the original offset
              should match that of the existing overlay block descriptor. If
              not these values seem to be ignored and the existing overlay
              is extended with the allocation bitmap in the new block descriptor.
        * Else:
            * Replace the existing block descriptor. Existing overlay block
              descriptors are applied to the new block descriptor.

* If the forwarder flag (0x01) is set:
    * If no previous reverse block descriptor was found:
        * Add the new block descriptor to the reverse block list.
    * Else:
        * Replace the existing reverse block descriptor.

Store block range list

The store block range list contains information about the data block ranges used by the store itself. It is probably used to maintain these ranges on the volume layer, since the corresponding NTFS file entry data runs are applied on the file system layer.

The store block range list is stored in blocks of 16384 (0x4000) bytes. Each store block range list block consists of:

  • a store block header of type 5
  • an array of store block range list entries

Store block range entry

The store block range entry is 24 bytes in size and consists of:

OffsetSizeValueDescription
08Store (block range start) offset, which is relative to the start of the volume
88Relative (block range start) offset, which is relative to the start of the store
168Block range size

Store bitmap

The store bitmap contains information about the allocation of blocks.

The store bitmap is stored in blocks of 16384 (0x4000) bytes. Each store bitmap block consists of:

  • a store block header of type 6
  • a bitmap

Store (current) bitmap data

Every bit in the store (current) bitmap represents a block of 16384 (0x4000) bytes, where the LSB is the first bit in a byte.

If a bit is set, the corresponding block is considered not in-use (or not allocated) by the store.

The use of this bitmap is described in the section: reading snapshot data.

Store previous bitmap data

Every bit in the store previous bitmap represents a block of 16384 (0x4000) bytes, where the LSB is the first bit in a byte.

If a bit is set, the corresponding block is not in-use (or not allocated) by the previous store.

Note that the first store can also contain a previous bitmap if an older store before it was removed.

The use of this bitmap is described in the section: reading snapshot data.

Store data block

The store data is stored in blocks of 16384 (0x4000) bytes.

Reading snapshot data

For the size of the data that will fit in the buffer:

* If the block offset has a corresponding block descriptor:
    * The data is defined by block descriptor and has a maximum size accordingly
    * If this is the active store and the block has an overlay:
        * If the overlay applies:
            * use the overlay block descriptor

    * If the forwarder flag (0x01) is set
      and there is a next store:
        * read the block from the next store using the relative store offset
    * Else:
        * read the block from the current volume using the store offset

* Else:
    * If there is a next store:
        * read the block from the next store
    * Else if the block offset has a corresponding reverse block descriptor:
        * read the block from the current volume
    * Else if the active store is the most recent (last) store
      and the block is flagged in the current bitmap
      and ( the store has no previous bitmap
            or the block is flagged in the previous bitmap ):
        * zero-fill the block
    * Else:
        * read the block from the current volume

    * Increment the block offset with the size of the block data that was read

Note that on Windows the actual behavior of unused block is undefined. A read of a corresponding block will return successful but will not alter the buffer passed to the read. For sanitation purposes Keramics will zero-fill the block.

Format edge cases and corruption scenarios

This chapter contains several corruption scenarios that have been encountered “in the wild”.

Catalog volume size out of bounds

Note that this currently considered a corruption scenario future findings may or may not prove otherwise.

The volume size of one of the catalog entries exceeds the size of the underlying volume and does not corresponds with the volume size defined by the rest of the catalog entries.

Scope snapshots

Technically scoped snaphots are a feature of volsnapa as of of Windows 8 or Windws Server 2012 and not a corruption scenario. It has been captured as a corruption scenario since it leads to some interesting side effects within file content of the snapshot.

Scope snapshots functionality can be controlled via the Windows Registry value:

Key path: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRestore
Value name: ScopeSnapshots

Per “Scoped Snapshots vmicvss Error 13 on Server 2012, Windows 8” a scope snapshot is a special volume snapshot for volsnap performance, which is mainly used by Windows critical updates. Scope means the volsnap only creates Copy on Write (Shadow) volume for the files that are involved in the updates instead of all the files on the volume.

References