diff --git a/README.md b/README.md index 36c941a..3ba7765 100644 --- a/README.md +++ b/README.md @@ -200,3 +200,6 @@ v1.0-1.8 * Bug fixes. * Visual Studio 2022 Support. * New write fpga algorithm. + +[v2.12](https://github.com/ufrisk/LeechCore/releases/tag/v2.12) +* Support for MemProcFS v5. diff --git a/includes/lib32/leechcore.lib b/includes/lib32/leechcore.lib index dcb9035..0c89baf 100644 Binary files a/includes/lib32/leechcore.lib and b/includes/lib32/leechcore.lib differ diff --git a/includes/lib64/leechcore.lib b/includes/lib64/leechcore.lib index b4a13c9..0dd8c68 100644 Binary files a/includes/lib64/leechcore.lib and b/includes/lib64/leechcore.lib differ diff --git a/leechagent/leechagent_procchild.c b/leechagent/leechagent_procchild.c index 191a6ad..1a46176 100644 --- a/leechagent/leechagent_procchild.c +++ b/leechagent/leechagent_procchild.c @@ -25,6 +25,10 @@ #define VMMDLL_VFS_FILELISTBLOB_VERSION 0xf88f0001 +typedef struct tdVMM_HANDLE *VMM_HANDLE; + +static VMM_HANDLE g_hVMM = NULL; + typedef struct tdVMMDLL_VFS_FILELISTBLOB_OPAQUE { DWORD dwVersion; // VMMDLL_VFS_FILELISTBLOB_VERSION DWORD cbStruct; @@ -37,14 +41,15 @@ typedef struct tdPROCCHILD_CONTEXT { HMODULE hDllPython3; HMODULE hDllPython3X; HMODULE hDllLeechCorePyC; - BOOL(*pfnVMMDLL_Initialize)(_In_ DWORD argc, _In_ LPSTR argv[]); - BOOL(*pfnVMMDLL_InitializePlugins)(); - BOOL(*pfnVMMDLL_Close)(); - PVMMDLL_VFS_FILELISTBLOB_OPAQUE(*pfnVMMDLL_VfsListBlobU)(LPSTR); - DWORD(*pfnVMMDLL_VfsReadU)(_In_ LPSTR uszFileName, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset); - DWORD(*pfnVMMDLL_VfsWriteU)(_In_ LPSTR uszFileName, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset); - BOOL(*pfnVMMDLL_ConfigGet)(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue); - BOOL(*pfnVMMDLL_ConfigSet)(_In_ ULONG64 fOption, _In_ ULONG64 qwValue); + VMM_HANDLE(*pfnVMMDLL_Initialize)(_In_ DWORD argc, _In_ LPSTR argv[]); + BOOL(*pfnVMMDLL_InitializePlugins)(VMM_HANDLE); + BOOL(*pfnVMMDLL_Close)(VMM_HANDLE); + VOID(*pfnVMMDLL_MemFree)(PVOID); + PVMMDLL_VFS_FILELISTBLOB_OPAQUE(*pfnVMMDLL_VfsListBlobU)(VMM_HANDLE, LPSTR); + DWORD(*pfnVMMDLL_VfsReadU)(VMM_HANDLE, _In_ LPSTR uszFileName, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset); + DWORD(*pfnVMMDLL_VfsWriteU)(VMM_HANDLE, _In_ LPSTR uszFileName, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset); + BOOL(*pfnVMMDLL_ConfigGet)(VMM_HANDLE, _In_ ULONG64 fOption, _Out_ PULONG64 pqwValue); + BOOL(*pfnVMMDLL_ConfigSet)(VMM_HANDLE, _In_ ULONG64 fOption, _In_ ULONG64 qwValue); BOOL(*pfnLeechCorePyC_EmbPythonInitialize)(_In_ HMODULE hDllPython); BOOL(*pfnLeechCorePyC_EmbExecPyInMem)(_In_ LPSTR szPythonProgram); VOID(*pfnLeechCorePyC_EmbClose)(); @@ -69,29 +74,35 @@ BOOL LeechAgent_ProcChild_InitializeVmm() szVMM_ARGUMENTS[2] = ctxProcChild.szDevice; szVMM_ARGUMENTS[4] = ctxProcChild.szRemote; ctxProcChild.hDllVmm = LoadLibraryExA("vmm.dll", NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR); + if(!ctxProcChild.hDllVmm) { + ctxProcChild.hDllVmm = LoadLibraryA("vmm.dll"); + } if(!ctxProcChild.hDllVmm) { fprintf(stderr, "LeechAgent: FAIL: CHILD could not locate/load MemProcFS library vmm.dll\n"); return FALSE; } - ctxProcChild.pfnVMMDLL_Initialize = (BOOL(*)(DWORD, LPSTR*))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_Initialize"); - ctxProcChild.pfnVMMDLL_InitializePlugins = (BOOL(*)())GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_InitializePlugins"); - ctxProcChild.pfnVMMDLL_Close = (BOOL(*)())GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_Close"); - ctxProcChild.pfnVMMDLL_VfsListBlobU = (PVMMDLL_VFS_FILELISTBLOB_OPAQUE(*)(LPSTR))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_VfsListBlobU"); - ctxProcChild.pfnVMMDLL_VfsReadU = (DWORD(*)(LPSTR, PBYTE, DWORD, PDWORD, ULONG64))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_VfsReadU"); - ctxProcChild.pfnVMMDLL_VfsWriteU = (DWORD(*)(LPSTR, PBYTE, DWORD, PDWORD, ULONG64))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_VfsWriteU"); - ctxProcChild.pfnVMMDLL_ConfigGet = (BOOL(*)(ULONG64, PULONG64))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_ConfigGet"); - ctxProcChild.pfnVMMDLL_ConfigSet = (BOOL(*)(ULONG64, ULONG64))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_ConfigSet"); + ctxProcChild.pfnVMMDLL_Initialize = (VMM_HANDLE(*)(DWORD, LPSTR*))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_Initialize"); + ctxProcChild.pfnVMMDLL_InitializePlugins = (BOOL(*)(VMM_HANDLE))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_InitializePlugins"); + ctxProcChild.pfnVMMDLL_Close = (BOOL(*)(VMM_HANDLE))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_Close"); + ctxProcChild.pfnVMMDLL_MemFree = (VOID(*)(PVOID))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_MemFree"); + ctxProcChild.pfnVMMDLL_VfsListBlobU = (PVMMDLL_VFS_FILELISTBLOB_OPAQUE(*)(VMM_HANDLE, LPSTR))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_VfsListBlobU"); + ctxProcChild.pfnVMMDLL_VfsReadU = (DWORD(*)(VMM_HANDLE, LPSTR, PBYTE, DWORD, PDWORD, ULONG64))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_VfsReadU"); + ctxProcChild.pfnVMMDLL_VfsWriteU = (DWORD(*)(VMM_HANDLE, LPSTR, PBYTE, DWORD, PDWORD, ULONG64))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_VfsWriteU"); + ctxProcChild.pfnVMMDLL_ConfigGet = (BOOL(*)(VMM_HANDLE, ULONG64, PULONG64))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_ConfigGet"); + ctxProcChild.pfnVMMDLL_ConfigSet = (BOOL(*)(VMM_HANDLE, ULONG64, ULONG64))GetProcAddress(ctxProcChild.hDllVmm, "VMMDLL_ConfigSet"); if(!ctxProcChild.pfnVMMDLL_Initialize || !ctxProcChild.pfnVMMDLL_InitializePlugins || !ctxProcChild.pfnVMMDLL_Close) { fprintf(stderr, "LeechAgent: FAIL: CHILD could not load MemProcFS library functions.\n"); return FALSE; } - result = ctxProcChild.pfnVMMDLL_Initialize((sizeof(szVMM_ARGUMENTS) / sizeof(LPCSTR)), szVMM_ARGUMENTS); - if(!result) { + g_hVMM = ctxProcChild.pfnVMMDLL_Initialize((sizeof(szVMM_ARGUMENTS) / sizeof(LPCSTR)), szVMM_ARGUMENTS); + if(!g_hVMM) { fprintf(stderr, "LeechAgent: FAIL: CHILD could not initialize MemProcFS library.\n"); return FALSE; } - result = ctxProcChild.pfnVMMDLL_InitializePlugins(); + result = ctxProcChild.pfnVMMDLL_InitializePlugins(g_hVMM); if(!result) { + ctxProcChild.pfnVMMDLL_Close(g_hVMM); + g_hVMM = NULL; fprintf(stderr, "LeechAgent: FAIL: CHILD could not initialize MemProcFS Plugins.\n"); return FALSE; } @@ -113,7 +124,7 @@ BOOL LeechAgent_ProcChild_VmmVfsList(_In_ PLC_CMD_AGENT_VFS_REQ pReq, _Out_ PLC_ PVMMDLL_VFS_FILELISTBLOB_OPAQUE pBlob = NULL; pReq->uszPathFile[_countof(pReq->uszPathFile) - 1] = 0; if(!ctxProcChild.pfnVMMDLL_VfsListBlobU) { goto fail; } - if(!(pBlob = ctxProcChild.pfnVMMDLL_VfsListBlobU(pReq->uszPathFile))) { goto fail; } + if(!(pBlob = ctxProcChild.pfnVMMDLL_VfsListBlobU(g_hVMM, pReq->uszPathFile))) { goto fail; } if((pBlob->dwVersion != VMMDLL_VFS_FILELISTBLOB_VERSION) || (pBlob->cbStruct > 0x04000000)) { goto fail; } if(!(pRsp = LocalAlloc(0, sizeof(LC_CMD_AGENT_VFS_RSP) + pBlob->cbStruct))) { goto fail; } ZeroMemory(pRsp, sizeof(LC_CMD_AGENT_VFS_RSP)); @@ -123,7 +134,7 @@ BOOL LeechAgent_ProcChild_VmmVfsList(_In_ PLC_CMD_AGENT_VFS_REQ pReq, _Out_ PLC_ *pcbRsp = sizeof(LC_CMD_AGENT_VFS_RSP) + pRsp->cb; *ppRsp = pRsp; fail: - LocalFree(pBlob); + ctxProcChild.pfnVMMDLL_MemFree(pBlob); return pRsp ? TRUE : FALSE; } @@ -145,7 +156,7 @@ BOOL LeechAgent_ProcChild_VmmVfsRead(_In_ PLC_CMD_AGENT_VFS_REQ pReq, _Out_ PLC_ if(!(pRsp = LocalAlloc(0, sizeof(LC_CMD_AGENT_VFS_RSP) + pReq->dwLength))) { return FALSE; } ZeroMemory(pRsp, sizeof(LC_CMD_AGENT_VFS_RSP)); pRsp->dwVersion = LC_CMD_AGENT_VFS_RSP_VERSION; - pRsp->dwStatus = ctxProcChild.pfnVMMDLL_VfsReadU(pReq->uszPathFile, pRsp->pb, pReq->dwLength, &pRsp->cbReadWrite, pReq->qwOffset); + pRsp->dwStatus = ctxProcChild.pfnVMMDLL_VfsReadU(g_hVMM, pReq->uszPathFile, pRsp->pb, pReq->dwLength, &pRsp->cbReadWrite, pReq->qwOffset); pRsp->cb = pRsp->cbReadWrite; *pcbRsp = sizeof(LC_CMD_AGENT_VFS_RSP) + pRsp->cb; *ppRsp = pRsp; @@ -168,7 +179,7 @@ BOOL LeechAgent_ProcChild_VmmVfsWrite(_In_ PLC_CMD_AGENT_VFS_REQ pReq, _Out_ PLC pReq->uszPathFile[_countof(pReq->uszPathFile) - 1] = 0; if(!(pRsp = LocalAlloc(LMEM_ZEROINIT, sizeof(LC_CMD_AGENT_VFS_RSP)))) { return FALSE; } pRsp->dwVersion = LC_CMD_AGENT_VFS_RSP_VERSION; - pRsp->dwStatus = ctxProcChild.pfnVMMDLL_VfsWriteU(pReq->uszPathFile, pReq->pb, pReq->cb, &pRsp->cbReadWrite, pReq->qwOffset); + pRsp->dwStatus = ctxProcChild.pfnVMMDLL_VfsWriteU(g_hVMM, pReq->uszPathFile, pReq->pb, pReq->cb, &pRsp->cbReadWrite, pReq->qwOffset); *pcbRsp = sizeof(LC_CMD_AGENT_VFS_RSP); *ppRsp = pRsp; return TRUE; @@ -190,7 +201,7 @@ BOOL LeechAgent_ProcChild_VmmVfsConfigGet(_In_ PLC_CMD_AGENT_VFS_REQ pReq, _Out_ if(!ctxProcChild.pfnVMMDLL_ConfigGet) { return FALSE; } if(!(pRsp = LocalAlloc(LMEM_ZEROINIT, sizeof(LC_CMD_AGENT_VFS_RSP) + sizeof(QWORD)))) { return FALSE; } pRsp->dwVersion = LC_CMD_AGENT_VFS_RSP_VERSION; - pRsp->dwStatus = (DWORD)ctxProcChild.pfnVMMDLL_ConfigGet(pReq->fOption, (PULONG64)pRsp->pb); + pRsp->dwStatus = (DWORD)ctxProcChild.pfnVMMDLL_ConfigGet(g_hVMM, pReq->fOption, (PULONG64)pRsp->pb); pRsp->cb = sizeof(QWORD); *pcbRsp = sizeof(LC_CMD_AGENT_VFS_RSP) + sizeof(QWORD); *ppRsp = pRsp; @@ -214,7 +225,7 @@ BOOL LeechAgent_ProcChild_VmmVfsConfigSet(_In_ PLC_CMD_AGENT_VFS_REQ pReq, _Out_ if(!ctxProcChild.pfnVMMDLL_ConfigSet || (pReq->cb != sizeof(QWORD))) { return FALSE; } if(!(pRsp = LocalAlloc(LMEM_ZEROINIT, sizeof(LC_CMD_AGENT_VFS_RSP)))) { return FALSE; } pRsp->dwVersion = LC_CMD_AGENT_VFS_RSP_VERSION; - pRsp->dwStatus = (DWORD)ctxProcChild.pfnVMMDLL_ConfigSet(pReq->fOption, *(PULONG64)pReq->pb); + pRsp->dwStatus = (DWORD)ctxProcChild.pfnVMMDLL_ConfigSet(g_hVMM, pReq->fOption, *(PULONG64)pReq->pb); *pcbRsp = sizeof(LC_CMD_AGENT_VFS_RSP); *ppRsp = pRsp; return TRUE; diff --git a/leechagent/version.h b/leechagent/version.h index cc5c565..181aec5 100644 --- a/leechagent/version.h +++ b/leechagent/version.h @@ -2,9 +2,9 @@ #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_MAJOR 2 -#define VERSION_MINOR 11 -#define VERSION_REVISION 1 -#define VERSION_BUILD 48 +#define VERSION_MINOR 12 +#define VERSION_REVISION 0 +#define VERSION_BUILD 49 #define VER_FILE_DESCRIPTION_STR "LeechAgent Memory Acquisition Service" #define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD diff --git a/leechcore/device_pmem.c b/leechcore/device_pmem.c index 7e2c96b..543bcce 100644 --- a/leechcore/device_pmem.c +++ b/leechcore/device_pmem.c @@ -269,24 +269,30 @@ VOID DevicePMEM_Close(_Inout_ PLC_CONTEXT ctxLC) } _Success_(return) -BOOL DevicePMEM_GetMemoryInformation(_Inout_ PLC_CONTEXT ctxLC) +BOOL DevicePMEM_GetMemoryInformation(_Inout_ PLC_CONTEXT ctxLC, _In_ BOOL fFirst) { PDEVICE_CONTEXT_PMEM ctx = (PDEVICE_CONTEXT_PMEM)ctxLC->hDevice; DWORD i, cbRead, dwMode = PMEM_MODE_PTE; // 1: retrieve information from kernel driver if(!DeviceIoControl(ctx->hFile, PMEM_INFO_IOCTRL, NULL, 0, &ctx->MemoryInfo, sizeof(ctx->MemoryInfo), &cbRead, NULL)) { - lcprintf(ctxLC, "DEVICE: ERROR: Unable to communicate with winpmem driver.\n"); + if(!fFirst) { + lcprintf(ctxLC, "DEVICE: ERROR: Unable to communicate with winpmem driver.\n"); + } return FALSE; } // 2: sanity checks if((ctx->MemoryInfo.NumberOfRuns.QuadPart == 0) || (ctx->MemoryInfo.NumberOfRuns.QuadPart > 100)) { - lcprintf(ctxLC, "DEVICE: ERROR: too few/many memory segments reported from winpmem driver. (%lli)\n", ctx->MemoryInfo.NumberOfRuns.QuadPart); + if(!fFirst) { + lcprintf(ctxLC, "DEVICE: ERROR: too few/many memory segments reported from winpmem driver. (%lli)\n", ctx->MemoryInfo.NumberOfRuns.QuadPart); + } return FALSE; } // 3: parse memory ranges for(i = 0; i < ctx->MemoryInfo.NumberOfRuns.QuadPart; i++) { if(!LcMemMap_AddRange(ctxLC, ctx->MemoryInfo.Run[i].start, ctx->MemoryInfo.Run[i].length, ctx->MemoryInfo.Run[i].start)) { - lcprintf(ctxLC, "DEVICE: FAIL: unable to add range to memory map. (%016llx %016llx %016llx)\n", ctx->MemoryInfo.Run[i].start, ctx->MemoryInfo.Run[i].length, ctx->MemoryInfo.Run[i].start); + if(!fFirst) { + lcprintf(ctxLC, "DEVICE: FAIL: unable to add range to memory map. (%016llx %016llx %016llx)\n", ctx->MemoryInfo.Run[i].start, ctx->MemoryInfo.Run[i].length, ctx->MemoryInfo.Run[i].start); + } return FALSE; } } @@ -342,7 +348,7 @@ BOOL DevicePMEM_GetOption(_In_ PLC_CONTEXT ctxLC, _In_ QWORD fOption, _Out_ PQWO } _Success_(return) -BOOL DevicePMEM_Open2(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_CONFIG_ERRORINFO ppLcCreateErrorInfo) +BOOL DevicePMEM_Open2(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_CONFIG_ERRORINFO ppLcCreateErrorInfo, _In_ BOOL fFirst) { BOOL result; PDEVICE_CONTEXT_PMEM ctx; @@ -360,7 +366,7 @@ BOOL DevicePMEM_Open2(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_CONFIG_ERRORINFO g_cDevicePMEM++; result = DevicePMEM_SvcStatusRunning(ctxLC) || DevicePMEM_SvcStart(ctxLC); // 3: retrieve memory map. - result = result && DevicePMEM_GetMemoryInformation(ctxLC); + result = result && DevicePMEM_GetMemoryInformation(ctxLC, fFirst); if(!result) { DevicePMEM_Close(ctxLC); return FALSE; @@ -375,9 +381,9 @@ BOOL DevicePMEM_Open(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_CONFIG_ERRORINFO // Sometimes communication with PMEM driver will fail even though the driver // is loaded. It's unknown why this is happening. But it always helps trying // again so wrap the open function to perform a retry if there is a fail. - if(DevicePMEM_Open2(ctxLC, ppLcCreateErrorInfo)) { return TRUE; } + if(DevicePMEM_Open2(ctxLC, ppLcCreateErrorInfo, TRUE)) { return TRUE; } Sleep(100); - return DevicePMEM_Open2(ctxLC, ppLcCreateErrorInfo); + return DevicePMEM_Open2(ctxLC, ppLcCreateErrorInfo, FALSE); } #endif /* _WIN32 */ diff --git a/leechcore/oscompatibility.c b/leechcore/oscompatibility.c index 9154483..0ac6088 100644 --- a/leechcore/oscompatibility.c +++ b/leechcore/oscompatibility.c @@ -212,9 +212,6 @@ HMODULE LoadLibraryA(LPSTR lpFileName) if(lpFileName && (0 == memcmp(lpFileName, "FTD2XX.dll", 10))) { lpFileName = "libftd2xx.so"; } - if(!strstr(lpFileName, "/")) { - Util_GetPathLib(szFileName); - } strncat(szFileName, lpFileName, MAX_PATH); return dlopen(szFileName, RTLD_NOW); } diff --git a/leechcore/version.h b/leechcore/version.h index 938c26b..48f59c8 100644 --- a/leechcore/version.h +++ b/leechcore/version.h @@ -2,9 +2,9 @@ #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_MAJOR 2 -#define VERSION_MINOR 11 -#define VERSION_REVISION 1 -#define VERSION_BUILD 48 +#define VERSION_MINOR 12 +#define VERSION_REVISION 0 +#define VERSION_BUILD 49 #define VER_FILE_DESCRIPTION_STR "LeechCore Memory Acquisition Library" #define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD diff --git a/leechcorepyc/pkggen_linux.sh b/leechcorepyc/pkggen_linux.sh index 014ea69..0689302 100644 --- a/leechcorepyc/pkggen_linux.sh +++ b/leechcorepyc/pkggen_linux.sh @@ -39,7 +39,7 @@ leechcorepyc = Extension( setup( name='leechcorepyc', - version='2.11.1', # VERSION_END + version='2.12.0', # VERSION_END description='LeechCore for Python', long_description='LeechCore for Python : native extension for physical memory access', url='https://github.com/ufrisk/LeechCore', diff --git a/leechcorepyc/version.h b/leechcorepyc/version.h index 4c1bf55..d01b586 100644 --- a/leechcorepyc/version.h +++ b/leechcorepyc/version.h @@ -2,9 +2,9 @@ #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_MAJOR 2 -#define VERSION_MINOR 11 -#define VERSION_REVISION 1 -#define VERSION_BUILD 48 +#define VERSION_MINOR 12 +#define VERSION_REVISION 0 +#define VERSION_BUILD 49 #define VER_FILE_DESCRIPTION_STR "LeechCore Memory Acquisition Library : Python API" #define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD