Jan's Blog on DFIR, TI, REM,....

# Analyzing VM images

<2021-06-20>

## tl;dr:

Virtualization is everywhere nowadays. So when you have to perform an analysis of an incident, you often come across virtual hard disks in the form of sparsely allocated VMDKs, VDIs, QCOW2s and the like. To inspect the data in the virtual machine images you have several options to do so. guestmount is a helpful tool to perform a logical inspection of the fileystem, while qemu-nbd is a good choice, if you want to work on a raw bock device without having to convert a sparsely allocated virtual disk into a raw image or to rely on proprietary software.

## Motivation

Popular open source forensic analysis suites like Sleuthkit can not handle sparsely allocated VMDKs and several other virtual machine image formats, like VDI, QCOW2 etc. Since virtualized systems are part of almost every investigation, it is often needed to perform a conversion of some kind, which can be cumbersome, if you decide to convert each and every piece of evidence to raw-format or .E01. Furthermore you might depend on proprietary tools like vmware-mount, which are not freely available.

Maybe you heard, that Sleuthkit can handle VMDKs. This is partly true, since it can handle only the so-called flat format and not sparsely allocated VMDKs. To check, whether you could ingest the .vmdk-file in question, you have to look at the so-called text descriptor within the .vmdk, which describes the layout of the data in the virtual disk 1 and starts at Offset 0x200. It may look like the following snippet:

# Disk DescriptorFile
version=1
CID=7cecb317
parentCID=ffffffff
createType="monolithicSparse"
# Extent description
RW 4194304 SPARSE "NewVirtualDisk.vdi.vhd.vmdk"
# The disk Data Base
<snip>


Within this descriptor you have to look for the "createType"-field, which specifies, whether the disk is flat or monolithic and if it was sparsely allocated or if it is of fixed size. To conveniently check for this, use the following command, which greps for the string within the byte-range of the offsets 0x200 and 0x400:

xxd -s 0x200 -l 0x200 file.vmdk | xxd -r | strings | grep -i sparse


If it is a sparsely allocated .vmdk-file, it is recommended by some renowned practitioners in the forensics community to use qemu-img to convert it then to a raw image 2 and be able to conduct a proper post-mortem-analysis.

# Check the size of the resulting raw image
cat evidences/srv.ovf | grep '<Disk'
# Convert .vmdk to raw
qemu-img convert evidences/srv.vmdk ./srv.dd


While this works well, it is a time- as well space-consuming endevour. So I have been looking for alternative solutions.

## Inspecting sparsely-allocated virtual disks without conversion

### Using vmware-mount

One solution is – as already mentioned above – the usage of VMWare's tool vmware-mount, which creates a flat representation of the disk at a given mount point, when the -f-option is specified. This approach, however, requires the use of a piece of proprietary software named Virtual Disk Development Kit (VDDK), which is not easily available (and of coursee not in Debians package archives ;)).

### Using guestmount for content inspection

If you only need to look and extract certain files, guestmount of the libguestfs-library is a a handy solution. Libguestfs is the library for accessing and modifying virtual machine images 3. After installing it via the package manager of your distribution, you can inspect the partitions inside the virtual machine image in question by using virt-filesystems. Once you identified the partition of your interest, you can mount it via guestmount – read-only of course – on a mount point of your forensics workstation. Alternatively you might explore it interactively with guestfish – the so-called guest filesystem shell. (If you install libguestfs-rescue, the tool virt-rescue comes already with TSK installed, but it is a bit cumbersome to use imho).

So you might use the following commands to get started with guestmount:

# Install it via apt
sudo apt-get install libguestfs-tools  # Debian/Ubuntu
# Check which partition to mount
virt-filesystems -a disk.img -l
# Mount it via guestmount on a mount point of the host
guestmount -a evidences/srv.vmdk -m /dev/sda2 --ro ./mntpt
# Alternatively: Inspect it interactively with guestfish
guestfish --ro -a evidences/srv.vmdk -m /dev/sda2


At times just accessing the filesystem might not be enough. If this is the case, you might look at the following solution.

### Using qemu-nbd

To access the sparsely allocated virtual disk image as a raw device, it is advisable to use qemu-nbd, which is the QEMU Disk Network Block Device Server. Install the containing package named qemu-utils via apt and load the NBD-kernel module via modprobe, then use qemu-nbd to expose the virtual disk image as a read-only block device – in the following example /dev/nbd0. Then you can work on it with Sleuthkit or your favorite FS forensics tool.

# Install qemu-nbd
sudo apt install qemu-utils
sudo modprobe nbd
# Check, that it was loaded
sudo lsmod | grep nbd
# Use QEMU Disk Network Block Device Server to expose .vmdk as NBD
# Note: make it read-only !
sudo qemu-nbd -r -c /dev/nbd0 evidences/srv.vmdk
# Check partition table
sudo mmls /dev/nbd0
# Access partitions directly
sudo fsstat /dev/nbd0p2
# Disconnect NBD
sudo qemu-nbd -d /dev/nbd0
# Remove kernel module
sudo rmmod nbd


IMHO this is the quickest and most elegant way of performing post-mortem-analysis or triage on a sparsely allocated virtual machine disk image.

There might be some alternatives

Another interesting solution is vminspect, which is a set of tools developed in Python for disk forensic analysis. It provides APIs and a command line tool for analysing disk images of various formats, whereas it relies on libguestfs. It focuses on the automation of virtual disk analysis and on safely supporting multiple file systems and disk formats. On the one hand it is not as generic as the previous presented solutions, but it offers some specific capabilities helpful in forensic investigations, like extracting event timelines of NTFS disks or parsing of Windows Event Log files. To make it tasty for you and get you going, refer to the following command-snippets taken from VMInspect's documentation 4:

# Compares to registries
vminspect compare --identify --registry win7.qcow2 win7zeroaccess.qcow2
#Extract the NTFS USN journal
vminspect usnjrnl_timeline --identify --hash win7.qcow2
# Parse eventlos
vminspect eventlog win7.qcow2 C:\\Windows\\System32\\winevt\\Logs\\Security.evtx


If you have know a better way of doing this or want to leave any notes, proposals or comments, please contact me under ca473c19fd9b81c045094121827b3548 at digital-investigations.info.