1- // hvmm .c : implementation of the Hyper-V Virtual Machines leechcore plugin based on LiveCloudKdSdk
1+ // leechcore_device_hvmm .c : implementation for Hyper-V memory access using Hyper-V memory access library
22// Please refer to the hvmm/ folder for more information or its original repository:
3- // https://github.com/comaeio /LiveCloudKd
3+ // https://github.com/gerhart01 /LiveCloudKd
44//
5- // (c) Ulf Frisk, 2018
5+ // (c) Ulf Frisk, 2018-2024
66// Author: Ulf Frisk, pcileech@frizk.net
77//
8- // (c) Arthur Khudyaev, 2020
8+ // (c) Arthur Khudyaev, 2018-2024
99// Author: Arthur Khudyaev, @gerhart_x
1010//
11- // (c) Matt Suiche, 2019
12- // Author: Matt Suiche, msuiche@comae .com
11+ // (c) Matt Suiche, 2018-2024
12+ // Author: Matt Suiche, www. msuiche.com
1313//
1414
1515
16-
17- #include "LiveCloudKdSdkHandle.h"
16+ #include "HvlibHandle.h"
1817#include "leechcore_device.h"
1918#include "util.h"
2019#include "leechcore_device_hvmm.h"
@@ -168,15 +167,14 @@ BOOL DeviceHVMM_GetOption(_In_ PLC_CONTEXT ctxLC, _In_ QWORD fOption, _Out_ PQWO
168167/*
169168* Unload the HVMM kernel driver and also delete the driver-loading service.
170169*/
170+
171171VOID DeviceHVMM_SvcClose ()
172172{
173173 SC_HANDLE hSCM , hSvcHvmm ;
174174 SERVICE_STATUS SvcStatus ;
175175
176176 // 1: shut down and delete service.
177177
178- SdkDestroyPartitions ();
179-
180178 if ((g_MemoryReadInterfaceType == ReadInterfaceHvmmDrvInternal ) || (g_MemoryReadInterfaceType == ReadInterfaceWinHv ))
181179 {
182180 if ((hSCM = OpenSCManager (NULL , NULL , SC_MANAGER_CREATE_SERVICE ))) {
@@ -194,79 +192,121 @@ VOID DeviceHVMM_SvcClose()
194192 }
195193}
196194
197- BOOL DeviceHVMM_CheckParams (_In_ PLC_CONTEXT ctxLC )
195+ ULONG GetNumberFromParam (_In_ PLC_CONTEXT ctxLC , PCHAR pId , _In_ PCSTR pszSrch )
198196{
199- ULONG64 uVmidLength = 0 ;
200- CHAR szVmid [10 ] = { 0 };
201- PCHAR pVmid = NULL ;
202197 PCHAR pDelim = NULL ;
203- PCHAR pListVm = NULL ;
204198 BOOLEAN bResult = FALSE;
199+ ULONG64 uParamIdLength = 0 ;
200+ CHAR szParamId [10 ] = { 0 };
201+ ULONG64 sizeOfParam = strlen (pszSrch );
202+ ULONG szResult = 0 ;
203+
204+ PDEVICE_CONTEXT_HVMM ctx = (PDEVICE_CONTEXT_HVMM )ctxLC -> hDevice ;
205205
206- ULONG64 device_size = sizeof (HVMM_PARAM_NAME ) - 1 ;
207- ULONG64 id_size = sizeof (ID_PARAM_NAME ) - 1 ;
206+ pId = StrStrIA (ctxLC -> Config .szDevice , pszSrch );
208207
209- PDEVICE_CONTEXT_HVMM ctx = (PDEVICE_CONTEXT_HVMM )ctxLC -> hDevice ;
210-
211- pVmid = StrStrIA (ctxLC -> Config .szDevice , ID_PARAM_NAME );
212- if (pVmid )
208+ if (pId )
213209 {
214- pDelim = StrStrIA (pVmid , HVMM_PARAM_DELIMITER );
210+ pDelim = StrStrIA (pId , HVMM_PARAM_DELIMITER );
215211
216212 if (pDelim )
217213 {
218- uVmidLength = pVmid - pDelim ;
219- if (uVmidLength < 6 )
220- {
221- memcpy (szVmid , pVmid + id_size , uVmidLength );
214+ uParamIdLength = pDelim - pId - sizeOfParam ;
215+ if (uParamIdLength < 6 )
216+ {
217+ memcpy (szParamId , pId + sizeOfParam , uParamIdLength );
222218
223- if (!IsDigital (ctxLC , szVmid , uVmidLength ))
224- return FALSE ;
219+ if (!IsDigital (ctxLC , szParamId , uParamIdLength ))
220+ return -1 ;
225221
226- ctx -> Vmid = atoi (szVmid );
222+ szResult = atoi (szParamId );
227223 ctx -> VmidPreselected = TRUE;
228224 bResult = TRUE;
229225 }
230226 else
231227 {
232228 lcprintf (ctxLC ,
233229 "DEVICE_HVMM: ERROR: vmid length is too big: %d\n" ,
234- uVmidLength );
235- return FALSE ;
230+ uParamIdLength );
231+ return -1 ;
236232 }
237233 }
238234 else
239- {
240- uVmidLength = strlen (ctxLC -> Config .szDevice ) - device_size - id_size ;
241- strcpy_s (szVmid , _countof (szVmid ), pVmid + id_size );
235+ {
236+ uParamIdLength = strlen (ctxLC -> Config .szDevice ) - (pId - ctxLC -> Config .szDevice ) - sizeOfParam ;
237+
238+ strcpy_s (szParamId , _countof (szParamId ), pId + sizeOfParam );
242239
243- if (!IsDigital (ctxLC , szVmid , uVmidLength ))
240+ if (!IsDigital (ctxLC , szParamId , uParamIdLength ))
244241 return FALSE;
245242
246- if (uVmidLength < 6 )
243+ if (uParamIdLength < 6 )
247244 {
248- ctx -> Vmid = atoi (szVmid );
245+ szResult = atoi (szParamId );
249246 ctx -> VmidPreselected = TRUE;
250247 bResult = TRUE;
251248 }
252249 else
253250 {
254251 lcprintf (ctxLC ,
255252 "DEVICE_HVMM: ERROR: vmid length is too big: %d\n" ,
256- uVmidLength );
257- return FALSE ;
253+ uParamIdLength );
254+ return -1 ;
258255 }
259256 }
260257 }
258+ return szResult ;
259+ }
261260
262- pListVm = StrStrIA (ctxLC -> Config .szDevice , LISTVM_PARAM_NAME );
261+ BOOL DeviceHVMM_CheckParams (_In_ PLC_CONTEXT ctxLC )
262+ {
263+ ULONG64 uVmidLength = 0 ;
264+ CHAR szVmid [10 ] = { 0 };
265+ PCHAR pVmid = NULL ;
266+ PCHAR pLogLevel = NULL ;
267+ PCHAR pDelim = NULL ;
268+ BOOLEAN bResult = FALSE;
269+
270+ ULONG64 id_size = sizeof (HVMM_ID_PARAM_NAME ) - 1 ;
271+ PDEVICE_CONTEXT_HVMM ctx = (PDEVICE_CONTEXT_HVMM )ctxLC -> hDevice ;
272+
273+ pVmid = StrStrIA (ctxLC -> Config .szDevice , HVMM_ID_PARAM_NAME );
263274
264- if (pListVm )
275+ if (pVmid )
276+ {
277+ ctx -> Vmid = GetNumberFromParam (ctxLC , pLogLevel , HVMM_ID_PARAM_NAME );
278+
279+ if (ctx -> Vmid != -1 )
280+ ctx -> VmidPreselected = TRUE;
281+
282+ bResult = TRUE;
283+ }
284+
285+ pLogLevel = StrStrIA (ctxLC -> Config .szDevice , HVMM_LOGLEVEL_PARAM_NAME );
286+
287+ if (pLogLevel )
288+ {
289+ ctx -> LogLevel = GetNumberFromParam (ctxLC , pLogLevel , HVMM_LOGLEVEL_PARAM_NAME );
290+ bResult = TRUE;
291+ }
292+
293+ if (StrStrIA (ctxLC -> Config .szDevice , HVMM_UNIX_PARAM_NAME ))
294+ {
295+ ctx -> SimpleMemory = TRUE;
296+ bResult = TRUE;
297+ }
298+
299+ if (StrStrIA (ctxLC -> Config .szDevice , HVMM_LISTVM_PARAM_NAME ))
265300 {
266301 ctx -> ListVm = TRUE;
267302 bResult = TRUE;
268303 }
269-
304+
305+ if (StrStrIA (ctxLC -> Config .szDevice , HVMM_ENUM_GUEST_OS_BUILD_PARAM_NAME ))
306+ {
307+ ctx -> EnumGuestOsBuild = TRUE;
308+ bResult = TRUE;
309+ }
270310
271311 return bResult ;
272312}
@@ -276,6 +316,41 @@ BOOL DeviceHVMM_CheckParams(_In_ PLC_CONTEXT ctxLC)
276316* into the kernel. Upon fail it's guaranteed that no lingering service exists.
277317*/
278318
319+ HANDLE GetHvmmHandle (_In_ PLC_CONTEXT ctxLC )
320+ {
321+ HANDLE hDevice = INVALID_HANDLE_VALUE ;
322+
323+ hDevice = CreateFileA (DEVICEHVMM_OBJECT ,
324+ GENERIC_READ | GENERIC_WRITE ,
325+ FILE_SHARE_READ |
326+ FILE_SHARE_WRITE ,
327+ NULL ,
328+ OPEN_EXISTING ,
329+ FILE_ATTRIBUTE_NORMAL ,
330+ 0 );
331+
332+ if (hDevice == INVALID_HANDLE_VALUE )
333+ return NULL ;
334+
335+ lcprintf (ctxLC , "DEVICE_HVMM: driver is already loaded\n" );
336+
337+ return hDevice ;
338+ }
339+
340+ BOOLEAN GetHvmmPresent (_In_ PLC_CONTEXT ctxLC )
341+ {
342+ HANDLE hDevice = GetHvmmHandle (ctxLC );
343+ BOOLEAN bResult = FALSE;
344+
345+ if (hDevice )
346+ {
347+ CloseHandle (hDevice );
348+ return TRUE;
349+ }
350+
351+ return FALSE;
352+ }
353+
279354_Success_ (return )
280355BOOL DeviceHVMM_SvcStart (_In_ PLC_CONTEXT ctxLC )
281356{
@@ -288,10 +363,14 @@ BOOL DeviceHVMM_SvcStart(_In_ PLC_CONTEXT ctxLC)
288363
289364 SC_HANDLE hSCM = 0 , hSvcHvmm = 0 ;
290365
366+ ctx -> hFile = GetHvmmHandle (ctxLC );
367+
368+ if (ctx -> hFile )
369+ return TRUE;
370+
291371 // 1: verify that driver file exists.
292372 if ((g_MemoryReadInterfaceType == ReadInterfaceHvmmDrvInternal ) || (g_MemoryReadInterfaceType == ReadInterfaceWinHv ))
293373 {
294-
295374 hModuleLeechCore = LoadLibraryA ("leechcore.dll" );
296375 // NB! defaults to locating 'hvmm.sys' relative to the loaded
297376 // 'leechcore.dll' - if unable to locate library (for whatever reason)
@@ -359,7 +438,7 @@ BOOL DeviceHVMM_SvcStart(_In_ PLC_CONTEXT ctxLC)
359438 // 3: open file handle
360439
361440 ctx -> hFile = CreateFileA (
362- DEVICEHVMM_MEMORYFILE ,
441+ DEVICEHVMM_OBJECT ,
363442 GENERIC_READ | GENERIC_WRITE ,
364443 FILE_SHARE_READ | FILE_SHARE_WRITE ,
365444 NULL ,
@@ -386,13 +465,18 @@ BOOL DeviceHVMM_SvcStart(_In_ PLC_CONTEXT ctxLC)
386465VOID DeviceHVMM_Close (_Inout_ PLC_CONTEXT ctxLC )
387466{
388467 PDEVICE_CONTEXT_HVMM ctx = (PDEVICE_CONTEXT_HVMM )ctxLC -> hDevice ;
389- DeviceHVMM_SvcClose ();
390-
468+
391469 if (ctx ) {
392- CloseHandle (ctx -> hFile );
470+ SdkClosePartition ((ULONG64 )ctx -> Partition );
471+
472+ if (ctx -> hFile )
473+ CloseHandle (ctx -> hFile );
474+
393475 LocalFree (ctx );
394476 }
395477
478+ DeviceHVMM_SvcClose ();
479+
396480 ctxLC -> hDevice = 0 ;
397481}
398482
@@ -445,10 +529,7 @@ EXPORTED_FUNCTION BOOL LcPluginCreate(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_
445529 ctx = (PDEVICE_CONTEXT_HVMM )LocalAlloc (LMEM_ZEROINIT , sizeof (DEVICE_CONTEXT_HVMM ));
446530 if (!ctx ) { return FALSE; }
447531
448- // 1: terminate any lingering HVMM service.
449- DeviceHVMM_SvcClose ();
450-
451- // 2: initialize core context.
532+ // 1: initialize core context.
452533
453534 ctxLC -> hDevice = (HANDLE )ctx ;
454535 // set callback functions and fix up config
@@ -531,15 +612,16 @@ EXPORTED_FUNCTION BOOL LcPluginCreate(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_
531612 else
532613 {
533614 DeviceHVMM_CheckParams (ctxLC );
534- }
535615
536- // 3: load hvmm kernel driver.
537- result = DeviceHVMM_SvcStart (ctxLC );
538- if (!result ) {
539- lcprintf (ctxLC , "DEVICE_HVMM: FAILED: Failed to initialize the driver.\n" );
540- goto fail ;
541- }
616+ // 3: load hvmm kernel driver.
542617
618+ result = DeviceHVMM_SvcStart (ctxLC );
619+ if (!result ) {
620+ lcprintf (ctxLC , "DEVICE_HVMM: FAILED: Failed to initialize the driver.\n" );
621+ goto fail ;
622+ }
623+ }
624+
543625 // 4: retrieve memory map.
544626 result = DeviceHVMM_GetMemoryInformation (ctxLC );
545627 if (!result ) {
0 commit comments