Portable Virtual Disks, ZIP Alternative
Contents
Recently, I have been thinking about alternate means of transferring content to and from enterprises in the presence of network inspection technology, like host based DLP and AVs.
So I looked into what Hyper-V Virtual Drives (VHDX) could offer in terms of packaging and whether they could be used as an alternative to something like a TAR/ZIP archives, and how the defensive tech interfaces with them on a Windows machine.
VHD/VHDX is a virtual container technology employed (created/designed?) by Microsoft for it’s Hyper-V stack. The drives are normally used to support VM images and can be created as either a fixed size container or a dynamic container. Something you would normally expect as part of a normal VM provisioning and operation.
The containers can be Attached , Mounted, Initialized, and managed with common Windows disk tools. They are also portable and Self Contained. Which would mean they could be built on one machine, transfered to another one and attached to a different VM, or can be Mounted standalone as drives.
Properties like portability, self-hosting and containerization appeared to be interesting enough to warrant a deeper dive.
Hyper-V feature support. Installing Hyper-V and VHD powershell tools
To build a VHD/VHDX drive I could just used the Windows drive management GUI, but I wanted to see if I could do it in a more automated fashion, partly because there could be a time when this process needs to be executed over a remote agent, without access to RDP.
Microsoft provides a set of features for Hyper-V management. They carry the various management tools, among them Powershell cmdlets like New-VHDX which will make creation of the VHDX container easy. However, the process of installation of those features takes a significant overhead and modifies the system enough to make it somewhat “heavy” for the purpose of just creating a disk container. But you could do this like so:
Elevated>
Get-WindowsOptionalFeature -Online -FeatureName *hyper-v* | select DisplayName, FeatureName
|
|
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell
No Hyper-V support needed.
I opted for a more portable way with less overhead. Plus, I wanted to learn some of the low level storage APIs Microsoft had bult the Hyper-V Powershell tooling on.
Hyper-V’s VHD/VHDX is a type of storage, and so for a regular disk query and management, Microsoft already created a Powershell Storage module which I could import without installing Hyper-V tooling. I could leverage them for my purposes like so:
Import Storage module and use disk and image cmdlets
User>
Import-Module Storage
User>
get-disk
|
|
Getting to the API
Window’s Virtual Storage virtdisk.h describes a handful of useful functions for us to be able to create VHD/VHDX containers ourselves.
and others.
Armed with this information and some references from MSDN it is possible to code up a utility to create small size (8MB in this case) fixed container that we can populate with data.
|
|
User>
.\Vhdx.exe CreateFixedVirtualDisk c:\Temp\fixed.vhdx 8388608 0 0 0
After the container is created, there is nothing in it, but Windows still wants Admin rights to Attach the disk to the OS.
Elevated>
.\Vhdx.exe AttachVirtualDisk C:\Temp\fixed.vhdx false
Verifying newly created disk
After this has been done, the disk appears ready and recognized by the OS.
User>
|
|
We can also code up the query for the disk we have just created with Storage API, to show information similar to this:
User>
.\Vhdx.exe GetVirtualDiskInformation c:\Temp\fixed.vhdx
|
|
Initialize disk, partition
While the VHDX is now attached and recognizable by the OS, it lacks any structured partition, and has no filesystem on it. Here is how we can get around that. It is possible to code up disk partitioning and NTFS by hand with the low level API. But I thought this would take a lot more effort and learning to do so than I had time for, so let’s use utilities provided by Windows. We will continue to use PowerShell, WMI and diskpart utility.
When we ran a query on visible disks in our previous step, we could see the new disk attached to the system, of type RAW. This is disk number 1. To lay over a filesystem the disk first needs to be Initialized , and a primary partition has to be created for the filesystem to live in.
The first (and the only) logical partition on an empty disk would be also number 1. We can define some variables for both of these parameters, and initialize the disk.
User>
$disknumber = 1 ; $partnumber = 1
User>
Initialize-Disk -Number $disknumber -PartitionStyle MBR
Then we can create the sigle partition, spanning the entire 8MB VHDX.
User>
New-Partition -DiskNumber $disknumber -UseMaximumSize
|
|
Laying over NTFS and marking the drive letter
Let’s also assign the NTFS Label - Install to the FS, and choose the drive letter which will be used persistently for this volume: I
Automating diskpart requires us to pipe commands into it like so:
|
|
|
|
Optionally, mount the disk if not mounted
The OS automatically mounts the drive to the letter but if needed we can mount the drive outselves:
User>
Mount-DiskImage -ImagePath C:\Temp\fixed2.vhd
Checking the container state, location and parameters
Of course, we can use PowerShell storage module to query the mounted volume:
User>
Get-PSDrive | where { $_.Root -eq 'I:\'}
|
|
The disk can still be seen:
User>
Get-DiskImage -ImagePath C:\Temp\fixed.vhdx
|
|
We can copy files and folders into the 8MB drive, unmount it and move it across the wire to the destination system. In my tests, the mail system did not trigger a scan on the attachment which contained a filesystem with an exploit. So far, it worked well.
Target: Container mount
Let’s see what the target machine needs to work withe that container.
Mounting VHDX
Mount-DiskImage : A required privilege is not held by the client.` is the message you get when attempting to mount the container. So you need to run from the elevated prompt. However, I could mount from the explorer shell menu without elevation or UAC. This remains an item for further investigation.
Target:Elevated>
Mount-DiskImage -ImagePath C:\Temp\fixed.vhdx
Mounting without a drive letter (Elevated)
Also, it is possible to mount VHDX without the drive letter. This is useful when you want to operate in a more stealthy fashion on the system. You could still interact with the contents of the container but the drive is not assigned and so the VHDX is not in the Explorer.
Mount the drive:
Target:Elevated>
Mount-DiskImage -NoDriveLetter -ImagePath C:\Temp\fixed.vhdx
Check that it’s attached
Target>
Get-DiskImage -ImagePath C:\Temp\fixed.vhdx
|
|
Check for the mounted volume without a drive letter by using WMI searching for the NTFS Label we have assigned before:
Target>
Get-WmiObject win32_volume -Filter "Label = 'Install'" -ErrorAction Stop
|
|
We could also do this from Powershell if needed like so:
Target>
Get-Volume -FriendlyName Install
|
|
Example: Operating on resources on the hidden volume without a drive
List files:
Target>
ls -l (Get-Volume -FriendlyName 'Install' ).Path
|
|
Start execution from volume:
Target>
start (Join-Path -Path (Get-Volume -FriendlyName 'Install' ).Path -ChildPath "Hello.md.txt")
Dismountng the VHDX container
Unmounting does not require elevation and can be done with PowerShell WMI or mountvol:
Target>
Dismount-DiskImage -ImagePath C:\Temp\fixed.vhdx
Conclusion
- VHDX is an interesting way to package and transfer files under the radar. Unlike
ISOs they are not yet scanable by many defense stacks. - VHDX can be a hidden volume. Gains stealth in the operation.
- It is possible to create VHD/VHDX witjout Hyper-V tooling. The code sample will be released shortly.
- More work is needed to proof what EDRs/AVs are seeing in the containers.
Thanks for reading.