fix: python plugin deadlock issue.

This commit is contained in:
Ulf Frisk
2019-03-16 15:55:06 +01:00
parent 5891fabbac
commit 09dd33976c
5 changed files with 145 additions and 20 deletions

Binary file not shown.

View File

@@ -68,13 +68,14 @@
// placed in same directory as the executable file.
//
// PMEM : load the rekall winpmem driver into the kernel and connect to it
// to acquire memory. The driver file 'winpmem_x64.sys' is found in
// the Rekall directory after most recent version has been installed.
// Copy 'winpmem_x64.sys' to the directory of leechcore.dll and run
// executable as elevated admin using syntax below:
// to acquire memory. The signed driver `.sys` file may be found at:
// https://github.com/Velocidex/c-aff4/tree/master/tools/pmem/resources/winpmem
// Download the driver file `att_winpmem_64.sys` and copy it to the
// directory of leechcore.dll and run executable as elevated admin
// using syntax below:
// Syntax:
// PMEM (use winpmem_x64.sys in directory of executable)
// PMEM://<non_default_path_to_file_winpmem_x64.sys>
// PMEM (use att_winpmem_64.sys in directory of executable)
// PMEM://<non_default_path_to_file_winpmem_64.sys>
//
// TOTALMELTDOWN : read/write - requires a Windows 7 system vulnerable to the
// "Total Meltdown" vulnerability - CVE-2018-1038.
@@ -110,7 +111,7 @@
// (c) Ulf Frisk, 2018-2019
// Author: Ulf Frisk, pcileech@frizk.net
//
// Header Version: 1.0
// Header Version: 1.1.0
//
#ifndef __LEECHCORE_H__
#define __LEECHCORE_H__
@@ -151,6 +152,7 @@ typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64;
#define _Printf_format_string_
#define _Inout_updates_bytes_(x)
#define _In_reads_(cbDataIn)
#define _Out_writes_opt_(x)
#define _Success_(return)
#endif /* LINUX */
@@ -227,7 +229,10 @@ typedef struct tdLEECHCORE_PAGESTAT_MINIMAL {
} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL;
/*
* Open a connection to the target device.
* Open a connection to the target device. The LeechCore initialization may fail
* if the underlying device cannot be opened or if the LeechCore is already
* initialized. If already initialized please connect with device EXISTING or
* call LeechCore_Close() before opening a new device.
* -- pInformation
* -- result
*/
@@ -455,9 +460,9 @@ DLLEXPORT BOOL LeechCore_CommandData(
_In_ ULONG64 fOption,
_In_reads_(cbDataIn) PBYTE pbDataIn,
_In_ DWORD cbDataIn,
_Out_writes_(cbDataOut) PBYTE pbDataOut,
_Out_writes_opt_(cbDataOut) PBYTE pbDataOut,
_In_ DWORD cbDataOut,
_Out_ PDWORD pcbDataOut
_Out_opt_ PDWORD pcbDataOut
);
#ifdef __cplusplus

View File

@@ -2,8 +2,8 @@
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_MAJOR 2
#define VERSION_MINOR 0
#define VERSION_REVISION 0
#define VERSION_MINOR 2
#define VERSION_REVISION 1
#define VERSION_BUILD 0
#define VER_FILE_DESCRIPTION_STR "The Memory Process File System : Python Plugin Manager"

View File

@@ -4,7 +4,7 @@
// (c) Ulf Frisk, 2018-2019
// Author: Ulf Frisk, pcileech@frizk.net
//
// Header Version: 2.0
// Header Version: 2.2
//
#include <windows.h>
@@ -26,13 +26,15 @@ extern "C" {
* about the parameters please see github wiki for Memory Process File System
* and LeechCore. THIS IS THE PREFERED WAY OF INITIALIZING VMM.DLL
* Important parameters are:
* -vdll = show printf style outputs)
* -printf = show printf style outputs)
* -v -vv -vvv = extra verbosity levels)
* -device = device as on format for LeechCore - please see leechcore.h or
* Github documentation for additional information. Some values
* are: <file>, fpga, usb3380, hvsavedstate, totalmeltdown, pmem
* -remote = remote LeechCore instance - please see leechcore.h or Github
* documentation for additional information.
* -norefresh = disable background refreshes (even if backing memory is
* volatile memory).
* -- argc
* -- argv
* -- return = success/fail
@@ -48,6 +50,17 @@ BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]);
_Success_(return)
BOOL VMMDLL_Close();
/*
* Perform a force refresh of all internal caches including:
* - process listings
* - memory cache
* - page table cache
* WARNING: function may take some time to execute!
* -- dwReserved = reserved future use - must be zero
* -- return = sucess/fail
*/
_Success_(return)
BOOL VMMDLL_Refresh(_In_ DWORD dwReserved);
//-----------------------------------------------------------------------------
@@ -289,7 +302,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
* -- ppMEMs = array of scatter read headers.
* -- cpMEMs = count of ppDMAs.
* -- pcpDMAsRead = optional count of number of successfully read ppDMAs.
* -- flags = optional flags as given by VMM_FLAG_*
* -- flags = optional flags as given by VMMDLL_FLAG_*
* -- return = the number of successfully read items.
*/
DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags);
@@ -322,13 +335,25 @@ BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DW
* -- pb
* -- cb
* -- pcbRead
* -- flags = flags as in VMM_FLAG_*
* -- flags = flags as in VMMDLL_FLAG_*
* -- return = success/fail. NB! reads may report as success even if 0 bytes are
* read - it's recommended to verify pcbReadOpt parameter.
*/
_Success_(return)
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
/*
* Prefetch a number of addresses (specified in the pA array) into the memory
* cache. This function is to be used to batch larger known reads into local
* cache before making multiple smaller reads - which will then happen from
* the cache. Function exists for performance reasons.
* -- dwPID = PID of target process, (DWORD)-1 for physical memory.
* -- pPrefetchAddresses = array of addresses to read into cache.
* -- cPrefetchAddresses
*/
_Success_(return)
BOOL VMMDLL_MemPrefetchPages(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses, _In_ DWORD cPrefetchAddresses);
/*
* Write a contigious arbitrary amount of memory. Please note some virtual memory
* such as pages of executables (such as DLLs) may be shared between different
@@ -527,6 +552,87 @@ BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMD
_Success_(return)
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
/*
* Retrieve the virtual address of a given function inside a process/module.
* -- dwPID
* -- szModuleName
* -- szFunctionName
* -- return = virtual address of function, zero on fail.
*/
ULONG64 VMMDLL_ProcessGetProcAddress(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szFunctionName);
/*
* Retrieve the base address of a given module.
* -- dwPID
* -- szModuleName
* -- return = virtual address of module base, zero on fail.
*/
ULONG64 VMMDLL_ProcessGetModuleBase(_In_ DWORD dwPID, _In_ LPSTR szModuleName);
//-----------------------------------------------------------------------------
// WINDOWS SPECIFIC UTILITY FUNCTIONS BELOW:
//-----------------------------------------------------------------------------
typedef struct tdVMMDLL_WIN_THUNKINFO_IAT {
BOOL fValid;
BOOL f32; // if TRUE fn is a 32-bit/4-byte entry, otherwise 64-bit/8-byte entry.
ULONG64 vaThunk; // address of import address table 'thunk'.
ULONG64 vaFunction; // value if import address table 'thunk' == address of imported function.
ULONG64 vaNameModule; // address of name string for imported module.
ULONG64 vaNameFunction; // address of name string for imported function.
} VMMDLL_WIN_THUNKINFO_IAT, *PVMMDLL_WIN_THUNKINFO_IAT;
typedef struct tdVMMDLL_WIN_THUNKINFO_EAT {
BOOL fValid;
DWORD valueThunk; // value of export address table 'thunk'.
ULONG64 vaThunk; // address of import address table 'thunk'.
ULONG64 vaNameFunction; // address of name string for exported function.
ULONG64 vaFunction; // address of exported function (module base + value parameter).
} VMMDLL_WIN_THUNKINFO_EAT, *PVMMDLL_WIN_THUNKINFO_EAT;
/*
* Retrieve information about the import address table IAT thunk for an imported
* function. This includes the virtual address of the IAT thunk which is useful
* for hooking.
* -- dwPID
* -- szModuleName
* -- szImportModuleName
* -- szImportFunctionName
* -- pThunkIAT
* -- return
*/
_Success_(return)
BOOL VMMDLL_WinGetThunkInfoIAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT);
/*
* Retrieve information about the export address table EAT thunk for an exported
* function. This includes the virtual address of the EAT thunk which is useful
* for hooking.
* -- dwPID
* -- szModuleName
* -- pThunkEAT
* -- return
*/
_Success_(return)
BOOL VMMDLL_WinGetThunkInfoEAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szExportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_EAT pThunkInfoEAT);
/*
* Decompress compressed memory page stored in the MemCompression process.
* -- vaCompressedData = virtual address in 'MemCompression' to decompress.
* -- cbCompressedData = length of compressed data in 'MemCompression' to decompress (or zero for auto-detect).
* -- pbDecompressedPage
* -- pcbCompressedData = optional ptr to receive length of compressed buffer.
* -- return
*/
_Success_(return)
BOOL VMMDLL_WinMemCompression_DecompressPage(
_In_ ULONG64 vaCompressedData,
_In_opt_ DWORD cbCompressedData,
_Out_writes_(4096) PBYTE pbDecompressedPage,
_Out_opt_ PDWORD pcbCompressedData
);
//-----------------------------------------------------------------------------

View File

@@ -279,7 +279,7 @@ VOID VmmPyPlugin_UpdateVerbosity()
}
}
#define PYTHON_PATH_MAX 4*MAX_PATH
#define PYTHON_PATH_MAX 7*MAX_PATH
#define PYTHON_PATH_DELIMITER L";"
BOOL VmmPyPlugin_PythonInitialize(_In_ HMODULE hDllPython)
{
@@ -299,14 +299,26 @@ BOOL VmmPyPlugin_PythonInitialize(_In_ HMODULE hDllPython)
wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBasePython);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"python36.zip");
// 2.3: python lib
// 2.3: python dlls
wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBasePython);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"DLLs\\");
// 2.4: python lib
wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBasePython);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"Lib\\");
// 2.4: .exe location of this process
// 2.5: python lib\site-packages (python pip)
wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBasePython);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"Lib\\site-packages\\");
// 2.6: .exe location of this process
wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBaseExe);
// 3: Initialize Embedded Python.
// 2.7: pylib relative to this process
wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBaseExe);
wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"pylib\\");
// 3: Initialize (Embedded) Python.
Py_SetProgramName(L"VmmPyPluginManager");
Py_SetPath(wszPathPython);
if(ctxPY2C->fVerboseExtra) {
@@ -314,6 +326,7 @@ BOOL VmmPyPlugin_PythonInitialize(_In_ HMODULE hDllPython)
}
PY2C_InitializeModuleVMMPYCC();
Py_Initialize();
PyEval_InitThreads();
// 4: Import VmmPyPlugin library/file to start the python part of the plugin manager.
pName = PyUnicode_DecodeFSDefault("vmmpyplugin");
if(!pName) { goto fail; }
@@ -322,6 +335,7 @@ BOOL VmmPyPlugin_PythonInitialize(_In_ HMODULE hDllPython)
// 5: Cleanups
Py_DECREF(pName);
Py_DECREF(pModule);
PyEval_ReleaseLock();
return TRUE;
fail:
if(pName) { Py_DECREF(pName); }