VSS Carving - Pt. 1, Setup

I'm actually having some problems getting the final results in a lab, so I'm going to go through the tool and lab setup first. Hopefully this will encourage someone to point out what I'm doing wrong or a lab setup that will work.

I'm using WSL 2, Ubuntu 22.04, on a Windows 11 system. We're going to work with vss_carver, which is the only tool I'm aware of that's built for this. You can find the BlackHat presentation with more information here. (edit: part 2 is now here)

1) Necessary Repos

git clone https://github.com/libyal/libewf
git clone https://github.com/mnrkbys/libvmdk-Shift_JIS
git clone https://github.com/mnrkbys/libvshadow-vss_carver
git clone https://github.com/mnrkbys/vss_carver

The first three of these are dependancies for the fourth, vss_carver. Two of them, libvmdk* and libvshadow* are forks that have been patched to support vss_carver.

2) Build/Install the dependancies above
This is a process that I feel is documented almost too well. The author of vss_carver says to "follow the instructions to build libvshadow, libewf and libvmdk." It doesn't really say what method we're using. Are we doing a standard make install? Building static executables (.deb packages) and installing? Python-bindings sound like something we'll need...

Turns out we need to borrow a few things from a few sets of instructions. For example, we need the Debian dependancies from the top (that include autoconf and automake), but we also need the build-essential package from the GCC section and the python3-dev from the DEB section. One purpose of this is to help you skip all of that, there's a list of steps below to follow for each of the three repos.

2a) Fix libvmdk_descriptor_file.c
There's one other thing we need to do first though. One of the files in libvmdk-Shift_JIS is... broken? When we try to build it (the python3 setup.py build step below), we get a bunch of errors that look something like this

libvmdk/libvmdk_descriptor_file.c:994:41: error: stray ‘\302’ in program
  994 |                                           && ( value[ 0 ] == 'S' )
      |                                         ^

followed by an exit code 1 (build failed). As always StackOverflow comes to the rescue. We're going to change into the directory holding that file and use the suggested tr fix. I think some Windows characters escaped into the Linux world, the tr fix isn't the "surgical" approach, but I've examined the before and after, and it doesn't appear to make any unwanted changes.

~/libvmdk-Shift_JIS$ cd libvmdk
~/libvmdk-Shift_JIS/libvmdk$ mv libvmdk_descriptor_file.c libvmdk_descriptor_file.c.old
~/libvmdk-Shift_JIS/libvmdk$ tr -cd '\11\12\15\40-\176' < libvmdk_descriptor_file.c.old > libvmdk_descriptor_file.c
~/libvmdk-Shift_JIS/libvmdk$ cd ..
~/libvmdk-Shift_JIS/$

2b) Build/Install each
First, install all the necessary dependencies

sudo apt install git autoconf automake autopoint libtool pkg-config flex bison build-essential python3-dev

Now go into each of the three dependancy repos and run the following:

./synclibs.sh
./autogen.sh
./configure --enable-python
python3 setup.py build
sudo python3 setup.py install

Note I did change the python to python3 here. Not sure it's strictly necessary, but I wanted to make sure I was calling the right thing.

If we now go into our vss_carver repo and run python3 vss_carver.py -h, we should get the help menu and no missing dependancy messages. You'll likely have to chmod 754 this file to be able to run it, as it doesn't have execute permissions stright from the repo.

3) Lab environment setup
Now I need a disk image to run vss_carver against. I setup a Server 2019 VM in VMware Workstation Pro 16 and used the option to store the disk in a single file, just so I wouldn't have to reassemble it later. My setup generally went like this:

  • Create a test file on the desktop
  • Enable VSS, which will create an initial shadow.
  • Confirm the shadow exists with vssadmin list shadows
  • Delete the file using sdelete (I want to confirm that I can find it in a shadow, not in slack space)
  • Delete the shadow using vssadmin delete shadows /all /quiet
  • Confirm the shadow is deleted using vssadmin list shadows
  • Shut down the machine.

I should now have a deleted file within a deleted shadow that I should be able to carve for.

4) Disk prep
I moved my .vmdk file to another directory. I need to find the offset to my primary drive. The easiest way I found to do this was to use qemu to convert the vmdk to a raw disk, and then fdisk -l to get the information. Running fdisk -l against the vmdk will give you the sector size, but not much else.

qemu-img convert -p -f vmdk -O raw /mnt/c/vss_test/server2019.vmdk /mnt/c/vss_test/server2019.raw

-p gives us the percent done. -f is our input format, -O is our output format. Follwed by the input file and output file.

fdisk -l /mnt/c/vss_test/server2019.raw

Now we multiply the sector bytes (512) by the start location of our primary disk (1259520), and we get an offset of 644874240.

fdisk

5) Recovery Efforts
Here's were it kind of goes sideways. I should be able to carve out my shadow, but I always end up with "Not found VSS volume header." This is returned quickly too, it feels like it's not even trying to carve anything.

nullsec@ISAAC:~/vss_carver$ python3 vss_carver.py -t raw -o 644874240 -i /mnt/c/vss_test/server2019.raw -c /mnt/c/vss_test/catalog -s /mnt/c/vss_test/store
vss_carver 20200312
==================================================
Stage 1: Checking if VSS is enabled.
Volume size: 0xed9800000
Not found VSS volume header.

vss_carver

  • I have managed to find a shadow that was not deleted. This was in the wild and on another machine though.
  • So lets try a disk with a live shadow on it in the lab environment. No luck
  • Maybe the VSS format has changed? I tried Server 2012 R2, no luck.
  • Maybe something with the virtual disk/snapshot changed? I tried using vmware-vdiskmanager.exe to combine any disks in that directory (enough though it should be one disk, I do see another .vmdk, likely a result of a snapshot). No luck here either.
  • Maybe it's the vmdk to raw conversion process. Same offset should work, so I tried that against the vmdk. No luck.

There's a ton of other things that could go wrong. Maybe it's because the disks are thin-provisioned? Maybe it's something with being stored on an SSD (trim/wear leveling of deleted files)? Maybe I need to let the snapshot "bake" for a while before I delete it? There's a ton of stuff I could be doing wrong, or that's with my tool install/setup, or wrong with my lab. Until I get a good test case though, it's hard to tell what.

I posted an issue here, in the hopes that the author would respond. If they do, hopefully it will give me something else to go on.