A Blog on digital investigations

Analyzing VM images

<2021-06-20>

tl;dr:

Virtualization is everywhere nowadays. So when you have to analyze 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 file system, and qemu-nbd is a good choice to work on a raw block device without having to convert a sparsely allocated virtual disk into a raw image or 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 piece of evidence into raw or EWF format. Furthermore, you might depend on proprietary tools like vmware-mount, which are not freely available.

Maybe you heard that Sleuthkit is able to work with 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 attribute, use the following command that 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 as a space-consuming endeavor. So I have been looking for alternative solutions.

Inspecting sparsely-allocated virtual disks without conversion

Using vmware-mount

As already mentioned above, one solution is using VMWare's tool vmware-mount, which creates a so-called 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 course not in Debian's package archives ;)).

Using guestmount for content inspection

If you only need to look and extract specific 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 is already shipped already with TSK installed, but it is a bit cumbersome to use.)

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 a 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 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 file system forensics tool.

# Install qemu-nbd
sudo apt install qemu-utils
# Load NBD kernel module
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

To me, this seems to be 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

Specific tasks with vminspect

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 analyzing 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 that are helpful in forensic investigations, like extracting event timelines of NTFS disks or parsing Windows Event Log files. To make it tasty for you and get you going, refer to the following snippet of commands 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

Footnotes:

Tags: DFIR