Tuesday, January 15, 2008

VirtualBox and forensics tools

I got a great question from Ted over at F3 about how to investigate a virtualbox virtual machine after the last entry.

As Ted pointed out, currently, forensics tools can't interpret a vdi file. Most can however work with a vmware vmdk file. As it turns out a vdi file isn't all that different truth be told. It looks like Innotek simply adds metadata to the disk image in the form of a header.

The required information (pay attention tool authors) is in VDICore.h in the OSE version of VirtualBox. It's located here in the unpacked tarball: src/VBox/Devices/Storage/VDICore.h The proper structs are available to parse the information.

For the investigators there are options....

1) Use vditool. It's available here. Be aware it's a 32bit binary and will not run on a 64bit system without some library configuration. **EDIT** I should point out that I had virtualbox installed on my system so the libraries were in the right place.

Here's some usage options.

hogfly@blackwootsy:/backups$ ~/vditool
vditool Copyright (c) 2004-2005 InnoTek Systemberatung GmbH.

Usage: vditool [Params]
Commands and params:
NEW Filename Mbytes - create new image;
DD Filename DDFilename - create new image from DD format image;
CONVERT Filename - convert VDI image from old format;
DUMP Filename - debug dump;
RESETGEO Filename - reset geometry information;
COPY FromImage ToImage - make image copy;
COPYDD FromImage DDFilename - make a DD copy of the image;
SHRINK Filename - optimize (reduce) VDI image size.

Ok sweet, this tool will do what we need it to do. Let's take a look at the .vdi and parse the header.

hogfly@blackwootsy:/backups$ ~/vditool DUMP 2Kbase.vdi
vditool Copyright (c) 2004-2005 InnoTek Systemberatung GmbH.

Dumping VDI image file="2Kbase.vdi" into the log file...
Log created: 2008-01-15T20:06:23.106689000Z
Executable: /home/hogfly/vditool
Arg[0]: /home/hogfly/vditool
Arg[1]: DUMP
Arg[2]: 2Kbase.vdi
--- Dumping VDI Disk, Images=1
Dumping VDI image "2Kbase.vdi" mode=r/o fOpen=1 File=00000003
Header: Version=00010001 Type=2 Flags=0 Size=10737418240
Header: cbBlock=1048576 cbBlockExtra=0 cBlocks=10240 cBlocksAllocated=10240
Header: offBlocks=512 offData=41472
Header: Geometry: C/H/S=20805/16/63 cbSector=512 Mode=3
Header: uuidCreation={8f8cc7fa-1538-4f2c-54ab-522e120fed0d}
Header: uuidModification={077a7a1f-9598-43f5-2189-1f3f5d105664}
Header: uuidParent={00000000-0000-0000-0000-000000000000}
Header: uuidParentModification={00000000-0000-0000-0000-000000000000}
Image: fFlags=00000000 offStartBlocks=512 offStartData=41472
Image: uBlockMask=000FFFFF uShiftIndex2Offset=20 uShiftOffset2Index=20 offStartBlockData=0
The operation completed successfully!

Some information:

Header Type=2 means this is a fixed disk. It's at offset 76 (0x4C). 1 is a dynamic disk. 2 is fixed.

Offset 344 supposedly indicates the offset location of the start of the data for the virtual machine. It's a 32bit int. In my case it's OffData=41472. This is the part I've bolded because I discovered the partition actually began at offset 73728. 41472 is where the MBR starts. This is important and I'll show why soon.

CHS info can be found: at offsets: 348,352,356

The uuid's containing data in my case begin at offset 392 and end at 423. These are created using libuuid. I've not yet figured out how to reverse the timestamp to unix epoch which is what they are representations of.

At this point we have more than enough information to get us started so we can analyze the image.

We can Mount the vdi for offline analysis in linux:

mount -t ntfs -o ro,noatime,noexec,loop,offset=73728 /backups/2Kbase.vdi /tmp/vdi

We now have a viable windows partition to look at.

hogfly@blackwootsy:/backups$ sudo ls /tmp/vdi
arcldr.exe CONFIG.SYS NTDETECT.COM System Volume Information
arcsetup.exe Documents and Settings ntldr WINNT
AUTOEXEC.BAT IO.SYS pagefile.sys
boot.ini MSDOS.SYS Program Files

3) In X-ways it's as easy as finding the partition.

4) One other way that's perhaps more portable is to use vditool to carve out the raw disk image. There are many ways to slice this one..but I'll use vditool.

hogfly@blackwootsy:/backups$ ~/vditool COPYDD 2Kbase.vdi 2Kbase.dd
vditool Copyright (c) 2004-2005 InnoTek Systemberatung GmbH.

Copying VDI image file="2Kbase.vdi" to DD file="2Kbase.dd"...
The operation completed successfully!

Ok, sweet now I have a dd copy of the vdi..but wait let's take a closer look.

hogfly@blackwootsy:/backups$ ls -l 2Kbase.*
-rw------- 1 hogfly hogfly 10737418240 2008-01-15 08:48 2Kbase.dd
-rw------- 1 hogfly hogfly 10737459712 2008-01-15 08:48 2Kbase.vdi

Go ahead and subtract the two image sizes..what do you get? How about 41472 which is the offset for the beginning of the data on my virtual disk.

Hopefully this helps someone when they have to analyze a VirtualBox virtual machine. Thanks for the question Ted.


Murali said...

thank you for your post. you helped me retrieve some important files that were in my office computer.

There is one thing i didnt understand. Why do we have to add 32256 to the offset to get it working??? Is this a constant we have to add, or does it vary from machine to machine?
ain the disk example, (and even my virtual disk) is fixed disk, do we have to do anything else if we use dynamic disk??

hogfly said...

I'm glad it helped. Offset 32256 is a constant if and only if the partition you're trying to mount begins at sector 63 and the sector size is 512 bytes.

This method will not work for dynamic disks. I've not yet worked with them, although I intend to.

Anonymous said...

To work with a variable sized vdi file, you have to dump it to a dd file first (COPYDD); this will create a fixed size dump that then can be opened on a loop device. The variable sized file does not allow mounting as the fs driver needs to see the expected disk size.

Anonymous said...

Just to add to the last comment... to work with a variable sized disk, you do use the COPYDD command, however you must still ensure you use the offset=32256 flag in the mount command. As said in the article, the first 32256 bytes is the MBR, and mount doesn't recognise this. I have done this successfully with ntfs.

# vditool COPYDD my.vdi my.dd
# sudo mount -t ntfs -o ro,noatime,noexex,loop,offset=32256 my.dd ./my_dir