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