Skip to content

Examples

Joachim Metz edited this page Dec 1, 2020 · 10 revisions

Correcting truncated Windows live volume images

Some imaging tools omit the last cluster block when they are used to create an image of a live volume on Windows. This means the image is technically truncated (cut short). In the case of a volume with NTFS this means that the backup volume header is missing from the image. Tooling that requires the volume to be complete like libvshadow will fail when attempting to open such a corrupted image.

bfoverlaymount (with the help of libbfoverlay) allows to create a virtual full version of the image.

Test data

Test file: ntfs_4096_with_2_vss.vhd was created with the scripts of the vss-specimens project.

fdisk -l ntfs_4096_with_2_vss.vhd
Disk ntfs_4096_with_2_vss.vhd: 128 MiB, 134218240 bytes, 262145 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x12345678

Device                    Boot Start    End Sectors   Size Id Type
ntfs_4096_with_2_vss.vhd1      128   260095  259968 126.9M  7 HPFS/NTFS/exFAT

# The volume offset is sector 128 x 512 bytes per sector = 65536 bytes
# The size of the partition/volume is 259968 sectors x 512 bytes per sector = 133103616 bytes

dd if=ntfs_4096_with_2_vss.vhd of=truncated_volume.raw skip=$(( ( 128 * 512 ) / 512 )) bs=512 count=$(( ( ( 259968 * 512 ) - 4096 ) / 512 )) 
vshadowinfo truncated_volume.raw
vshadowinfo 20201119

Unable to open: truncated_volume.raw.
libvshadow_ntfs_volume_header_read_file_io_handle: unable to read NTFS volume header data.
libvshadow_volume_open_read_ntfs_volume_headers: unable to read backup NTFS volume header.
libvshadow_volume_open_read: unable to read NTFS volume headers.
libvshadow_volume_open_file_io_handle: unable to read from file IO handle.
info_handle_open_input: unable to open input volume.

Creating a full volume image

Overlay descriptor file

# basic file overlay descriptor file
layer: offset=0 size=133103616
layer: offset=0 size=133099520 file="truncated_volume.raw" file_offset=0
layer: offset=133103104 size=512 file="truncated_volume.raw" file_offset=0
  • The first layer describes the full volume, which is 133103616 bytes in size. Since it does not specify a file it will be filled with 0-byte values.
  • The second layer describes the truncated volume image
  • The third layer describes the NTFS volume header in the truncated volume image that is mapped to the offset of the last sector of the volume where the backup NTFS volume header typically resides (volume size - sector size).

The 3584 bytes between the end of the truncated image (offset 133099520) and the start of the backup NTFS volume header (offset 133103104) will be emulated by the first layer as 0-byte values.

The third layer alternatively can be described using an offset relative to the end of the first layer namely:

layer: offset=-512 size=512 file="truncated_volume.raw" file_offset=0

Expose a virtual full volume image

To expose a virtual full volume image run bfoverlaymount with the overlay descriptor file

mkdir -p fuse && bfoverlaymount truncated_volume.overlaydescriptor fuse
bfoverlaymount 20201201

The virtual full volume image is now available as fuse/bfoverlay1

When vshadowinfo is run on the full image it now shows the information about the stores

vshadowinfo fuse/bfoverlay1 
vshadowinfo 20201119

Volume Shadow Snapshot information:
	Number of stores:	2

Store: 1
   ...

Recovering deleted VSS snapshots

vss_carver can recreate VSS catalog and stores of deleted VSS snapshots. However libvshadow has no built-in functionality to overlay the recreated VSS catalog and stores on the original image.

Making a "patched" version of the image can be space and time consuming. However bfoverlaymount (with the help of libbfoverlay) allows to create a virtual "patched" version of the image.

Test data

Test file: ntfs_4096_with_2_vss.vhd was created with the scripts of the vss-specimens project.

# The volume offset is sector 128 x 512 bytes per sector = 65536 bytes
# The VSS catalog offset is 8208384 (0x007d4000)

# Make a copy of the VSS catalog
dd if=ntfs_4096_with_2_vss.vhd of=vss_catalog.bin skip=$(( ( ( 128 * 512 ) + 0x007d4000 ) / 512 )) bs=512 count=2

# Overwrite the VSS catalog with 0-byte values
dd if=/dev/zero of=ntfs_4096_with_2_vss.vhd seek=$(( ( ( 128 * 512 ) + 0x007d4000 ) / 512 )) bs=512 count=2 conv=notrunc

vshadowinfo will indicate it cannot find the catalog header identifier.

vshadowinfo -o $(( 128 * 512 )) ntfs_4096_with_2_vss.vhd

Unable to open: ntfs_4096_with_2_vss.vhd.
libvshadow_io_handle_read_catalog_header_data: invalid catalog header identifier.
libvshadow_io_handle_read_catalog: unable to read catalog block header.
libvshadow_volume_open_read: unable to read catalog.
libvshadow_volume_open_file_io_handle: unable to read from file IO handle.
info_handle_open_input: unable to open input volume.

Creating a "patched" image

Overlay descriptor file

# basic file overlay descriptor file
layer: offset=0 size=133103616 file="ntfs_4096_with_2_vss.vhd" file_offset=65536
layer: offset=8208384 size=1024 file="vss_catalog.bin" file_offset=0
  • The first layer describes the partition that contains the VSS, which is 133103616 bytes in size and starts at file offset: 65536.
  • The second layer describes the overlay of the VSS catalog

Expose a virtual "patched" image

To expose a virtual "patched" image run bfoverlaymount with the overlay descriptor file

mkdir -p fuse && bfoverlaymount vss.overlaydescriptor fuse
bfoverlaymount 20201201

The virtual "patched" image is now available as fuse/bfoverlay1

When vshadowinfo is run on the "patched" image it now shows the information about the stores

vshadowinfo fuse/bfoverlay1 
vshadowinfo 20201119

Volume Shadow Snapshot information:
	Number of stores:	2

Store: 1
   ...