diff --git a/README.md b/README.md index 3695088..edee4a9 100644 --- a/README.md +++ b/README.md @@ -143,3 +143,7 @@ v2.1 * IAT/EAT hook functionality. * Limited Windows 10 MemCompression support. * Bug fixes. + +v2.2 +* New API: + * Force refresh of process list and caches. diff --git a/files/vmm.dll b/files/vmm.dll index 838340e..4adf8c4 100644 Binary files a/files/vmm.dll and b/files/vmm.dll differ diff --git a/files/vmm.lib b/files/vmm.lib index 7be0dfa..30509c6 100644 Binary files a/files/vmm.lib and b/files/vmm.lib differ diff --git a/files/vmmdll.h b/files/vmmdll.h index 42befa8..6b1e71b 100644 --- a/files/vmmdll.h +++ b/files/vmmdll.h @@ -4,7 +4,7 @@ // (c) Ulf Frisk, 2018-2019 // Author: Ulf Frisk, pcileech@frizk.net // -// Header Version: 2.1 +// Header Version: 2.2 // #include @@ -50,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); //----------------------------------------------------------------------------- diff --git a/files/vmmpy.py b/files/vmmpy.py index 65d65fe..8db72fb 100644 --- a/files/vmmpy.py +++ b/files/vmmpy.py @@ -62,6 +62,19 @@ def VmmPy_Close(): +def VmmPy_Refresh(): + """Force refresh the internal state of the VMM.DLL - refreshing process listings and internal caches. NB! function may take a long time to execute! + + Keyword arguments: + N/A + + Example: + VmmPy_Refresh() + """ + VMMPYC_Refresh(0) + + + def VmmPy_Initialize(args, is_printf = True, is_verbose = False, is_verbose_extra = False, is_verbose_tlp = False, page_table_base = 0): """Initialize VmmPy and the Virtual Memory Manager VMM.DLL with arguments as in the argument list args. Important is the -device option and optionally diff --git a/files/vmmpyc.pyd b/files/vmmpyc.pyd index 0b9a4c2..66638a8 100644 Binary files a/files/vmmpyc.pyd and b/files/vmmpyc.pyd differ diff --git a/vmm/m_status.c b/vmm/m_status.c index d6ea7ad..70b2302 100644 --- a/vmm/m_status.c +++ b/vmm/m_status.c @@ -172,7 +172,7 @@ NTSTATUS MStatus_Write(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWO if(nt == VMMDLL_STATUS_SUCCESS) { ctxVmm->flags &= ~VMM_FLAG_PROCESS_SHOW_TERMINATED; ctxVmm->flags |= fEnable ? VMM_FLAG_PROCESS_SHOW_TERMINATED : 0; - VmmProc_Refresh(TRUE); + VmmProc_RefreshProcesses(TRUE); } return nt; } diff --git a/vmm/pluginmanager.c b/vmm/pluginmanager.c index 75d745f..d0a15a4 100644 --- a/vmm/pluginmanager.c +++ b/vmm/pluginmanager.c @@ -305,6 +305,7 @@ BOOL PluginManager_Initialize() if(ctxVmm->pVmmVfsModuleList) { return FALSE; } // already initialized ZeroMemory(&ri, sizeof(VMMDLL_PLUGIN_REGINFO)); // 1: process built-in modules + EnterCriticalSection(&ctxVmm->MasterLock); PluginManager_Initialize_RegInfoInit(&ri, NULL); M_Virt2Phys_Initialize(&ri); PluginManager_Initialize_RegInfoInit(&ri, NULL); @@ -344,5 +345,6 @@ BOOL PluginManager_Initialize() } // 3: process 'special status' python plugin manager. PluginManager_Initialize_Python(); + LeaveCriticalSection(&ctxVmm->MasterLock); return TRUE; } diff --git a/vmm/statistics.c b/vmm/statistics.c index ca23bcd..44164da 100644 --- a/vmm/statistics.c +++ b/vmm/statistics.c @@ -77,7 +77,7 @@ VOID _PageStatShowUpdate(_Inout_ PPAGE_STATISTICS ps) " Pages read: %llu / %llu (%llu%%) \n" \ " Pages failed: %llu (%llu%%) \n", ps->szAction, - ps->fKMD ? "KMD (kernel module assisted DMA)" : "DMA (hardware only) ", + ps->fKMD ? "KMD (kernel module assisted DMA)" : "Normal ", (ps->cPageSuccess + ps->cPageFail) / 256, ps->cPageTotal / 256, qwPercentTotal, @@ -99,7 +99,7 @@ VOID _PageStatShowUpdate(_Inout_ PPAGE_STATISTICS ps) " Pages read: %llu \n" \ " Pages failed: %llu \n", ps->szAction, - ps->fKMD ? "KMD (kernel module assisted DMA)" : "DMA (hardware only) ", + ps->fKMD ? "KMD (kernel module assisted DMA)" : "Normal ", (ps->cPageSuccess + ps->cPageFail) / 256, (isMBs ? qwSpeed >> 10 : qwSpeed), (isMBs ? "MB/s" : "kB/s"), @@ -202,6 +202,7 @@ const LPSTR NAMES_VMM_STATISTICS_CALL[] = { "VMMDLL_WinGetThunkEAT", "VMMDLL_WinGetThunkIAT", "VMMDLL_WinMemCompression_DecompressPage", + "VMMDLL_Refresh", "PluginManager_List", "PluginManager_Read", "PluginManager_Write", diff --git a/vmm/statistics.h b/vmm/statistics.h index 298f28c..11dc164 100644 --- a/vmm/statistics.h +++ b/vmm/statistics.h @@ -92,11 +92,12 @@ VOID PageStatUpdate(_In_opt_ PPAGE_STATISTICS pPageStat, _In_ QWORD qwAddr, _In_ #define STATISTICS_ID_VMMDLL_WinGetThunkEAT 0x16 #define STATISTICS_ID_VMMDLL_WinGetThunkIAT 0x17 #define STATISTICS_ID_VMMDLL_WinMemCompression_DecompressPage 0x18 -#define STATISTICS_ID_PluginManager_List 0x19 -#define STATISTICS_ID_PluginManager_Read 0x1a -#define STATISTICS_ID_PluginManager_Write 0x1b -#define STATISTICS_ID_PluginManager_Notify 0x1c -#define STATISTICS_ID_MAX 0x1c +#define STATISTICS_ID_VMMDLL_Refresh 0x19 +#define STATISTICS_ID_PluginManager_List 0x1a +#define STATISTICS_ID_PluginManager_Read 0xab +#define STATISTICS_ID_PluginManager_Write 0x1c +#define STATISTICS_ID_PluginManager_Notify 0x1d +#define STATISTICS_ID_MAX 0x1d #define STATISTICS_ID_NOLOG 0xffffffff VOID Statistics_CallSetEnabled(_In_ BOOL fEnabled); diff --git a/vmm/version.h b/vmm/version.h index 5720f62..b428978 100644 --- a/vmm/version.h +++ b/vmm/version.h @@ -2,7 +2,7 @@ #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_MAJOR 2 -#define VERSION_MINOR 1 +#define VERSION_MINOR 2 #define VERSION_REVISION 0 #define VERSION_BUILD 0 diff --git a/vmm/vmm.c b/vmm/vmm.c index 30b9181..5a11a06 100644 --- a/vmm/vmm.c +++ b/vmm/vmm.c @@ -383,10 +383,22 @@ VOID VmmCacheClear(_In_ WORD wTblTag) { DWORD i; PVMM_CACHE_TABLE t; + PVMM_PROCESS pObProcess = NULL; + // 1: clear cache t = VmmCacheTableGet(wTblTag); for(i = 0; i < VMM_CACHE2_REGIONS; i++) { VmmCacheReclaim(t, i, TRUE); } + // 2: if tlb cache clear -> update process 'is spider done' flag + if(wTblTag == VMM_CACHE_TAG_TLB) { + while((pObProcess = VmmProcessGetNext(pObProcess))) { + if(pObProcess->fTlbSpiderDone) { + EnterCriticalSection(&pObProcess->LockUpdate); + pObProcess->fTlbSpiderDone = FALSE; + LeaveCriticalSection(&pObProcess->LockUpdate); + } + } + } } VOID VmmCache_CallbackRefCount1(PVMMOB_MEM pOb) diff --git a/vmm/vmmdll.c b/vmm/vmmdll.c index c946933..b1abad6 100644 --- a/vmm/vmmdll.c +++ b/vmm/vmmdll.c @@ -491,6 +491,42 @@ BOOL VMMDLL_VfsInitializePlugins() PluginManager_Initialize()) } + + +//----------------------------------------------------------------------------- +// REFRESH FUNCTIONALITY BELOW: +//----------------------------------------------------------------------------- + +_Success_(return) +BOOL VMMDLL_Refresh_Impl(_In_ DWORD dwReserved) +{ + ULONG64 paMax; + // enforce global lock even if 'multi thread' is enabled + // we wish to avoid parallel process refreshes ... + EnterCriticalSection(&ctxVmm->MasterLock); + VmmCacheClear(VMM_CACHE_TAG_PHYS); + VmmCacheClear(VMM_CACHE_TAG_TLB); + VmmProc_RefreshProcesses(TRUE); + // update max physical address (if volatile). + if(ctxMain->dev.fVolatileMaxAddress) { + if(LeechCore_GetOption(LEECHCORE_OPT_MEMORYINFO_ADDR_MAX, &paMax) && (paMax > 0x01000000)) { + ctxMain->dev.paMax = paMax; + } + } + LeaveCriticalSection(&ctxVmm->MasterLock); + return TRUE; +} + +_Success_(return) +BOOL VMMDLL_Refresh(_In_ DWORD dwReserved) +{ + CALL_SYNCHRONIZED_IMPLEMENTATION_VMM( + STATISTICS_ID_VMMDLL_Refresh, + VMMDLL_Refresh_Impl(dwReserved)) +} + + + //----------------------------------------------------------------------------- // VMM CORE FUNCTIONALITY BELOW: //----------------------------------------------------------------------------- diff --git a/vmm/vmmdll.def b/vmm/vmmdll.def index 5e61a51..ce972b7 100644 --- a/vmm/vmmdll.def +++ b/vmm/vmmdll.def @@ -2,6 +2,7 @@ LIBRARY VMM EXPORTS VMMDLL_Initialize VMMDLL_Close + VMMDLL_Refresh VMMDLL_ConfigGet VMMDLL_ConfigSet diff --git a/vmm/vmmdll.h b/vmm/vmmdll.h index 42befa8..6b1e71b 100644 --- a/vmm/vmmdll.h +++ b/vmm/vmmdll.h @@ -4,7 +4,7 @@ // (c) Ulf Frisk, 2018-2019 // Author: Ulf Frisk, pcileech@frizk.net // -// Header Version: 2.1 +// Header Version: 2.2 // #include @@ -50,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); //----------------------------------------------------------------------------- diff --git a/vmm/vmmproc.c b/vmm/vmmproc.c index 6fa488a..5c35a74 100644 --- a/vmm/vmmproc.c +++ b/vmm/vmmproc.c @@ -37,7 +37,7 @@ BOOL VmmProcUserCR3TryInitialize64() return TRUE; } -BOOL VmmProc_Refresh(_In_ BOOL fRefreshTotal) +BOOL VmmProc_RefreshProcesses(_In_ BOOL fRefreshTotal) { BOOL result; PVMM_PROCESS pObProcessSystem; @@ -116,7 +116,7 @@ DWORD VmmProcCacheUpdaterThread() } // refresh proc list if(fProcPartial || fProcTotal) { - if(!VmmProc_Refresh(fProcTotal)) { + if(!VmmProc_RefreshProcesses(fProcTotal)) { vmmprintf("VmmProc: Failed to refresh memory process file system - aborting.\n"); LeaveCriticalSection(&ctxVmm->MasterLock); goto fail; diff --git a/vmm/vmmproc.h b/vmm/vmmproc.h index 595b02c..2fbf814 100644 --- a/vmm/vmmproc.h +++ b/vmm/vmmproc.h @@ -12,7 +12,7 @@ * -- fRefreshTotal = full refresh of processes should be done instead of partial. * -- return */ -BOOL VmmProc_Refresh(_In_ BOOL fRefreshTotal); +BOOL VmmProc_RefreshProcesses(_In_ BOOL fRefreshTotal); /* * Load operating system dependant module names, such as parsed from PE or ELF diff --git a/vmmpyc/version.h b/vmmpyc/version.h index 3faa79f..a2ebf60 100644 --- a/vmmpyc/version.h +++ b/vmmpyc/version.h @@ -2,7 +2,7 @@ #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_MAJOR 2 -#define VERSION_MINOR 1 +#define VERSION_MINOR 2 #define VERSION_REVISION 0 #define VERSION_BUILD 0 diff --git a/vmmpyc/vmmdll.h b/vmmpyc/vmmdll.h index 42befa8..6b1e71b 100644 --- a/vmmpyc/vmmdll.h +++ b/vmmpyc/vmmdll.h @@ -4,7 +4,7 @@ // (c) Ulf Frisk, 2018-2019 // Author: Ulf Frisk, pcileech@frizk.net // -// Header Version: 2.1 +// Header Version: 2.2 // #include @@ -50,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); //----------------------------------------------------------------------------- diff --git a/vmmpyc/vmmpyc.c b/vmmpyc/vmmpyc.c index 0bb625b..c3d03a5 100644 --- a/vmmpyc/vmmpyc.c +++ b/vmmpyc/vmmpyc.c @@ -58,6 +58,20 @@ VMMPYC_Close(PyObject *self, PyObject *args) return Py_BuildValue("s", NULL); // None returned on success. } +// (DWORD) -> None +static PyObject* +VMMPYC_Refresh(PyObject *self, PyObject *args) +{ + BOOL result; + DWORD dwReserved = 0; + if(!PyArg_ParseTuple(args, "k", &dwReserved)) { return NULL; } + Py_BEGIN_ALLOW_THREADS; + result = VMMDLL_Refresh(dwReserved); + Py_END_ALLOW_THREADS; + if(!result) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_Refresh: Refresh failed."); } + return Py_BuildValue("s", NULL); // None returned on success. +} + //----------------------------------------------------------------------------- @@ -946,6 +960,7 @@ VMMPYC_VfsList(PyObject *self, PyObject *args) static PyMethodDef VMMPYC_EmbMethods[] = { {"VMMPYC_Initialize", VMMPYC_Initialize, METH_VARARGS, "Initialize the VMM"}, {"VMMPYC_Close", VMMPYC_Close, METH_VARARGS, "Try close the VMM"}, + {"VMMPYC_Refresh", VMMPYC_Refresh, METH_VARARGS, "Force refresh the VMM (process listings and caches)."}, {"VMMPYC_ConfigGet", VMMPYC_ConfigGet, METH_VARARGS, "Get a device specific option value."}, {"VMMPYC_ConfigSet", VMMPYC_ConfigSet, METH_VARARGS, "Set a device specific option value."}, {"VMMPYC_MemReadScatter", VMMPYC_MemReadScatter, METH_VARARGS, "Read multiple 4kB page sized and aligned chunks of memory given as an address list."},