Available in Windows 10 and the Windows Server 2016 Technical Preview, there is a new feature of PowerShell and Hyper-V that enables you to connect to guest machines that lack network access: PowerShell Direct. The standard PSSession cmdlets along with Invoke-Command now offer a VMID and VMName parameter. Simply run any of these commands as you normally would with a remote machine and you have access to a remoting session to the guest. It worked perfectly for me.

powershellDirect

After playing with it a bit, I was curious to find out just how it works. The first place I looked was in the guest where there is a new service installed called the “Hyper-V VM Session Service” (vmicvmsession). It’s initially stopped but when I attempted to connect via Enter-PSSession from the host machine, the service was automatically started.

On the client end, I popped open .NET Reflector and dug into the Enter-PSSession cmdlet. This cmdlet can be found in the System.Management.Automation.dll. This is where you will see the new properties for VMName and VMID.

enterpssessionCode

When a VM name or ID is specified, a new HyperVSocketConnectionInfo class is used rather than the typical WSManConnectionInfo class.

connectionInfo

There were a bunch of interesting classes associated with Hyper-V remoting. They implement the glue necessary to open the connection and allow the PowerShell remoting proctol to go over the Hyper-V socket.

classes

One class that is interesting is the RemoteSessionHyperVSocketClient class. It’s responsible for initiating the socket connection to the guest. In the constructor to the client, it instantiates a HyperVSocketEndPoint to pass to the Socket constructor.

remoteSEssionConst

Interesting to note is the protocol type is listed as ICMP and the socket family is a 0x22 magic number. Looking at the AddressFamily enumeration, this address family is not listed. Also, the address family is not registered with IANA. The endpoint’s serialized value is a combination of the address family, VMID and service ID. The service ID depends on whether or not this is the first connection to the guest.

endpoint

On the first connection, the first step is to send the username and domain name.

sendUsername

Next a string is sent to indicate whether or not a password will be sent and then the password is sent. Afterwards, the client checks for a failure string.

password

Once this socket is open, standard PS Remoting protocols seem to be used just as you would with a WSMan connection.

Overall, it’s a super handy feature and it’s interesting to see how it’s being accomplished. I do wonder what the magical address family 0x22 will be called or if it will remain 0x22.