mirror of
https://github.com/ufrisk/MemProcFS.git
synced 2026-10-12 02:23:53 +00:00
Version 5.18
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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--) {
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,6 +1,6 @@
|
||||
[package]
|
||||
name = "leechcore_example"
|
||||
version = "5.17.9"
|
||||
version = "5.18.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "m_example_plugin"
|
||||
version = "5.17.9"
|
||||
version = "5.18.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
[package]
|
||||
name = "memprocfs_example"
|
||||
version = "5.17.9"
|
||||
version = "5.18.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user