Version 5.18

This commit is contained in:
Ulf Frisk
2026-07-25 22:13:29 +02:00
parent d8f8b95de9
commit e3b10a943f
56 changed files with 5624 additions and 168 deletions
+5 -2
View File
@@ -223,7 +223,6 @@ v5.8
* Bug fixes.
* updates (FindEvil, New signatures, etc.).
* New APIs for Kernel Objects, Drivers and Devices.
</details>
[v5.13](https://github.com/ufrisk/MemProcFS/releases/tag/v5.13)
* Bug fixes.
@@ -242,6 +241,7 @@ v5.8
* Linux LeechAgent support using gRPC (LeechCore v2.21).
* New FindEvil detection: High Entropy.
* [DNS cache parsing](https://github.com/ufrisk/MemProcFS/wiki/FS_SysInfo_Network). Thanks [@MattCore71](https://github.com/MattCore71) for the contribution.
</details>
[v5.16](https://github.com/ufrisk/MemProcFS/releases/tag/v5.16)
* Bug fixes.
@@ -254,6 +254,9 @@ v5.8
* New optional logging callback in the API.
* Support for non-ascii characters in file paths.
Latest:
[v5.18](https://github.com/ufrisk/MemProcFS/releases/tag/v5.18)
* Bug fixes.
* New module: Windows Terminal parser (Win11+).
* New forensic module: amcache parser (Win10+).
* PTE map upper limit adjusted from 65536 to 131072.
* Fix: File writes in WSL mounted MemProcFS (drvfs) now works.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+3 -3
View File
@@ -2,9 +2,9 @@
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_MAJOR 5
#define VERSION_MINOR 17
#define VERSION_REVISION 9
#define VERSION_BUILD 238
#define VERSION_MINOR 18
#define VERSION_REVISION 0
#define VERSION_BUILD 239
#define VER_FILE_DESCRIPTION_STR "MemProcFS : Plugin vmemd"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
+61 -8
View File
@@ -23,8 +23,7 @@
#define VER_OSARCH "Windows"
typedef struct tdVMMVFS_CONFIG {
FILETIME ftDefaultTime;
NTSTATUS(*DokanNtStatusFromWin32)(DWORD Error);
FILETIME ftDefaultTime;
BOOL fInitialized;
} VMMVFS_CONFIG, *PVMMVFS_CONFIG;
@@ -39,6 +38,25 @@ CHAR g_VfsMountPoint = 'M';
// DOKAN CALLBACK FUNCTIONS BELOW:
//-------------------------------------------------------------------------------
NTSTATUS
VfsDokanCallback_CreateFile_ExistingDisposition(_In_ ULONG CreateDisposition)
{
// Dokan passes the native NtCreateFile FILE_* disposition values here,
// not the similarly numbered Win32 CreateFile CREATE_*/OPEN_* values.
switch(CreateDisposition) {
case FILE_OPEN:
case FILE_OVERWRITE:
return STATUS_SUCCESS;
case FILE_SUPERSEDE:
case FILE_CREATE:
case FILE_OPEN_IF:
case FILE_OVERWRITE_IF:
return STATUS_OBJECT_NAME_COLLISION;
default:
return STATUS_INVALID_PARAMETER;
}
}
NTSTATUS
VfsDokanCallback_CreateFile_Impl(_In_ LPSTR uszFullPath, PDOKAN_IO_SECURITY_CONTEXT SecurityContext, ACCESS_MASK DesiredAccess, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PDOKAN_FILE_INFO DokanFileInfo)
{
@@ -51,19 +69,25 @@ VfsDokanCallback_CreateFile_Impl(_In_ LPSTR uszFullPath, PDOKAN_IO_SECURITY_CONT
if(!ctxVfs || !ctxVfs->fInitialized) { return STATUS_FILE_INVALID; }
// root directory
if(!strcmp(uszFullPath, "\\")) {
if(CreateDisposition == CREATE_ALWAYS) { return ctxVfs->DokanNtStatusFromWin32(ERROR_ACCESS_DENIED); }
DokanFileInfo->IsDirectory = TRUE;
return STATUS_SUCCESS;
if(CreateOptions & FILE_NON_DIRECTORY_FILE) { return STATUS_FILE_IS_A_DIRECTORY; }
if((CreateDisposition == FILE_SUPERSEDE) || (CreateDisposition == FILE_OVERWRITE) || (CreateDisposition == FILE_OVERWRITE_IF)) { return STATUS_FILE_IS_A_DIRECTORY; }
return VfsDokanCallback_CreateFile_ExistingDisposition(CreateDisposition);
}
// other files
if(CreateDisposition == CREATE_ALWAYS) { return ctxVfs->DokanNtStatusFromWin32(ERROR_ACCESS_DENIED); }
uszFile = CharUtil_PathSplitLastEx(uszFullPath, uszPath, sizeof(uszPath));
if(!VfsList_GetSingle(uszPath[0] ? uszPath : "\\", uszFile, &VfsEntry, &fIsDirectoryExisting)) {
return fIsDirectoryExisting ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_OBJECT_PATH_NOT_FOUND;
}
DokanFileInfo->Nocache = TRUE;
if(!DokanFileInfo->IsDirectory && (CreateOptions & FILE_DIRECTORY_FILE)) { return STATUS_NOT_A_DIRECTORY; } // fail upon open normal file as directory
return (CreateDisposition == OPEN_ALWAYS) ? STATUS_OBJECT_NAME_COLLISION : STATUS_SUCCESS;
DokanFileInfo->IsDirectory = VfsEntry.fDirectory;
if(VfsEntry.fDirectory) {
if(CreateOptions & FILE_NON_DIRECTORY_FILE) { return STATUS_FILE_IS_A_DIRECTORY; }
if((CreateDisposition == FILE_SUPERSEDE) || (CreateDisposition == FILE_OVERWRITE) || (CreateDisposition == FILE_OVERWRITE_IF)) { return STATUS_FILE_IS_A_DIRECTORY; }
} else if(CreateOptions & FILE_DIRECTORY_FILE) {
return STATUS_NOT_A_DIRECTORY;
}
return VfsDokanCallback_CreateFile_ExistingDisposition(CreateDisposition);
}
NTSTATUS DOKAN_CALLBACK
@@ -172,6 +196,32 @@ VfsDokanCallback_WriteFile(LPCWSTR wcsFileName, LPCVOID Buffer, DWORD NumberOfBy
return nt;
}
NTSTATUS DOKAN_CALLBACK
VfsDokanCallback_SetFileSize(LPCWSTR wcsFileName, LONGLONG ByteOffset, PDOKAN_FILE_INFO DokanFileInfo)
{
if(!ctxVfs || !ctxVfs->fInitialized) { return STATUS_FILE_INVALID; }
if(ByteOffset < 0) { return STATUS_INVALID_PARAMETER; }
// MemProcFS files have a fixed virtual size. Acknowledge advisory allocation
// and end-of-file changes and let writes update the virtual file by path.
return STATUS_SUCCESS;
}
NTSTATUS DOKAN_CALLBACK
VfsDokanCallback_SetFileAttributes(LPCWSTR wcsFileName, DWORD FileAttributes, PDOKAN_FILE_INFO DokanFileInfo)
{
if(!ctxVfs || !ctxVfs->fInitialized) { return STATUS_FILE_INVALID; }
// File attributes are synthesized by MemProcFS and cannot be persisted.
return STATUS_SUCCESS;
}
NTSTATUS DOKAN_CALLBACK
VfsDokanCallback_SetFileTime(LPCWSTR wcsFileName, CONST FILETIME *CreationTime, CONST FILETIME *LastAccessTime, CONST FILETIME *LastWriteTime, PDOKAN_FILE_INFO DokanFileInfo)
{
if(!ctxVfs || !ctxVfs->fInitialized) { return STATUS_FILE_INVALID; }
// File timestamps are synthesized by MemProcFS and cannot be persisted.
return STATUS_SUCCESS;
}
//-------------------------------------------------------------------------------
// VFS INITIALIZATION FUNCTIONALITY BELOW:
//-------------------------------------------------------------------------------
@@ -303,7 +353,6 @@ VOID VfsDokan_InitializeAndMount(_In_ CHAR chMountPoint)
// set vfs context
GetSystemTime(&SystemTimeNow);
SystemTimeToFileTime(&SystemTimeNow, &ctxVfs->ftDefaultTime);
ctxVfs->DokanNtStatusFromWin32 = (NTSTATUS(*)(DWORD))GetProcAddress(hModuleDokan, "DokanNtStatusFromWin32");
ctxVfs->fInitialized = TRUE;
// set options
pDokanOptions->Version = DOKAN_VERSION;
@@ -319,6 +368,10 @@ VOID VfsDokan_InitializeAndMount(_In_ CHAR chMountPoint)
pDokanOperations->FindFiles = VfsDokanCallback_FindFiles;
pDokanOperations->ReadFile = VfsDokanCallback_ReadFile;
pDokanOperations->WriteFile = VfsDokanCallback_WriteFile;
pDokanOperations->SetFileAttributes = VfsDokanCallback_SetFileAttributes;
pDokanOperations->SetFileTime = VfsDokanCallback_SetFileTime;
pDokanOperations->SetEndOfFile = VfsDokanCallback_SetFileSize;
pDokanOperations->SetAllocationSize = VfsDokanCallback_SetFileSize;
// print system information to console
VfsDokan_InitializeAndMount_DisplayInfo(wszMountPoint);
// mount file system
+3
View File
@@ -652,6 +652,7 @@ VOID ObMap_FilterSet_FilterAllKey(_In_opt_ PVOID ctx, _In_ POB_SET ps, _In_ QWOR
/*
* Filter map objects into a generic context by using a user-supplied filter function.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* -- pm
* -- ctx = optional context to pass on to the filter function.
* -- pfnFilterCB = filter callback function. NULL = fail.
@@ -662,6 +663,7 @@ BOOL ObMap_Filter(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTE
/*
* Filter map objects into a POB_SET by using a user-supplied filter function.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* CALLER DECREF: return
* -- pm
* -- ctx = optional context to pass on to the filter function.
@@ -689,6 +691,7 @@ typedef int(*OB_MAP_SORT_COMPARE_FUNCTION)(_In_ POB_MAP_ENTRY e1, _In_ POB_MAP_E
* Sort the ObMap entry index by a sort compare function.
* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects
* which points to the underlying map object key/value.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* -- pm
* -- pfnSort = sort function callback. const void* == const OB_MAP_ENTRY*
* -- return
+4 -4
View File
@@ -28,7 +28,7 @@
* Allocate a new object manager memory object.
* -- H = an optional handle to embed as OB.H in the header.
* -- tag = tag of the object to be allocated.
* -- uFlags = flags as given by LocalAlloc.
* -- uFlags = flags as given by LocalAlloc, 0 (LMEM_FIXED) or LMEM_ZEROINIT.
* -- uBytes = bytes of object (_including_ object headers).
* -- pfnRef_0 = optional callback for cleanup o be called before object is destroyed.
* (if object has references that should be decremented before destruction).
@@ -39,7 +39,7 @@ PVOID Ob_AllocEx(_In_opt_ VMM_HANDLE H, _In_ DWORD tag, _In_ UINT uFlags, _In_ S
{
POB pOb;
if((uBytes > 0x40000000) || (uBytes < sizeof(OB))) { return NULL; }
pOb = (POB)LocalAlloc(uFlags, uBytes + OB_DEBUG_FOOTER_SIZE);
pOb = (POB)LocalAlloc(uFlags & LMEM_ZEROINIT, uBytes + OB_DEBUG_FOOTER_SIZE);
if(!pOb) { return NULL; }
pOb->_magic1 = OB_HEADER_MAGIC;
pOb->_magic2 = OB_HEADER_MAGIC;
@@ -101,16 +101,16 @@ PVOID Ob_XDECREF(_In_opt_ PVOID pObIn)
}
#endif /* OB_DEBUG */
if(c == 0) {
if(pOb->_pfnRef_0) { pOb->_pfnRef_0(pOb); }
pOb->_magic1 = 0;
pOb->_magic2 = 0;
if(pOb->_pfnRef_0) { pOb->_pfnRef_0(pOb); }
#ifdef OB_DEBUG_MEMZERO
ZeroMemory(pOb, sizeof(OB) + pOb->cbData);
#endif /* OB_DEBUG_MEMZERO */
LocalFree(pOb);
} else if((c == 1) && pOb->_pfnRef_1) {
pOb->_pfnRef_1(pOb);
return pOb;
return ((pOb->_magic2 == OB_HEADER_MAGIC) && (pOb->_magic1 == OB_HEADER_MAGIC)) ? pOb : NULL;
} else {
return pOb;
}
+4 -2
View File
@@ -535,6 +535,7 @@ QWORD ObMap_PeekKey(_In_opt_ POB_MAP pm)
/*
* Filter map objects into a generic context by using a user-supplied filter function.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* -- pm
* -- ctx = optional context to pass on to the filter function.
* -- pfnFilterCB
@@ -549,6 +550,7 @@ BOOL ObMap_Filter(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTE
/*
* Filter map objects into a POB_SET by using a user-supplied filter function.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* CALLER DECREF: return
* -- pm
* -- ctx = optional context to pass on to the filter function.
@@ -763,8 +765,8 @@ int _ObMap_SortEntryIndexByKey_CmpSort(_In_ POB_MAP_ENTRY e1, _In_ POB_MAP_ENTRY
/*
* Sort the ObMap entry index by a sort compare function.
* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects
* which points to the underlying map object key/value.
* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects which points to the underlying map object key/value.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* -- pm
* -- pfnSort = sort function callback. const void* == const OB_MAP_ENTRY*
* -- return
+1
View File
@@ -464,6 +464,7 @@ _Success_(return)
BOOL _ObSet_PushSet(_In_ POB_SET pvs, _In_opt_ POB_SET pvsSrc)
{
DWORD iValue;
if(pvs == pvsSrc) { return FALSE; }
if(pvsSrc) {
AcquireSRWLockShared(&pvsSrc->LockSRW);
for(iValue = pvsSrc->c - 1; iValue; iValue--) {
+3 -3
View File
@@ -2,9 +2,9 @@
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_MAJOR 5
#define VERSION_MINOR 17
#define VERSION_REVISION 9
#define VERSION_BUILD 238
#define VERSION_MINOR 18
#define VERSION_REVISION 0
#define VERSION_BUILD 239
#define VER_FILE_DESCRIPTION_STR "MemProcFS"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
+3 -1
View File
@@ -27,6 +27,7 @@ OBJ = oscompatibility.o charutil.o util.o pe.o vmmdll.o vmmdll_core.o \
mm/mm_vad.o mm/mm_win.o \
pluginmanager.o pdb.o infodb.o \
ext/lz4.o ext/miniz.o ext/sha256.o ext/sqlite3.o \
ext/sqlite_vfs_memprocfs.o \
ob/ob_bytequeue.o ob/ob_cachemap.o ob/ob_compressed.o \
ob/ob_container.o ob/ob_core.o ob/ob_counter.o ob/ob_map.o \
ob/ob_memfile.o ob/ob_set.o ob/ob_strmap.o \
@@ -36,6 +37,7 @@ OBJ = oscompatibility.o charutil.o util.o pe.o vmmdll.o vmmdll_core.o \
vmmyarautil.o vmmyarawrap.o \
modules/m_vfsroot.o modules/m_vfsproc.o modules/m_vfsfc.o \
modules/m_conf.o modules/m_vm.o modules/m_winreg.o \
modules/m_fc_amcache.o \
modules/m_fc_csv.o modules/m_fc_file.o modules/m_fc_findevil.o \
modules/m_fc_handle.o modules/m_fc_json.o modules/m_fc_module.o \
modules/m_fc_ntfs.o modules/m_fc_prefetch.o modules/m_fc_proc.o \
@@ -58,7 +60,7 @@ OBJ = oscompatibility.o charutil.o util.o pe.o vmmdll.o vmmdll_core.o \
modules/m_proc_heap.o modules/m_proc_ldrmodules.o \
modules/m_proc_memmap.o modules/m_proc_minidump.o \
modules/m_proc_thread.o modules/m_proc_token.o \
modules/m_proc_virt2phys.o
modules/m_proc_virt2phys.o modules/m_proc_winterm.o
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
+3 -1
View File
@@ -19,6 +19,7 @@ OBJ = oscompatibility.o charutil.o util.o pe.o vmmdll.o vmmdll_core.o \
mm/mm_vad.o mm/mm_win.o \
pluginmanager.o pdb.o infodb.o \
ext/lz4.o ext/miniz.o ext/sha256.o ext/sqlite3.o \
ext/sqlite_vfs_memprocfs.o \
ob/ob_bytequeue.o ob/ob_cachemap.o ob/ob_compressed.o \
ob/ob_container.o ob/ob_core.o ob/ob_counter.o ob/ob_map.o \
ob/ob_memfile.o ob/ob_set.o ob/ob_strmap.o \
@@ -28,6 +29,7 @@ OBJ = oscompatibility.o charutil.o util.o pe.o vmmdll.o vmmdll_core.o \
vmmyarautil.o vmmyarawrap.o \
modules/m_vfsroot.o modules/m_vfsproc.o modules/m_vfsfc.o \
modules/m_conf.o modules/m_vm.o modules/m_winreg.o \
modules/m_fc_amcache.o \
modules/m_fc_csv.o modules/m_fc_file.o modules/m_fc_findevil.o \
modules/m_fc_handle.o modules/m_fc_json.o modules/m_fc_module.o \
modules/m_fc_ntfs.o modules/m_fc_prefetch.o modules/m_fc_proc.o \
@@ -50,7 +52,7 @@ OBJ = oscompatibility.o charutil.o util.o pe.o vmmdll.o vmmdll_core.o \
modules/m_proc_heap.o modules/m_proc_ldrmodules.o \
modules/m_proc_memmap.o modules/m_proc_minidump.o \
modules/m_proc_thread.o modules/m_proc_token.o \
modules/m_proc_virt2phys.o
modules/m_proc_virt2phys.o modules/m_proc_winterm.o
# ARCH SPECIFIC FLAGS:
CFLAGS_X86_64 = $(CFLAGS) -arch x86_64
File diff suppressed because it is too large Load Diff
+62
View File
@@ -0,0 +1,62 @@
/*
* sqlite_vfs_memprocfs.h
*
* Read-only SQLite VFS for opening a SQLite main database and its WAL from
* caller-owned memory buffers. Designed to be compiled directly into a program
* that already embeds the SQLite amalgamation.
*
* Public API:
*
* int MemProcFS_SqliteVfsRegister(void);
*
* int MemProcFS_SqliteVfsOpen(
* const unsigned char *pbDatabase,
* sqlite3_int64 cbDatabase,
* const unsigned char *pbWal,
* sqlite3_int64 cbWal,
* sqlite3 **ppDatabase);
*
* int MemProcFS_SqliteVfsClose(sqlite3 *pDatabase);
*
* int MemProcFS_SqliteVfsPrepareReadOnly(
* sqlite3 *pDatabase,
* const char *zSql,
* sqlite3_stmt **ppStatement);
*
* int MemProcFS_SqliteVfsResetProgress(sqlite3 *pDatabase);
*
* int MemProcFS_SqliteVfsSetProgressLimit(
* sqlite3 *pDatabase,
* sqlite3_uint64 cVmOperations);
*
* The input buffers are borrowed, not copied. They must remain valid and
* unchanged until MemProcFS_SqliteVfsClose() (or sqlite3_close()) succeeds.
*
* WAL support uses SQLite's single-client, exclusive-locking mode. Therefore
* the sqlite3_io_methods object intentionally has iVersion == 1 and does not
* implement xShmMap/xShmLock. MemProcFS_SqliteVfsOpen() sets
* PRAGMA locking_mode=EXCLUSIVE before the first schema access.
*
* This implementation exposes only the main database and optional WAL as
* memory-backed files. It fails closed for every other filename and never
* delegates file access or dynamic-library loading to the host VFS. SQLite
* temporary storage is forced into memory.
*
* The connection is hardened for attacker-controlled database bytes: trusted
* schema is disabled; triggers and views are disabled; defensive and query-only
* modes are enabled; ATTACH, PRAGMA, writes, virtual tables and extension loading
* are blocked; limits and a progress budget constrain resource consumption.
*
* Compile this file together with sqlite3.c and include the matching sqlite3.h.
* Do not build SQLite with SQLITE_OMIT_WAL.
*/
#include "sqlite3.h"
/* Forward declarations for the public API. */
int MemProcFS_SqliteVfsRegister(void);
int MemProcFS_SqliteVfsOpen(const unsigned char *pbDatabase, sqlite3_int64 cbDatabase, const unsigned char *pbWal, sqlite3_int64 cbWal, sqlite3 **ppDatabase);
int MemProcFS_SqliteVfsClose(sqlite3 *pDatabase);
int MemProcFS_SqliteVfsPrepareReadOnly(sqlite3 *pDatabase, const char *zSql, sqlite3_stmt **ppStatement);
int MemProcFS_SqliteVfsResetProgress(sqlite3 *pDatabase);
int MemProcFS_SqliteVfsSetProgressLimit(sqlite3 *pDatabase, sqlite3_uint64 cVmOperations);
+7 -7
View File
@@ -16,11 +16,10 @@
#include "fc.h"
#include "vmmdll.h"
#include "pdb.h"
#include "vmmwin.h"
#include "vmmwinobj.h"
#include "vmmwinreg.h"
#include "pluginmanager.h"
#include "ext/sqlite3.h"
#include "ext/sqlite_vfs_memprocfs.h"
#include "statistics.h"
#include "charutil.h"
#include "infodb.h"
@@ -444,7 +443,7 @@ VOID FcEvilInitialize_ThreadProc(_In_ VMM_HANDLE H, _In_ QWORD qwNotUsed)
/*
* FindEvil compare / sort function.
* Sorts on Severity, PID, Address.
* Sorts on Severity (1), PID (2), Address (3), Description(4).
*/
int FcEvilFinalize_CmpSort(_In_ POB_MAP_ENTRY e1, _In_ POB_MAP_ENTRY e2)
{
@@ -459,8 +458,8 @@ int FcEvilFinalize_CmpSort(_In_ POB_MAP_ENTRY e1, _In_ POB_MAP_ENTRY e2)
// 3: Address
if(pe1->va < pe2->va) { return -1; }
if(pe1->va > pe2->va) { return 1; }
// 4: Hash of Description
return CharUtil_Hash32U(pe1->usz, FALSE) - CharUtil_Hash32U(pe2->usz, FALSE);
// 4: strcmp description
return strcmp(pe1->usz, pe2->usz);
}
/*
@@ -1502,12 +1501,12 @@ VOID FcInitialize_ThreadProc(_In_ VMM_HANDLE H, _In_ QWORD qwNotUsed)
FCINITIALIZE_PROGRESS_UPDATE(10);
// parallel async init of: scan virtual per-process/kernel address space & init of log for CSV/JSON.
VmmWork_Value(H, FcScanObjectAndVirtmem_ThreadProc, 0, hEventAsyncIngestObjectAndVirtmem, VMMWORK_FLAG_PRIO_NORMAL);
VmmWork_Void(H, (PVMM_WORK_START_ROUTINE_PVOID_PFN)PluginManager_FcLogCSV, hCSV, hEventAsyncLogCSV, VMMWORK_FLAG_PRIO_LOW);
VmmWork_Void(H, (PVMM_WORK_START_ROUTINE_PVOID_PFN)PluginManager_FcLogJSON, FcJson_Callback_EntryAdd, hEventAsyncLogJSON, VMMWORK_FLAG_PRIO_LOW);
FcScanPhysmem(H);
WaitForSingleObject(hEventAsyncIngestObjectAndVirtmem, INFINITE);
// 60%
FCINITIALIZE_PROGRESS_UPDATE(60);
VmmWork_Void(H, (PVMM_WORK_START_ROUTINE_PVOID_PFN)PluginManager_FcLogCSV, hCSV, hEventAsyncLogCSV, VMMWORK_FLAG_PRIO_LOW);
VmmWork_Void(H, (PVMM_WORK_START_ROUTINE_PVOID_PFN)PluginManager_FcLogJSON, FcJson_Callback_EntryAdd, hEventAsyncLogJSON, VMMWORK_FLAG_PRIO_LOW);
PluginManager_FcIngestFinalize(H);
// 70%
FCINITIALIZE_PROGRESS_UPDATE(70);
@@ -1720,6 +1719,7 @@ BOOL FcInitialize_Impl(_In_ VMM_HANDLE H, _In_ DWORD dwDatabaseType, _In_ BOOL f
if(!(H->fc->db.hEventIngestPhys[i] = CreateEvent(NULL, FALSE, TRUE, NULL))) { goto fail; }
if(SQLITE_OK != sqlite3_open_v2(H->fc->db.szuDatabase, &H->fc->db.hSql[i], SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_SHAREDCACHE | SQLITE_OPEN_NOMUTEX, NULL)) { goto fail; }
}
MemProcFS_SqliteVfsRegister();
H->fc->fInitStart = TRUE;
VmmWork_Value(H, FcInitialize_ThreadProc, 0, 0, VMMWORK_FLAG_PRIO_LOW);
return TRUE;
+4 -2
View File
@@ -518,8 +518,9 @@ BOOL InfoDB_TypeSize_Static(_In_ VMM_HANDLE H, _In_ LPCSTR szModule, _In_ LPCSTR
*pdwTypeSize = 0;
if(!(pObCtx = ObContainer_GetOb(H->vmm.pObCInfoDB))) { goto fail; }
hSql = InfoDB_SqlReserve(H, pObCtx);
if(!H->vmm.f32 && (szModule[0] == 'w')) {
if(!H->vmm.f32 && (szModule[0] == 'w') && strcmp(szModule, "wt")) {
// wow64 modules start with 'w' (wntdll == 32-bit ntdll on a 64-bit system) -> use the 32-bit offset instead.
// "wt" is the 64-bit Windows Terminal virtual module.
szModule = szModule + 1;
dwArch = 32;
}
@@ -603,8 +604,9 @@ BOOL InfoDB_TypeChildOffset_Static(_In_ VMM_HANDLE H, _In_ LPCSTR szModule, _In_
*pdwTypeOffset = 0;
if(!(pObCtx = ObContainer_GetOb(H->vmm.pObCInfoDB))) { goto fail; }
hSql = InfoDB_SqlReserve(H, pObCtx);
if(!H->vmm.f32 && (szModule[0] == 'w')) {
if(!H->vmm.f32 && (szModule[0] == 'w') && strcmp(szModule, "wt")) {
// wow64 modules start with 'w' (wntdll == 32-bit ntdll on a 64-bit system) -> use the 32-bit offset instead.
// "wt" is the 64-bit Windows Terminal virtual module.
szModule = szModule + 1;
dwArch = 32;
}
File diff suppressed because it is too large Load Diff
+6 -1
View File
@@ -20,10 +20,15 @@ NTSTATUS M_FcTimeline_ReadInfo(_In_ VMM_HANDLE H, _In_ DWORD dwTimelineType, _Ou
LPSTR szuBuffer = NULL;
DWORD dwEntryType, dwEntryAction;
CHAR szTime[24];
*pcbRead = 0;
if(!FcTimeline_GetIdFromPosition(H, dwTimelineType, FC_FORMAT_TYPE_UTF8, cbOffset, &qwIdBase)) { goto fail; }
if(!FcTimeline_GetIdFromPosition(H, dwTimelineType, FC_FORMAT_TYPE_UTF8, cbOffset + cb, &qwIdTop)) { goto fail; }
cId = min(cb / FC_LINELENGTH_TIMELINE_UTF8, qwIdTop - qwIdBase) + 1;
if(!FcTimelineMap_GetFromIdRange(H, dwTimelineType, qwIdBase, cId, &pObMap) || !pObMap->cMap) { goto fail; }
if(!FcTimelineMap_GetFromIdRange(H, dwTimelineType, qwIdBase, cId, &pObMap)) { goto fail; }
if(!pObMap->cMap) {
nt = VMMDLL_STATUS_END_OF_FILE;
goto fail;
}
cbOffsetBuffer = pObMap->pMap[0].cuszOffset;
if((cbOffsetBuffer > cbOffset) || (cbOffset - cbOffsetBuffer > 0x10000)) { goto fail; }
cszuBuffer = 0x01000000;
+6 -34
View File
@@ -12,6 +12,7 @@
#include "modules.h"
#include "../ext/sqlite3.h"
#include "../ext/sqlite_vfs_memprocfs.h"
#include "../vmmwinobj.h"
LPSTR szMWEB_README =
@@ -248,43 +249,14 @@ VOID FcWeb_Chromium_LoginData_CB(_In_ VMM_HANDLE H, _In_ PMWEB_CONTEXT ctx)
*/
VOID FcWeb_LoadSqliteDispatch(_In_ VMM_HANDLE H, _In_ PMWEB_CONTEXT ctx, _In_ FCWEB_SQLITE_PFN_CB pfnCB)
{
int rc;
DWORD cbDB;
DWORD cbDB = 0;
PBYTE pbDB = NULL;
BYTE pbTest[0x10] = { 0 };
CHAR szFile[MAX_PATH], szURI[MAX_PATH];
FILE *phFile = NULL;
// 1: sanity checks
if((ctx->pFile->cb < 0x1000) || (ctx->pFile->cb > 0x04000000)) { goto fail; }
VmmWinObjFile_Read(H, ctx->pFile, 0, pbTest, sizeof(pbTest) - 1, 0, VMMWINOBJ_FILE_TP_DEFAULT);
if(pbTest != (PBYTE)strstr((LPCSTR)pbTest, "SQLite ")) { goto fail; }
// 2: read file handle into memory
cbDB = (DWORD)ctx->pFile->cb;
if(!(pbDB = LocalAlloc(0, cbDB))) { goto fail; }
cbDB = VmmWinObjFile_Read(H, ctx->pFile, 0, pbDB, cbDB, 0, VMMWINOBJ_FILE_TP_DEFAULT);
// 3: create and write to temp file
if(tmpnam_s(szFile, MAX_PATH)) { goto fail; }
strncat_s(szFile, _countof(szFile), ".vmmsqlite3.tmp", _TRUNCATE);
if(fopen_su(&phFile, szFile, "wb")) {
VmmLog(H, ctx->MID, LOGLEVEL_DEBUG, "fail open temp file: %s", szFile);
goto fail;
}
fwrite(pbDB, 1, cbDB, phFile);
fclose(phFile);
// 4: open sqlite and dispatch
sprintf_s(szURI, _countof(szURI), "file:///%s", szFile);
CharUtil_ReplaceAllA(szURI, '\\', '/');
rc = sqlite3_open_v2(szURI, &ctx->hDB, SQLITE_OPEN_URI | SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_EXCLUSIVE, NULL);
if(rc == SQLITE_OK) {
sqlite3_db_config(ctx->hDB, SQLITE_DBCONFIG_ENABLE_TRIGGER, 0, 0);
sqlite3_db_config(ctx->hDB, SQLITE_DBCONFIG_ENABLE_VIEW, 0, 0);
if(!VmmWinObjFile_ReadAlloc(H, ctx->pFile, 0x01000000, 0, VMMWINOBJ_FILE_TP_DEFAULT, &pbDB, &cbDB, NULL)) { return; }
if(SQLITE_OK == MemProcFS_SqliteVfsOpen(pbDB, cbDB, NULL, 0, &ctx->hDB)) {
pfnCB(H, ctx);
} else {
VmmLog(H, ctx->MID, LOGLEVEL_DEBUG, "fail sqlite3 open: rc=%i db='%s'", rc, ctx->pFile->uszName);
}
fail:
sqlite3_close(ctx->hDB); ctx->hDB = NULL;
if(phFile) { remove(szFile); }
MemProcFS_SqliteVfsClose(ctx->hDB);
ctx->hDB = NULL;
LocalFree(pbDB);
}
+1 -1
View File
@@ -10,7 +10,7 @@ LPCSTR szMHEAP_README =
"Information about the heap process module \n" \
"========================================= \n" \
"The heap process module tries to parse user-mode heaps and display results. \n" \
"Some heap parsing is dependant on debug symbols. Parsing may be degraded if \n" \
"Some heap parsing is dependent on debug symbols. Parsing may be degraded if \n" \
"symbols are missing. The heap module is work in progress. \n" \
"NT heap parsing is supported on Vista and above. \n" \
"Segment heap parsing is supported on Windows 10 1709 and above. \n" \
File diff suppressed because it is too large Load Diff
+4
View File
@@ -55,6 +55,7 @@ VOID M_VM_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRe
/*
* Initialization functions for FORENSIC related modules.
*/
VOID M_FcAmcache_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
VOID M_FcCSV_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
VOID M_FcFile_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
VOID M_FcFindEvil_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
@@ -97,6 +98,7 @@ VOID M_ProcMemMap_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO p
VOID M_ProcMiniDump_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
VOID M_ProcToken_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
VOID M_ProcThread_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
VOID M_ProcWinTerm_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
VOID M_Search_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
VOID M_SearchYara_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
@@ -117,6 +119,7 @@ VOID(*g_pfnModulesAllInternal[])(_In_ VMM_HANDLE H, _In_ PVMMDLL_PLUGIN_REGINFO
M_ProcMiniDump_Initialize,
M_ProcThread_Initialize,
M_ProcToken_Initialize,
M_ProcWinTerm_Initialize,
M_Search_Initialize,
M_SearchYara_Initialize,
M_Virt2Phys_Initialize,
@@ -142,6 +145,7 @@ VOID(*g_pfnModulesAllInternal[])(_In_ VMM_HANDLE H, _In_ PVMMDLL_PLUGIN_REGINFO
M_WinReg_Initialize,
M_VM_Initialize,
// forensic modules
M_FcAmcache_Initialize,
M_FcCSV_Initialize,
M_FcFile_Initialize,
M_FcFindEvil_Initialize,
+3
View File
@@ -652,6 +652,7 @@ VOID ObMap_FilterSet_FilterAllKey(_In_opt_ PVOID ctx, _In_ POB_SET ps, _In_ QWOR
/*
* Filter map objects into a generic context by using a user-supplied filter function.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* -- pm
* -- ctx = optional context to pass on to the filter function.
* -- pfnFilterCB = filter callback function. NULL = fail.
@@ -662,6 +663,7 @@ BOOL ObMap_Filter(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTE
/*
* Filter map objects into a POB_SET by using a user-supplied filter function.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* CALLER DECREF: return
* -- pm
* -- ctx = optional context to pass on to the filter function.
@@ -689,6 +691,7 @@ typedef int(*OB_MAP_SORT_COMPARE_FUNCTION)(_In_ POB_MAP_ENTRY e1, _In_ POB_MAP_E
* Sort the ObMap entry index by a sort compare function.
* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects
* which points to the underlying map object key/value.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* -- pm
* -- pfnSort = sort function callback. const void* == const OB_MAP_ENTRY*
* -- return
+4 -3
View File
@@ -70,7 +70,7 @@ BOOL _ObByteQueue_Peek(_In_ POB_BYTEQUEUE pq, _Out_opt_ QWORD *pqwTag, _In_ SIZE
return FALSE;
}
*pcbRead = p->cb;
if(p->cb < cb) {
if(p->cb > cb) {
return FALSE;
}
if(pqwTag) {
@@ -111,7 +111,7 @@ BOOL _ObByteQueue_Push(_In_ POB_BYTEQUEUE pq, _In_opt_ QWORD qwTag, _In_ SIZE_T
{
PBYTEQUEUE_PACKET p;
SIZE_T cboEoQ, cbEoQ, cbPkt = sizeof(BYTEQUEUE_PACKET) + cb;
if(pq->cb < cbPkt) {
if((pq->cb < cbPkt) || (cb >= 0x80000000)) {
return FALSE;
}
if(!pq->cPackets) {
@@ -216,7 +216,8 @@ POB_BYTEQUEUE ObByteQueue_New(_In_opt_ VMM_HANDLE H, _In_ DWORD cbQueueSize)
{
POB_BYTEQUEUE pObQ;
if(cbQueueSize < 0x1000) { return NULL; }
pObQ = Ob_AllocEx(H, OB_TAG_CORE_BYTEQUEUE, LMEM_ZEROINIT, sizeof(POB_BYTEQUEUE) + cbQueueSize, NULL, NULL);
if((sizeof(void*) == 4) && (cbQueueSize >= 0x40000000)) { return NULL; }
pObQ = Ob_AllocEx(H, OB_TAG_CORE_BYTEQUEUE, LMEM_ZEROINIT, sizeof(OB_BYTEQUEUE) + cbQueueSize, NULL, NULL);
if(!pObQ) { return NULL; }
InitializeSRWLock(&pObQ->LockSRW);
pObQ->cb = cbQueueSize;
+1 -3
View File
@@ -21,9 +21,7 @@
*/
VOID ObContainer_ObCloseCallback(_In_ POB_CONTAINER pObContainer)
{
if(OB_CONTAINER_IS_VALID(pObContainer)) {
Ob_DECREF(pObContainer->pOb);
}
Ob_DECREF(pObContainer->pOb);
}
/*
+4 -4
View File
@@ -28,7 +28,7 @@
* Allocate a new object manager memory object.
* -- H = an optional handle to embed as OB.H in the header.
* -- tag = tag of the object to be allocated.
* -- uFlags = flags as given by LocalAlloc.
* -- uFlags = flags as given by LocalAlloc, 0 (LMEM_FIXED) or LMEM_ZEROINIT.
* -- uBytes = bytes of object (_including_ object headers).
* -- pfnRef_0 = optional callback for cleanup o be called before object is destroyed.
* (if object has references that should be decremented before destruction).
@@ -39,7 +39,7 @@ PVOID Ob_AllocEx(_In_opt_ VMM_HANDLE H, _In_ DWORD tag, _In_ UINT uFlags, _In_ S
{
POB pOb;
if((uBytes > 0x40000000) || (uBytes < sizeof(OB))) { return NULL; }
pOb = (POB)LocalAlloc(uFlags, uBytes + OB_DEBUG_FOOTER_SIZE);
pOb = (POB)LocalAlloc(uFlags & LMEM_ZEROINIT, uBytes + OB_DEBUG_FOOTER_SIZE);
if(!pOb) { return NULL; }
pOb->_magic1 = OB_HEADER_MAGIC;
pOb->_magic2 = OB_HEADER_MAGIC;
@@ -101,16 +101,16 @@ PVOID Ob_XDECREF(_In_opt_ PVOID pObIn)
}
#endif /* OB_DEBUG */
if(c == 0) {
if(pOb->_pfnRef_0) { pOb->_pfnRef_0(pOb); }
pOb->_magic1 = 0;
pOb->_magic2 = 0;
if(pOb->_pfnRef_0) { pOb->_pfnRef_0(pOb); }
#ifdef OB_DEBUG_MEMZERO
ZeroMemory(pOb, sizeof(OB) + pOb->cbData);
#endif /* OB_DEBUG_MEMZERO */
LocalFree(pOb);
} else if((c == 1) && pOb->_pfnRef_1) {
pOb->_pfnRef_1(pOb);
return pOb;
return ((pOb->_magic2 == OB_HEADER_MAGIC) && (pOb->_magic1 == OB_HEADER_MAGIC)) ? pOb : NULL;
} else {
return pOb;
}
+4 -2
View File
@@ -535,6 +535,7 @@ QWORD ObMap_PeekKey(_In_opt_ POB_MAP pm)
/*
* Filter map objects into a generic context by using a user-supplied filter function.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* -- pm
* -- ctx = optional context to pass on to the filter function.
* -- pfnFilterCB
@@ -549,6 +550,7 @@ BOOL ObMap_Filter(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTE
/*
* Filter map objects into a POB_SET by using a user-supplied filter function.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* CALLER DECREF: return
* -- pm
* -- ctx = optional context to pass on to the filter function.
@@ -763,8 +765,8 @@ int _ObMap_SortEntryIndexByKey_CmpSort(_In_ POB_MAP_ENTRY e1, _In_ POB_MAP_ENTRY
/*
* Sort the ObMap entry index by a sort compare function.
* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects
* which points to the underlying map object key/value.
* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects which points to the underlying map object key/value.
* NB! The callback is invoked while the map lock is held and must not call back into the same ObMap.
* -- pm
* -- pfnSort = sort function callback. const void* == const OB_MAP_ENTRY*
* -- return
+2 -1
View File
@@ -16,7 +16,7 @@
#define OB_MEMFILE_ENTRIES_DIRECTORY 0x200
#define OB_MEMFILE_ENTRIES_TABLE 0x200
#define OB_MEMFILE_BUFSIZE 0x00010000
#define OB_MEMFILE_BUFSIZE 0x00010000ULL
#define OB_MEMFILE_MAXSIZE (OB_MEMFILE_ENTRIES_DIRECTORY*OB_MEMFILE_ENTRIES_TABLE*OB_MEMFILE_BUFSIZE) // 16GB
#define OB_MEMFILE_INDEX_DIRECTORY(cb) (((cb) >> 25) & 0x1ff)
@@ -147,6 +147,7 @@ BOOL _ObMemFile_Append(_In_ POB_MEMFILE pmf, _In_reads_(cbData) PBYTE pbData, _I
{
QWORD oBuffer, cbCopy;
if(!cbData) { return TRUE; }
if((cbData > OB_MEMFILE_MAXSIZE) || (pmf->cb + cbData > OB_MEMFILE_MAXSIZE)) { return FALSE; }
while(cbData) {
// fill as many bytes as possible to buffer
oBuffer = pmf->cb % OB_MEMFILE_BUFSIZE;
+1
View File
@@ -464,6 +464,7 @@ _Success_(return)
BOOL _ObSet_PushSet(_In_ POB_SET pvs, _In_opt_ POB_SET pvsSrc)
{
DWORD iValue;
if(pvs == pvsSrc) { return FALSE; }
if(pvsSrc) {
AcquireSRWLockShared(&pvsSrc->LockSRW);
for(iValue = pvsSrc->c - 1; iValue; iValue--) {
+1
View File
@@ -41,6 +41,7 @@
#define OB_TAG_MAP_TASK 'Mtsk'
#define OB_TAG_MAP_VM 'Mvm_'
#define OB_TAG_MAP_WEB 'Mweb'
#define OB_TAG_MAP_AMCACHE 'MAmC'
#define OB_TAG_MOD_CERTIFICATES 'mCer'
#define OB_TAG_MOD_FCNTFS_CTX 'mFnt'
#define OB_TAG_MOD_FCTIMELINE 'mFtl'
+1 -1
View File
@@ -80,7 +80,7 @@ typedef uint8_t UCHAR, *PUCHAR;
typedef char CHAR, *PCHAR, *PSTR, *LPSTR;
typedef const char *LPCSTR;
typedef int16_t SHORT, *PSHORT;
typedef int32_t LONG;
typedef int32_t LONG, *PLONG;
typedef int64_t LONGLONG;
typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT;
typedef uint16_t WCHAR, *PWCHAR, *LPWSTR;
+34 -15
View File
@@ -159,6 +159,26 @@ fail:
return FALSE;
}
/*
* Validate that an EAT array is fully contained in the local export directory.
* -- oExpDir
* -- cbExpDir
* -- rvaArray
* -- cEntry
* -- cbEntry
* -- poArray
* -- return
*/
_Success_(return)
static BOOL PE_ExportArrayValidate(_In_ DWORD oExpDir, _In_ DWORD cbExpDir, _In_ DWORD rvaArray, _In_ DWORD cEntry, _In_ DWORD cbEntry, _Out_ PDWORD poArray)
{
*poArray = 0;
if(!cEntry) { return TRUE; }
if(!cbEntry || (rvaArray < oExpDir)) { return FALSE; }
*poArray = rvaArray - oExpDir;
return (*poArray <= cbExpDir) && (cEntry <= (cbExpDir - *poArray) / cbEntry);
}
_Success_(return)
BOOL PE_GetThunkInfoEAT(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPCSTR szProcName, _Out_ PPE_THUNKINFO_EAT pThunkInfoEAT)
{
@@ -168,11 +188,11 @@ BOOL PE_GetThunkInfoEAT(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _In_ QWOR
PDWORD pdwRVAAddrNames, pdwRVAAddrFunctions;
PWORD pwNameOrdinals;
DWORD i, cbProcName, cbExportDirectoryOffset, cbRead = 0;
DWORD oName, oNames, oNameOrdinals, oFunctions;
LPSTR sz;
QWORD vaExportDirectory;
DWORD cbExportDirectory;
PBYTE pbExportDirectory = NULL;
QWORD vaRVAAddrNames, vaNameOrdinals, vaRVAAddrFunctions;
BOOL f32;
if(!(ntHeader64 = (PIMAGE_NT_HEADERS64)PE_HeaderGetVerify(H, pProcess, vaModuleBase, pbModuleHeader, &f32))) { goto cleanup; }
if(f32) { // 32-bit PE
@@ -188,28 +208,27 @@ BOOL PE_GetThunkInfoEAT(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _In_ QWOR
VmmReadEx(H, pProcess, vaExportDirectory, pbExportDirectory, cbExportDirectory, &cbRead, VMM_FLAG_ZEROPAD_ON_FAIL);
if(!cbRead) { goto cleanup; }
PIMAGE_EXPORT_DIRECTORY exp = (PIMAGE_EXPORT_DIRECTORY)pbExportDirectory;
if(!exp || !exp->NumberOfNames || (exp->NumberOfNames > 0x00100000) || !exp->AddressOfNames) { goto cleanup; }
vaRVAAddrNames = vaModuleBase + exp->AddressOfNames;
vaNameOrdinals = vaModuleBase + exp->AddressOfNameOrdinals;
vaRVAAddrFunctions = vaModuleBase + exp->AddressOfFunctions;
if((vaRVAAddrNames < vaExportDirectory) || (vaRVAAddrNames > vaExportDirectory + cbExportDirectory - exp->NumberOfNames * sizeof(DWORD))) { goto cleanup; }
if((vaNameOrdinals < vaExportDirectory) || (vaNameOrdinals > vaExportDirectory + cbExportDirectory - exp->NumberOfNames * sizeof(WORD))) { goto cleanup; }
if((vaRVAAddrFunctions < vaExportDirectory) || (vaRVAAddrFunctions > vaExportDirectory + cbExportDirectory - exp->NumberOfNames * sizeof(DWORD))) { goto cleanup; }
if(!exp->NumberOfFunctions || (exp->NumberOfFunctions > 0xffff) || !exp->NumberOfNames || (exp->NumberOfNames > exp->NumberOfFunctions)) { goto cleanup; }
cbProcName = (DWORD)strnlen_s(szProcName, MAX_PATH) + 1;
cbExportDirectoryOffset = (DWORD)(vaExportDirectory - vaModuleBase);
pdwRVAAddrNames = (PDWORD)(pbExportDirectory + exp->AddressOfNames - cbExportDirectoryOffset);
pwNameOrdinals = (PWORD)(pbExportDirectory + exp->AddressOfNameOrdinals - cbExportDirectoryOffset);
pdwRVAAddrFunctions = (PDWORD)(pbExportDirectory + exp->AddressOfFunctions - cbExportDirectoryOffset);
if(!PE_ExportArrayValidate(cbExportDirectoryOffset, cbExportDirectory, exp->AddressOfNames, exp->NumberOfNames, sizeof(DWORD), &oNames)) { goto cleanup; }
if(!PE_ExportArrayValidate(cbExportDirectoryOffset, cbExportDirectory, exp->AddressOfNameOrdinals, exp->NumberOfNames, sizeof(WORD), &oNameOrdinals)) { goto cleanup; }
if(!PE_ExportArrayValidate(cbExportDirectoryOffset, cbExportDirectory, exp->AddressOfFunctions, exp->NumberOfFunctions, sizeof(DWORD), &oFunctions)) { goto cleanup; }
pdwRVAAddrNames = (PDWORD)(pbExportDirectory + oNames);
pwNameOrdinals = (PWORD)(pbExportDirectory + oNameOrdinals);
pdwRVAAddrFunctions = (PDWORD)(pbExportDirectory + oFunctions);
for(i = 0; i < exp->NumberOfNames; i++) {
if(pdwRVAAddrNames[i] - cbExportDirectoryOffset + cbProcName > cbExportDirectory) { continue; }
sz = (LPSTR)(pbExportDirectory + pdwRVAAddrNames[i] - cbExportDirectoryOffset);
if(pdwRVAAddrNames[i] < cbExportDirectoryOffset) { continue; }
oName = pdwRVAAddrNames[i] - cbExportDirectoryOffset;
if((oName >= cbExportDirectory) || (cbProcName > cbExportDirectory - oName)) { continue; }
sz = (LPSTR)(pbExportDirectory + oName);
if(0 == memcmp(sz, szProcName, cbProcName)) {
if(pwNameOrdinals[i] >= exp->NumberOfFunctions) { goto cleanup; }
pThunkInfoEAT->fValid = TRUE;
pThunkInfoEAT->vaFunction = (QWORD)(vaModuleBase + pdwRVAAddrFunctions[pwNameOrdinals[i]]);
pThunkInfoEAT->valueThunk = pdwRVAAddrFunctions[pwNameOrdinals[i]];
pThunkInfoEAT->vaThunk = vaExportDirectory + exp->AddressOfFunctions - cbExportDirectoryOffset + sizeof(DWORD) * pwNameOrdinals[i];
pThunkInfoEAT->vaNameFunction = vaExportDirectory + pdwRVAAddrNames[i] - cbExportDirectoryOffset;
pThunkInfoEAT->vaThunk = vaExportDirectory + oFunctions + sizeof(DWORD) * pwNameOrdinals[i];
pThunkInfoEAT->vaNameFunction = vaExportDirectory + oName;
LocalFree(pbExportDirectory);
return TRUE;
}
+2 -2
View File
@@ -324,8 +324,8 @@ VOID Util_VfsTimeStampFile(_In_ VMM_HANDLE H, _In_opt_ PVMM_PROCESS pProcess, _O
_Success_(return)
BOOL Util_VfsHelper_GetIdDir(_In_ LPCSTR uszPath, _In_ BOOL fHex, _Out_ PDWORD pdwID, _Out_opt_ LPCSTR *puszSubPath);
#define UTIL_VFSLINEFIXED_LINECOUNT(H, c) (c + (H->cfg.fFileInfoHeader ? 2ULL : 0ULL))
#define UTIL_VFSLINEVARIABLE_BYTECOUNT(H, c, pdwo, szHdr) ((c ? (pdwo[c - 1]) : 0) + (H->cfg.fFileInfoHeader ? 2 * strlen(szHdr) + 2 : 0ULL))
#define UTIL_VFSLINEFIXED_LINECOUNT(H, c) ((c) + (H->cfg.fFileInfoHeader ? 2ULL : 0ULL))
#define UTIL_VFSLINEVARIABLE_BYTECOUNT(H, c, pdwo, szHdr) (((c) ? (pdwo[(c) - 1]) : 0) + (H->cfg.fFileInfoHeader ? 2 * strlen(szHdr) + 2 : 0ULL))
/*
* FixedLineRead: Callback function to populate a fixed-length line in a
+3 -3
View File
@@ -2,9 +2,9 @@
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_MAJOR 5
#define VERSION_MINOR 17
#define VERSION_REVISION 9
#define VERSION_BUILD 238
#define VERSION_MINOR 18
#define VERSION_REVISION 0
#define VERSION_BUILD 239
#define VER_FILE_DESCRIPTION_STR "MemProcFS : Core"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
+6 -2
View File
@@ -2705,12 +2705,15 @@ BOOL VmmSearch_VirtPteVad(_In_ VMM_HANDLE H, _In_ PVMM_MEMORY_SEARCH_INTERNAL_CO
PVMMOB_MAP_VAD pObVAD = NULL;
PVMM_MAP_PTEENTRY pePTE;
PVMM_MAP_VADENTRY peVAD;
VMM_VADMAP_TP tpVAD;
BOOL fPteExtendedText;
ctxs->cResult = 0;
ctxs->cbReadTotal = 0;
ctxs->vaCurrent = ctxs->vaMin;
if(ctxs->fForceVAD || (ctxi->pProcess->fUserOnly && !ctxs->fForcePTE)) {
// VAD method:
if(!VmmMap_GetVad(H, ctxi->pProcess, &pObVAD, VMM_VADMAP_TP_CORE)) { goto fail; }
tpVAD = ctxs->pfnFilterOptCB ? VMM_VADMAP_TP_FULL : VMM_VADMAP_TP_CORE;
if(!VmmMap_GetVad(H, ctxi->pProcess, &pObVAD, tpVAD)) { goto fail; }
for(ie = 0; ie < pObVAD->cMap; ie++) {
peVAD = pObVAD->pMap + ie;
if(peVAD->vaStart + peVAD->vaEnd < ctxs->vaMin) { continue; } // skip entries below min address
@@ -2724,7 +2727,8 @@ BOOL VmmSearch_VirtPteVad(_In_ VMM_HANDLE H, _In_ PVMM_MEMORY_SEARCH_INTERNAL_CO
}
} else {
// PTE method:
if(!VmmMap_GetPte(H, ctxi->pProcess, &pObPTE, FALSE)) { goto fail; }
fPteExtendedText = ctxs->pfnFilterOptCB ? TRUE : FALSE;
if(!VmmMap_GetPte(H, ctxi->pProcess, &pObPTE, fPteExtendedText)) { goto fail; }
for(ie = 0; ie < pObPTE->cMap; ie++) {
pePTE = pObPTE->pMap + ie;
cbPTE = pePTE->cPages << 12;
+4
View File
@@ -21,6 +21,8 @@
#define VMM_STRLEN(s) (sizeof(s)/sizeof(s[0])-1)
#endif /* VMM_STRLEN */
#define VMM_STR_NONULL(s) ((s) ? (s) : "")
// ----------------------------------------------------------------------------
@@ -110,6 +112,8 @@
#define VMM_UADDR_DUAL_8_16(f32, va) (f32 ? VMM_UADDR32_8(va) : VMM_UADDR64_16(va))
#define VMM_UADDR_DUAL_PAGE(f32, va) (f32 ? VMM_UADDR32_PAGE(va) : VMM_UADDR64_PAGE(va))
#define VMM_DEC_NOZERO(v) ((v) ? ((v) - 1) : 0)
#define VMM_ALIGN_PAGE(a) ((a) & ~0xfff)
#define VMM_PID_PROCESS_CLONE_WITH_KERNELMEMORY 0x80000000 // Combine with PID to create a shallowly cloned process with fUserOnly = FALSE
+4
View File
@@ -331,6 +331,7 @@
<ClInclude Include="ext\sha256.h" />
<ClInclude Include="ext\sqlite3.h" />
<ClInclude Include="ext\sqlite3ext.h" />
<ClInclude Include="ext\sqlite_vfs_memprocfs.h" />
<ClInclude Include="fc.h" />
<ClInclude Include="infodb.h" />
<ClInclude Include="mm\mm.h" />
@@ -376,6 +377,7 @@
<ClCompile Include="ext\miniz.c" />
<ClCompile Include="ext\sha256.c" />
<ClCompile Include="ext\sqlite3.c" />
<ClCompile Include="ext\sqlite_vfs_memprocfs.c" />
<ClCompile Include="fc.c" />
<ClCompile Include="infodb.c" />
<ClCompile Include="mm\mm_arm64.c" />
@@ -395,6 +397,7 @@
<ClCompile Include="modules\m_evil_proc2.c" />
<ClCompile Include="modules\m_evil_proc3.c" />
<ClCompile Include="modules\m_evil_thread1.c" />
<ClCompile Include="modules\m_fc_amcache.c" />
<ClCompile Include="modules\m_fc_csv.c" />
<ClCompile Include="modules\m_fc_file.c" />
<ClCompile Include="modules\m_fc_findevil.c" />
@@ -426,6 +429,7 @@
<ClCompile Include="modules\m_proc_thread.c" />
<ClCompile Include="modules\m_proc_token.c" />
<ClCompile Include="modules\m_proc_virt2phys.c" />
<ClCompile Include="modules\m_proc_winterm.c" />
<ClCompile Include="modules\m_search.c" />
<ClCompile Include="modules\m_searchyara.c" />
<ClCompile Include="modules\m_sys.c" />
+15 -3
View File
@@ -171,9 +171,6 @@
<ClInclude Include="vmmuserconfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ob\ob_tag.h">
<Filter>Source Files\ob</Filter>
</ClInclude>
<ClInclude Include="ext\sha256.h">
<Filter>Header Files\ext</Filter>
</ClInclude>
@@ -186,6 +183,12 @@
<ClInclude Include="vmmex.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ob\ob_tag.h">
<Filter>Header Files\ob</Filter>
</ClInclude>
<ClInclude Include="ext\sqlite_vfs_memprocfs.h">
<Filter>Source Files\ext</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="vmmdll.c">
@@ -533,6 +536,15 @@
<ClCompile Include="vmmex_light.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="modules\m_fc_amcache.c">
<Filter>Source Files\modules</Filter>
</ClCompile>
<ClCompile Include="modules\m_proc_winterm.c">
<Filter>Source Files\modules</Filter>
</ClCompile>
<ClCompile Include="ext\sqlite_vfs_memprocfs.c">
<Filter>Source Files\ext</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="vmmdll.def">
+5 -2
View File
@@ -520,6 +520,9 @@ VOID VmmHeapAlloc_SegLFH(_In_ VMM_HANDLE H, _In_ PVMMHEAPNT_CTX ctx, _In_ QWORD
DWORD iBlock, cBlock, oBlock;
DWORD cbBlockSize, oFirstBlock, dwvaShift;
PVMMHEAPALLOC_SEG_LFHENCODED_OFFSETS pEncoded;
if(ctx->po->seg.HEAP_LFH_SUBSEGMENT.BlockOffsets > cb) { return; }
if(sizeof(VMMHEAPALLOC_SEG_LFHENCODED_OFFSETS) > cb - ctx->po->seg.HEAP_LFH_SUBSEGMENT.BlockOffsets) { return; }
if(cb < ctx->po->seg.HEAP_LFH_SUBSEGMENT.BlockBitmap) { return; }
VmmLog(H, MID_HEAP, LOGLEVEL_6_TRACE, "[SegLfhR %llx +%x]", va, cb);
pbBitmap = pb + ctx->po->seg.HEAP_LFH_SUBSEGMENT.BlockBitmap;
pEncoded = (PVMMHEAPALLOC_SEG_LFHENCODED_OFFSETS)(pb + ctx->po->seg.HEAP_LFH_SUBSEGMENT.BlockOffsets);
@@ -527,11 +530,11 @@ VOID VmmHeapAlloc_SegLFH(_In_ VMM_HANDLE H, _In_ PVMMHEAPNT_CTX ctx, _In_ QWORD
pEncoded->EncodedData = (DWORD)(pEncoded->EncodedData ^ ctx->dwSegLfhKey ^ dwvaShift);
oFirstBlock = pEncoded->FirstBlockOffset;
cbBlockSize = pEncoded->BlockSize;
if((cbBlockSize >= 0xff8) || (oFirstBlock > cb)) { return; }
if(!cbBlockSize || (cbBlockSize >= 0xff8) || (oFirstBlock > cb)) { return; }
cBlock = (cb - oFirstBlock) / cbBlockSize;
for(iBlock = 0; iBlock < cBlock; iBlock++) {
oBlock = oFirstBlock + iBlock * cbBlockSize;
if(oBlock + cbBlockSize > cb) { return; }
if((oBlock > cb) || (cbBlockSize > cb - oBlock)) { return; }
if((oBlock & 0xfff) + cbBlockSize > 0x1000) { continue; } // block do not cross page boundaries
ucBits = pbBitmap[iBlock >> 2] >> ((iBlock & 0x3) << 1);
if(((ucBits & 3) == 1)) {
+51 -13
View File
@@ -68,6 +68,26 @@ VOID VmmWinEAT_ObCloseCallback(_In_ PVMMOB_MAP_EAT pObEAT)
LocalFree(pObEAT->pbMultiText);
}
/*
* Validate that an EAT array is fully contained in the local export directory.
* -- oExpDir
* -- cbExpDir
* -- rvaArray
* -- cEntry
* -- cbEntry
* -- poArray
* -- return
*/
_Success_(return)
static BOOL VmmWinEAT_ExportArrayValidate(_In_ DWORD oExpDir, _In_ DWORD cbExpDir, _In_ DWORD rvaArray, _In_ DWORD cEntry, _In_ DWORD cbEntry, _Out_ PDWORD poArray)
{
*poArray = 0;
if(!cEntry) { return TRUE; }
if(!cbEntry || (rvaArray < oExpDir)) { return FALSE; }
*poArray = rvaArray - oExpDir;
return (*poArray <= cbExpDir) && (cEntry <= (cbExpDir - *poArray) / cbEntry);
}
/*
* Helper function for EAT initialization.
* CALLER DECREF: return
@@ -81,8 +101,9 @@ PVMMOB_MAP_EAT VmmWinEAT_Initialize_DoWork(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS
BYTE pbModuleHeader[0x1000] = { 0 };
PIMAGE_NT_HEADERS64 ntHeader64;
PIMAGE_NT_HEADERS32 ntHeader32;
QWORD vaExpDir, vaExpDirTop, vaAddressOfNames, vaAddressOfNameOrdinals, vaAddressOfFunctions;
QWORD vaExpDir, vaExpDirTop, vaAddressOfNames, vaAddressOfFunctions;
DWORD i, oExpDir, cbExpDir, cForwardedFunctions = 0;
DWORD oName, oNames, oNameOrdinals, oFunctions;
PWORD pwNameOrdinals;
PDWORD pdwRvaNames, pdwRvaFunctions;
PBYTE pbExpDir = NULL;
@@ -101,9 +122,9 @@ PVMMOB_MAP_EAT VmmWinEAT_Initialize_DoWork(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS
cbExpDir = fHdr32 ?
ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size :
ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
if(!oExpDir || (cbExpDir < sizeof(IMAGE_EXPORT_DIRECTORY)) || (cbExpDir > 0x01000000)) { goto fail; }
vaExpDir = pModule->vaBase + oExpDir;
vaExpDirTop = vaExpDir + cbExpDir - 1;
if(!oExpDir || !cbExpDir || cbExpDir > 0x01000000) { goto fail; }
if(!(pbExpDir = LocalAlloc(0, cbExpDir + 1ULL))) { goto fail; }
if(!VmmRead(H, pProcess, vaExpDir, pbExpDir, cbExpDir)) { goto fail; }
pbExpDir[cbExpDir] = 0;
@@ -112,14 +133,13 @@ PVMMOB_MAP_EAT VmmWinEAT_Initialize_DoWork(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS
if(!pExpDir->NumberOfFunctions || (pExpDir->NumberOfFunctions > 0xffff)) { goto fail; }
if(pExpDir->NumberOfNames > pExpDir->NumberOfFunctions) { goto fail; }
vaAddressOfNames = pModule->vaBase + pExpDir->AddressOfNames;
vaAddressOfNameOrdinals = pModule->vaBase + pExpDir->AddressOfNameOrdinals;
vaAddressOfFunctions = pModule->vaBase + pExpDir->AddressOfFunctions;
if((vaAddressOfNames < vaExpDir) || (vaAddressOfNames >= vaExpDirTop - pExpDir->NumberOfNames * sizeof(DWORD))) { goto fail; }
if((vaAddressOfNameOrdinals < vaExpDir) || (vaAddressOfNameOrdinals >= vaExpDirTop - pExpDir->NumberOfNames * sizeof(WORD))) { goto fail; }
if((vaAddressOfFunctions < vaExpDir) || (vaAddressOfFunctions >= vaExpDirTop - pExpDir->NumberOfNames * sizeof(DWORD))) { goto fail; }
pdwRvaNames = (PDWORD)(pbExpDir + pExpDir->AddressOfNames - oExpDir);
pwNameOrdinals = (PWORD)(pbExpDir + pExpDir->AddressOfNameOrdinals - oExpDir);
pdwRvaFunctions = (PDWORD)(pbExpDir + pExpDir->AddressOfFunctions - oExpDir);
if(!VmmWinEAT_ExportArrayValidate(oExpDir, cbExpDir, pExpDir->AddressOfNames, pExpDir->NumberOfNames, sizeof(DWORD), &oNames)) { goto fail; }
if(!VmmWinEAT_ExportArrayValidate(oExpDir, cbExpDir, pExpDir->AddressOfNameOrdinals, pExpDir->NumberOfNames, sizeof(WORD), &oNameOrdinals)) { goto fail; }
if(!VmmWinEAT_ExportArrayValidate(oExpDir, cbExpDir, pExpDir->AddressOfFunctions, pExpDir->NumberOfFunctions, sizeof(DWORD), &oFunctions)) { goto fail; }
pdwRvaNames = (PDWORD)(pbExpDir + oNames);
pwNameOrdinals = (PWORD)(pbExpDir + oNameOrdinals);
pdwRvaFunctions = (PDWORD)(pbExpDir + oFunctions);
// allocate EAT-MAP
if(!(pObStrMap = ObStrMap_New(H, OB_STRMAP_FLAGS_CASE_SENSITIVE))) { goto fail; }
if(!(pObEAT = Ob_AllocEx(H, OB_TAG_MAP_EAT, LMEM_ZEROINIT, sizeof(VMMOB_MAP_EAT) + pExpDir->NumberOfFunctions * (sizeof(VMM_MAP_EATENTRY) + sizeof(QWORD)), (OB_CLEANUP_CB)VmmWinEAT_ObCloseCallback, NULL))) { goto fail; }
@@ -134,13 +154,15 @@ PVMMOB_MAP_EAT VmmWinEAT_Initialize_DoWork(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS
// walk exported function names
for(i = 0; i < pExpDir->NumberOfNames && i < pObEAT->cMap; i++) {
if(pwNameOrdinals[i] >= pExpDir->NumberOfFunctions) { continue; } // name ordinal >= number of functions -> "fail"
if(pdwRvaNames[i] < oExpDir || (pdwRvaNames[i] > vaExpDirTop)) { continue; } // name outside export directory -> "fail"
if(pdwRvaNames[i] < oExpDir) { continue; }
oName = pdwRvaNames[i] - oExpDir;
if((oName >= cbExpDir) || !memchr(pbExpDir + oName, 0, cbExpDir - oName)) { continue; }
pe = pObEAT->pMap + pwNameOrdinals[i];
pe->vaFunction = pModule->vaBase + pdwRvaFunctions[pwNameOrdinals[i]];
pe->dwOrdinal = pExpDir->Base + pwNameOrdinals[i];
pe->oFunctionsArray = pwNameOrdinals[i];
pe->oNamesArray = i;
ObStrMap_PushPtrAU(pObStrMap, (LPSTR)(pbExpDir - oExpDir + pdwRvaNames[i]), &pe->uszFunction, &pe->cbuFunction);
ObStrMap_PushPtrAU(pObStrMap, (LPSTR)(pbExpDir + oName), &pe->uszFunction, &pe->cbuFunction);
if((pe->vaFunction > vaExpDir) && (pe->vaFunction < vaExpDirTop)) {
// function pointer to export directory -> probably forwarded symbol
if(PE_EatForwardedFunctionNameValidate((LPSTR)(pbExpDir + pe->vaFunction - vaExpDir), NULL, 0, NULL)) {
@@ -208,6 +230,22 @@ VOID VmmWinIAT_ObCloseCallback(_In_ PVMMOB_MAP_IAT pObIAT)
LocalFree(pObIAT->pbMultiText);
}
/*
* Validate an IMAGE_IMPORT_BY_NAME thunk and ensure that both its WORD hint and
* NULL-terminated function name are fully contained in the local module buffer.
* -- pbModule
* -- cbModule
* -- qwThunk
* -- return
*/
static BOOL VmmWinIAT_ImportByNameValidate(_In_reads_(cbModule) PBYTE pbModule, _In_ DWORD cbModule, _In_ QWORD qwThunk)
{
DWORD oImportByName = (DWORD)qwThunk;
if(!qwThunk || (qwThunk >= cbModule)) { return FALSE; }
if(cbModule - oImportByName <= sizeof(WORD)) { return FALSE; }
return memchr(pbModule + oImportByName + sizeof(WORD), 0, cbModule - oImportByName - sizeof(WORD)) ? TRUE : FALSE;
}
/*
* Helper function for IAT initialization.
* CALLER DECREF: return
@@ -267,7 +305,7 @@ PVMMOB_MAP_IAT VmmWinIAT_Initialize_DoWork(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS
if((QWORD)(pHNA32 + j) + sizeof(DWORD) - (QWORD)pbModule > cbModule) { break; }
if(!pIAT32[j]) { break; }
if(!pHNA32[j]) { break; }
fNameFn = (pHNA32[j] < cbModule);
fNameFn = VmmWinIAT_ImportByNameValidate(pbModule, cbModule, pHNA32[j]);
fNameMod = (pIID[i].Name < cbModule);
// store
pe = pObIAT->pMap + c;
@@ -294,7 +332,7 @@ PVMMOB_MAP_IAT VmmWinIAT_Initialize_DoWork(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS
if((QWORD)(pHNA64 + j) + sizeof(QWORD) - (QWORD)pbModule > cbModule) { break; }
if(!pIAT64[j] || (!VMM_UADDR64(pIAT64[j]) && !VMM_KADDR64(pIAT64[j]))) { break; }
if(!pHNA64[j]) { break; }
fNameFn = (pHNA64[j] < cbModule);
fNameFn = VmmWinIAT_ImportByNameValidate(pbModule, cbModule, pHNA64[j]);
fNameMod = (pIID[i].Name < cbModule);
// store
pe = pObIAT->pMap + c;
+48 -10
View File
@@ -1254,16 +1254,54 @@ DWORD VmmWinObjFile_Read(_In_ VMM_HANDLE H, _In_ POB_VMMWINOBJ_FILE pFile, _In_
}
/*
* Read a contigious amount of file data and report the number of bytes read.
* -- H
* -- vaFileObject
* -- cbOffset
* -- pb
* -- cb
* -- fVmmRead = flags as in VMM_FLAG_*
* -- tp = VMMWINOBJ_FILE_TP_*
* -- return = the number of bytes read.
*/
* Read a complete file into the newly allocated memory.
* -- CALLER LocalFree: *ppbFile
* -- H
* -- pFile
* -- cbFileMaxSize = max allowed file size in bytes, 0 = no limit.
* -- fVmmRead = flags as in VMM_FLAG_*
* -- tp = VMMWINOBJ_FILE_TP_*
* -- ppbFile = ptr to receive the allocated file contents.
* -- pcbFile = size of ppbFile.
* -- pcbRead = number of read bytes, may be less than the file size.
* -- return
*/
_Success_(return)
BOOL VmmWinObjFile_ReadAlloc(_In_ VMM_HANDLE H, _In_ POB_VMMWINOBJ_FILE pFile, _In_ DWORD cbFileMaxSize, _In_ QWORD fVmmRead, _In_ VMMWINOBJ_FILE_TP tp, _Out_ PBYTE *ppbFile, _Out_opt_ PDWORD pcbFile, _Out_opt_ PDWORD pcbRead)
{
PBYTE pbFile = NULL;
DWORD cbRead = 0;
QWORD cbFile = 0;
*ppbFile = NULL;
if(pcbFile) { *pcbFile = 0; }
if(pcbRead) { *pcbRead = 0; }
// calculate and validate file size & buffer:
cbFile = VmmWinObjFile_Size(H, pFile, tp);
if(!cbFile || (cbFile > 0x80000000)) { return FALSE; }
if(cbFileMaxSize && (cbFile > cbFileMaxSize)) { return FALSE; }
if(!(pbFile = LocalAlloc(LMEM_ZEROINIT, cbFile))) { return FALSE; }
// read file:
if(!(cbRead = VmmWinObjFile_Read(H, pFile, 0, pbFile, (DWORD)cbFile, fVmmRead, tp))) {
LocalFree(pbFile);
return FALSE;
}
if(pcbFile) { *pcbFile = (DWORD)cbFile; }
if(pcbRead) { *pcbRead = cbRead; }
*ppbFile = pbFile;
return TRUE;
}
/*
* Read a contigious amount of file data and report the number of bytes read.
* -- H
* -- vaFileObject
* -- cbOffset
* -- pb
* -- cb
* -- fVmmRead = flags as in VMM_FLAG_*
* -- tp = VMMWINOBJ_FILE_TP_*
* -- return = the number of bytes read.
*/
_Success_(return != 0)
DWORD VmmWinObjFile_ReadFromObjectAddress(_In_ VMM_HANDLE H, _In_ QWORD vaFileObject, _In_ QWORD cbOffset, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _In_ QWORD fVmmRead, _In_ VMMWINOBJ_FILE_TP tp)
{
+16
View File
@@ -175,6 +175,22 @@ QWORD VmmWinObjFile_Size(_In_ VMM_HANDLE H, _In_ POB_VMMWINOBJ_FILE pFile, _In_
_Success_(return != 0)
DWORD VmmWinObjFile_Read(_In_ VMM_HANDLE H, _In_ POB_VMMWINOBJ_FILE pFile, _In_ QWORD cbOffset, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _In_ QWORD fVmmRead, _In_ VMMWINOBJ_FILE_TP tp);
/*
* Read a complete file into the newly allocated memory.
* -- CALLER LocalFree: *ppbFile
* -- H
* -- pFile
* -- cbFileMaxSize = max allowed file size in bytes, 0 = no limit.
* -- fVmmRead = flags as in VMM_FLAG_*
* -- tp = VMMWINOBJ_FILE_TP_*
* -- ppbFile = ptr to receive the allocated file contents.
* -- pcbFile = size of ppbFile.
* -- pcbRead = number of read bytes, may be less than the file size.
* -- return
*/
_Success_(return)
BOOL VmmWinObjFile_ReadAlloc(_In_ VMM_HANDLE H, _In_ POB_VMMWINOBJ_FILE pFile, _In_ DWORD cbFileMaxSize, _In_ QWORD fVmmRead, _In_ VMMWINOBJ_FILE_TP tp, _Out_ PBYTE *ppbFile, _Out_opt_ PDWORD pcbFile, _Out_opt_ PDWORD pcbRead);
/*
* Scatter read file data.
* Function is compatible with VmmScatter_ExecuteEx().
+5 -2
View File
@@ -934,6 +934,8 @@ VOID VmmWinPool_AllPool1903_5_LFH_DoWork(
DWORD cbBitmap, iBlock, cBlock, oBlock;
DWORD cbBlockSize, oFirstBlock, dwvaShift;
P_HEAP_LFH_SUBSEGMENT_ENCODED_OFFSETS pEncoded;
if(ctx->po->_HEAP_LFH_SUBSEGMENT.oBlockOffsets > cb) { return; }
if(sizeof(_HEAP_LFH_SUBSEGMENT_ENCODED_OFFSETS) > cb - ctx->po->_HEAP_LFH_SUBSEGMENT.oBlockOffsets) { return; }
if(cb < ctx->po->_HEAP_LFH_SUBSEGMENT.oBlockBitmap) { return; }
pbBitmap = pb + ctx->po->_HEAP_LFH_SUBSEGMENT.oBlockBitmap;
cbBitmap = cb - ctx->po->_HEAP_LFH_SUBSEGMENT.oBlockBitmap;
@@ -942,13 +944,14 @@ VOID VmmWinPool_AllPool1903_5_LFH_DoWork(
pEncoded->EncodedData = (DWORD)(pEncoded->EncodedData ^ ctx->qwKeyLfh ^ dwvaShift);
oFirstBlock = pEncoded->FirstBlockOffset;
cbBlockSize = pEncoded->BlockSize;
if((cbBlockSize >= 0xff8) || (oFirstBlock > cb)) { return; }
if(!cbBlockSize || (cbBlockSize >= 0xff8) || (oFirstBlock > cb)) { return; }
cBlock = (cb - oFirstBlock) / cbBlockSize;
if(cbBitmap < (cBlock >> 2)) {
cBlock = cbBitmap >> 2;
cBlock = cbBitmap << 2;
}
for(iBlock = 0; iBlock < cBlock; iBlock++) {
oBlock = oFirstBlock + iBlock * cbBlockSize;
if((oBlock > cb) || (cbBlockSize > cb - oBlock)) { return; }
if((oBlock & 0xfff) + cbBlockSize > 0x1000) { continue; } // block do not cross page boundaries
ucBits = pbBitmap[iBlock >> 2] >> ((iBlock & 0x3) << 1);
VmmWinPool_AllPool_PushItem(H, &ctx->pLfh, pPgSeg->pHeap->tpPool, VMM_MAP_POOL_TPSS_LFH, va + oBlock, pb + oBlock, cbBlockSize, ((ucBits & 3) == 1));
+34 -22
View File
@@ -1191,6 +1191,8 @@ POB_REGISTRY_HIVE VmmWinReg_HiveGetByAddress(_In_ VMM_HANDLE H, _In_ QWORD vaCMH
#define REG_CM_KEY_SIGNATURE_KEYVALUE 0x6B76 // 'vk'-key
#define REG_CM_HASH_LEAF_SIGNATURE 0x686C // 'hl'-key
#define REG_CM_KEY_SIGNATURE_BIGDATA 0x6264 // 'db'-key
#define REG_CM_BIGDATA_SEGMENT_DATA_SIZE 16344
#define REG_CM_BIGDATA_SEGMENT_CELL_SIZE (REG_CM_BIGDATA_SEGMENT_DATA_SIZE + 8)
#define REG_CM_KEY_VALUE_FLAGS_COMP_NAME 0x01
#define REG_CM_KEY_NODE_FLAGS_COMP_NAME 0x20
@@ -1658,19 +1660,26 @@ POB_REGISTRY_VALUE VmmWinReg_ValueByKeyAndName(_In_ VMM_HANDLE H, _In_ POB_REGIS
VOID VmmWinReg_ValueQueryInternal_BigDataCell(_In_ POB_REGISTRY_HIVE pHive, _In_ DWORD oDataCell, _In_ BOOL fDataCellLast, _Out_writes_opt_(cbData) PBYTE pbData, _In_ DWORD cbData, _In_ DWORD cbDataOffset)
{
BOOL f;
DWORD iDataCellSV, oDataCellRaw, cbDataCell;
PBYTE pbSnapshot;
DWORD iDataCellSV, oDataCellRaw, cbDataCell, cbDataCellPayload, cbDataCopy, cbSnapshot;
if(!pbData) { return; }
ZeroMemory(pbData, cbData);
iDataCellSV = REG_CELL_SV(oDataCell);
oDataCellRaw = REG_CELL_ORAW(oDataCell);
cbDataCell = REG_CELL_SIZE_EX(pHive->Snapshot._DUAL[iDataCellSV].pb, oDataCellRaw);
f = (oDataCellRaw + cbDataCell <= pHive->Snapshot._DUAL[iDataCellSV].cb) &&
(fDataCellLast || (cbDataCell == 16344 + 8)) &&
(cbDataCell <= 16344 + 8) &&
(cbDataCell > 8);
if(f) {
memcpy(pbData, pHive->Snapshot._DUAL[iDataCellSV].pb + oDataCellRaw + 4 + cbDataOffset, min(cbData, cbDataCell));
} else {
ZeroMemory(pbData, cbData);
pbSnapshot = pHive->Snapshot._DUAL[iDataCellSV].pb;
cbSnapshot = pHive->Snapshot._DUAL[iDataCellSV].cb;
if(!pbSnapshot || (oDataCellRaw > cbSnapshot) || (cbSnapshot - oDataCellRaw < sizeof(DWORD))) { return; }
cbDataCell = REG_CELL_SIZE_EX(pbSnapshot, oDataCellRaw);
f = (cbDataCell <= cbSnapshot - oDataCellRaw) &&
(cbDataCell <= REG_CM_BIGDATA_SEGMENT_CELL_SIZE) &&
(cbDataCell > 8) &&
!(!fDataCellLast && (cbDataCell != REG_CM_BIGDATA_SEGMENT_CELL_SIZE));
if(!f) { return; }
cbDataCellPayload = cbDataCell - 4;
if(cbDataOffset > cbDataCellPayload) { return; }
cbDataCopy = min(cbData, cbDataCellPayload - cbDataOffset);
if(cbDataCopy) {
memcpy(pbData, pbSnapshot + oDataCellRaw + sizeof(DWORD) + cbDataOffset, cbDataCopy);
}
}
@@ -1689,38 +1698,41 @@ VOID VmmWinReg_ValueQueryInternal_BigDataCell(_In_ POB_REGISTRY_HIVE pHive, _In_
_Success_(return)
BOOL VmmWinReg_ValueQueryInternal_BigDataList(_In_ POB_REGISTRY_HIVE pHive, _In_ WORD cNumSegments, _In_ DWORD oListCell, _Out_writes_opt_(cbData) PBYTE pbData, _In_ DWORD cbData, _Out_opt_ PDWORD pcbDataRead, _In_ DWORD cbDataOffset)
{
DWORD i, cbMaxSizeTotalSegments, iListCellSV, oListCellRaw, cbListCell, cbReadDataCell;
cbMaxSizeTotalSegments = cNumSegments * 16344;
PBYTE pbSnapshot;
DWORD i, cbMaxSizeTotalSegments, iListCellSV, oListCellRaw, cbListCell, cbListCellRequired, cbReadDataCell, cbSnapshot;
cbMaxSizeTotalSegments = cNumSegments * REG_CM_BIGDATA_SEGMENT_DATA_SIZE;
// adjust read size (if required)
if(cbDataOffset > cbMaxSizeTotalSegments) { return FALSE; }
if(cbData + cbDataOffset > cbMaxSizeTotalSegments) {
if(cbData > cbMaxSizeTotalSegments - cbDataOffset) {
cbData = cbMaxSizeTotalSegments - cbDataOffset;
}
// verify list cell
iListCellSV = REG_CELL_SV(oListCell);
oListCellRaw = REG_CELL_ORAW(oListCell);
if(oListCellRaw + 4 + cNumSegments * 4 > pHive->Snapshot._DUAL[iListCellSV].cb) { return FALSE; }
cbListCell = REG_CELL_SIZE_EX(pHive->Snapshot._DUAL[iListCellSV].pb, oListCellRaw);
if(oListCellRaw + cbListCell > pHive->Snapshot._DUAL[iListCellSV].cb) { return FALSE; }
if(cbListCell < 4 + cNumSegments * 4UL) { return FALSE; }
pbSnapshot = pHive->Snapshot._DUAL[iListCellSV].pb;
cbSnapshot = pHive->Snapshot._DUAL[iListCellSV].cb;
cbListCellRequired = 4 + cNumSegments * 4;
if(!pbSnapshot || (oListCellRaw > cbSnapshot) || (cbListCellRequired > cbSnapshot - oListCellRaw)) { return FALSE; }
cbListCell = REG_CELL_SIZE_EX(pbSnapshot, oListCellRaw);
if((cbListCell < cbListCellRequired) || (cbListCell > cbSnapshot - oListCellRaw)) { return FALSE; }
// read individual data cells
if(pcbDataRead) { *pcbDataRead = cbData; }
if(pbData) { ZeroMemory(pbData, cbData); }
for(i = 0; cbData && (i < cNumSegments); i++) {
if(cbDataOffset > 16344) {
cbDataOffset -= 16344;
if(cbDataOffset >= REG_CM_BIGDATA_SEGMENT_DATA_SIZE) {
cbDataOffset -= REG_CM_BIGDATA_SEGMENT_DATA_SIZE;
continue;
}
cbReadDataCell = min(cbData, 16344 - cbDataOffset);
cbReadDataCell = min(cbData, REG_CM_BIGDATA_SEGMENT_DATA_SIZE - cbDataOffset);
VmmWinReg_ValueQueryInternal_BigDataCell(
pHive,
*(PDWORD)(pHive->Snapshot._DUAL[iListCellSV].pb + oListCellRaw + 4 + i * 4ULL),
*(PDWORD)(pbSnapshot + oListCellRaw + 4 + i * 4ULL),
(i + 1 == cNumSegments),
pbData,
cbReadDataCell,
cbDataOffset
);
pbData += cbReadDataCell;
if(pbData) { pbData += cbReadDataCell; }
cbData -= cbReadDataCell;
cbDataOffset -= min(cbReadDataCell, cbDataOffset);
}
+11 -1
View File
@@ -246,7 +246,8 @@ public class VmmImpl implements IVmm
}
public void prepare(long va, int size) {
if(jnative == null) {
validateReadSize(size);
if(jnative == null) {
if(this.hS == null) { throw new VmmException(); }
boolean f = VmmNative.INSTANCE.VMMDLL_Scatter_Prepare(hS, va, size);
if(!f) { throw new VmmException(); }
@@ -290,6 +291,7 @@ public class VmmImpl implements IVmm
}
public byte[] read(long va, int size) {
validateReadSize(size);
if(jnative == null) {
if(this.hS == null) { throw new VmmException(); }
IntByReference pcbRead = new IntByReference();
@@ -334,6 +336,7 @@ public class VmmImpl implements IVmm
public byte[] _memRead(int pid, long va, int size, int flags)
{
validateReadSize(size);
if(jnative == null) {
// JNA implementation:
IntByReference pcbRead = new IntByReference();
@@ -346,6 +349,13 @@ public class VmmImpl implements IVmm
return jnative.memRead(pid, va, size, flags);
}
}
private static void validateReadSize(int size)
{
if(size < 0) {
throw new IllegalArgumentException("Memory read size must not be negative.");
}
}
public void _memWrite(int pid, long va, byte[] data)
{
+3 -3
View File
@@ -2,9 +2,9 @@
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_MAJOR 5
#define VERSION_MINOR 17
#define VERSION_REVISION 9
#define VERSION_BUILD 238
#define VERSION_MINOR 18
#define VERSION_REVISION 0
#define VERSION_BUILD 239
#define VER_FILE_DESCRIPTION_STR "MemProcFS : Python API"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "leechcore_example"
version = "5.17.9"
version = "5.18.0"
edition = "2021"
publish = false
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "m_example_plugin"
version = "5.17.9"
version = "5.18.0"
edition = "2021"
publish = false
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "memprocfs"
version = "5.17.9"
version = "5.18.0"
edition = "2021"
description = "MemProcFS - Physical Memory Analysis Framework"
documentation = "https://docs.rs/memprocfs"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "memprocfs_example"
version = "5.17.9"
version = "5.18.0"
edition = "2021"
publish = false
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.Versioning;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.17.9.238")]
[assembly: AssemblyFileVersion("5.17.9.238")]
[assembly: AssemblyVersion("5.18.0.239")]
[assembly: AssemblyFileVersion("5.18.0.239")]
+1 -1
View File
@@ -109,7 +109,7 @@
<None Include="logo.png" Pack="true" Visible="true" PackagePath="" />
</ItemGroup>
<PropertyGroup>
<Version>5.17.9</Version>
<Version>5.18.0</Version>
<RepositoryUrl>https://github.com/ufrisk/MemProcFS</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseFile>LICENSE</PackageLicenseFile>