diff --git a/files/leechcore.h b/files/leechcore.h index 46af16a..e5baf92 100644 --- a/files/leechcore.h +++ b/files/leechcore.h @@ -23,13 +23,23 @@ // kerberos. If not possible or desirable the 'insecure' value may be specified // to disable authentication and security. // Syntax: -// rpc://:: (port = optional, remote_spn = kerberos) -// (SPN of remote service or 'insecure' ) +// rpc://:[:] (remote_spn = kerberos SPN of ) +// (remote service or 'insecure' ) +// +// Valid options: (optional comma-separated list ) +// port= (RPC TCP port of the remote system) +// nocompress (disable transport compression ) +// // Examples: // rpc://insecure:remotehost.example.com (connect insecure to remote host ) // rpc://user@ad.domain.com:192.0.0.5 (connect secure to remote host ) // rpc://insecure:127.0.0.0:6666 (connect insecure non-default port) // +// The remote connector may also connect to pipe handles provided in the config +// string. This is only used internally by the LeechAgent for communication for +// parent/child process and may not be used by external applications. Syntax is +// pipe://:. +// // ---------------------------------------------------------------------------- // // Device to connect to: szDevice contains the device to capture memory from. @@ -107,11 +117,16 @@ // Syntax: // EXISTING // +// EXISTINGREMOTE : Same as EXISTING but applying the EXISTING device on the +// remote system. Use only in conjunction with a remote system. +// Syntax: +// EXISTINGREMOTE +// // // (c) Ulf Frisk, 2018-2019 // Author: Ulf Frisk, pcileech@frizk.net // -// Header Version: 1.1.0 +// Header Version: 1.2.0 // #ifndef __LEECHCORE_H__ #define __LEECHCORE_H__ @@ -127,8 +142,12 @@ extern "C" { #include typedef unsigned __int64 QWORD, *PQWORD; #define DLLEXPORT __declspec(dllexport) +#ifdef _WIN64 +#define ARCH_64 +#endif /* _WIN64 */ #endif /* _WIN32 */ #ifdef LINUX +#define ARCH_X64 #include #include typedef void VOID, *PVOID, *LPVOID; @@ -163,6 +182,7 @@ typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64; #define MEM_IO_SCATTER_HEADER_MAGIC 0xffff6548 #define MEM_IO_SCATTER_HEADER_VERSION 0x0003 +#ifdef ARCH_64 typedef struct tdMEM_IO_SCATTER_HEADER { DWORD magic; // magic WORD version; // version @@ -175,6 +195,26 @@ typedef struct tdMEM_IO_SCATTER_HEADER { PVOID pvReserved2; // reserved for use by caller. PVOID Future2[8]; } MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER; +#endif /* ARCH_64 */ + +#ifndef ARCH_64 +typedef struct tdMEM_IO_SCATTER_HEADER { + DWORD magic; // magic + WORD version; // version + WORD Future1; + ULONG64 qwA; // base address. + DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pb must have room for this. + DWORD cb; // bytes read into result buffer. + PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes. + DWORD dwFiller64_1; + PVOID pvReserved1; // reserved for use by caller. + DWORD dwFiller64_2; + PVOID pvReserved2; // reserved for use by caller. + DWORD dwFiller64_3; + PVOID Future2[8]; + DWORD dwFiller64_4[8]; +} MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER; +#endif /* ARCH_64 */ //----------------------------------------------------------------------------- // LEECHCORE INITIALIZATION / CLOSE FUNCTIONALITY BELOW: @@ -221,12 +261,26 @@ typedef struct tdLEECHCORE_CONFIG { // optional 'printf' function pointer. if set to non null value 'printf' // calls will be redirected. useful when logging to files. _Check_return_opt_ int(*pfn_printf_opt)(_In_z_ _Printf_format_string_ char const* const _Format, ...); // set by caller. +#ifndef ARCH_64 + DWORD dwFiller64_1; +#endif /* ARCH_64 */ } LEECHCORE_CONFIG, *PLEECHCORE_CONFIG; +#ifdef ARCH_64 typedef struct tdLEECHCORE_PAGESTAT_MINIMAL { HANDLE h; VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd); } LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL; +#endif /* ARCH_64 */ + +#ifndef ARCH_64 +typedef struct tdLEECHCORE_PAGESTAT_MINIMAL { + HANDLE h; + DWORD dwFiller64_1; + VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd); + DWORD dwFiller64_2; +} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL; +#endif /* ARCH_64 */ /* * Open a connection to the target device. The LeechCore initialization may fail @@ -306,7 +360,7 @@ DLLEXPORT DWORD LeechCore_ReadEx(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In * -- return */ _Success_(return) -DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb); +DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_reads_(cb) PBYTE pb, _In_ DWORD cb); /* * Write data to the target system if supported by the device. @@ -317,7 +371,7 @@ DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb); * -- return */ _Success_(return) -DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD flags); +DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _In_ DWORD flags); /* * Probe the memory of the target system to check whether it's readable or not. @@ -350,6 +404,7 @@ DLLEXPORT BOOL LeechCore_Probe(_In_ QWORD pa, _In_ DWORD cPages, _Inout_updates_ #define LEECHCORE_OPT_CORE_VERSION_MAJOR 0x01000001 // R #define LEECHCORE_OPT_CORE_VERSION_MINOR 0x01000002 // R #define LEECHCORE_OPT_CORE_VERSION_REVISION 0x01000003 // R +#define LEECHCORE_OPT_CORE_FLAG_BACKEND_FUNCTIONS 0x01000004 // R #define LEECHCORE_OPT_MEMORYINFO_VALID 0x02000001 // R #define LEECHCORE_OPT_MEMORYINFO_ADDR_MAX 0x02000002 // R @@ -420,7 +475,8 @@ DLLEXPORT BOOL LeechCore_SetOption(_In_ ULONG64 fOption, _In_ ULONG64 qwValue); #define LEECHCORE_STATISTICS_ID_GETOPTION 0x04 #define LEECHCORE_STATISTICS_ID_SETOPTION 0x05 #define LEECHCORE_STATISTICS_ID_COMMANDDATA 0x06 -#define LEECHCORE_STATISTICS_ID_MAX 0x06 +#define LEECHCORE_STATISTICS_ID_COMMANDSVC 0x07 +#define LEECHCORE_STATISTICS_ID_MAX 0x07 static const LPSTR LEECHCORE_STATISTICS_NAME[] = { "LeechCore_Open", @@ -429,7 +485,8 @@ static const LPSTR LEECHCORE_STATISTICS_NAME[] = { "LeechCore_Probe", "LeechCore_GetOption", "LeechCore_SetOption", - "LeechCore_CommandData" + "LeechCore_CommandData", + "LeechCore_CommandSvc" }; typedef struct tdLEECHCORE_STATISTICS { @@ -465,6 +522,30 @@ DLLEXPORT BOOL LeechCore_CommandData( _Out_opt_ PDWORD pcbDataOut ); +#define LEECHCORE_AGENTCOMMAND_EXEC_PYTHON_INMEM 0x1166000000000001 +#define LEECHCORE_AGENTCOMMAND_EXITPROCESS 0x1166000000000010 + +/* +* Transfer commands/data to/from the remote agent (if it exists). +* NB! USER-FREE: ppbDataOut (LocalFree) +* -- fCommand = the option / command to the remote service as defined in LEECHCORE_AGENTCOMMAND_* +* -- fDataIn = optional 64-bit tiny input value +* -- cbDataIn +* -- pbDataIn +* -- ppbDataOut = ptr to receive function allocated output - must be LocalFree'd by caller! +* -- pcbDataOut = ptr to receive length of *pbDataOut. +* -- return +*/ +_Success_(return) +DLLEXPORT BOOL LeechCore_AgentCommand( + _In_ ULONG64 fCommand, + _In_ ULONG64 fDataIn, + _In_reads_(cbDataIn) PBYTE pbDataIn, + _In_ DWORD cbDataIn, + _Out_writes_opt_(*pcbDataOut) PBYTE *ppbDataOut, + _Out_opt_ PDWORD pcbDataOut +); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/files/leechcore.lib b/files/leechcore.lib index 4920775..31abb65 100644 Binary files a/files/leechcore.lib and b/files/leechcore.lib differ diff --git a/pcileech.sln b/pcileech.sln index bb2667f..54cf28b 100644 --- a/pcileech.sln +++ b/pcileech.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.421 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcileech", "pcileech\pcileech.vcxproj", "{DFFA1B4C-279B-4356-ADB1-08A6F4795931}" EndProject @@ -41,15 +41,14 @@ Global ReleaseMT|x64 = ReleaseMT|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DFFA1B4C-279B-4356-ADB1-08A6F4795931}.Debug|x64.ActiveCfg = Release|x64 - {DFFA1B4C-279B-4356-ADB1-08A6F4795931}.Debug|x64.Build.0 = Release|x64 + {DFFA1B4C-279B-4356-ADB1-08A6F4795931}.Debug|x64.ActiveCfg = Debug|x64 + {DFFA1B4C-279B-4356-ADB1-08A6F4795931}.Debug|x64.Build.0 = Debug|x64 {DFFA1B4C-279B-4356-ADB1-08A6F4795931}.Release|x64.ActiveCfg = Release|x64 {DFFA1B4C-279B-4356-ADB1-08A6F4795931}.Release|x64.Build.0 = Release|x64 {DFFA1B4C-279B-4356-ADB1-08A6F4795931}.ReleaseMT|x64.ActiveCfg = ReleaseMT|x64 {DFFA1B4C-279B-4356-ADB1-08A6F4795931}.ReleaseMT|x64.Build.0 = ReleaseMT|x64 - {C55314C6-71A0-4AE2-A4F0-E5E531A5E065}.Debug|x64.ActiveCfg = Release|x64 + {C55314C6-71A0-4AE2-A4F0-E5E531A5E065}.Debug|x64.ActiveCfg = Debug|x64 {C55314C6-71A0-4AE2-A4F0-E5E531A5E065}.Release|x64.ActiveCfg = Release|x64 - {C55314C6-71A0-4AE2-A4F0-E5E531A5E065}.Release|x64.Build.0 = ReleaseMT|x64 {C55314C6-71A0-4AE2-A4F0-E5E531A5E065}.ReleaseMT|x64.ActiveCfg = ReleaseMT|x64 {5C698F13-6E9F-46F3-95FC-55376A65D8BF}.Debug|x64.ActiveCfg = Release|x64 {5C698F13-6E9F-46F3-95FC-55376A65D8BF}.Release|x64.ActiveCfg = Release|x64 @@ -61,17 +60,11 @@ Global {3476ABD2-5DEA-43E6-A676-8BE25F74535A}.ReleaseMT|x64.ActiveCfg = ReleaseMT|x64 {3476ABD2-5DEA-43E6-A676-8BE25F74535A}.ReleaseMT|x64.Build.0 = ReleaseMT|x64 {E11BECC1-685F-41B9-A352-A6127FAB3758}.Debug|x64.ActiveCfg = Debug|x64 - {E11BECC1-685F-41B9-A352-A6127FAB3758}.Debug|x64.Build.0 = Debug|x64 - {E11BECC1-685F-41B9-A352-A6127FAB3758}.Release|x64.ActiveCfg = Debug|x64 - {E11BECC1-685F-41B9-A352-A6127FAB3758}.Release|x64.Build.0 = Debug|x64 + {E11BECC1-685F-41B9-A352-A6127FAB3758}.Release|x64.ActiveCfg = Release|x64 {E11BECC1-685F-41B9-A352-A6127FAB3758}.ReleaseMT|x64.ActiveCfg = ReleaseMT|x64 - {E11BECC1-685F-41B9-A352-A6127FAB3758}.ReleaseMT|x64.Build.0 = ReleaseMT|x64 {F2F4AA4A-BEFE-4738-9412-820007919334}.Debug|x64.ActiveCfg = Debug|x64 - {F2F4AA4A-BEFE-4738-9412-820007919334}.Debug|x64.Build.0 = Debug|x64 - {F2F4AA4A-BEFE-4738-9412-820007919334}.Release|x64.ActiveCfg = Debug|x64 - {F2F4AA4A-BEFE-4738-9412-820007919334}.Release|x64.Build.0 = Debug|x64 + {F2F4AA4A-BEFE-4738-9412-820007919334}.Release|x64.ActiveCfg = Release|x64 {F2F4AA4A-BEFE-4738-9412-820007919334}.ReleaseMT|x64.ActiveCfg = ReleaseMT|x64 - {F2F4AA4A-BEFE-4738-9412-820007919334}.ReleaseMT|x64.Build.0 = ReleaseMT|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/pcileech/Makefile b/pcileech/Makefile index 4f649f2..aa9a97a 100644 --- a/pcileech/Makefile +++ b/pcileech/Makefile @@ -1,5 +1,5 @@ CC=gcc -CFLAGS=-I. -D LINUX -L. -l:../files/leechcore.so -pthread `pkg-config libusb-1.0 --libs --cflags` +CFLAGS=-I. -D LINUX -L. -l:leechcore.so -pthread `pkg-config libusb-1.0 --libs --cflags` LDFLAGS=-Wl,-rpath,'$$ORIGIN' DEPS = pcileech.h OBJ = pcileech oscompatibility.o pcileech.o device.o executor.o extra.o help.o kmd.o memdump.o mempatch.o statistics.o umd.o util.o vfs.o vmmprx.o @@ -8,9 +8,12 @@ OBJ = pcileech oscompatibility.o pcileech.o device.o executor.o extra.o help.o k $(CC) -c -o $@ $< $(CFLAGS) pcileech: $(OBJ) + cp ../files/leechcore.so . |true + cp ../../LeechCore-dev/files/leechcore.so . |true $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) rm *.o mv pcileech ../files/ + mv leechcore.so ../files/ clean: rm *.o diff --git a/pcileech/executor.c b/pcileech/executor.c index 2182dd9..1566af3 100644 --- a/pcileech/executor.c +++ b/pcileech/executor.c @@ -7,6 +7,7 @@ #include "device.h" #include "util.h" #include "vmmprx.h" +#include "leechcore.h" #define EXEC_IO_MAGIC 0x12651232dfef9521 #define EXEC_IO_CONSOLE_BUFFER_SIZE 0x800 @@ -387,3 +388,50 @@ fail: LocalFree(szBufferText); if(pFile) { fclose(pFile); } } + +VOID ActionSvcExecPy() +{ + BOOL result; + DWORD cb = 0; + PBYTE pb = NULL; + FILE *pFile = NULL; + if(!ctxMain->cfg.pbIn || (ctxMain->cfg.cbIn < 4)) { + printf("AGENT-PYEXEC: Failed. Input file not valid. Please supply input file in -in option.\n"); + return; + } + printf("AGENT-PYEXEC: Sending script to remote LeechAgent for processing.\n"); + printf("AGENT-PYEXEC: Waiting for result ...\n"); + result = LeechCore_AgentCommand(LEECHCORE_AGENTCOMMAND_EXEC_PYTHON_INMEM, 0, ctxMain->cfg.pbIn, (DWORD)ctxMain->cfg.cbIn, &pb, &cb); + if(!result) { + printf("AGENT-PYEXEC: Failed.\n"); + return; + } + if(pb && (cb > 0)) { + // write to out file + if(ctxMain->cfg.szFileOut[0]) { + // open output file + if(!fopen_s(&pFile, ctxMain->cfg.szFileOut, "r") || pFile) { + printf("AGENT-PYEXEC: Error writing output to file. File already exists: %s\n", ctxMain->cfg.szFileOut); + goto fail; + } + if(fopen_s(&pFile, ctxMain->cfg.szFileOut, "wb") || !pFile) { + printf("AGENT-PYEXEC: Error writing output to file.\n"); + goto fail; + } + if(cb != fwrite(pb, 1, cb, pFile)) { + printf("AGENT-PYEXEC: Error writing output to file.\n"); + goto fail; + } + printf("AGENT-PYEXEC: Wrote %i bytes to file %s.\n", cb, ctxMain->cfg.szFileOut); + } + // print to screen + printf("AGENT-PYEXEC: Please see result below: \n================================ \n"); + Util_AsciiFilter(pb, cb); // filter away potentially harmful chars from untrusted remote input + printf("%s\n", (LPSTR)pb); + } + +fail: + if(pFile) { fclose(pFile); } + LocalFree(pb); +} + diff --git a/pcileech/executor.h b/pcileech/executor.h index 1d9fd31..4833f02 100644 --- a/pcileech/executor.h +++ b/pcileech/executor.h @@ -52,4 +52,9 @@ BOOL Exec_ExecSilent(_In_ LPSTR szShellcodeName, _In_ PBYTE pbIn, _In_ QWORD cbI */ VOID ActionExecShellcode(); +/* +* Try execute python code on a remote host in the context of the LeechSvc. +*/ +VOID ActionSvcExecPy(); + #endif /* __EXECUTOR_H__ */ diff --git a/pcileech/help.c b/pcileech/help.c index 90d3225..282e900 100644 --- a/pcileech/help.c +++ b/pcileech/help.c @@ -63,6 +63,7 @@ VOID Help_ShowGeneral() " probe NATIVE [ min, max ] (FPGA) \n" \ " pslist NATIVE (MemProcFS/Windows) \n" \ " psvirt2phys NATIVE [ 0, 1 ] (MemProcFS/Windows) \n" \ + " agent-execpy NATIVE [ in, out ] (Remote LeechAgent) \n" \ " System specific commands and valid MODEs [ and options ]: \n" \ " mac_fvrecover NATIVE (USB3380) \n" \ " mac_fvrecover2 NATIVE (USB3380) \n" \ @@ -582,6 +583,23 @@ VOID Help_ShowDetailed() " -0 632 -1 0x08000000 -s c:\\windows\\system32\\cmd.exe \n" \ ); break; + case AGENT_EXEC_PY: + printf( + " EXECUTE A PYTHON SCRIPT ON A REMOTE HOST RUNNING LeechAgent \n" \ + " MODES : NATIVE \n" \ + " REQUIRE : Windows/Remote LeechSvc \n" \ + " OPTIONS : -in, -out \n" \ + " Execute a Python script contained in the -in parameter on a remote host having\n" \ + " the LeechAgent installed. The script will be executed in an embedded Python\n" \ + " and the MemProcFS/LeechCore python APIs will be available and initialized. \n" \ + " Outout will be displayed on screen unless -out parameter is specified. \n" \ + " EXAMPLE: \n" \ + " 1) Execute the script 'myscript.py' on the remote host test1.contoso.com using\n" \ + " physical memory acquired from WinPmem: \n" \ + " pcileech.exe agent-execpy -in myscript.py -device pmem \n" \ + " -remote rpc://test1$@contoso.com:test1.contoso.com \n" \ + ); + break; case EXEC_KMD: _HelpShowExecCommand(); break; diff --git a/pcileech/leechcore.h b/pcileech/leechcore.h index 46af16a..e5baf92 100644 --- a/pcileech/leechcore.h +++ b/pcileech/leechcore.h @@ -23,13 +23,23 @@ // kerberos. If not possible or desirable the 'insecure' value may be specified // to disable authentication and security. // Syntax: -// rpc://:: (port = optional, remote_spn = kerberos) -// (SPN of remote service or 'insecure' ) +// rpc://:[:] (remote_spn = kerberos SPN of ) +// (remote service or 'insecure' ) +// +// Valid options: (optional comma-separated list ) +// port= (RPC TCP port of the remote system) +// nocompress (disable transport compression ) +// // Examples: // rpc://insecure:remotehost.example.com (connect insecure to remote host ) // rpc://user@ad.domain.com:192.0.0.5 (connect secure to remote host ) // rpc://insecure:127.0.0.0:6666 (connect insecure non-default port) // +// The remote connector may also connect to pipe handles provided in the config +// string. This is only used internally by the LeechAgent for communication for +// parent/child process and may not be used by external applications. Syntax is +// pipe://:. +// // ---------------------------------------------------------------------------- // // Device to connect to: szDevice contains the device to capture memory from. @@ -107,11 +117,16 @@ // Syntax: // EXISTING // +// EXISTINGREMOTE : Same as EXISTING but applying the EXISTING device on the +// remote system. Use only in conjunction with a remote system. +// Syntax: +// EXISTINGREMOTE +// // // (c) Ulf Frisk, 2018-2019 // Author: Ulf Frisk, pcileech@frizk.net // -// Header Version: 1.1.0 +// Header Version: 1.2.0 // #ifndef __LEECHCORE_H__ #define __LEECHCORE_H__ @@ -127,8 +142,12 @@ extern "C" { #include typedef unsigned __int64 QWORD, *PQWORD; #define DLLEXPORT __declspec(dllexport) +#ifdef _WIN64 +#define ARCH_64 +#endif /* _WIN64 */ #endif /* _WIN32 */ #ifdef LINUX +#define ARCH_X64 #include #include typedef void VOID, *PVOID, *LPVOID; @@ -163,6 +182,7 @@ typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64; #define MEM_IO_SCATTER_HEADER_MAGIC 0xffff6548 #define MEM_IO_SCATTER_HEADER_VERSION 0x0003 +#ifdef ARCH_64 typedef struct tdMEM_IO_SCATTER_HEADER { DWORD magic; // magic WORD version; // version @@ -175,6 +195,26 @@ typedef struct tdMEM_IO_SCATTER_HEADER { PVOID pvReserved2; // reserved for use by caller. PVOID Future2[8]; } MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER; +#endif /* ARCH_64 */ + +#ifndef ARCH_64 +typedef struct tdMEM_IO_SCATTER_HEADER { + DWORD magic; // magic + WORD version; // version + WORD Future1; + ULONG64 qwA; // base address. + DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pb must have room for this. + DWORD cb; // bytes read into result buffer. + PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes. + DWORD dwFiller64_1; + PVOID pvReserved1; // reserved for use by caller. + DWORD dwFiller64_2; + PVOID pvReserved2; // reserved for use by caller. + DWORD dwFiller64_3; + PVOID Future2[8]; + DWORD dwFiller64_4[8]; +} MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER; +#endif /* ARCH_64 */ //----------------------------------------------------------------------------- // LEECHCORE INITIALIZATION / CLOSE FUNCTIONALITY BELOW: @@ -221,12 +261,26 @@ typedef struct tdLEECHCORE_CONFIG { // optional 'printf' function pointer. if set to non null value 'printf' // calls will be redirected. useful when logging to files. _Check_return_opt_ int(*pfn_printf_opt)(_In_z_ _Printf_format_string_ char const* const _Format, ...); // set by caller. +#ifndef ARCH_64 + DWORD dwFiller64_1; +#endif /* ARCH_64 */ } LEECHCORE_CONFIG, *PLEECHCORE_CONFIG; +#ifdef ARCH_64 typedef struct tdLEECHCORE_PAGESTAT_MINIMAL { HANDLE h; VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd); } LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL; +#endif /* ARCH_64 */ + +#ifndef ARCH_64 +typedef struct tdLEECHCORE_PAGESTAT_MINIMAL { + HANDLE h; + DWORD dwFiller64_1; + VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd); + DWORD dwFiller64_2; +} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL; +#endif /* ARCH_64 */ /* * Open a connection to the target device. The LeechCore initialization may fail @@ -306,7 +360,7 @@ DLLEXPORT DWORD LeechCore_ReadEx(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In * -- return */ _Success_(return) -DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb); +DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_reads_(cb) PBYTE pb, _In_ DWORD cb); /* * Write data to the target system if supported by the device. @@ -317,7 +371,7 @@ DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb); * -- return */ _Success_(return) -DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD flags); +DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _In_ DWORD flags); /* * Probe the memory of the target system to check whether it's readable or not. @@ -350,6 +404,7 @@ DLLEXPORT BOOL LeechCore_Probe(_In_ QWORD pa, _In_ DWORD cPages, _Inout_updates_ #define LEECHCORE_OPT_CORE_VERSION_MAJOR 0x01000001 // R #define LEECHCORE_OPT_CORE_VERSION_MINOR 0x01000002 // R #define LEECHCORE_OPT_CORE_VERSION_REVISION 0x01000003 // R +#define LEECHCORE_OPT_CORE_FLAG_BACKEND_FUNCTIONS 0x01000004 // R #define LEECHCORE_OPT_MEMORYINFO_VALID 0x02000001 // R #define LEECHCORE_OPT_MEMORYINFO_ADDR_MAX 0x02000002 // R @@ -420,7 +475,8 @@ DLLEXPORT BOOL LeechCore_SetOption(_In_ ULONG64 fOption, _In_ ULONG64 qwValue); #define LEECHCORE_STATISTICS_ID_GETOPTION 0x04 #define LEECHCORE_STATISTICS_ID_SETOPTION 0x05 #define LEECHCORE_STATISTICS_ID_COMMANDDATA 0x06 -#define LEECHCORE_STATISTICS_ID_MAX 0x06 +#define LEECHCORE_STATISTICS_ID_COMMANDSVC 0x07 +#define LEECHCORE_STATISTICS_ID_MAX 0x07 static const LPSTR LEECHCORE_STATISTICS_NAME[] = { "LeechCore_Open", @@ -429,7 +485,8 @@ static const LPSTR LEECHCORE_STATISTICS_NAME[] = { "LeechCore_Probe", "LeechCore_GetOption", "LeechCore_SetOption", - "LeechCore_CommandData" + "LeechCore_CommandData", + "LeechCore_CommandSvc" }; typedef struct tdLEECHCORE_STATISTICS { @@ -465,6 +522,30 @@ DLLEXPORT BOOL LeechCore_CommandData( _Out_opt_ PDWORD pcbDataOut ); +#define LEECHCORE_AGENTCOMMAND_EXEC_PYTHON_INMEM 0x1166000000000001 +#define LEECHCORE_AGENTCOMMAND_EXITPROCESS 0x1166000000000010 + +/* +* Transfer commands/data to/from the remote agent (if it exists). +* NB! USER-FREE: ppbDataOut (LocalFree) +* -- fCommand = the option / command to the remote service as defined in LEECHCORE_AGENTCOMMAND_* +* -- fDataIn = optional 64-bit tiny input value +* -- cbDataIn +* -- pbDataIn +* -- ppbDataOut = ptr to receive function allocated output - must be LocalFree'd by caller! +* -- pcbDataOut = ptr to receive length of *pbDataOut. +* -- return +*/ +_Success_(return) +DLLEXPORT BOOL LeechCore_AgentCommand( + _In_ ULONG64 fCommand, + _In_ ULONG64 fDataIn, + _In_reads_(cbDataIn) PBYTE pbDataIn, + _In_ DWORD cbDataIn, + _Out_writes_opt_(*pcbDataOut) PBYTE *ppbDataOut, + _Out_opt_ PDWORD pcbDataOut +); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/pcileech/oscompatibility.c b/pcileech/oscompatibility.c index 0426f39..c26d7b5 100644 --- a/pcileech/oscompatibility.c +++ b/pcileech/oscompatibility.c @@ -168,6 +168,15 @@ DWORD InterlockedAdd(DWORD *Addend, DWORD Value) return __sync_add_and_fetch(Addend, Value); } +BOOL IsWow64Process(HANDLE hProcess, PBOOL Wow64Process) +{ + if(Wow64Process) { + *Wow64Process = FALSE; + return TRUE; + } + return FALSE; +} + // ---------------------------------------------------------------------------- // Facade implementation of FTDI functions using functionality provided by // kernel driver ft60x by @key2fr in the backend. NB! functionality below diff --git a/pcileech/oscompatibility.h b/pcileech/oscompatibility.h index e170e67..8cdfd2f 100644 --- a/pcileech/oscompatibility.h +++ b/pcileech/oscompatibility.h @@ -123,6 +123,7 @@ typedef struct tdEXCEPTION_RECORD64 { CHAR sz[152]; } EXCEPTION_RECORD64 #define _fileno(f) (fileno(f)) #define InterlockedAdd64(p, v) (__sync_fetch_and_add(p, v)) #define InterlockedIncrement64(p) (__sync_fetch_and_add(p, 1)) +#define GetCurrentProcess() ((HANDLE)-1) typedef struct tdCRITICAL_SECTION { pthread_mutex_t mutex; @@ -159,6 +160,7 @@ BOOL QueryPerformanceCounter(_Out_ LARGE_INTEGER *lpPerformanceCount); VOID GetLocalTime(LPSYSTEMTIME lpSystemTime); DWORD InterlockedAdd(DWORD *Addend, DWORD Value); BOOL WinUsb_Free(WINUSB_INTERFACE_HANDLE InterfaceHandle); +BOOL IsWow64Process(HANDLE hProcess, PBOOL Wow64Process); HANDLE CreateThread( PVOID lpThreadAttributes, diff --git a/pcileech/pcileech.c b/pcileech/pcileech.c index 52fc8a0..825ecb8 100644 --- a/pcileech/pcileech.c +++ b/pcileech/pcileech.c @@ -44,6 +44,7 @@ BOOL PCILeechConfigIntialize(_In_ DWORD argc, _In_ char* argv[]) {.tp = PROBE,.sz = "probe" }, {.tp = PSLIST,.sz = "pslist" }, {.tp = PSVIRT2PHYS,.sz = "psvirt2phys" }, + {.tp = AGENT_EXEC_PY,.sz = "agent-execpy" }, }; DWORD j, i = 1; ctxMain = LocalAlloc(LMEM_ZEROINIT, sizeof(PCILEECH_CONTEXT)); @@ -59,19 +60,19 @@ BOOL PCILeechConfigIntialize(_In_ DWORD argc, _In_ char* argv[]) // 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)) { - ctxMain->cfg.tpAction = ACTIONS[j].tp; - i++; - goto loop; + for(j = 0; j < sizeof(ACTIONS) / sizeof(ACTION); j++) { // parse command (if found) + if(0 == _stricmp(argv[i], ACTIONS[j].sz)) { + ctxMain->cfg.tpAction = ACTIONS[j].tp; + i++; + goto loop; + } + } + if(ctxMain->cfg.tpAction == NA && 0 != memcmp(argv[i], "-", 1)) { + ctxMain->cfg.tpAction = ((strlen(argv[i]) > 3) && !_strnicmp("umd", argv[i], 3)) ? EXEC_UMD : EXEC_KMD; + strcpy_s(ctxMain->cfg.szShellcodeName, MAX_PATH, argv[i]); + i++; + continue; } - } - if(ctxMain->cfg.tpAction == NA && 0 != memcmp(argv[i], "-", 1)) { - ctxMain->cfg.tpAction = ((strlen(argv[i]) > 3) && !_strnicmp("umd", argv[i], 3)) ? EXEC_UMD : EXEC_KMD; - strcpy_s(ctxMain->cfg.szShellcodeName, MAX_PATH, argv[i]); - i++; - continue; - } // parse options (command not found) if(0 == strcmp(argv[i], "-pt")) { ctxMain->cfg.fPageTableScan = TRUE; @@ -113,7 +114,7 @@ BOOL PCILeechConfigIntialize(_In_ DWORD argc, _In_ char* argv[]) ctxMain->cfg.qwAddrMax = Util_GetNumeric(argv[i + 1]); } else if(0 == strcmp(argv[i], "-cr3")) { ctxMain->cfg.qwCR3 = Util_GetNumeric(argv[i + 1]); - }else if(0 == strcmp(argv[i], "-efibase")) { + } else if(0 == strcmp(argv[i], "-efibase")) { ctxMain->cfg.qwEFI_IBI_SYST = Util_GetNumeric(argv[i + 1]); } else if(0 == strcmp(argv[i], "-iosize")) { ctxMain->cfg.qwMaxSizeDmaIo = Util_GetNumeric(argv[i + 1]); @@ -195,6 +196,50 @@ VOID PCILeechFreeContext() ctxMain = NULL; } +#ifdef _WIN32 +/* +* Call the free context functionality in a separate thread (in case it gets stuck). +* -- pv +*/ +VOID PCILeechCtrlHandler_TryShutdownThread(PVOID pv) +{ + __try { + PCILeechFreeContext(); + } __except(EXCEPTION_EXECUTE_HANDLER) { ; } +} + +/* +* SetConsoleCtrlHandler for PCILeech - clean up whenever CTRL+C is pressed. +* -- fdwCtrlType +* -- return +*/ +BOOL WINAPI PCILeechCtrlHandler(DWORD fdwCtrlType) +{ + if(fdwCtrlType == CTRL_C_EVENT) { + printf("CTRL+C detected - shutting down ...\n"); + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PCILeechCtrlHandler_TryShutdownThread, NULL, 0, NULL); + Sleep(500); + TerminateProcess(GetCurrentProcess(), 1); + Sleep(1000); + ExitProcess(1); + return TRUE; + } + return FALSE; +} + +VOID PCILeechCtrlHandlerInitialize() +{ + SetConsoleCtrlHandler(PCILeechCtrlHandler, TRUE); +} +#endif /* _WIN32 */ + +#ifdef LINUX +VOID PCILeechCtrlHandlerInitialize() +{ + return; +} +#endif /* LINUX */ + int main(_In_ int argc, _In_ char* argv[]) { BOOL result; @@ -245,6 +290,9 @@ int main(_In_ int argc, _In_ char* argv[]) return 1; } } + // enable ctrl+c event handler if remote (to circumvent blocking thread) + PCILeechCtrlHandlerInitialize(); + // main dispatcher switch(ctxMain->cfg.tpAction) { case DUMP: ActionMemoryDump(); @@ -298,6 +346,9 @@ int main(_In_ int argc, _In_ char* argv[]) case PSVIRT2PHYS: Action_UmdPsVirt2Phys(); break; + case AGENT_EXEC_PY: + ActionSvcExecPy(); + break; case KMDLOAD: if(ctxMain->cfg.qwKMD) { printf("KMD: Successfully loaded at address: 0x%08x\n", (DWORD)ctxMain->cfg.qwKMD); diff --git a/pcileech/pcileech.h b/pcileech/pcileech.h index 5a20beb..dfefa3e 100644 --- a/pcileech/pcileech.h +++ b/pcileech/pcileech.h @@ -44,7 +44,8 @@ typedef enum tdActionType { TLP, PROBE, PSLIST, - PSVIRT2PHYS + PSVIRT2PHYS, + AGENT_EXEC_PY } ACTION_TYPE; typedef struct tdCONFIG_OPTION { diff --git a/pcileech/pcileech.vcxproj b/pcileech/pcileech.vcxproj index d0abfc9..2ea9bd2 100644 --- a/pcileech/pcileech.vcxproj +++ b/pcileech/pcileech.vcxproj @@ -60,20 +60,20 @@ {DFFA1B4C-279B-4356-ADB1-08A6F4795931} pcileech - 10.0.17763.0 + 10.0 Application true - v141 + v142 Unicode false Application false - v141 + v142 false Unicode false @@ -81,7 +81,7 @@ Application false - v141 + v142 false Unicode false @@ -132,11 +132,11 @@ Console - copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y + copy "$(OutDir)leechcore.h" "$(ProjectDir)" /y - del "$(SolutionDir)\files\pcileech_files.zip" -powershell Compress-Archive -Path '$(SolutionDir)\files\*.*','$(SolutionDir)\files\pcileech' -DestinationPath '$(SolutionDir)\files\pcileech_files.zip' -Force -CompressionLevel Optimal + del "$(OutDir)pcileech_files.zip" +powershell Compress-Archive -Path '$(OutDir)*.*','$(OutDir)pcileech' -DestinationPath '$(OutDir)pcileech_files.zip' -Force -CompressionLevel Optimal @@ -163,11 +163,11 @@ powershell Compress-Archive -Path '$(SolutionDir)\files\*.*','$(SolutionDir)\fil $(SolutionDir)\files\leechcore.lib;%(AdditionalDependencies) - copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y + copy "$(OutDir)leechcore.h" "$(ProjectDir)" /y - del "$(SolutionDir)\files\pcileech_files.zip" -powershell Compress-Archive -Path '$(SolutionDir)\files\*.*','$(SolutionDir)\files\pcileech' -DestinationPath '$(SolutionDir)\files\pcileech_files.zip' -Force -CompressionLevel Optimal + del "$(OutDir)pcileech_files.zip" +powershell Compress-Archive -Path '$(OutDir)*.*','$(OutDir)pcileech' -DestinationPath '$(OutDir)pcileech_files.zip' -Force -CompressionLevel Optimal @@ -196,11 +196,11 @@ powershell Compress-Archive -Path '$(SolutionDir)\files\*.*','$(SolutionDir)\fil $(SolutionDir)\files\leechcore.lib;%(AdditionalDependencies) - copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y + copy "$(OutDir)leechcore.h" "$(ProjectDir)" /y - del "$(SolutionDir)\files\pcileech_files.zip" -powershell Compress-Archive -Path '$(SolutionDir)\files\*.*','$(SolutionDir)\files\pcileech' -DestinationPath '$(SolutionDir)\files\pcileech_files.zip' -Force -CompressionLevel Optimal + del "$(OutDir)pcileech_files.zip" +powershell Compress-Archive -Path '$(OutDir)*.*','$(OutDir)pcileech' -DestinationPath '$(OutDir)pcileech_files.zip' -Force -CompressionLevel Optimal diff --git a/pcileech/util.c b/pcileech/util.c index eb225df..383a078 100644 --- a/pcileech/util.c +++ b/pcileech/util.c @@ -693,41 +693,97 @@ VOID Util_WaitForPowerCycle() Util_WaitForPowerOn(); } -VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset) +#define Util_2HexChar(x) (((((x) & 0xf) <= 9) ? '0' : ('a' - 10)) + ((x) & 0xf)) + +#define UTIL_PRINTASCII \ + "................................ !\"#$%&'()*+,-./0123456789:;<=>?" \ + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz`{|}~" \ + "................................................................" \ + "................................................................" \ + +BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz) { - DWORD i, j; - if(cb > 0x10000) { - printf("Large output. Only displaying first 65kB.\n"); - cb = 0x10000 - cbInitialOffset; - } - cb += cbInitialOffset; + DWORD i, j, o = 0, szMax, iMod; + // checks + if((cbInitialOffset > cb) || (cbInitialOffset > 0x1000) || (cbInitialOffset & 0xf)) { return FALSE; } + *pcsz = szMax = cb * 5 + 80; + if(cb > szMax) { return FALSE; } + if(!sz) { return TRUE; } + // fill buffer with bytes for(i = cbInitialOffset; i < cb + ((cb % 16) ? (16 - cb % 16) : 0); i++) { // address if(0 == i % 16) { - printf("%04x ", i % 0x10000); + iMod = i % 0x10000; + sz[o++] = Util_2HexChar(iMod >> 12); + sz[o++] = Util_2HexChar(iMod >> 8); + sz[o++] = Util_2HexChar(iMod >> 4); + sz[o++] = Util_2HexChar(iMod); + sz[o++] = ' '; + sz[o++] = ' '; + sz[o++] = ' '; + sz[o++] = ' '; } else if(0 == i % 8) { - putchar(' '); + sz[o++] = ' '; } // hex if(i < cb) { - printf("%02x ", pb[i]); + sz[o++] = Util_2HexChar(pb[i] >> 4); + sz[o++] = Util_2HexChar(pb[i]); + sz[o++] = ' '; } else { - printf(" "); + sz[o++] = ' '; + sz[o++] = ' '; + sz[o++] = ' '; } // ascii if(15 == i % 16) { - printf(" "); + sz[o++] = ' '; + sz[o++] = ' '; for(j = i - 15; j <= i; j++) { if(j >= cb) { - putchar(' '); + sz[o++] = ' '; } else { - putchar(isprint(pb[j]) ? pb[j] : '.'); + sz[o++] = UTIL_PRINTASCII[pb[j]]; } } - putchar('\n'); + sz[o++] = '\n'; } } + sz[o++] = 0; + return TRUE; +} + +VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset) +{ + DWORD szMax; + LPSTR sz; + if(cb > 0x10000) { + printf("Large output. Only displaying first 65kB.\n"); + cb = 0x10000 - cbInitialOffset; + } + Util_FillHexAscii(pb, cb, cbInitialOffset, NULL, &szMax); + if(!(sz = LocalAlloc(0, szMax))) { return; } + Util_FillHexAscii(pb, cb, cbInitialOffset, sz, &szMax); + printf("%s", sz); + LocalFree(sz); +} + +#define UTIL_PRINTABLE_CHARACTERS_MAP "" \ + "0000000001100100000000000000000011111111111111111111111111111111" \ + "1111111111111111111111111111111111111111111111111111111111111110" \ + "1111111111111111111111111111111111111111111111111111111111111111" \ + "1111111111111111111111111111111111111111111111111111111111111110" + +VOID Util_AsciiFilter(_In_reads_(cb) PBYTE pb, _In_ DWORD cb) +{ + DWORD i; + CHAR ch; + for(i = 0; i < cb; i++) { + ch = pb[i]; + if(0xff & UTIL_PRINTABLE_CHARACTERS_MAP[ch]) { continue; } + pb[i] = '?'; + } } VOID Util_SplitString2(_In_ LPSTR sz, _In_ CHAR chSplit, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2) diff --git a/pcileech/util.h b/pcileech/util.h index 39a2621..8462dd8 100644 --- a/pcileech/util.h +++ b/pcileech/util.h @@ -231,6 +231,14 @@ VOID Util_WaitForPowerOn(); */ VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset); +/* +* Filter away (replace with '?') potentially harmful characters from an ascii +* string / text. +* -- pb +* -- cb +*/ +VOID Util_AsciiFilter(_In_reads_(cb) PBYTE pb, _In_ DWORD cb); + /* * Split a string into two at the first 'chSplit' character. If no 2nd string * is found then it's returned as null character '\0' (i.e. not as NULL). diff --git a/pcileech/version.h b/pcileech/version.h index 18c0eea..69e8662 100644 --- a/pcileech/version.h +++ b/pcileech/version.h @@ -2,7 +2,7 @@ #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_MAJOR 4 -#define VERSION_MINOR 0 +#define VERSION_MINOR 1 #define VERSION_REVISION 0 #define VERSION_BUILD 0 diff --git a/pcileech_gensig/pcileech_gensig.vcxproj b/pcileech_gensig/pcileech_gensig.vcxproj index 2f68e7f..8f851e3 100644 --- a/pcileech_gensig/pcileech_gensig.vcxproj +++ b/pcileech_gensig/pcileech_gensig.vcxproj @@ -17,13 +17,13 @@ {C55314C6-71A0-4AE2-A4F0-E5E531A5E065} pcileech_gensig - 10.0.17763.0 + 10.0 Application true - v141 + v142 Unicode @@ -32,7 +32,7 @@ Application false - v141 + v142 false Unicode false @@ -40,7 +40,7 @@ Application false - v141 + v142 false Unicode false diff --git a/pcileech_shellcode/pcileech_shellcode.vcxproj b/pcileech_shellcode/pcileech_shellcode.vcxproj index 115059d..fd0a71e 100644 --- a/pcileech_shellcode/pcileech_shellcode.vcxproj +++ b/pcileech_shellcode/pcileech_shellcode.vcxproj @@ -9,13 +9,13 @@ {5C698F13-6E9F-46F3-95FC-55376A65D8BF} pcileech_shellcode - 10.0.17763.0 + 10.0 Application false - v141 + v142 false Unicode false diff --git a/readme.md b/readme.md index 757a3a3..af09d1d 100644 --- a/readme.md +++ b/readme.md @@ -30,7 +30,9 @@ Capabilities: * Pull and Push files [Linux, FreeBSD, Windows, macOS Sierra*]. * Patch / Unlock (remove password requirement) [Windows, macOS Sierra*]. * Easy to create own kernel shellcode and/or custom signatures. -* Connect to a remote LeechService over the network. +* Connect to a remote LeechAgent over the network to remotely: + * Dump physical memory over the network. + * Execute Python memory analysis scripts on the remote host. * Even more features not listed here ... \*) macOS High Sierra and above are not supported. @@ -126,8 +128,11 @@ Dump all memory between addresses min and max, don't stop on failed pages. Nativ Force the usage of a specific device (instead of default auto detecting it). The pmem device is not auto detected. * ` pcileech.exe pagedisplay -min 0x1000 -device pmem ` -Dump remote memory from a remote LeechService using connection encrypted and mutually authenticated by kerberos. -* ` pcileech.exe dump -device pmem -remote rpc://computer$@ad.contoso.com ` +Dump remote memory from a remote LeechAgent running as `SYSTEM` on the computer `computer.ad.contoso.com` using connection encrypted and mutually authenticated by kerberos. +* ` pcileech.exe dump -device pmem -remote rpc://computer$@ad.contoso.com:computer.ad.contoso.com ` + +Execute the Python analysis script `example-find-rwx.py` on the remote computer `computer.ad.contoso.com` using the LeechAgent embedded Python environment. +* ` pcileech.exe agent-execpy -in example-find-rwx.py -device pmem -remote rpc://computer$@ad.contoso.com:computer.ad.contoso.com ` Dump memory using the the reported "TotalMeltdown" [Windows 7/2008R2 x64 PML4 page table permission vulnerability](https://blog.frizk.net/2018/03/total-meltdown.html). * ` pcileech.exe dump -out memdump_win7.raw -device totalmeltdown -v -force ` @@ -146,6 +151,7 @@ Limitations/Known Issues: * 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. * File system mount support only exists for Windows. +* Remote connectivity support only exists for Windows. Building: ========= @@ -183,3 +189,6 @@ v1.1-v3.6 * remote devices via -remote setting. * Removal of API and built-in _Memory Process File System_ - please use the more capable APIs in the [LeechCore](https://github.com/ufrisk/LeechCore) and [Memory Process File System](https://github.com/ufrisk/MemProcFS) instead. * Multiple other changes and syntax updates. + +v4.1 +* LeechAgent support - remote memory acquisition and analysis. diff --git a/usb3380_flash/windows/USB3380Flash_Installer/USB3380Flash_Installer.vcxproj b/usb3380_flash/windows/USB3380Flash_Installer/USB3380Flash_Installer.vcxproj index 339988c..833f9e3 100644 --- a/usb3380_flash/windows/USB3380Flash_Installer/USB3380Flash_Installer.vcxproj +++ b/usb3380_flash/windows/USB3380Flash_Installer/USB3380Flash_Installer.vcxproj @@ -18,21 +18,21 @@ {F2F4AA4A-BEFE-4738-9412-820007919334} Win32Proj PCILeechFlash_Installer - 10.0.17763.0 + 10.0 USB3380Flash_installer Application true - v141 + v142 Unicode false Application false - v141 + v142 true Unicode false @@ -40,7 +40,7 @@ Application false - v141 + v142 true Unicode false