Save to My DOJO
You’d be hard-pressed to find any feature of Hyper-V that’s been around as long as Data Exchange yet received so little attention. That’s not surprising, since it’s fairly difficult to use at all, much less effectively. My goal with this post is to introduce you to this feature along with a few methods that make using it easier. At the worst, you’ll get a decent understanding of what it does. If you’re lucky, you’ll come up with a use for it.
This blog is part of a series on Hyper-V Key-Value Pair (KVP) Data Exchange
Comparing Hyper-V Data Exchange to PowerShell Direct
PowerShell Direct is a new feature that will debut with the 2016 version of Hyper-V. Sarah Cooley of Microsoft has written a couple of good reads on this feature so I won’t spend a lot of time on it. You can read her blog article and somewhat more formal documentation. The quick description is that PowerShell Direct allows you to operate PowerShell commands inside a guest by issuing them on the host. I believe that the existence of PowerShell Direct is a testament to how useful Hyper-V Data Exchange could be, if the bar to using it were lower. A few points of comparison:
- Is PowerShell Direct stronger? No; quicker, easier. There is nothing that can be done with PowerShell Direct that cannot be done by leveraging Hyper-V Data Exchange. The amount of effort to produce the same results is likely to be quite a bit higher for Hyper-V Data Exchange. However, there are things you can do with Hyper-V Data Exchange that you can’t do with PowerShell Direct.
- Flow direction. With Hyper-V Data Exchange, you can send from the guest to the host and vice versa. The push can be initiated from either side. However, it is a send-only operation. The only way you’ll know if your message was heard is if there is something on the other side that is listening and chooses to push a message in response. With PowerShell Direct, the flow direction is restricted to host-to-guest, so you can’t start the conversation from the guest’s side. However, the script that operates in the guest can return information to the host. In fact, PowerShell Direct can run interactively, so it’s a lot like PowerShell Remoting.
- Non-Microsoft guest operating system support. Unless things have changed while I wasn’t paying attention, there aren’t any PowerShell hosts on non-Microsoft systems, and if there are, I have no idea if they’ll support PowerShell Direct. Hyper-V Data Exchange is part of the Linux Integration Components. I didn’t check every distribution, but you can go to Microsoft’s master TechNet page for Linux support on Hyper-V and, on the left, choose your distribution. Look for a table item named “Key-Value Pair” (KVP) to see if you have support. The bad news is that to exploit it on Linux, you have to do real programming. I’ll provide links later that have demo code listings.
- Down-level Windows support. Hyper-V Data Exchange works on every host running a supported version of Hyper-V and any Windows guest that is running the Hyper-V Integration Services. PowerShell Direct only works when both the host and the guest are at the Windows 10/Server 2016 code base or later.
Security Implications of Hyper-V Data Exchange
The security risks presented by Hyper-V Data Exchange are extremely low for four reasons.
- Hyper-V Data Exchange is push-only. You cannot force the receiving side to do anything with the data that comes through.
- The entry and exit points for the pushed data are tightly controlled and not overridable.
- The data is transmitted in string format only (if you’re not familiar with computer data types, a string is treated as a series of unprocessable bits).
- To send data to the other side, you must have administrative rights on the source. To receive data incoming from the host on a guest, you must be at least an Authenticated User within the guest’s security context. To receive data incoming from a guest on the host, you must have administrative rights within the host’s security context.
So, while it wouldn’t be accurate to say that Hyper-V Data Exchange presents zero risk, its risk level should not keep anyone awake at night. The greatest threat would be if someone figures out a break-out attack to overcome point #2. With all of these points combined, in order for an attacker to be in a position to exploit Hyper-V Data Exchange, s/he is already in a position to carry out a different assault with considerably less effort than using KVP exchanges.
The security model for PowerShell Direct is different. When you instruct PowerShell on the host to run something on the guest, you must supply credentials that are in context of the guest with sufficient privileges to carry out your desired script. There are issues around storing these credentials securely, but they are not showstopping problems. The bigger issue, especially in comparison to Hyper-V Data Exchange, is that the operator of the host must have access to credentials that are valid on the guest. In hosted environments and in private clouds where Hyper-V administrators do not have privileges within guests and it would be unreasonable to ask clients to provide such credentials, this means that PowerShell Direct runs the risk of being dead on arrival. Hyper-V Data Exchange could still be made to work because there is no sharing of credentials.
What Can be Done with Hyper-V Data Exchange?
I certainly don’t have a comprehensive list of what this technology can be used for. I imagine that if I got ten or fifteen of you in a room with a whiteboard, we could probably fill it up in a half hour of brainstorming. Start with the functionality: you can use Hyper-V Data Exchange to send messages from a Hyper-V host to a guest and vice versa. Imagine the ways that could be useful.
Some ideas that I’ve had, including some that are in projects I’m involved:
- Host-initiated patching of guests. This is especially useful for standalone Hyper-V hosts. The host signals to all of the guests that they should start a Windows Update cycle. When they report success, they are shut down. Then the host patches and restarts. When it comes back, all the guests are brought online. This means that you don’t need to do anything fancy with staggered schedules. You can have a single defined maintenance window instead.
- Guest-initiated checkpoints. The loss of AzMan in Hyper-V Server 2012 R2 made some things harder for those shops that want to grant virtual machine control to their owners but don’t want the expense or hassle of SCVMM. Checkpointing would be one of the powers that you could resurrect.
- State information sharing. As I’ll show you in a bit, the host and the guest have access to a fair bit of information about each other. You could easily extend this to include any status updates that you want. For instance, you could let the guest know that it’s got a checkpoint.
- Run scripts. You can leverage Hyper-V Data Exchange to kick off scripts or executables. Of course, it’s not “direct” like PowerShell Direct, but you don’t have to share credentials, either. The guest can even initiate things in the host (I hope I don’t have to warn you how potentially dangerous that could be).
I should point out that in terms of raw functionality, PowerShell Remoting, especially with constrained endpoints, could be used to do all of these things as well, as long as the guest is running Windows. As with PowerShell Direct, PowerShell Remoting would be easier than KVP exchange in most cases. Hyper-V Data Exchange still has its merits. To point out a few: there is no concern about the double-hop issue, credential storage, firewall restrictions, VMs being disconnected from a network, or unauthorized message interception.
What is the Architecture of Hyper-V Data Exchange?
There are two major components of Hyper-V Data Exchange.
- The Hyper-V Virtual Machine Management service (vmms.exe) operates everything on the host side. Its functionality is exposed through WMI.
- The Hyper-V Data Exchange Service inside the guest is responsible for handling the data exchange. Its functionality is exposed through the Windows registry.
Hyper-V Data Exchange Host Operations
VMMS exposes three functions via WMI for the purpose of sending data to a guest.
- AddKvpItems. This function creates new key-value pairs for a guest. Once the pair is created, it exists until it is explicitly removed with RemoveKVPItems. From inside the guest, you can delete or change the registry key-value pair that corresponds to the created item, but it will be recreated automatically when the Hyper-V Data Exchange Service is restarted. Furthermore, checking for the existence of the KVP item on the host side will continue to show that it exists, because the client-side registry key is a view of the KVP data item, not the data item itself.
- ModifyKvpItems. This function changes the value(s) of the specified key-value pair(s). From inside the guest, you can change the value of the KVP in the representative registry key, but it will be restored to the last value set by the host when the Hyper-V Data Exchange Service is restarted. Furthermore, querying the KVP data item on the host will not return any value that was set inside the guest for the same reason explained in #1.
- RemoveKvpItems. This function removes KVP data exchange pairs from a guest. This is the only way to permanently remove the registry entries that appear inside the guest’s registry.
To determine what the extant KVP names and values for any given virtual machine are, VMMS exposes XML data structures that allow you query a guest for its KVP pairs. You can list both host-to-guest and guest-to-host pairs. These structures are read-only.
If the virtual machine is off, none of the KVPs are retrievable, even the host-to-guest KVPs that are not dependent upon the guest service. However, all of the host-to-guest KVP operations work while the guest is off. The KVPs are retrievable from the moment that the guest is started, even before the guest operating system is fully booted.
If the virtual machine is on and the Data Exchange service is disabled, all host-to-guest KVPs are retrievable and all of the host operations function. All of the guest-to-host values will be invisible.
The three host functions are case-sensitive, which I consider to be a fairly egregious design flaw because the registry is case-insensitive. As an example, you use AddKvpItems to add a KVP with a key named “SaltOrPepper” and a value of “Salt”. You then use ModifyKvpItem to change “saltorpepper” to “Pepper”. This command will fail because the KVP doesn’t exist. So, you use AddKvpItems to add a KVP with a key named “saltorpepper” and a value of “Pepper”. You will now have two KVPs, one with a key named “SaltOrPepper” and one with a key named “saltorpepper”, each with the respective values that you set. Querying the KVPs from the host side will show all entries. The guest will only show the oldest KVP with the original casing, but it will contain the value of the last case-insensitive add/modify. Likewise, RemoveKvpItems will only remove a KVP with a perfectly matched name.
Hyper-V Data Exchange Guest Operations
There are no “functions” inside the guest, per se. Everything is handled by writing to and reading from the Windows registry. When the host issues any of its three commands, the results are instantly visible in the related guest registry keys. When the guest writes to its guest-to-host keys, the host’s virtual machine WMI object immediately changes accordingly.
The root key for Hyper-V Data Exchange is HKEY_LOCAL_MACHINESOFTWAREMicrosoftVirtual Machine. If you access this key on any guest and check the permissions, you’ll see something like the following:
Authenticated Users has read-only permissions. All other entries in the list have Full Control. This screen shot was taken on a Windows Server 2012 R2 guest, which is why the sppsvc account appears. This is the account used by the Software Protection service; on Server 2012 R2 (and presumably later), the service uses Data Exchange to pass some information involving Automatic Virtual Machine Activation up to the host from the guest. You won’t see this service in the permissions list on Windows desktop or earlier Windows Server guests.
Notice that these permissions are not inherited from above this level. I don’t know what happens if you tinker with the permissions; it’s not something that I would do. All subkeys inherit the permissions that you see here.
There are four subkeys, each with designated functionality.
The Auto key contains data that is automatically created when the Hyper-V Data Exchange Service starts. The official documentation says that “This data is available to the host as intrinsic data.” There is a special section of the KVP data on the virtual machine WMI data for these entries. Some of these are retrievable via PowerShell, such as the IP addresses.
The External key is where KVP items controlled by the three host functions listed earlier will appear. When you use AddKvpItems, ModifyKvpItems, and RemoveKvpItems from the host, look for the results here. As a reminder: creating, modifying, and deleting these pairs from inside the guest is a largely fruitless endeavor. They are only views on the KVP items, not the KVP items themselves. They will be reverted to the host’s KVP item set when the Hyper-V Data Exchange Service starts. Initially, there are no KVP items in this registry key.
The Guest key is where data is sent from the guest to the host. For most systems prior to 2012 R2, this key will be empty by default. The following screenshot was taken on a 2012 R2 guest that is using Automatic Virtual Machine Activation (AVMA):
All entries that start with Security-SPP are automatically created by SPP and AVMA. These are guest-to-host informational entries only, so don’t think that tinkering with them will magically activate your guest if you aren’t running 2012 R2 Datacenter as your host. I’m not entirely certain what the SessionMonitor and Sessions entries represent.
Any entries that you create here are immediately visible on the host. If you want to send data to the host, simply create a KVP here. From the host side, they’ll show up instantly in the VM’s data structures. I’ll get to the “how” in a bit. The host cannot modify these values. You’ll notice that the SPP service has created a DWORD item; I did not test doing the same, but all items here end up in XML format so it’s still going to come out on the host side as string data.
The GuestParameters subkey contains data that is automatically generated by the host (as opposed to data generated by the AddKvpItems and ModifyKvpItems functions). Why this is a subkey of Guest and not External is one of the great mysteries of the universe, probably explainable by “Oops!” Some of these KVPs might be valuable to you right away:
As you can see, the guest knows what operating system its host is running, what the host’s name is, what the virtual machine’s container name is, and its VMID.
Are There Immediately Practical Things Involving Hyper-V Data Exchange?
Failover Cluster Manager uses KVP exchange to populate many of the fields in the VM’s Summary pane:
If you stop or disable the Hyper-V Data Exchange Service, these fields will be blank.
Hyper-V Manager, Failover Cluster Manager, and PowerShell all retrieve the guest’s IP address(es) using KVP Data Exchange.
How to Put Hyper-V Data Exchange to Use
To push and pull data from the guest side, you can manipulate the registry with RegEdit.exe or PowerShell. So, to pull all that information about the host, you can use:
Get-ChildItem -Path 'HKLM:SOFTWAREMicrosoftVirtual MachineGuest'
The Scripting Guy has a great blog series on using PowerShell with the registry. Check the Note section near the beginning of that post for links to the other articles.
This is the point where the post stops being as much fun as I’d like, because there’s no doubt that KVP Data Exchange can be tough to use. Some of the things that I’m doing with KVP Data Exchange might be a bit beyond a lot of administrators. I found PowerShell a bit too restrictive for what I wanted and instead cooked up some .Net solutions. For instance, for my synchronized host/guest patching, I have a .Net service that watches the registry for a KVP data item to change to a value that basically says “patch and shut down” and responds accordingly.
There is a decent, but not wonderful, article on TechNet that demonstrates the necessary functions. My issue with the PowerShell examples is that they’re not presented with any degree of reusability; you have to dig into them to figure out what to change to fit the KVP data items that you’ll be using. It’s not overly tough but it could have been presented better. If you’re using Linux guests, it has a C/C++ code sample for reading and manipulating the KVP IC. It’s not very well-documented and contains several unexplained magic numbers, but it should be simple enough to follow along (about as simple as useful C/C++ gets, anyway).
To end the post on a positive note, part 2 will be focused on the implementation of KVP Data Exchange, with almost a pure script/code post that contains wrappers that I’ve developed to make working with KVP Data Exchange much easier.
More in this series:
Not a DOJO Member yet?
Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!