Saturday, June 17, 2017

Hyper-V Sockets and PnP

How does Powershell Direct session work internally? When application, which uses Hyper-V socket, makes CONNECT call, root partition sends message to guest OS using winhvr!WinHvPostMessage:
kd> !dc @rdx – before vmcall (part of message body)
#227b36000 00000001 00000000 00000001 000000c4 ................
#227b36010 00000001 00000000 999e53d4 4c3e3d5c .........S..\=>L
#227b36020 d0be7987 e156c06e

If we look at the parameters of vmicvmsession, we find out, that it has trigger for start.

After the message was delivered to guest OS, vmbus driver added new interface:

kd> kcn
# Call Site
00 nt!IoRegisterDeviceInterface
01 Wdf01000!Mx::MxRegisterDeviceInterface
02 Wdf01000!FxDeviceInterface::Register
03 Wdf01000!FxDeviceInterface::Register
04 Wdf01000!imp_WdfDeviceCreateDeviceInterface
05 vmbus!RootStartDeviceInterfaceByContext
06 hvsocket!VmbusTlXPartProcessNewConnection
07 vmbus!RootNotifyDeviceInterfaceArrival
08 Wdf01000!FxWorkItem::WorkItemHandler
09 Wdf01000!FxWorkItem::WorkItemThunk
0a nt!IopProcessWorkItem
0b nt!ExpWorkerThread
0c nt!PspSystemThreadStartup
0d nt!KiStartSystemThread

And PnP mechanism works:
kd> kcn
# Call Site
00 nt!PnpNotifyDeviceClassChange
01 nt!PnpDeviceEventWorker
02 nt!ExpWorkerThread
03 nt!PspSystemThreadStartup

Service trigger works and service starts. After that icsvc.dll configures socket and begins communication with Host OS.
It is interesting that we can change that GUID to GUID of another device. We can get list of services, that have trigger on DEVICE INTERFACE ARRIVAL event:

All Hyper-V guest services
Bluetooth Support Service
Windows Camera Frame Server
Human Interface Device Service
Geolocation Service
Microsoft Passport
Portable Device Enumerator Service
Sensor Service
Sensor Monitoring Service
Storage Service
Touch Keyboard and Handwriting (probably)

And if we point that GUID in CONNECT call

clsid_str = L"{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
CLSIDFromString(clsid_str, &ServiceID); //when you call CONNECT with that GUID Portable Device Enumerator Service will start in guest OS (even in shielded VM)

guest OS starts this service, because it believes, that triggered device was appeared in system.
One point: before do this you must add GUID to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices as key in Host OS (need local admin rights)

It works on Shielded VM too (tested in Admin-Trusted mode), besides Hyper-V Powershell Direct Service – it not started

               It very interesting to see integration between Hyper-V sockets and PnP subsystem in Windows.