mirror of
https://github.com/ufrisk/MemProcFS-plugins.git
synced 2026-05-22 16:39:17 +08:00
Version 1.2
This commit is contained in:
@@ -30,7 +30,6 @@ typedef struct tdVFS_FILELIST {
|
||||
} VFS_FILELIST, *PVFS_FILELIST;
|
||||
|
||||
BOOL VfsListVmmDirectory(_In_ LPWSTR wszDirectoryName);
|
||||
VOID Vfs_UtilSplitPathFile(_Out_ WCHAR wszPath[MAX_PATH], _Out_ LPWSTR *pwcsFile, _In_ LPCWSTR wcsFileName);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// FILELIST FUNCTIONALITY BELOW:
|
||||
@@ -151,6 +150,7 @@ PWIN32_FIND_DATAW VfsFileList_FindSingle(_In_ PVFS_FILELIST pFileList, _In_ LPWS
|
||||
// (caching is used to cache vmmproc directory listings for performance reasons)
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
_Success_(return)
|
||||
BOOL VfsCacheDirectory_GetSingle2(_In_ LPWSTR wszPath, _In_ LPWSTR wszFile, _Out_ PWIN32_FIND_DATAW pFindData, _Out_ PBOOL pIsDirectoryExisting)
|
||||
{
|
||||
QWORD i, qwCurrentTickCount;
|
||||
@@ -247,7 +247,7 @@ BOOL VfsListVmmDirectory(_In_ LPWSTR wszDirectoryName)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID Vfs_UtilSplitPathFile(_Out_ WCHAR wszPath[MAX_PATH], _Out_ LPWSTR *pwcsFile, _In_ LPCWSTR wcsFileName)
|
||||
VOID Vfs_UtilSplitPathFile(_Out_writes_(MAX_PATH) PWCHAR wszPath, _Out_ LPWSTR *pwcsFile, _In_ LPCWSTR wcsFileName)
|
||||
{
|
||||
DWORD i, iSplitFilePath = 0;
|
||||
wcsncpy_s(wszPath, MAX_PATH, wcsFileName, _TRUNCATE);
|
||||
@@ -395,10 +395,8 @@ VOID VfsClose()
|
||||
VfsCacheDirectory_Close();
|
||||
DeleteCriticalSection(&ctxVfs->CacheDirectoryLock);
|
||||
}
|
||||
if(ctxVfs) {
|
||||
LocalFree(ctxVfs);
|
||||
ctxVfs = NULL;
|
||||
}
|
||||
LocalFree(ctxVfs);
|
||||
ctxVfs = NULL;
|
||||
}
|
||||
|
||||
VOID VfsInitializeAndMount(_In_ CHAR chMountPoint, _In_ PVMMDLL_FUNCTIONS pVmmDll)
|
||||
@@ -417,8 +415,13 @@ VOID VfsInitializeAndMount(_In_ CHAR chMountPoint, _In_ PVMMDLL_FUNCTIONS pVmmDl
|
||||
pVmmDll->ConfigGet(VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION, &qwVersionRevision);
|
||||
// allocate
|
||||
hModuleDokan = LoadLibraryExA("dokan1.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if(!hModuleDokan) {
|
||||
printf("MOUNT: Failed. The required DOKANY file system library is not installed. \n");
|
||||
printf("Please download from : https://github.com/dokan-dev/dokany/releases/latest\n");
|
||||
goto fail;
|
||||
}
|
||||
fnDokanMain = (int(*)(PDOKAN_OPTIONS, PDOKAN_OPERATIONS))GetProcAddress(hModuleDokan, "DokanMain");
|
||||
if(!hModuleDokan || !fnDokanMain) {
|
||||
if(!fnDokanMain) {
|
||||
printf("MOUNT: Failed. The required DOKANY file system library is not installed. \n");
|
||||
printf("Please download from : https://github.com/dokan-dev/dokany/releases/latest\n");
|
||||
goto fail;
|
||||
@@ -462,7 +465,7 @@ VOID VfsInitializeAndMount(_In_ CHAR chMountPoint, _In_ PVMMDLL_FUNCTIONS pVmmDl
|
||||
"a convenient process file system for analysis purposes. \n" \
|
||||
" - File system is read-only when dump files are used. \n" \
|
||||
" - File system is read-write when FPGA hardware acquisition devices are used. \n" \
|
||||
" - Full support exists for x64 Windows operating systems. \n" \
|
||||
" - Full support exists for Windows XP to Windows 10 (x86 and x64). \n" \
|
||||
" - Limited support for other x64 operating systems. \n" \
|
||||
" - Memory Process File System: https://github.com/ufrisk/MemProcFS \n" \
|
||||
" - File system by: Ulf Frisk - pcileech@frizk.net - https://frizk.net \n" \
|
||||
@@ -476,7 +479,7 @@ VOID VfsInitializeAndMount(_In_ CHAR chMountPoint, _In_ PVMMDLL_FUNCTIONS pVmmDl
|
||||
printf("MOUNT: Failed. Status Code: %i\n", status);
|
||||
fail:
|
||||
if(hModuleDokan) { FreeLibrary(hModuleDokan); }
|
||||
if(pDokanOptions) { LocalFree(pDokanOptions); }
|
||||
if(pDokanOperations) { LocalFree(pDokanOperations); }
|
||||
LocalFree(pDokanOptions);
|
||||
LocalFree(pDokanOperations);
|
||||
VfsClose();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ extern "C" {
|
||||
* Call other VMMDLL_Intialize functions to initialize VMM.DLL and the memory
|
||||
* process file system.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
|
||||
/*
|
||||
@@ -37,6 +38,7 @@ BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -52,6 +54,7 @@ BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBase
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -60,6 +63,7 @@ BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPST
|
||||
* initialized in read/write mode upon success.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
|
||||
/*
|
||||
@@ -67,6 +71,7 @@ BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
* including plugins, linked PCILeech.DLL and other memory resources.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_Close();
|
||||
|
||||
|
||||
@@ -103,7 +108,8 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
|
||||
#define VMMDLL_OPT_CORE_TARGET_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
|
||||
|
||||
#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
|
||||
#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
|
||||
@@ -116,6 +122,22 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
|
||||
#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
|
||||
|
||||
static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
|
||||
|
||||
typedef enum tdVMMDLL_MEMORYMODEL_TP {
|
||||
VMMDLL_MEMORYMODEL_NA = 0,
|
||||
VMMDLL_MEMORYMODEL_X86 = 1,
|
||||
VMMDLL_MEMORYMODEL_X86PAE = 2,
|
||||
VMMDLL_MEMORYMODEL_X64 = 3
|
||||
} VMMDLL_MEMORYMODEL_TP;
|
||||
|
||||
typedef enum tdVMMDLL_SYSTEM_TP {
|
||||
VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
|
||||
VMMDLL_SYSTEM_WINDOWS_X64 = 2,
|
||||
VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
|
||||
VMMDLL_SYSTEM_WINDOWS_X86 = 4
|
||||
} VMMDLL_SYSTEM_TP;
|
||||
|
||||
/*
|
||||
* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
|
||||
* mation about valid option values. Please note that option values may overlap
|
||||
@@ -124,6 +146,7 @@ BOOL VMMDLL_Close();
|
||||
* -- pqwValue = pointer to ULONG64 to receive option value.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
|
||||
/*
|
||||
@@ -134,6 +157,7 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
* -- qwValue
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
|
||||
|
||||
|
||||
@@ -171,6 +195,7 @@ typedef struct tdVMMDLL_VFS_FILELIST {
|
||||
* -- pFileList
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
|
||||
|
||||
/*
|
||||
@@ -227,12 +252,13 @@ NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb,
|
||||
* will be unloaded on a general close of the vmm dll.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsInitializePlugins();
|
||||
|
||||
#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
|
||||
#define VMMDLL_PLUGIN_CONTEXT_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 2
|
||||
|
||||
#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
|
||||
|
||||
@@ -254,7 +280,8 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem;
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel;
|
||||
VMMDLL_SYSTEM_TP tpSystem;
|
||||
HMODULE hDLL;
|
||||
HMODULE hReservedDll; // not for general use (only used for python).
|
||||
BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
|
||||
@@ -272,7 +299,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
// function plugin registration info to be filled out by the plugin below:
|
||||
struct {
|
||||
BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
|
||||
VOID(*pfnNotify)(_Inout_opt_ PHANDLE phModulePrivate, _In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
|
||||
VOID(*pfnCloseHandleModule)(_Inout_opt_ PHANDLE phModulePrivate);
|
||||
@@ -296,8 +323,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
|
||||
#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
|
||||
|
||||
#define VMMDLL_TARGET_UNKNOWN_X64 0x0001
|
||||
#define VMMDLL_TARGET_WINDOWS_X64 0x0002
|
||||
#define VMMDLL_MEM_IO_SCATTER_HEADER_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
ULONG64 qwA; // base address (DWORD boundry).
|
||||
@@ -306,6 +332,10 @@ typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
|
||||
PVOID pvReserved1; // reserved for use by caller.
|
||||
PVOID pvReserved2; // reserved for use by caller.
|
||||
WORD version; // version of struct
|
||||
WORD Future1; // reserved for future use.
|
||||
DWORD Future2; // reserved for future use.
|
||||
ULONG64 qwDeviceA; // device-physical address (used by device layer).
|
||||
struct {
|
||||
PVOID pvReserved1;
|
||||
PVOID pvReserved2;
|
||||
@@ -335,6 +365,7 @@ DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPVMMDLL_MEM_IO_SCATTER_HE
|
||||
* -- pbPage
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
|
||||
|
||||
/*
|
||||
@@ -345,6 +376,7 @@ BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4
|
||||
* -- cb
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
@@ -358,7 +390,8 @@ BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DW
|
||||
* -- return = success/fail. NB! reads may report as success even if 0 bytes are
|
||||
* read - it's recommended to verify pcbReadOpt parameter.
|
||||
*/
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
|
||||
/*
|
||||
* Write a contigious arbitrary amount of memory. Please note some virtual memory
|
||||
@@ -373,7 +406,8 @@ BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In
|
||||
* -- cb
|
||||
* -- return = TRUE on success, FALSE on partial or zero write.
|
||||
*/
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address by walking the page tables
|
||||
@@ -383,6 +417,7 @@ BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ D
|
||||
* -- pqwPA
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
|
||||
|
||||
|
||||
@@ -401,6 +436,7 @@ BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqw
|
||||
* -- pdwPID = pointer that will receive PID on success.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
|
||||
/*
|
||||
@@ -409,7 +445,8 @@ BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_PidList(_Out_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
|
||||
// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
|
||||
#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
|
||||
@@ -437,6 +474,7 @@ typedef struct tdVMMDLL_MEMMAP_ENTRY {
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
|
||||
|
||||
/*
|
||||
@@ -448,6 +486,7 @@ BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
|
||||
|
||||
typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
@@ -469,7 +508,8 @@ typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
* -- pcModuleEntries = pointer to number of memory map entries.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
|
||||
/*
|
||||
* Retrieve a module (.exe or .dll or similar) given a module name.
|
||||
@@ -478,29 +518,31 @@ BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY
|
||||
* -- pModuleEntry
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
|
||||
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 1
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem; // as given by VMMDLL_TARGET_*
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
|
||||
VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
DWORD dwPID;
|
||||
DWORD dwState;
|
||||
CHAR szName[16];
|
||||
ULONG64 paPML4;
|
||||
ULONG64 paPML4_UserOpt; // may not exist
|
||||
ULONG64 paDTB;
|
||||
ULONG64 paDTB_UserOpt; // may not exist
|
||||
union {
|
||||
struct {
|
||||
ULONG64 vaEPROCESS;
|
||||
ULONG64 vaPEB;
|
||||
ULONG64 vaENTRY;
|
||||
BOOL fWow64;
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
} win;
|
||||
} os;
|
||||
} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
|
||||
@@ -513,6 +555,7 @@ typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
|
||||
|
||||
typedef struct tdVMMDLL_EAT_ENTRY {
|
||||
@@ -539,10 +582,14 @@ typedef struct tdVMMDLL_IAT_ENTRY {
|
||||
* -- pcData
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
|
||||
|
||||
|
||||
@@ -558,7 +605,8 @@ BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_I
|
||||
* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
|
||||
* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
|
||||
*/
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_ LPSTR sz, _Inout_ PDWORD pcsz);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
14
README.md
14
README.md
@@ -77,11 +77,12 @@ Detailed build instructions may be found in the [Wiki](https://github.com/ufrisk
|
||||
|
||||
Current Limitations & Future Development:
|
||||
=========================================
|
||||
The Memory Process File System is currently limited to analyzing Windows x64 memory dumps (other x64 dumps in a very limited way). Also, the Memory Process File System currently does not run on Linux.
|
||||
The Memory Process File System is currently limited to analyzing Windows (32-bit and 64-bit XP to 10) memory dumps (other x64 dumps in a very limited way). Also, the Memory Process File System currently does not run on Linux.
|
||||
|
||||
Please find some ideas for possible future expansions of the memory process file system listed below. This is a list of ideas - not a list of features that will be implemented. Even though some items are put as prioritized there is no guarantee that they will be implemented in a timely fashion.
|
||||
|
||||
### Prioritized items:
|
||||
- Support for Microsoft crash dump format (full memory dump / DumpIt).
|
||||
- More/new plugins.
|
||||
- Linux support - .so files for easy and convenient Linux API access from both C/C++ and Python.
|
||||
- Additional core functionality (exported functions in .DLL). Please request in Issues section if ideas exist.
|
||||
@@ -91,7 +92,7 @@ Please find some ideas for possible future expansions of the memory process file
|
||||
- Multithreading support in main library.
|
||||
- Linux support in mounted FUSE file system.
|
||||
- Support for analyzing x64 Linux, macOS and UEFI memory dumps.
|
||||
- Support for non-x64 memory models (such as x86 32-bit).
|
||||
- ~~Support for non-x64 memory models (such as x86 32-bit).~~
|
||||
- Hash lookup of executable memory pages in DB.
|
||||
|
||||
Links:
|
||||
@@ -107,4 +108,11 @@ v1.0
|
||||
* Initial Release.
|
||||
|
||||
v1.1
|
||||
* Loaded kernel drivers in System process 'modules' sub-directory.
|
||||
* Loaded kernel drivers in System process 'modules' sub-directory (Windows 10).
|
||||
|
||||
v1.2
|
||||
* Support for 32-bit Windows - XP to 10.
|
||||
* Support for 32-bit memory models (x86 and PAE).
|
||||
* Improved auto-identification of memory model and Windows.
|
||||
* Loaded kernel drivers in System process 'modules' sub-directory (all Windows versions).
|
||||
* PE (exe/dll/sys) Sections and Data Directories as files in 'modules' sub-directory.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -140,7 +140,7 @@ def IsProcessPeb6432(pid):
|
||||
if(procinfo['state'] != 0):
|
||||
result = False, False
|
||||
else:
|
||||
result = procinfo['va-peb'] > 0, procinfo['va-peb32'] > 0
|
||||
result = procinfo['va-peb'] > 0, ('va-peb32' in procinfo and procinfo['va-peb32'] > 0)
|
||||
procstruct_cache_proc_wow64[pid] = result
|
||||
return result
|
||||
|
||||
@@ -185,11 +185,11 @@ def Close():
|
||||
|
||||
|
||||
|
||||
def Initialize(os_target):
|
||||
# Check that the operating system is 64-bit Windows. If it's not then raise
|
||||
# an exception to terminate loading of this module.
|
||||
if os_target != VMMPY_TARGET_WINDOWS_X64:
|
||||
raise RuntimeError("Only x64 Windows is supported by the pym_procstruct module.")
|
||||
def Initialize(target_system, target_memorymodel):
|
||||
# Check that the operating system is 32-bit or 64-bit Windows. If it's not
|
||||
# then raise an exception to terminate loading of this module.
|
||||
if target_system != VMMPY_SYSTEM_WINDOWS_X64 and target_system != VMMPY_SYSTEM_WINDOWS_X86:
|
||||
raise RuntimeError("Only Windows is supported by the pym_procstruct module.")
|
||||
# Calculate the size of the 'eprocess_size_hex' global variable. This is
|
||||
# only done once - at module instantiation to speed up the list operation.
|
||||
global procstruct_eprocess_size_hex
|
||||
|
||||
BIN
files/vmm.dll
BIN
files/vmm.dll
Binary file not shown.
BIN
files/vmm.lib
BIN
files/vmm.lib
Binary file not shown.
@@ -23,6 +23,7 @@ extern "C" {
|
||||
* Call other VMMDLL_Intialize functions to initialize VMM.DLL and the memory
|
||||
* process file system.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
|
||||
/*
|
||||
@@ -37,6 +38,7 @@ BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -52,6 +54,7 @@ BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBase
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -60,6 +63,7 @@ BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPST
|
||||
* initialized in read/write mode upon success.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
|
||||
/*
|
||||
@@ -67,6 +71,7 @@ BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
* including plugins, linked PCILeech.DLL and other memory resources.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_Close();
|
||||
|
||||
|
||||
@@ -103,7 +108,8 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
|
||||
#define VMMDLL_OPT_CORE_TARGET_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
|
||||
|
||||
#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
|
||||
#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
|
||||
@@ -116,6 +122,22 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
|
||||
#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
|
||||
|
||||
static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
|
||||
|
||||
typedef enum tdVMMDLL_MEMORYMODEL_TP {
|
||||
VMMDLL_MEMORYMODEL_NA = 0,
|
||||
VMMDLL_MEMORYMODEL_X86 = 1,
|
||||
VMMDLL_MEMORYMODEL_X86PAE = 2,
|
||||
VMMDLL_MEMORYMODEL_X64 = 3
|
||||
} VMMDLL_MEMORYMODEL_TP;
|
||||
|
||||
typedef enum tdVMMDLL_SYSTEM_TP {
|
||||
VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
|
||||
VMMDLL_SYSTEM_WINDOWS_X64 = 2,
|
||||
VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
|
||||
VMMDLL_SYSTEM_WINDOWS_X86 = 4
|
||||
} VMMDLL_SYSTEM_TP;
|
||||
|
||||
/*
|
||||
* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
|
||||
* mation about valid option values. Please note that option values may overlap
|
||||
@@ -124,6 +146,7 @@ BOOL VMMDLL_Close();
|
||||
* -- pqwValue = pointer to ULONG64 to receive option value.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
|
||||
/*
|
||||
@@ -134,6 +157,7 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
* -- qwValue
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
|
||||
|
||||
|
||||
@@ -171,6 +195,7 @@ typedef struct tdVMMDLL_VFS_FILELIST {
|
||||
* -- pFileList
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
|
||||
|
||||
/*
|
||||
@@ -227,12 +252,13 @@ NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb,
|
||||
* will be unloaded on a general close of the vmm dll.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsInitializePlugins();
|
||||
|
||||
#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
|
||||
#define VMMDLL_PLUGIN_CONTEXT_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 2
|
||||
|
||||
#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
|
||||
|
||||
@@ -254,7 +280,8 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem;
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel;
|
||||
VMMDLL_SYSTEM_TP tpSystem;
|
||||
HMODULE hDLL;
|
||||
HMODULE hReservedDll; // not for general use (only used for python).
|
||||
BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
|
||||
@@ -272,7 +299,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
// function plugin registration info to be filled out by the plugin below:
|
||||
struct {
|
||||
BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
|
||||
VOID(*pfnNotify)(_Inout_opt_ PHANDLE phModulePrivate, _In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
|
||||
VOID(*pfnCloseHandleModule)(_Inout_opt_ PHANDLE phModulePrivate);
|
||||
@@ -296,8 +323,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
|
||||
#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
|
||||
|
||||
#define VMMDLL_TARGET_UNKNOWN_X64 0x0001
|
||||
#define VMMDLL_TARGET_WINDOWS_X64 0x0002
|
||||
#define VMMDLL_MEM_IO_SCATTER_HEADER_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
ULONG64 qwA; // base address (DWORD boundry).
|
||||
@@ -306,6 +332,10 @@ typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
|
||||
PVOID pvReserved1; // reserved for use by caller.
|
||||
PVOID pvReserved2; // reserved for use by caller.
|
||||
WORD version; // version of struct
|
||||
WORD Future1; // reserved for future use.
|
||||
DWORD Future2; // reserved for future use.
|
||||
ULONG64 qwDeviceA; // device-physical address (used by device layer).
|
||||
struct {
|
||||
PVOID pvReserved1;
|
||||
PVOID pvReserved2;
|
||||
@@ -335,6 +365,7 @@ DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPVMMDLL_MEM_IO_SCATTER_HE
|
||||
* -- pbPage
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
|
||||
|
||||
/*
|
||||
@@ -345,6 +376,7 @@ BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4
|
||||
* -- cb
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
@@ -358,7 +390,8 @@ BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DW
|
||||
* -- return = success/fail. NB! reads may report as success even if 0 bytes are
|
||||
* read - it's recommended to verify pcbReadOpt parameter.
|
||||
*/
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
|
||||
/*
|
||||
* Write a contigious arbitrary amount of memory. Please note some virtual memory
|
||||
@@ -373,7 +406,8 @@ BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In
|
||||
* -- cb
|
||||
* -- return = TRUE on success, FALSE on partial or zero write.
|
||||
*/
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address by walking the page tables
|
||||
@@ -383,6 +417,7 @@ BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ D
|
||||
* -- pqwPA
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
|
||||
|
||||
|
||||
@@ -401,6 +436,7 @@ BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqw
|
||||
* -- pdwPID = pointer that will receive PID on success.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
|
||||
/*
|
||||
@@ -409,7 +445,8 @@ BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_PidList(_Out_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
|
||||
// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
|
||||
#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
|
||||
@@ -437,6 +474,7 @@ typedef struct tdVMMDLL_MEMMAP_ENTRY {
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
|
||||
|
||||
/*
|
||||
@@ -448,6 +486,7 @@ BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
|
||||
|
||||
typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
@@ -469,7 +508,8 @@ typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
* -- pcModuleEntries = pointer to number of memory map entries.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
|
||||
/*
|
||||
* Retrieve a module (.exe or .dll or similar) given a module name.
|
||||
@@ -478,29 +518,31 @@ BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY
|
||||
* -- pModuleEntry
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
|
||||
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 1
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem; // as given by VMMDLL_TARGET_*
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
|
||||
VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
DWORD dwPID;
|
||||
DWORD dwState;
|
||||
CHAR szName[16];
|
||||
ULONG64 paPML4;
|
||||
ULONG64 paPML4_UserOpt; // may not exist
|
||||
ULONG64 paDTB;
|
||||
ULONG64 paDTB_UserOpt; // may not exist
|
||||
union {
|
||||
struct {
|
||||
ULONG64 vaEPROCESS;
|
||||
ULONG64 vaPEB;
|
||||
ULONG64 vaENTRY;
|
||||
BOOL fWow64;
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
} win;
|
||||
} os;
|
||||
} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
|
||||
@@ -513,6 +555,7 @@ typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
|
||||
|
||||
typedef struct tdVMMDLL_EAT_ENTRY {
|
||||
@@ -539,10 +582,14 @@ typedef struct tdVMMDLL_IAT_ENTRY {
|
||||
* -- pcData
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
|
||||
|
||||
|
||||
@@ -558,7 +605,8 @@ BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_I
|
||||
* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
|
||||
* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
|
||||
*/
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_ LPSTR sz, _Inout_ PDWORD pcsz);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -27,10 +27,19 @@ VMMPY_STATUS_UNSUCCESSFUL = 0xC0000001
|
||||
VMMPY_STATUS_END_OF_FILE = 0xC0000011
|
||||
VMMPY_STATUS_FILE_INVALID = 0xC0000098
|
||||
|
||||
# TARGET SYSTEM values - used to determine if a plugin is supported or not for
|
||||
# SYSTEM values - used to determine if a plugin is supported or not for
|
||||
# the current system that is being analyzed.
|
||||
VMMPY_TARGET_UNKNOWN_X64 = 0x0001
|
||||
VMMPY_TARGET_WINDOWS_X64 = 0x0002
|
||||
VMMPY_SYSTEM_UNKNOWN_X64 = 0x0001
|
||||
VMMPY_SYSTEM_WINDOWS_X64 = 0x0002
|
||||
VMMPY_SYSTEM_UNKNOWN_X86 = 0x0003
|
||||
VMMPY_SYSTEM_WINDOWS_X86 = 0x0004
|
||||
|
||||
# MEMORYMODEL values - used to determine if a plugin is supported or not
|
||||
# for a specific memory model.
|
||||
VMMPY_MEMORYMODEL_NA = 0x0000
|
||||
VMMPY_MEMORYMODEL_X86 = 0x0001
|
||||
VMMPY_MEMORYMODEL_X86PAE = 0x0002
|
||||
VMMPY_MEMORYMODEL_X64 = 0x0003
|
||||
|
||||
# EVENT values - received by the notify callback function for specific events
|
||||
# occuring in the native plugin manager / vmm / memory process file system.
|
||||
@@ -154,7 +163,8 @@ VMMPY_OPT_CORE_VERBOSE_EXTRA = 0x80000003 # RW
|
||||
VMMPY_OPT_CORE_VERBOSE_EXTRA_TLP = 0x80000004 # RW
|
||||
VMMPY_OPT_CORE_MAX_NATIVE_ADDRESS = 0x80000005 # R
|
||||
VMMPY_OPT_CORE_MAX_NATIVE_IOSIZE = 0x80000006 # R
|
||||
VMMPY_OPT_CORE_TARGET_SYSTEM = 0x80000007 # R
|
||||
VMMPY_OPT_CORE_SYSTEM = 0x80000007 # R
|
||||
VMMPY_OPT_CORE_MEMORYMODEL = 0x80000008 # R
|
||||
|
||||
VMMPY_OPT_CONFIG_IS_REFRESH_ENABLED = 0x40000001 # R - 1/0
|
||||
VMMPY_OPT_CONFIG_TICK_PERIOD = 0x40000002 # RW - base tick period in ms
|
||||
@@ -383,7 +393,7 @@ def VmmPy_ProcessGetInformation(pid):
|
||||
return -- dict: of process information.
|
||||
|
||||
Example:
|
||||
VmmPy_ProcessGetInformation(332) --> {'pid': 8796, 'pa-pml4': 5798625280, 'pa-pml4-user': 6237978624, 'state': 0, 'target': 2, 'usermode': True, 'name': 'cmd.exe', 'wow64': False, 'va-entry': 140700131683072, 'va-eprocess': 18446635809067693440, 'va-peb': 708313505792, 'va-peb32': 0}
|
||||
VmmPy_ProcessGetInformation(332) --> {'pid': 8796, 'pa-dtb': 5798625280, 'pa-dtb-user': 6237978624, 'state': 0, 'tp-system': 2, 'usermode': True, 'name': 'cmd.exe', 'wow64': False, 'va-entry': 140700131683072, 'va-eprocess': 18446635809067693440, 'va-peb': 708313505792, 'va-peb32': 0}
|
||||
"""
|
||||
return VMMPYC_ProcessGetInformation(pid)
|
||||
|
||||
@@ -396,7 +406,7 @@ def VmmPy_ProcessListInformation():
|
||||
return -- dict: dict of process information with pid as key.
|
||||
|
||||
Example:
|
||||
VmmPy_ProcessListInformation() --> {4: {...}, ..., 322: {'pid': 8796, 'pa-pml4': 5798625280, 'pa-pml4-user': 6237978624, 'state': 0, 'target': 2, 'usermode': True, 'name': 'cmd.exe', 'wow64': False, 'va-entry': 140700131683072, 'va-eprocess': 18446635809067693440, 'va-peb': 708313505792, 'va-peb32': 0}
|
||||
VmmPy_ProcessListInformation() --> {4: {...}, ..., 322: {'pid': 8796, 'pa-dtb': 5798625280, 'pa-dtb-user': 6237978624, 'state': 0, 'tp-system': 2, 'usermode': True, 'name': 'cmd.exe', 'wow64': False, 'va-entry': 140700131683072, 'va-eprocess': 18446635809067693440, 'va-peb': 708313505792, 'va-peb32': 0}
|
||||
"""
|
||||
pids = VmmPy_PidList()
|
||||
result = {}
|
||||
|
||||
BIN
files/vmmpyc.pyd
BIN
files/vmmpyc.pyd
Binary file not shown.
Binary file not shown.
@@ -69,11 +69,13 @@ def VmmPyPlugin_InternalInitialize():
|
||||
global VmmPyPlugin_IsInitialized
|
||||
global VmmPyPlugin_RootDirectoryRoot
|
||||
global VmmPyPlugin_RootDirectoryProcess
|
||||
global VmmPyPlugin_OsTarget
|
||||
global VmmPyPlugin_TargetSystem
|
||||
global VmmPyPlugin_TargetMemoryModel
|
||||
VmmPyPlugin_IsInitialized = True
|
||||
VmmPyPlugin_RootDirectoryRoot = {}
|
||||
VmmPyPlugin_RootDirectoryProcess = {}
|
||||
VmmPyPlugin_OsTarget = VmmPy_ConfigGet(VMMPY_OPT_CORE_TARGET_SYSTEM)
|
||||
VmmPyPlugin_TargetSystem = VmmPy_ConfigGet(VMMPY_OPT_CORE_SYSTEM)
|
||||
VmmPyPlugin_TargetMemoryModel = VmmPy_ConfigGet(VMMPY_OPT_CORE_MEMORYMODEL)
|
||||
VmmPyPlugin_InternalSetVerbosity();
|
||||
VmmPyPlugin_InternalInitializePlugins()
|
||||
VMMPYCC_CallbackRegister(
|
||||
@@ -102,7 +104,7 @@ def VmmPyPlugin_InternalInitializePlugins():
|
||||
for e in plugin_names:
|
||||
try:
|
||||
module = importlib.import_module(e)
|
||||
module.Initialize(VmmPyPlugin_OsTarget)
|
||||
module.Initialize(VmmPyPlugin_TargetSystem, VmmPyPlugin_TargetMemoryModel)
|
||||
VmmPyPlugin_PluginModules.append(module)
|
||||
if VmmPyPlugin_fPrintV:
|
||||
print("VmmPyPlugin: Loaded '" + e + "'")
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
ULONG64 VMemD_GetBaseFromFileName(LPSTR sz)
|
||||
{
|
||||
if((strlen(sz) < 18) || (sz[0] != '0') || (sz[1] != 'x')) { return (ULONG64)-1; }
|
||||
if((strlen(sz) < 15) || (sz[0] != '0') || (sz[1] != 'x')) { return (ULONG64)-1; }
|
||||
return strtoull(sz, NULL, 16);
|
||||
}
|
||||
|
||||
@@ -100,13 +100,23 @@ BOOL VMemD_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
|
||||
return FALSE;
|
||||
}
|
||||
for(i = 0; i < cEntries; i++) {
|
||||
sprintf_s(
|
||||
szBufferFileName,
|
||||
MAX_PATH - 1,
|
||||
"0x%016llx%s%s.vmem",
|
||||
pMemMap[i].AddrBase,
|
||||
pMemMap[i].szTag[0] ? "-" : "",
|
||||
pMemMap[i].szTag[0] ? pMemMap[i].szTag : "");
|
||||
if(32 == (ULONG64)*ctx->phModulePrivate) {
|
||||
sprintf_s(
|
||||
szBufferFileName,
|
||||
MAX_PATH - 1,
|
||||
"0x%08x%s%s.vmem",
|
||||
(DWORD)pMemMap[i].AddrBase,
|
||||
pMemMap[i].szTag[0] ? "-" : "",
|
||||
pMemMap[i].szTag[0] ? pMemMap[i].szTag : "");
|
||||
} else {
|
||||
sprintf_s(
|
||||
szBufferFileName,
|
||||
MAX_PATH - 1,
|
||||
"0x%016llx%s%s.vmem",
|
||||
pMemMap[i].AddrBase,
|
||||
pMemMap[i].szTag[0] ? "-" : "",
|
||||
pMemMap[i].szTag[0] ? pMemMap[i].szTag : "");
|
||||
}
|
||||
VMMDLL_VfsList_AddFile(pFileList, szBufferFileName, (pMemMap[i].cPages << 12));
|
||||
}
|
||||
LocalFree(pMemMap);
|
||||
@@ -125,11 +135,15 @@ BOOL VMemD_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
|
||||
__declspec(dllexport)
|
||||
VOID InitializeVmmPlugin(_In_ PVMMDLL_PLUGIN_REGINFO pRegInfo)
|
||||
{
|
||||
if(0 == (pRegInfo->fTargetSystem & (VMMDLL_TARGET_UNKNOWN_X64 | VMMDLL_TARGET_WINDOWS_X64))) { return; }
|
||||
if((pRegInfo->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRegInfo->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
|
||||
// Ensure that the plugin support the memory model that is used. The plugin
|
||||
// currently supports the 64-bit x64 and 32-bit x86 and x86-pae memory models.
|
||||
if(!((pRegInfo->tpMemoryModel == VMMDLL_MEMORYMODEL_X64) || (pRegInfo->tpMemoryModel == VMMDLL_MEMORYMODEL_X86) || (pRegInfo->tpMemoryModel == VMMDLL_MEMORYMODEL_X86PAE))) { return; }
|
||||
strcpy_s(pRegInfo->reg_info.szModuleName, 32, "vmemd"); // module name - 'vmemd'.
|
||||
pRegInfo->reg_info.fProcessModule = TRUE; // module shows in process directory.
|
||||
pRegInfo->reg_fn.pfnList = VMemD_List; // List function supported.
|
||||
pRegInfo->reg_fn.pfnRead = VMemD_Read; // Read function supported.
|
||||
pRegInfo->reg_fn.pfnWrite = VMemD_Write; // Write function supported.
|
||||
pRegInfo->reg_info.hModulePrivate = (HANDLE)(ULONG64)((pRegInfo->tpMemoryModel == VMMDLL_MEMORYMODEL_X64) ? 64 : 32); // use handle for "bitness".
|
||||
pRegInfo->pfnPluginManager_Register(pRegInfo); // Register with the plugin maanger.
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ extern "C" {
|
||||
* Call other VMMDLL_Intialize functions to initialize VMM.DLL and the memory
|
||||
* process file system.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
|
||||
/*
|
||||
@@ -37,6 +38,7 @@ BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -52,6 +54,7 @@ BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBase
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -60,6 +63,7 @@ BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPST
|
||||
* initialized in read/write mode upon success.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
|
||||
/*
|
||||
@@ -67,6 +71,7 @@ BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
* including plugins, linked PCILeech.DLL and other memory resources.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_Close();
|
||||
|
||||
|
||||
@@ -103,7 +108,8 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
|
||||
#define VMMDLL_OPT_CORE_TARGET_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
|
||||
|
||||
#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
|
||||
#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
|
||||
@@ -116,6 +122,22 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
|
||||
#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
|
||||
|
||||
static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
|
||||
|
||||
typedef enum tdVMMDLL_MEMORYMODEL_TP {
|
||||
VMMDLL_MEMORYMODEL_NA = 0,
|
||||
VMMDLL_MEMORYMODEL_X86 = 1,
|
||||
VMMDLL_MEMORYMODEL_X86PAE = 2,
|
||||
VMMDLL_MEMORYMODEL_X64 = 3
|
||||
} VMMDLL_MEMORYMODEL_TP;
|
||||
|
||||
typedef enum tdVMMDLL_SYSTEM_TP {
|
||||
VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
|
||||
VMMDLL_SYSTEM_WINDOWS_X64 = 2,
|
||||
VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
|
||||
VMMDLL_SYSTEM_WINDOWS_X86 = 4
|
||||
} VMMDLL_SYSTEM_TP;
|
||||
|
||||
/*
|
||||
* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
|
||||
* mation about valid option values. Please note that option values may overlap
|
||||
@@ -124,6 +146,7 @@ BOOL VMMDLL_Close();
|
||||
* -- pqwValue = pointer to ULONG64 to receive option value.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
|
||||
/*
|
||||
@@ -134,6 +157,7 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
* -- qwValue
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
|
||||
|
||||
|
||||
@@ -171,6 +195,7 @@ typedef struct tdVMMDLL_VFS_FILELIST {
|
||||
* -- pFileList
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
|
||||
|
||||
/*
|
||||
@@ -227,12 +252,13 @@ NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb,
|
||||
* will be unloaded on a general close of the vmm dll.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsInitializePlugins();
|
||||
|
||||
#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
|
||||
#define VMMDLL_PLUGIN_CONTEXT_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 2
|
||||
|
||||
#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
|
||||
|
||||
@@ -254,7 +280,8 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem;
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel;
|
||||
VMMDLL_SYSTEM_TP tpSystem;
|
||||
HMODULE hDLL;
|
||||
HMODULE hReservedDll; // not for general use (only used for python).
|
||||
BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
|
||||
@@ -272,7 +299,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
// function plugin registration info to be filled out by the plugin below:
|
||||
struct {
|
||||
BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
|
||||
VOID(*pfnNotify)(_Inout_opt_ PHANDLE phModulePrivate, _In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
|
||||
VOID(*pfnCloseHandleModule)(_Inout_opt_ PHANDLE phModulePrivate);
|
||||
@@ -296,8 +323,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
|
||||
#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
|
||||
|
||||
#define VMMDLL_TARGET_UNKNOWN_X64 0x0001
|
||||
#define VMMDLL_TARGET_WINDOWS_X64 0x0002
|
||||
#define VMMDLL_MEM_IO_SCATTER_HEADER_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
ULONG64 qwA; // base address (DWORD boundry).
|
||||
@@ -306,6 +332,10 @@ typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
|
||||
PVOID pvReserved1; // reserved for use by caller.
|
||||
PVOID pvReserved2; // reserved for use by caller.
|
||||
WORD version; // version of struct
|
||||
WORD Future1; // reserved for future use.
|
||||
DWORD Future2; // reserved for future use.
|
||||
ULONG64 qwDeviceA; // device-physical address (used by device layer).
|
||||
struct {
|
||||
PVOID pvReserved1;
|
||||
PVOID pvReserved2;
|
||||
@@ -335,6 +365,7 @@ DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPVMMDLL_MEM_IO_SCATTER_HE
|
||||
* -- pbPage
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
|
||||
|
||||
/*
|
||||
@@ -345,6 +376,7 @@ BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4
|
||||
* -- cb
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
@@ -358,7 +390,8 @@ BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DW
|
||||
* -- return = success/fail. NB! reads may report as success even if 0 bytes are
|
||||
* read - it's recommended to verify pcbReadOpt parameter.
|
||||
*/
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
|
||||
/*
|
||||
* Write a contigious arbitrary amount of memory. Please note some virtual memory
|
||||
@@ -373,7 +406,8 @@ BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In
|
||||
* -- cb
|
||||
* -- return = TRUE on success, FALSE on partial or zero write.
|
||||
*/
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address by walking the page tables
|
||||
@@ -383,6 +417,7 @@ BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ D
|
||||
* -- pqwPA
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
|
||||
|
||||
|
||||
@@ -401,6 +436,7 @@ BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqw
|
||||
* -- pdwPID = pointer that will receive PID on success.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
|
||||
/*
|
||||
@@ -409,7 +445,8 @@ BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_PidList(_Out_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
|
||||
// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
|
||||
#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
|
||||
@@ -437,6 +474,7 @@ typedef struct tdVMMDLL_MEMMAP_ENTRY {
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
|
||||
|
||||
/*
|
||||
@@ -448,6 +486,7 @@ BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
|
||||
|
||||
typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
@@ -469,7 +508,8 @@ typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
* -- pcModuleEntries = pointer to number of memory map entries.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
|
||||
/*
|
||||
* Retrieve a module (.exe or .dll or similar) given a module name.
|
||||
@@ -478,29 +518,31 @@ BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY
|
||||
* -- pModuleEntry
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
|
||||
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 1
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem; // as given by VMMDLL_TARGET_*
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
|
||||
VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
DWORD dwPID;
|
||||
DWORD dwState;
|
||||
CHAR szName[16];
|
||||
ULONG64 paPML4;
|
||||
ULONG64 paPML4_UserOpt; // may not exist
|
||||
ULONG64 paDTB;
|
||||
ULONG64 paDTB_UserOpt; // may not exist
|
||||
union {
|
||||
struct {
|
||||
ULONG64 vaEPROCESS;
|
||||
ULONG64 vaPEB;
|
||||
ULONG64 vaENTRY;
|
||||
BOOL fWow64;
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
} win;
|
||||
} os;
|
||||
} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
|
||||
@@ -513,6 +555,7 @@ typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
|
||||
|
||||
typedef struct tdVMMDLL_EAT_ENTRY {
|
||||
@@ -539,10 +582,14 @@ typedef struct tdVMMDLL_IAT_ENTRY {
|
||||
* -- pcData
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
|
||||
|
||||
|
||||
@@ -558,7 +605,8 @@ BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_I
|
||||
* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
|
||||
* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
|
||||
*/
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_ LPSTR sz, _Inout_ PDWORD pcsz);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
10
vmm/device.c
10
vmm/device.c
@@ -90,11 +90,13 @@ BOOL DeviceOpen()
|
||||
return result;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL DeviceGetOption(_In_ QWORD fOption, _Out_ PQWORD pqwValue)
|
||||
{
|
||||
return ctxMain->dev.pfnGetOption && ctxMain->dev.pfnGetOption(fOption, pqwValue);
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL DeviceSetOption(_In_ QWORD fOption, _In_ QWORD qwValue)
|
||||
{
|
||||
return ctxMain->dev.pfnSetOption && ctxMain->dev.pfnSetOption(fOption, qwValue);
|
||||
@@ -122,7 +124,7 @@ DWORD DeviceReadMEMEx_DoWork_Scatter(_In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWO
|
||||
PageStatUpdate(pPageStat, pDMAs[i].qwA + 0x1000, 1, 0);
|
||||
} else {
|
||||
PageStatUpdate(pPageStat, pDMAs[i].qwA + 0x1000, 0, 1);
|
||||
ZeroMemory(pDMAs[i].pb, 0x1000);
|
||||
ZeroMemory(pDMAs[i].pb, pDMAs[i].cbMax);
|
||||
}
|
||||
}
|
||||
LocalFree(pbBuffer);
|
||||
@@ -148,17 +150,17 @@ DWORD DeviceReadMEMEx_DoWork(_In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _
|
||||
return cbSuccess;
|
||||
}
|
||||
|
||||
DWORD DeviceReadMEMEx(_In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat)
|
||||
DWORD DeviceReadMEMEx(_In_ QWORD qwAddr, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat)
|
||||
{
|
||||
BYTE pbWorkaround[4096];
|
||||
DWORD cbDataRead;
|
||||
// read memory (with strange workaround for 1-page reads...)
|
||||
if(cb != 0x1000) {
|
||||
if(cb > 0x1000) {
|
||||
cbDataRead = DeviceReadMEMEx_DoWork(qwAddr, pb, cb, pPageStat, (DWORD)ctxMain->dev.qwMaxSizeMemIo);
|
||||
} else {
|
||||
// why is this working ??? if not here console is screwed up... (threading issue?)
|
||||
cbDataRead = DeviceReadMEMEx_DoWork(qwAddr, pbWorkaround, 0x1000, pPageStat, (DWORD)ctxMain->dev.qwMaxSizeMemIo);
|
||||
memcpy(pb, pbWorkaround, 0x1000);
|
||||
memcpy(pb, pbWorkaround, cb);
|
||||
}
|
||||
return cbDataRead;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ VOID DeviceReadScatterMEM(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpM
|
||||
* -- pPageStat = optional page statistics
|
||||
* -- return = the number of bytes successfully read.
|
||||
*/
|
||||
DWORD DeviceReadMEMEx(_In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat);
|
||||
DWORD DeviceReadMEMEx(_In_ QWORD qwAddr, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat);
|
||||
|
||||
/*
|
||||
* Write data to the target system using DMA.
|
||||
@@ -58,6 +58,7 @@ BOOL DeviceWriteMEM(_In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
* -- pqwValue = pointer to QWORD to receive option value.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL DeviceGetOption(_In_ QWORD fOption, _Out_ PQWORD pqwValue);
|
||||
|
||||
/*
|
||||
@@ -67,6 +68,7 @@ BOOL DeviceGetOption(_In_ QWORD fOption, _Out_ PQWORD pqwValue);
|
||||
* -- qwValue
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL DeviceSetOption(_In_ QWORD fOption, _In_ QWORD qwValue);
|
||||
|
||||
#endif /* __DEVICE_H__ */
|
||||
|
||||
@@ -31,7 +31,10 @@ VOID DevicePCILeechDll_ReadScatterMEM(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _I
|
||||
{
|
||||
DWORD cMEMsRead;
|
||||
PDEVICE_CONTEXT_PCILEECH_DLL ctxDll = (PDEVICE_CONTEXT_PCILEECH_DLL)ctxMain->dev.hDevice;
|
||||
if(!ctxDll) { return; }
|
||||
if(!ctxDll) {
|
||||
if(pcMEMsRead) { *pcMEMsRead = 0; }
|
||||
return;
|
||||
}
|
||||
cMEMsRead = ctxDll->PCILeech_DeviceReadScatterMEM(ppMEMs, cpMEMs);
|
||||
if(pcMEMsRead) {
|
||||
*pcMEMsRead = cMEMsRead;
|
||||
@@ -41,7 +44,7 @@ VOID DevicePCILeechDll_ReadScatterMEM(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _I
|
||||
BOOL DevicePCILeechDll_GetOption(_In_ QWORD fOption, _Out_ PQWORD pqwValue)
|
||||
{
|
||||
PDEVICE_CONTEXT_PCILEECH_DLL ctxDll = (PDEVICE_CONTEXT_PCILEECH_DLL)ctxMain->dev.hDevice;
|
||||
if(!ctxDll) { return FALSE; }
|
||||
if(!ctxDll) { *pqwValue = 0; return FALSE; }
|
||||
return ctxDll->PCIleech_DeviceConfigGet(fOption, pqwValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#include "m_ldrmodules.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "vmm.h"
|
||||
#include "vmmproc_windows.h"
|
||||
#include "vmmwin.h"
|
||||
#include "vmmvfs.h"
|
||||
#include "util.h"
|
||||
#include "pe.h"
|
||||
|
||||
#define LDRMODULES_CACHE_TP_EAT 1
|
||||
#define LDRMODULES_CACHE_TP_IAT 2
|
||||
@@ -82,7 +83,7 @@ PLDRMODULES_CACHE_ENTRY LdrModule_GetEAT(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ P
|
||||
cEATs = LDRMODULES_MAX_IATEAT;
|
||||
pEATs = LocalAlloc(0, LDRMODULES_MAX_IATEAT * sizeof(VMMPROC_WINDOWS_EAT_ENTRY));
|
||||
if(!pEATs) { goto fail; }
|
||||
VmmProcWindows_PE_LoadEAT_DisplayBuffer(ctx->pProcess, pModule, pEATs, &cEATs);
|
||||
VmmWin_PE_LoadEAT_DisplayBuffer(ctx->pProcess, pModule, pEATs, &cEATs);
|
||||
if(!cEATs) { goto fail; }
|
||||
// 3: fill "display buffer"
|
||||
pCacheEntry->cb = cEATs * 64 + 1;
|
||||
@@ -109,16 +110,16 @@ fail:
|
||||
PLDRMODULES_CACHE_ENTRY LdrModule_GetIAT(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ PVMM_MODULEMAP_ENTRY pModule)
|
||||
{
|
||||
DWORD i, o, cIATs;
|
||||
PVMMPROC_WINDOWS_IAT_ENTRY pIATs = NULL;
|
||||
PVMMWIN_IAT_ENTRY pIATs = NULL;
|
||||
PLDRMODULES_CACHE_ENTRY pCacheEntry;
|
||||
// 1: retrieve cache
|
||||
pCacheEntry = LdrModule_GetCacheEntry(ctx, pModule->szName, LDRMODULES_CACHE_TP_IAT);
|
||||
if(pCacheEntry->pb) { return pCacheEntry; }
|
||||
// 2: retrieve exported functions
|
||||
cIATs = LDRMODULES_MAX_IATEAT;
|
||||
pIATs = LocalAlloc(0, LDRMODULES_MAX_IATEAT * sizeof(VMMPROC_WINDOWS_IAT_ENTRY));
|
||||
pIATs = LocalAlloc(0, LDRMODULES_MAX_IATEAT * sizeof(VMMWIN_IAT_ENTRY));
|
||||
if(!pIATs) { goto fail; }
|
||||
VmmProcWindows_PE_LoadIAT_DisplayBuffer(ctx->pProcess, pModule, pIATs, &cIATs);
|
||||
VmmWin_PE_LoadIAT_DisplayBuffer(ctx->pProcess, pModule, pIATs, &cIATs);
|
||||
if(!cIATs) { goto fail; }
|
||||
// 3: fill "display buffer"
|
||||
pCacheEntry->cb = cIATs * 128 + 1;
|
||||
@@ -143,6 +144,112 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper write function - Write to a virtual memory backed "file".
|
||||
*/
|
||||
VOID LdrModules_Write_MemFile(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaMem, _In_ QWORD cbMem, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset)
|
||||
{
|
||||
if(cbMem <= cbOffset) { *pcbWrite = 0; return; }
|
||||
*pcbWrite = (DWORD)min(cb, cbMem - cbOffset);
|
||||
VmmWrite(pProcess, vaMem + cbOffset, pb, *pcbWrite);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper write function - Write to the requested data directory file.
|
||||
*/
|
||||
VOID LdrModules_Write_DirectoriesD(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _In_ LPSTR szDirectory, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
|
||||
{
|
||||
DWORD i;
|
||||
IMAGE_DATA_DIRECTORY pDataDirectories[16];
|
||||
*pcbWrite = 0;
|
||||
for(i = 0; i < 16; i++) {
|
||||
if(!strcmp(szDirectory, PE_DATA_DIRECTORIES[i])) {
|
||||
VmmWin_PE_DIRECTORY_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, pDataDirectories);
|
||||
LdrModules_Write_MemFile(pProcess, pModule->BaseAddress + pDataDirectories[i].VirtualAddress, pDataDirectories[i].Size, pb, cb, pcbWrite, cbOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper write function - Write to the requested section header file.
|
||||
*/
|
||||
VOID LdrModules_Write_SectionsD(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _In_ LPSTR szSection, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
|
||||
{
|
||||
IMAGE_SECTION_HEADER SectionHeader;
|
||||
if(!PE_SectionGetFromName(pProcess, pModule->BaseAddress, szSection, &SectionHeader)) { *pcbWrite = 0; return; }
|
||||
LdrModules_Write_MemFile(pProcess, pModule->BaseAddress + SectionHeader.VirtualAddress, SectionHeader.Misc.VirtualSize, pb, cb, pcbWrite, cbOffset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write : function as specified by the module manager. The module manager will
|
||||
* call into this callback function whenever a write shall occur from a "file".
|
||||
* -- ctx
|
||||
* -- pb
|
||||
* -- cb
|
||||
* -- pcbWrite
|
||||
* -- cbOffset
|
||||
* -- return
|
||||
*/
|
||||
NTSTATUS LdrModules_Write(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
|
||||
{
|
||||
DWORD i;
|
||||
CHAR _szBuf[MAX_PATH] = { 0 };
|
||||
LPSTR szPath1, szPath2;
|
||||
PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
|
||||
*pcbWrite = 0;
|
||||
Util_PathSplit2(ctx->szPath, _szBuf, &szPath1, &szPath2);
|
||||
if(szPath1[0] && szPath2[0]) {
|
||||
for(i = 0; i < pProcess->cModuleMap; i++) {
|
||||
if(0 == strncmp(szPath1, pProcess->pModuleMap[i].szName, MAX_PATH)) {
|
||||
if(!_strnicmp(szPath2, "sectionsd\\", 10)) {
|
||||
LdrModules_Write_SectionsD(pProcess, pProcess->pModuleMap + i, szPath2 + 10, pb, cb, pcbWrite, cbOffset);
|
||||
}
|
||||
if(!_strnicmp(szPath2, "directoriesd\\", 13)) {
|
||||
LdrModules_Write_DirectoriesD(pProcess, pProcess->pModuleMap + i, szPath2 + 13, pb, cb, pcbWrite, cbOffset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return VMM_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper read function - Read a virtual memory backed "file".
|
||||
*/
|
||||
NTSTATUS LdrModules_Read_MemFile(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaMem, _In_ QWORD cbMem, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset)
|
||||
{
|
||||
if(cbMem <= cbOffset) { return VMM_STATUS_END_OF_FILE; }
|
||||
VmmReadEx(pProcess, vaMem + cbOffset, pb, (DWORD)min(cb, cbMem - cbOffset), pcbRead, 0);
|
||||
return *pcbRead ? VMMDLL_STATUS_SUCCESS : VMMDLL_STATUS_END_OF_FILE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper read function - Read the requested data directory file.
|
||||
*/
|
||||
NTSTATUS LdrModules_Read_DirectoriesD(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _In_ LPSTR szDirectory, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
|
||||
{
|
||||
DWORD i;
|
||||
IMAGE_DATA_DIRECTORY pDataDirectories[16];
|
||||
for(i = 0; i < 16; i++) {
|
||||
if(!strcmp(szDirectory, PE_DATA_DIRECTORIES[i])) {
|
||||
VmmWin_PE_DIRECTORY_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, pDataDirectories);
|
||||
return LdrModules_Read_MemFile(pProcess, pModule->BaseAddress + pDataDirectories[i].VirtualAddress, pDataDirectories[i].Size, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
}
|
||||
return VMMDLL_STATUS_FILE_INVALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper read function - Read the requested section header file.
|
||||
*/
|
||||
NTSTATUS LdrModules_Read_SectionsD(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _In_ LPSTR szSection, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
|
||||
{
|
||||
IMAGE_SECTION_HEADER SectionHeader;
|
||||
if(!PE_SectionGetFromName(pProcess, pModule->BaseAddress, szSection, &SectionHeader)) { return VMMDLL_STATUS_FILE_INVALID; }
|
||||
return LdrModules_Read_MemFile(pProcess, pModule->BaseAddress + SectionHeader.VirtualAddress, SectionHeader.Misc.VirtualSize, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read : function as specified by the module manager. The module manager will
|
||||
* call into this callback function whenever a read shall occur from a "file".
|
||||
@@ -162,6 +269,7 @@ NTSTATUS LdrModules_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_
|
||||
PLDRMODULES_CACHE_ENTRY pCacheEntry;
|
||||
PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
|
||||
Util_PathSplit2(ctx->szPath, _szBuf, &szPath1, &szPath2);
|
||||
*pcbRead = 0;
|
||||
if(szPath1[0] && szPath2[0]) {
|
||||
for(i = 0; i < pProcess->cModuleMap; i++) {
|
||||
if(0 == strncmp(szPath1, pProcess->pModuleMap[i].szName, MAX_PATH)) {
|
||||
@@ -175,7 +283,7 @@ NTSTATUS LdrModules_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_
|
||||
return Util_VfsReadFile_FromDWORD(pProcess->pModuleMap[i].SizeOfImage, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
}
|
||||
if(!_stricmp(szPath2, "directories")) {
|
||||
VmmProcWindows_PE_DIRECTORY_DisplayBuffer(ctx->pProcess, pProcess->pModuleMap + i, pbBuffer, 0x400, &cbBuffer, NULL);
|
||||
VmmWin_PE_DIRECTORY_DisplayBuffer(ctx->pProcess, pProcess->pModuleMap + i, pbBuffer, 0x400, &cbBuffer, NULL);
|
||||
return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
if(!_stricmp(szPath2, "export")) {
|
||||
@@ -189,9 +297,15 @@ NTSTATUS LdrModules_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_
|
||||
return Util_VfsReadFile_FromPBYTE(pCacheEntry->pb, pCacheEntry->cb, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
if(!_stricmp(szPath2, "sections")) {
|
||||
VmmProcWindows_PE_SECTION_DisplayBuffer(ctx->pProcess, pProcess->pModuleMap + i, pbBuffer, 0x800, &cbBuffer, NULL);
|
||||
VmmWin_PE_SECTION_DisplayBuffer(ctx->pProcess, pProcess->pModuleMap + i, pbBuffer, 0x800, &cbBuffer, NULL, NULL);
|
||||
return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
if(!_strnicmp(szPath2, "sectionsd\\", 10)) {
|
||||
return LdrModules_Read_SectionsD(pProcess, pProcess->pModuleMap + i, szPath2 + 10, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
if(!_strnicmp(szPath2, "directoriesd\\", 13)) {
|
||||
return LdrModules_Read_DirectoriesD(pProcess, pProcess->pModuleMap + i, szPath2 + 13, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
return VMMDLL_STATUS_FILE_INVALID;
|
||||
}
|
||||
}
|
||||
@@ -209,9 +323,12 @@ NTSTATUS LdrModules_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_
|
||||
*/
|
||||
BOOL LdrModules_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
|
||||
{
|
||||
DWORD i;
|
||||
DWORD c, i;
|
||||
CHAR _szBuf[MAX_PATH] = { 0 };
|
||||
LPSTR szPath1, szPath2;
|
||||
PVMM_MODULEMAP_ENTRY pModule = NULL;
|
||||
PIMAGE_SECTION_HEADER pSections = NULL;
|
||||
IMAGE_DATA_DIRECTORY pDataDirectories[16];
|
||||
PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
|
||||
// modules root directory -> add directory per DLL
|
||||
if(!ctx->szPath[0]) {
|
||||
@@ -222,21 +339,47 @@ BOOL LdrModules_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
|
||||
}
|
||||
// individual module directory -> list files
|
||||
Util_PathSplit2(ctx->szPath, _szBuf, &szPath1, &szPath2);
|
||||
if(!szPath2[0]) {
|
||||
for(i = 0; i < pProcess->cModuleMap; i++) {
|
||||
if(0 == strncmp(szPath1, pProcess->pModuleMap[i].szName, MAX_PATH)) {
|
||||
VmmProcWindows_PE_SetSizeSectionIATEAT_DisplayBuffer(ctx->pProcess, pProcess->pModuleMap + i);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "base", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "entry", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "size", 8);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "directories", 864);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "export", pProcess->pModuleMap[i].cbDisplayBufferEAT);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "import", pProcess->pModuleMap[i].cbDisplayBufferIAT);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "sections", pProcess->pModuleMap[i].cbDisplayBufferSections);
|
||||
return TRUE;
|
||||
}
|
||||
for(i = 0; i < pProcess->cModuleMap; i++) {
|
||||
if(0 == strncmp(szPath1, pProcess->pModuleMap[i].szName, 32)) {
|
||||
pModule = pProcess->pModuleMap + i;
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if(!pModule) { return FALSE; }
|
||||
// module-specific 'root' directory
|
||||
if(!szPath2[0]) {
|
||||
VmmWin_PE_SetSizeSectionIATEAT_DisplayBuffer(ctx->pProcess, pProcess->pModuleMap + i);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "base", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "entry", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "size", 8);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "directories", 864);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "export", pProcess->pModuleMap[i].cbDisplayBufferEAT);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "import", pProcess->pModuleMap[i].cbDisplayBufferIAT);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "sections", pProcess->pModuleMap[i].cbDisplayBufferSections);
|
||||
VMMDLL_VfsList_AddDirectory(pFileList, "sectionsd");
|
||||
VMMDLL_VfsList_AddDirectory(pFileList, "directoriesd");
|
||||
return TRUE;
|
||||
}
|
||||
// module-specific 'sectiond' directory
|
||||
if(szPath2[0] && !strcmp(szPath2, "sectionsd")) {
|
||||
_szBuf[8] = 0;
|
||||
c = PE_SectionGetNumberOf(pProcess, pModule->BaseAddress);
|
||||
if(!(pSections = LocalAlloc(0, c * sizeof(IMAGE_SECTION_HEADER)))) { return FALSE; }
|
||||
VmmWin_PE_SECTION_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, &c, pSections);
|
||||
for(i = 0; i < c; i++) {
|
||||
*(PQWORD)_szBuf = *(PQWORD)pSections[i].Name;
|
||||
VMMDLL_VfsList_AddFile(pFileList, _szBuf, pSections[i].Misc.VirtualSize);
|
||||
}
|
||||
LocalFree(pSections);
|
||||
return TRUE;
|
||||
}
|
||||
// module-specific 'directoriesd' directory
|
||||
if(szPath2[0] && !strcmp(szPath2, "directoriesd")) {
|
||||
VmmWin_PE_DIRECTORY_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, pDataDirectories);
|
||||
for(i = 0; i < 16; i++) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, (LPSTR)PE_DATA_DIRECTORIES[i], pDataDirectories[i].Size);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -249,17 +392,19 @@ BOOL LdrModules_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
|
||||
* operating system or architecture is unsupported.
|
||||
* -- pPluginRegInfo
|
||||
*/
|
||||
VOID M_LdrModules_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo)
|
||||
VOID M_LdrModules_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pRI)
|
||||
{
|
||||
PLDRMODULES_CACHE_ENTRY pCache;
|
||||
if(0 == (pPluginRegInfo->fTargetSystem & VMM_TARGET_WINDOWS_X64)) { return; }
|
||||
if((pRI->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRI->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
|
||||
if((pRI->tpSystem != VMM_SYSTEM_WINDOWS_X64) && (pRI->tpSystem != VMM_SYSTEM_WINDOWS_X86)) { return; }
|
||||
pCache = LocalAlloc(LMEM_ZEROINIT, LDRMODULES_NUM_CACHE * sizeof(LDRMODULES_CACHE_ENTRY));
|
||||
if(!pCache) { return; }
|
||||
strcpy_s(pPluginRegInfo->reg_info.szModuleName, 32, "modules"); // module name
|
||||
pPluginRegInfo->reg_info.fProcessModule = TRUE; // module shows in process directory
|
||||
pPluginRegInfo->reg_info.hModulePrivate = pCache; // module private handle (for cache)
|
||||
pPluginRegInfo->reg_fn.pfnList = LdrModules_List; // List function supported
|
||||
pPluginRegInfo->reg_fn.pfnRead = LdrModules_Read; // Read function supported
|
||||
pPluginRegInfo->reg_fn.pfnCloseHandleModule = LdrModule_CloseHandleModule; // Close module private handle supported
|
||||
pPluginRegInfo->pfnPluginManager_Register(pPluginRegInfo);
|
||||
strcpy_s(pRI->reg_info.szModuleName, 32, "modules"); // module name
|
||||
pRI->reg_info.fProcessModule = TRUE; // module shows in process directory
|
||||
pRI->reg_info.hModulePrivate = pCache; // module private handle (for cache)
|
||||
pRI->reg_fn.pfnList = LdrModules_List; // List function supported
|
||||
pRI->reg_fn.pfnRead = LdrModules_Read; // Read function supported
|
||||
pRI->reg_fn.pfnWrite = LdrModules_Write; // Write function supported
|
||||
pRI->reg_fn.pfnCloseHandleModule = LdrModule_CloseHandleModule; // Close module private handle supported
|
||||
pRI->pfnPluginManager_Register(pRI);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "pluginmanager.h"
|
||||
#include "util.h"
|
||||
#include "vmm.h"
|
||||
#include "vmmproc.h"
|
||||
#include "vmmvfs.h"
|
||||
#include "statistics.h"
|
||||
|
||||
@@ -49,6 +50,9 @@ NTSTATUS MStatus_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWO
|
||||
}
|
||||
// "ROOT"
|
||||
if(!pProcess) {
|
||||
if(!_stricmp(ctx->szPath, "config_process_show_terminated")) {
|
||||
return Util_VfsReadFile_FromBOOL(ctxVmm->flags & VMM_FLAG_PROCESS_SHOW_TERMINATED, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
if(!_stricmp(ctx->szPath, "config_cache_enable")) {
|
||||
return Util_VfsReadFile_FromBOOL(!(ctxVmm->flags & VMM_FLAG_NOCACHE), pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
@@ -162,6 +166,16 @@ NTSTATUS MStatus_Write(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWO
|
||||
}
|
||||
// "ROOT"
|
||||
if(!pProcess) {
|
||||
|
||||
if(!_stricmp(ctx->szPath, "config_process_show_terminated")) {
|
||||
nt = Util_VfsWriteFile_BOOL(&fEnable, pb, cb, pcbWrite, cbOffset);
|
||||
if(nt == VMMDLL_STATUS_SUCCESS) {
|
||||
ctxVmm->flags &= ~VMM_FLAG_PROCESS_SHOW_TERMINATED;
|
||||
ctxVmm->flags |= fEnable ? VMM_FLAG_PROCESS_SHOW_TERMINATED : 0;
|
||||
VmmProc_Refresh(FALSE, TRUE);
|
||||
}
|
||||
return nt;
|
||||
}
|
||||
if(!_stricmp(ctx->szPath, "config_cache_enable")) {
|
||||
nt = Util_VfsWriteFile_BOOL(&fEnable, pb, cb, pcbWrite, cbOffset);
|
||||
if(nt == VMMDLL_STATUS_SUCCESS) {
|
||||
@@ -241,6 +255,7 @@ BOOL MStatus_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
|
||||
VMMDLL_VfsList_AddFile(pFileList, "config_printf_v", 1);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "config_printf_vv", 1);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "config_printf_vvv", 1);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "config_process_show_terminated", 1);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "native_max_address", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "native_max_iosize", 16);
|
||||
Statistics_CallToString(NULL, 0, &cbCallStatistics);
|
||||
@@ -261,14 +276,15 @@ BOOL MStatus_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
|
||||
* operating system or architecture is unsupported.
|
||||
* -- pPluginRegInfo
|
||||
*/
|
||||
VOID M_Status_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo)
|
||||
VOID M_Status_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pRI)
|
||||
{
|
||||
if(0 == (pPluginRegInfo->fTargetSystem & (VMM_TARGET_UNKNOWN_X64 | VMM_TARGET_WINDOWS_X64))) { return; }
|
||||
strcpy_s(pPluginRegInfo->reg_info.szModuleName, 32, ".status"); // module name
|
||||
pPluginRegInfo->reg_info.fRootModule = TRUE; // module shows in root directory
|
||||
pPluginRegInfo->reg_info.fProcessModule = TRUE; // module shows in process directory
|
||||
pPluginRegInfo->reg_fn.pfnList = MStatus_List; // List function supported
|
||||
pPluginRegInfo->reg_fn.pfnRead = MStatus_Read; // Read function supported
|
||||
pPluginRegInfo->reg_fn.pfnWrite = MStatus_Write; // Write function supported
|
||||
pPluginRegInfo->pfnPluginManager_Register(pPluginRegInfo);
|
||||
if((pRI->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRI->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
|
||||
// .status module is always valid - no check against pPluginRegInfo->tpMemoryModel, tpSystem
|
||||
strcpy_s(pRI->reg_info.szModuleName, 32, ".status"); // module name
|
||||
pRI->reg_info.fRootModule = TRUE; // module shows in root directory
|
||||
pRI->reg_info.fProcessModule = TRUE; // module shows in process directory
|
||||
pRI->reg_fn.pfnList = MStatus_List; // List function supported
|
||||
pRI->reg_fn.pfnRead = MStatus_Read; // Read function supported
|
||||
pRI->reg_fn.pfnWrite = MStatus_Write; // Write function supported
|
||||
pRI->pfnPluginManager_Register(pRI);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* -- pDummy
|
||||
* -- return
|
||||
*/
|
||||
PVMM_VIRT2PHYS_INFORMATION Virt2Phys_GetContext(_Inout_opt_ PHANDLE phProcessPrivate, _Inout_opt_ PVMM_VIRT2PHYS_INFORMATION pDummy)
|
||||
PVMM_VIRT2PHYS_INFORMATION Virt2Phys_GetContext(_Inout_ PHANDLE phProcessPrivate, _Out_opt_ PVMM_VIRT2PHYS_INFORMATION pDummy)
|
||||
{
|
||||
if(*phProcessPrivate) {
|
||||
return (PVMM_VIRT2PHYS_INFORMATION)*phProcessPrivate;
|
||||
@@ -51,26 +51,64 @@ NTSTATUS Virt2Phys_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ D
|
||||
VMM_VIRT2PHYS_INFORMATION Virt2PhysInfo_Dummy, *pVirt2PhysInfo;
|
||||
pVirt2PhysInfo = Virt2Phys_GetContext(ctx->phProcessPrivate, &Virt2PhysInfo_Dummy);
|
||||
if(!_stricmp(ctx->szPath, "virt")) {
|
||||
return Util_VfsReadFile_FromQWORD(pVirt2PhysInfo->va, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
switch(ctxVmm->tpMemoryModel) {
|
||||
case VMM_MEMORYMODEL_X64:
|
||||
return Util_VfsReadFile_FromQWORD(pVirt2PhysInfo->va, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
break;
|
||||
case VMM_MEMORYMODEL_X86:
|
||||
case VMM_MEMORYMODEL_X86PAE:
|
||||
return Util_VfsReadFile_FromDWORD((DWORD)pVirt2PhysInfo->va, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!_stricmp(ctx->szPath, "phys")) {
|
||||
return Util_VfsReadFile_FromQWORD(pVirt2PhysInfo->x64.pas[0], pb, cb, pcbRead, cbOffset, FALSE);
|
||||
return Util_VfsReadFile_FromQWORD(pVirt2PhysInfo->pas[0], pb, cb, pcbRead, cbOffset, FALSE);
|
||||
}
|
||||
if(!_stricmp(ctx->szPath, "map")) {
|
||||
cbBuffer = snprintf(
|
||||
pbBuffer,
|
||||
0x1000,
|
||||
"PML4 %016llx +%03x %016llx\n" \
|
||||
"PDPT %016llx +%03x %016llx\n" \
|
||||
"PD %016llx +%03x %016llx\n" \
|
||||
"PT %016llx +%03x %016llx\n" \
|
||||
"PAGE %016llx\n",
|
||||
pVirt2PhysInfo->x64.pas[4], pVirt2PhysInfo->x64.iPTEs[4] << 3, pVirt2PhysInfo->x64.PTEs[4],
|
||||
pVirt2PhysInfo->x64.pas[3], pVirt2PhysInfo->x64.iPTEs[3] << 3, pVirt2PhysInfo->x64.PTEs[3],
|
||||
pVirt2PhysInfo->x64.pas[2], pVirt2PhysInfo->x64.iPTEs[2] << 3, pVirt2PhysInfo->x64.PTEs[2],
|
||||
pVirt2PhysInfo->x64.pas[1], pVirt2PhysInfo->x64.iPTEs[1] << 3, pVirt2PhysInfo->x64.PTEs[1],
|
||||
pVirt2PhysInfo->x64.pas[0]
|
||||
);
|
||||
switch(ctxVmm->tpMemoryModel) {
|
||||
case VMM_MEMORYMODEL_X64:
|
||||
cbBuffer = snprintf(
|
||||
pbBuffer,
|
||||
0x1000,
|
||||
"PML4 %016llx +%03x %016llx\n" \
|
||||
"PDPT %016llx +%03x %016llx\n" \
|
||||
"PD %016llx +%03x %016llx\n" \
|
||||
"PT %016llx +%03x %016llx\n" \
|
||||
"PAGE %016llx\n",
|
||||
pVirt2PhysInfo->pas[4], pVirt2PhysInfo->iPTEs[4] << 3, pVirt2PhysInfo->PTEs[4],
|
||||
pVirt2PhysInfo->pas[3], pVirt2PhysInfo->iPTEs[3] << 3, pVirt2PhysInfo->PTEs[3],
|
||||
pVirt2PhysInfo->pas[2], pVirt2PhysInfo->iPTEs[2] << 3, pVirt2PhysInfo->PTEs[2],
|
||||
pVirt2PhysInfo->pas[1], pVirt2PhysInfo->iPTEs[1] << 3, pVirt2PhysInfo->PTEs[1],
|
||||
pVirt2PhysInfo->pas[0]
|
||||
);
|
||||
break;
|
||||
case VMM_MEMORYMODEL_X86PAE:
|
||||
cbBuffer = snprintf(
|
||||
pbBuffer,
|
||||
0x1000,
|
||||
"PDPT %016llx +%03x %016llx\n" \
|
||||
"PD %016llx +%03x %016llx\n" \
|
||||
"PT %016llx +%03x %016llx\n" \
|
||||
"PAGE %016llx\n",
|
||||
pVirt2PhysInfo->pas[3], pVirt2PhysInfo->iPTEs[3] << 3, pVirt2PhysInfo->PTEs[3],
|
||||
pVirt2PhysInfo->pas[2], pVirt2PhysInfo->iPTEs[2] << 3, pVirt2PhysInfo->PTEs[2],
|
||||
pVirt2PhysInfo->pas[1], pVirt2PhysInfo->iPTEs[1] << 3, pVirt2PhysInfo->PTEs[1],
|
||||
pVirt2PhysInfo->pas[0]
|
||||
);
|
||||
break;
|
||||
case VMM_MEMORYMODEL_X86:
|
||||
cbBuffer = snprintf(
|
||||
pbBuffer,
|
||||
0x1000,
|
||||
"PD %016llx +%03x %08x\n" \
|
||||
"PT %016llx +%03x %08x\n" \
|
||||
"PAGE %016llx\n",
|
||||
pVirt2PhysInfo->pas[2], pVirt2PhysInfo->iPTEs[2] << 2, (DWORD)pVirt2PhysInfo->PTEs[2],
|
||||
pVirt2PhysInfo->pas[1], pVirt2PhysInfo->iPTEs[1] << 2, (DWORD)pVirt2PhysInfo->PTEs[1],
|
||||
pVirt2PhysInfo->pas[0]
|
||||
);
|
||||
break;
|
||||
}
|
||||
return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
// "page table" or data page
|
||||
@@ -78,13 +116,15 @@ NTSTATUS Virt2Phys_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ D
|
||||
if(!_stricmp(ctx->szPath, "pt_pdpt")) { iPML = 3; }
|
||||
if(!_stricmp(ctx->szPath, "pt_pd")) { iPML = 2; }
|
||||
if(!_stricmp(ctx->szPath, "pt_pt")) { iPML = 1; }
|
||||
if((ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86) && (iPML > 2)) { return VMMDLL_STATUS_FILE_INVALID; }
|
||||
if((ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86PAE) && (iPML > 3)) { return VMMDLL_STATUS_FILE_INVALID; }
|
||||
ZeroMemory(pbBuffer, 0x1000);
|
||||
pbSourceData = pbBuffer;
|
||||
if(iPML && (pVirt2PhysInfo->x64.pas[iPML] & ~0xfff)) {
|
||||
pbSourceData = VmmTlbGetPageTable(pVirt2PhysInfo->x64.pas[iPML] & ~0xfff, FALSE);
|
||||
if(iPML && (pVirt2PhysInfo->pas[iPML] & ~0xfff)) {
|
||||
pbSourceData = VmmTlbGetPageTable(pVirt2PhysInfo->pas[iPML] & ~0xfff, FALSE);
|
||||
}
|
||||
if(!_stricmp(ctx->szPath, "page") && (pVirt2PhysInfo->x64.pas[0] & ~0xfff)) {
|
||||
VmmReadPhysicalPage(pVirt2PhysInfo->x64.pas[0] & ~0xfff, pbBuffer);
|
||||
if(!_stricmp(ctx->szPath, "page") && (pVirt2PhysInfo->pas[0] & ~0xfff)) {
|
||||
VmmReadPhysicalPage(pVirt2PhysInfo->pas[0] & ~0xfff, pbBuffer);
|
||||
}
|
||||
if(iPML || !_stricmp(ctx->szPath, "page")) {
|
||||
return Util_VfsReadFile_FromPBYTE(pbSourceData, 0x1000, pb, cb, pcbRead, cbOffset);
|
||||
@@ -107,7 +147,8 @@ NTSTATUS Virt2Phys_WriteVA(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_
|
||||
PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
|
||||
BYTE pbBuffer[17];
|
||||
PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo;
|
||||
if(cbOffset < 16) {
|
||||
VMM_MEMORYMODEL_TP tp = ctxVmm->tpMemoryModel;
|
||||
if((tp == VMM_MEMORYMODEL_X64) && (cbOffset < 16)) {
|
||||
pVirt2PhysInfo = Virt2Phys_GetContext(ctx->phProcessPrivate, NULL);
|
||||
*pcbWrite = cb;
|
||||
snprintf(pbBuffer, 17, "%016llx", pVirt2PhysInfo->va);
|
||||
@@ -116,6 +157,15 @@ NTSTATUS Virt2Phys_WriteVA(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_
|
||||
pbBuffer[16] = 0;
|
||||
pVirt2PhysInfo->va = strtoull(pbBuffer, NULL, 16);
|
||||
VmmVirt2PhysGetInformation(pProcess, pVirt2PhysInfo);
|
||||
} else if ((tp == VMM_MEMORYMODEL_X86) || (tp == VMM_MEMORYMODEL_X86PAE)) {
|
||||
pVirt2PhysInfo = Virt2Phys_GetContext(ctx->phProcessPrivate, NULL);
|
||||
*pcbWrite = cb;
|
||||
snprintf(pbBuffer, 9, "%08x", (DWORD)pVirt2PhysInfo->va);
|
||||
cb = (DWORD)min(8 - cbOffset, cb);
|
||||
memcpy(pbBuffer + cbOffset, pb, cb);
|
||||
pbBuffer[8] = 0;
|
||||
pVirt2PhysInfo->va = strtoul(pbBuffer, NULL, 16);
|
||||
VmmVirt2PhysGetInformation(pProcess, pVirt2PhysInfo);
|
||||
} else {
|
||||
*pcbWrite = 0;
|
||||
}
|
||||
@@ -147,10 +197,10 @@ NTSTATUS Virt2Phys_Write(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ D
|
||||
if(!_stricmp(ctx->szPath, "pt_pt")) { i = 1; }
|
||||
if(!_stricmp(ctx->szPath, "page")) { i = 0; }
|
||||
if(i > 4) { return VMMDLL_STATUS_FILE_INVALID; }
|
||||
if(pVirt2PhysInfo->x64.pas[i] < 0x1000) { return VMMDLL_STATUS_FILE_INVALID; }
|
||||
if(pVirt2PhysInfo->pas[i] < 0x1000) { return VMMDLL_STATUS_FILE_INVALID; }
|
||||
if(cbOffset > 0x1000) { return VMMDLL_STATUS_END_OF_FILE; }
|
||||
*pcbWrite = (DWORD)min(cb, 0x1000 - cbOffset);
|
||||
VmmWritePhysical(pVirt2PhysInfo->x64.pas[i] + cbOffset, pb, *pcbWrite);
|
||||
VmmWritePhysical(pVirt2PhysInfo->pas[i] + cbOffset, pb, *pcbWrite);
|
||||
return *pcbWrite ? VMMDLL_STATUS_SUCCESS : VMMDLL_STATUS_END_OF_FILE;
|
||||
}
|
||||
|
||||
@@ -169,14 +219,35 @@ BOOL Virt2Phys_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
|
||||
// not root directory == error for this module.
|
||||
return FALSE;
|
||||
}
|
||||
VMMDLL_VfsList_AddFile(pFileList, "virt", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "phys", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "map", 198);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "page", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pml4", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pdpt", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pd", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pt", 0x1000);
|
||||
switch(ctxVmm->tpMemoryModel) {
|
||||
case VMM_MEMORYMODEL_X64:
|
||||
VMMDLL_VfsList_AddFile(pFileList, "virt", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "phys", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "map", 198);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pml4", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pdpt", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pd", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pt", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "page", 0x1000);
|
||||
break;
|
||||
case VMM_MEMORYMODEL_X86PAE:
|
||||
VMMDLL_VfsList_AddFile(pFileList, "virt", 8);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "phys", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "map", 154);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pdpt", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pd", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pt", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "page", 0x1000);
|
||||
break;
|
||||
case VMM_MEMORYMODEL_X86:
|
||||
VMMDLL_VfsList_AddFile(pFileList, "virt", 8);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "phys", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "map", 94);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pd", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pt_pt", 0x1000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "page", 0x1000);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -192,6 +263,7 @@ BOOL Virt2Phys_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
|
||||
VOID Virt2Phys_CloseHandleProcess(_In_opt_ PHANDLE phModulePrivate, _Inout_ PHANDLE phProcessPrivate)
|
||||
{
|
||||
LocalFree(*phProcessPrivate);
|
||||
*phProcessPrivate = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -202,14 +274,15 @@ VOID Virt2Phys_CloseHandleProcess(_In_opt_ PHANDLE phModulePrivate, _Inout_ PHAN
|
||||
* operating system or architecture is unsupported.
|
||||
* -- pPluginRegInfo
|
||||
*/
|
||||
VOID M_Virt2Phys_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo)
|
||||
VOID M_Virt2Phys_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pRI)
|
||||
{
|
||||
if(0 == (pPluginRegInfo->fTargetSystem & (VMM_TARGET_UNKNOWN_X64 | VMM_TARGET_WINDOWS_X64))) { return; }
|
||||
strcpy_s(pPluginRegInfo->reg_info.szModuleName, 32, "virt2phys"); // module name
|
||||
pPluginRegInfo->reg_info.fProcessModule = TRUE; // module shows in process directory
|
||||
pPluginRegInfo->reg_fn.pfnList = Virt2Phys_List; // List function supported
|
||||
pPluginRegInfo->reg_fn.pfnRead = Virt2Phys_Read; // Read function supported
|
||||
pPluginRegInfo->reg_fn.pfnWrite = Virt2Phys_Write; // Write function supported
|
||||
pPluginRegInfo->reg_fn.pfnCloseHandleProcess = Virt2Phys_CloseHandleProcess; // Close process module private handle supported
|
||||
pPluginRegInfo->pfnPluginManager_Register(pPluginRegInfo);
|
||||
if((pRI->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRI->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
|
||||
if(!((pRI->tpMemoryModel == VMM_MEMORYMODEL_X64) || (pRI->tpMemoryModel == VMM_MEMORYMODEL_X86) || (pRI->tpMemoryModel == VMM_MEMORYMODEL_X86PAE))) { return; }
|
||||
strcpy_s(pRI->reg_info.szModuleName, 32, "virt2phys"); // module name
|
||||
pRI->reg_info.fProcessModule = TRUE; // module shows in process directory
|
||||
pRI->reg_fn.pfnList = Virt2Phys_List; // List function supported
|
||||
pRI->reg_fn.pfnRead = Virt2Phys_Read; // Read function supported
|
||||
pRI->reg_fn.pfnWrite = Virt2Phys_Write; // Write function supported
|
||||
pRI->reg_fn.pfnCloseHandleProcess = Virt2Phys_CloseHandleProcess; // Close process module private handle supported
|
||||
pRI->pfnPluginManager_Register(pRI);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vmmx64.c : implementation of the x64 / IA32e / long-mode paging / memory model.
|
||||
// mm_x64.c : implementation of the x64 / IA32e / long-mode paging / memory model.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
@@ -10,7 +10,7 @@
|
||||
* Tries to verify that a loaded page table is correct. If just a bit strange
|
||||
* bytes/ptes supplied in pb will be altered to look better.
|
||||
*/
|
||||
BOOL VmmX64_TlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq)
|
||||
BOOL MmX64_TlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq)
|
||||
{
|
||||
DWORD i;
|
||||
QWORD *ptes, c = 0, pte;
|
||||
@@ -46,50 +46,50 @@ BOOL VmmX64_TlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfR
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define VMMX64_TLB_SIZE_STAGEBUF 0x200
|
||||
#define MMX64_TLB_SIZE_STAGEBUF 0x200
|
||||
|
||||
typedef struct tdVMMX64_TLB_SPIDER_STAGE_INTERNAL {
|
||||
typedef struct tdMMX64_TLB_SPIDER_STAGE_INTERNAL {
|
||||
QWORD c;
|
||||
PMEM_IO_SCATTER_HEADER ppDMAs[VMMX64_TLB_SIZE_STAGEBUF];
|
||||
PVMM_CACHE_ENTRY ppEntrys[VMMX64_TLB_SIZE_STAGEBUF];
|
||||
} VMMX64_TLB_SPIDER_STAGE_INTERNAL, *PVMMX64_TLB_SPIDER_STAGE_INTERNAL;
|
||||
PMEM_IO_SCATTER_HEADER ppDMAs[MMX64_TLB_SIZE_STAGEBUF];
|
||||
PVMM_CACHE_ENTRY ppEntrys[MMX64_TLB_SIZE_STAGEBUF];
|
||||
} MMX64_TLB_SPIDER_STAGE_INTERNAL, *PMMX64_TLB_SPIDER_STAGE_INTERNAL;
|
||||
|
||||
VOID VmmX64_TlbSpider_ReadToCache(PVMMX64_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
|
||||
VOID MmX64_TlbSpider_ReadToCache(PMMX64_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
|
||||
{
|
||||
QWORD i;
|
||||
DeviceReadScatterMEM(pTlbSpiderStage->ppDMAs, (DWORD)pTlbSpiderStage->c, NULL);
|
||||
for(i = 0; i < pTlbSpiderStage->c; i++) {
|
||||
VmmX64_TlbPageTableVerify(pTlbSpiderStage->ppEntrys[i]->h.pb, pTlbSpiderStage->ppEntrys[i]->h.qwA, FALSE);
|
||||
MmX64_TlbPageTableVerify(pTlbSpiderStage->ppEntrys[i]->h.pb, pTlbSpiderStage->ppEntrys[i]->h.qwA, FALSE);
|
||||
VmmCachePut(ctxVmm->ptTLB, pTlbSpiderStage->ppEntrys[i]);
|
||||
}
|
||||
pTlbSpiderStage->c = 0;
|
||||
}
|
||||
|
||||
BOOL VmmX64_TlbSpider_Stage(_In_ QWORD qwPA, _In_ QWORD qwPML, _In_ BOOL fUserOnly, PVMMX64_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
|
||||
BOOL MmX64_TlbSpider_Stage(_In_ QWORD pa, _In_ BYTE iPML, _In_ BOOL fUserOnly, PMMX64_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
|
||||
{
|
||||
BOOL fSpiderComplete = TRUE;
|
||||
PMEM_IO_SCATTER_HEADER pt;
|
||||
QWORD i, pe;
|
||||
// 1: retrieve from cache, add to staging if not found
|
||||
pt = VmmCacheGet(ctxVmm->ptTLB, qwPA);
|
||||
pt = VmmCacheGet(ctxVmm->ptTLB, pa);
|
||||
if(!pt) {
|
||||
pTlbSpiderStage->ppEntrys[pTlbSpiderStage->c] = VmmCacheReserve(ctxVmm->ptTLB);
|
||||
pTlbSpiderStage->ppDMAs[pTlbSpiderStage->c] = &pTlbSpiderStage->ppEntrys[pTlbSpiderStage->c]->h;
|
||||
pTlbSpiderStage->ppDMAs[pTlbSpiderStage->c]->qwA = qwPA;
|
||||
pTlbSpiderStage->ppDMAs[pTlbSpiderStage->c]->qwA = pa;
|
||||
pTlbSpiderStage->c++;
|
||||
if(pTlbSpiderStage->c == VMMX64_TLB_SIZE_STAGEBUF) {
|
||||
VmmX64_TlbSpider_ReadToCache(pTlbSpiderStage);
|
||||
if(pTlbSpiderStage->c == MMX64_TLB_SIZE_STAGEBUF) {
|
||||
MmX64_TlbSpider_ReadToCache(pTlbSpiderStage);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
// 2: walk trough all entries for PML4, PDPT, PD
|
||||
if(qwPML == 1) { return TRUE; }
|
||||
if(iPML == 1) { return TRUE; }
|
||||
for(i = 0; i < 0x1000; i += 8) {
|
||||
pe = *(PQWORD)(pt->pb + i);
|
||||
if(!(pe & 0x01)) { continue; } // not valid
|
||||
if(pe & 0x80) { continue; } // not valid ptr to (PDPT || PD || PT)
|
||||
if(fUserOnly && !(pe & 0x04)) { continue; } // supervisor page when fUserOnly -> not valid
|
||||
fSpiderComplete = VmmX64_TlbSpider_Stage(pe & 0x0000fffffffff000, qwPML - 1, fUserOnly, pTlbSpiderStage) && fSpiderComplete;
|
||||
fSpiderComplete = MmX64_TlbSpider_Stage(pe & 0x0000fffffffff000, iPML - 1, fUserOnly, pTlbSpiderStage) && fSpiderComplete;
|
||||
}
|
||||
return fSpiderComplete;
|
||||
}
|
||||
@@ -98,23 +98,20 @@ BOOL VmmX64_TlbSpider_Stage(_In_ QWORD qwPA, _In_ QWORD qwPML, _In_ BOOL fUserOn
|
||||
* Iterate over PML4, PTPT, PD (3 times in total) to first stage uncached pages
|
||||
* and then commit them to the cache.
|
||||
*/
|
||||
VOID VmmX64_TlbSpider(_In_ QWORD paDTB, _In_ BOOL fUserOnly)
|
||||
VOID MmX64_TlbSpider(_In_ QWORD paDTB, _In_ BOOL fUserOnly)
|
||||
{
|
||||
BOOL result;
|
||||
QWORD i = 0;
|
||||
PVMMX64_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage;
|
||||
if(!(pTlbSpiderStage = (PVMMX64_TLB_SPIDER_STAGE_INTERNAL)LocalAlloc(LMEM_ZEROINIT, sizeof(VMMX64_TLB_SPIDER_STAGE_INTERNAL)))) { return; }
|
||||
while(TRUE) {
|
||||
i++;
|
||||
result = VmmX64_TlbSpider_Stage(paDTB, 4, fUserOnly, pTlbSpiderStage);
|
||||
DWORD i = 0;
|
||||
BOOL result = FALSE;
|
||||
PMMX64_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage;
|
||||
if(!(pTlbSpiderStage = (PMMX64_TLB_SPIDER_STAGE_INTERNAL)LocalAlloc(LMEM_ZEROINIT, sizeof(MMX64_TLB_SPIDER_STAGE_INTERNAL)))) { return; }
|
||||
while(!result && (i < 3)) {
|
||||
result = MmX64_TlbSpider_Stage(paDTB, 4, fUserOnly, pTlbSpiderStage);
|
||||
if(pTlbSpiderStage->c) {
|
||||
VmmX64_TlbSpider_ReadToCache(pTlbSpiderStage);
|
||||
}
|
||||
if(result || (i == 3)) {
|
||||
LocalFree(pTlbSpiderStage);
|
||||
return;
|
||||
MmX64_TlbSpider_ReadToCache(pTlbSpiderStage);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
LocalFree(pTlbSpiderStage);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -126,7 +123,7 @@ VOID VmmX64_TlbSpider(_In_ QWORD paDTB, _In_ BOOL fUserOnly)
|
||||
* -- szTag
|
||||
* -- wszTag
|
||||
*/
|
||||
VOID VmmX64_MapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_opt_ BOOL fWoW64)
|
||||
VOID MmX64_MapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_opt_ BOOL fWoW64)
|
||||
{
|
||||
PVMM_MEMMAP_ENTRY pMap;
|
||||
QWORD i, lvl, cMap;
|
||||
@@ -166,7 +163,7 @@ VOID VmmX64_MapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaL
|
||||
}
|
||||
}
|
||||
|
||||
VOID VmmX64_MapDisplayBufferGenerate(_In_ PVMM_PROCESS pProcess)
|
||||
VOID MmX64_MapDisplayBufferGenerate(_In_ PVMM_PROCESS pProcess)
|
||||
{
|
||||
DWORD i, o = 0;
|
||||
PBYTE pbBuffer;
|
||||
@@ -200,7 +197,7 @@ fail:
|
||||
LocalFree(pbBuffer);
|
||||
}
|
||||
|
||||
PVMM_MEMMAP_ENTRY VmmX64_MapGetEntry(_In_ PVMM_PROCESS pProcess, _In_ QWORD va)
|
||||
PVMM_MEMMAP_ENTRY MmX64_MapGetEntry(_In_ PVMM_PROCESS pProcess, _In_ QWORD va)
|
||||
{
|
||||
QWORD i, ce;
|
||||
PVMM_MEMMAP_ENTRY pe;
|
||||
@@ -215,12 +212,12 @@ PVMM_MEMMAP_ENTRY VmmX64_MapGetEntry(_In_ PVMM_PROCESS pProcess, _In_ QWORD va)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const QWORD VMMX64_PAGETABLEMAP_PML_REGION_SIZE[5] = { 0, 12, 21, 30, 39 };
|
||||
const QWORD MMX64_PAGETABLEMAP_PML_REGION_SIZE[5] = { 0, 12, 21, 30, 39 };
|
||||
|
||||
VOID VmmX64_MapInitialize_Index(_In_ PVMM_PROCESS pProcess, _In_ QWORD qwVABase, _In_ QWORD qwPML, _In_ QWORD PTEs[512], _In_ BOOL fSupervisorPML, _In_ QWORD paMax)
|
||||
VOID MmX64_MapInitialize_Index(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ BYTE iPML, _In_ QWORD PTEs[512], _In_ BOOL fSupervisorPML, _In_ QWORD paMax)
|
||||
{
|
||||
PBYTE pbNextPageTable;
|
||||
QWORD i, pte, qwVA, qwNextVA, qwNextPA = 0;
|
||||
QWORD i, pte, va;
|
||||
BOOL fUserOnly, fNextSupervisorPML;
|
||||
QWORD cMemMap = pProcess->cMemMap;
|
||||
PVMM_MEMMAP_ENTRY pMemMap = pProcess->pMemMap;
|
||||
@@ -229,41 +226,38 @@ VOID VmmX64_MapInitialize_Index(_In_ PVMM_PROCESS pProcess, _In_ QWORD qwVABase,
|
||||
for(i = 0; i < 512; i++) {
|
||||
pte = PTEs[i];
|
||||
if(!(pte & 0x01)) { continue; }
|
||||
qwNextPA = pte & 0x0000fffffffff000;
|
||||
if(qwNextPA > paMax) { continue; }
|
||||
if((pte & 0x0000fffffffff000) > paMax) { continue; }
|
||||
if(fSupervisorPML) { pte = pte & 0xfffffffffffffffb; }
|
||||
if(fUserOnly && !(pte & 0x04)) { continue; }
|
||||
qwVA = qwVABase + (i << VMMX64_PAGETABLEMAP_PML_REGION_SIZE[qwPML]);
|
||||
va = vaBase + (i << MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
// maps page
|
||||
if((qwPML == 1) || (pte & 0x80) /* PS */) {
|
||||
if(qwPML == 4) { continue; } // not supported - PML4 cannot map page directly
|
||||
if((iPML == 1) || (pte & 0x80) /* PS */) {
|
||||
if(iPML == 4) { continue; } // not supported - PML4 cannot map page directly
|
||||
if((cMemMap == 0) ||
|
||||
(pMemMapEntry->fPage != (pte & VMM_MEMMAP_FLAG_PAGE_MASK)) ||
|
||||
(qwVA != pMemMapEntry->AddrBase + (pMemMapEntry->cPages << 12))) {
|
||||
(va != pMemMapEntry->AddrBase + (pMemMapEntry->cPages << 12))) {
|
||||
if(cMemMap + 1 >= VMM_MEMMAP_ENTRIES_MAX) { return; }
|
||||
pMemMapEntry = pProcess->pMemMap + cMemMap;
|
||||
pMemMapEntry->AddrBase = qwVA;
|
||||
pMemMapEntry->AddrBase = va;
|
||||
pMemMapEntry->fPage = pte & VMM_MEMMAP_FLAG_PAGE_MASK;
|
||||
pMemMapEntry->cPages = 1ULL << (VMMX64_PAGETABLEMAP_PML_REGION_SIZE[qwPML] - 12);
|
||||
pMemMapEntry->cPages = 1ULL << (MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
|
||||
pProcess->cMemMap++;
|
||||
cMemMap++;
|
||||
continue;
|
||||
}
|
||||
pMemMapEntry->cPages += 1ULL << (VMMX64_PAGETABLEMAP_PML_REGION_SIZE[qwPML] - 12);
|
||||
pMemMapEntry->cPages += 1ULL << (MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
|
||||
continue;
|
||||
}
|
||||
// maps page table (PDPT, PD, PT)
|
||||
qwNextVA = qwVA;
|
||||
pbNextPageTable = VmmTlbGetPageTable(qwNextPA, FALSE);
|
||||
if(!pbNextPageTable) { continue; }
|
||||
fNextSupervisorPML = !(pte & 0x04);
|
||||
VmmX64_MapInitialize_Index(pProcess, qwNextVA, qwPML - 1, (PQWORD)pbNextPageTable, fNextSupervisorPML, paMax);
|
||||
if(!(pbNextPageTable = VmmTlbGetPageTable(pte & 0x0000fffffffff000, FALSE))) { continue; }
|
||||
MmX64_MapInitialize_Index(pProcess, va, iPML - 1, (PQWORD)pbNextPageTable, fNextSupervisorPML, paMax);
|
||||
cMemMap = pProcess->cMemMap;
|
||||
pMemMapEntry = pProcess->pMemMap + cMemMap - 1;
|
||||
}
|
||||
}
|
||||
|
||||
VOID VmmX64_MapInitialize(_In_ PVMM_PROCESS pProcess)
|
||||
VOID MmX64_MapInitialize(_In_ PVMM_PROCESS pProcess)
|
||||
{
|
||||
QWORD i, cMemMap;
|
||||
PBYTE pbPML4;
|
||||
@@ -274,9 +268,9 @@ VOID VmmX64_MapInitialize(_In_ PVMM_PROCESS pProcess)
|
||||
pProcess->cMemMap = 0;
|
||||
pProcess->pMemMap = (PVMM_MEMMAP_ENTRY)LocalAlloc(LMEM_ZEROINIT, VMM_MEMMAP_ENTRIES_MAX * sizeof(VMM_MEMMAP_ENTRY));
|
||||
if(!pProcess->pMemMap) { return; }
|
||||
pbPML4 = VmmTlbGetPageTable(pProcess->paPML4, FALSE);
|
||||
pbPML4 = VmmTlbGetPageTable(pProcess->paDTB, FALSE);
|
||||
if(!pbPML4) { return; }
|
||||
VmmX64_MapInitialize_Index(pProcess, 0, 4, (PQWORD)pbPML4, FALSE, ctxMain->cfg.paAddrMax);
|
||||
MmX64_MapInitialize_Index(pProcess, 0, 4, (PQWORD)pbPML4, FALSE, ctxMain->cfg.paAddrMax);
|
||||
cMemMap = pProcess->cMemMap;
|
||||
for(i = 0; i < cMemMap; i++) { // fixup sign extension for kernel addresses
|
||||
if(pProcess->pMemMap[i].AddrBase & 0x0000800000000000) {
|
||||
@@ -286,95 +280,87 @@ VOID VmmX64_MapInitialize(_In_ PVMM_PROCESS pProcess)
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VmmX64_Virt2PhysEx(_In_ BOOL fUserOnly, _In_ QWORD va, _In_ BYTE iPML, _In_reads_(4096) PBYTE pbPTEs, _Out_ PQWORD ppa)
|
||||
BOOL MmX64_Virt2Phys(_In_ QWORD paPT, _In_ BOOL fUserOnly, _In_ BYTE iPML, _In_ QWORD va, _Out_ PQWORD ppa)
|
||||
{
|
||||
QWORD pte, i, qwMask;
|
||||
PBYTE pbNextPageTable;
|
||||
PBYTE pbPTEs;
|
||||
if(iPML == (BYTE)-1) { iPML = 4; }
|
||||
i = 0x1ff & (va >> VMMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
if(!(pbPTEs = VmmTlbGetPageTable(paPT & 0x0000fffffffff000, FALSE))) { return FALSE; }
|
||||
i = 0x1ff & (va >> MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
pte = ((PQWORD)pbPTEs)[i];
|
||||
if(!(pte & 0x01)) { return FALSE; } // NOT VALID
|
||||
if(fUserOnly && !(pte & 0x04)) { return FALSE; } // SUPERVISOR PAGE & USER MODE REQ
|
||||
if(pte & 0x000f000000000000) { return FALSE; } // RESERVED
|
||||
if((iPML == 1) || (pte & 0x80) /* PS */) {
|
||||
if(iPML == 4) { return FALSE; } // NO SUPPORT IN PML4
|
||||
qwMask = 0xffffffffffffffff << VMMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML];
|
||||
*ppa = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB/1GB PAGES
|
||||
if(iPML == 4) { return FALSE; } // NO SUPPORT IN PML4
|
||||
qwMask = 0xffffffffffffffff << MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML];
|
||||
*ppa = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB/1GB PAGES
|
||||
qwMask = qwMask ^ 0xffffffffffffffff;
|
||||
*ppa = *ppa | (qwMask & va); // FILL LOWER ADDRESS BITS
|
||||
*ppa = *ppa | (qwMask & va); // FILL LOWER ADDRESS BITS
|
||||
return TRUE;
|
||||
}
|
||||
pbNextPageTable = VmmTlbGetPageTable(pte & 0x0000fffffffff000, FALSE);
|
||||
if(!pbNextPageTable) { return FALSE; }
|
||||
return VmmX64_Virt2PhysEx(fUserOnly, va, iPML - 1, pbNextPageTable, ppa);
|
||||
return MmX64_Virt2Phys(pte, fUserOnly, iPML - 1, va, ppa);
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VmmX64_Virt2Phys(_In_ PVMM_PROCESS pProcess, _In_ QWORD va, _Out_ PQWORD ppa)
|
||||
{
|
||||
PBYTE pbPML4 = VmmTlbGetPageTable(pProcess->paPML4, FALSE);
|
||||
if(!pbPML4) { return FALSE; }
|
||||
*ppa = 0;
|
||||
return VmmX64_Virt2PhysEx(pProcess->fUserOnly, va, 4, pbPML4, ppa);
|
||||
}
|
||||
|
||||
VOID VmmX64_Virt2PhysGetInformation_DoWork(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo, _In_ BYTE iPML, _In_ QWORD PTEs[512])
|
||||
VOID MmX64_Virt2PhysGetInformation_DoWork(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo, _In_ BYTE iPML, _In_ QWORD PTEs[512])
|
||||
{
|
||||
QWORD pte, i, qwMask;
|
||||
PBYTE pbNextPageTable;
|
||||
i = 0x1ff & (pVirt2PhysInfo->va >> VMMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
i = 0x1ff & (pVirt2PhysInfo->va >> MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
pte = PTEs[i];
|
||||
pVirt2PhysInfo->x64.iPTEs[iPML] = (WORD)i;
|
||||
pVirt2PhysInfo->x64.PTEs[iPML] = pte;
|
||||
pVirt2PhysInfo->iPTEs[iPML] = (WORD)i;
|
||||
pVirt2PhysInfo->PTEs[iPML] = pte;
|
||||
if(!(pte & 0x01)) { return; } // NOT VALID
|
||||
if(pProcess->fUserOnly && !(pte & 0x04)) { return; } // SUPERVISOR PAGE & USER MODE REQ
|
||||
if(pte & 0x000f000000000000) { return; } // RESERVED
|
||||
if((iPML == 1) || (pte & 0x80) /* PS */) {
|
||||
if(iPML == 4) { return; } // NO SUPPORT IN PML4
|
||||
qwMask = 0xffffffffffffffff << VMMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML];
|
||||
pVirt2PhysInfo->x64.pas[0] = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB/1GB PAGES
|
||||
qwMask = 0xffffffffffffffff << MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML];
|
||||
pVirt2PhysInfo->pas[0] = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB/1GB PAGES
|
||||
qwMask = qwMask ^ 0xffffffffffffffff;
|
||||
pVirt2PhysInfo->x64.pas[0] = pVirt2PhysInfo->x64.pas[0] | (qwMask & pVirt2PhysInfo->va); // FILL LOWER ADDRESS BITS
|
||||
pVirt2PhysInfo->pas[0] = pVirt2PhysInfo->pas[0] | (qwMask & pVirt2PhysInfo->va); // FILL LOWER ADDRESS BITS
|
||||
return;
|
||||
}
|
||||
if(!(pbNextPageTable = VmmTlbGetPageTable(pte & 0x0000fffffffff000, FALSE))) { return; }
|
||||
pVirt2PhysInfo->x64.pas[iPML - 1] = pte & 0x0000fffffffff000;
|
||||
VmmX64_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, iPML - 1, (PQWORD)pbNextPageTable);
|
||||
pVirt2PhysInfo->pas[iPML - 1] = pte & 0x0000fffffffff000;
|
||||
MmX64_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, iPML - 1, (PQWORD)pbNextPageTable);
|
||||
}
|
||||
|
||||
VOID VmmX64_Virt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo)
|
||||
VOID MmX64_Virt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo)
|
||||
{
|
||||
QWORD va;
|
||||
PBYTE pbPML4;
|
||||
va = pVirt2PhysInfo->va;
|
||||
ZeroMemory(pVirt2PhysInfo, sizeof(VMM_VIRT2PHYS_INFORMATION));
|
||||
pVirt2PhysInfo->tpMemoryModel = X64;
|
||||
pVirt2PhysInfo->tpMemoryModel = VMM_MEMORYMODEL_X64;
|
||||
pVirt2PhysInfo->va = va;
|
||||
pVirt2PhysInfo->x64.pas[4] = pProcess->paPML4;
|
||||
if(!(pbPML4 = VmmTlbGetPageTable(pProcess->paPML4, FALSE))) { return; }
|
||||
VmmX64_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, 4, (PQWORD)pbPML4);
|
||||
pVirt2PhysInfo->pas[4] = pProcess->paDTB;
|
||||
if(!(pbPML4 = VmmTlbGetPageTable(pProcess->paDTB, FALSE))) { return; }
|
||||
MmX64_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, 4, (PQWORD)pbPML4);
|
||||
}
|
||||
|
||||
VOID VmmX64_Close()
|
||||
VOID MmX64_Close()
|
||||
{
|
||||
ZeroMemory(&ctxVmm->MemoryModel, sizeof(VMM_MEMORYMODEL));
|
||||
ctxVmm->f32 = FALSE;
|
||||
ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_NA;
|
||||
ZeroMemory(&ctxVmm->fnMemoryModel, sizeof(VMM_MEMORYMODEL_FUNCTIONS));
|
||||
}
|
||||
|
||||
VOID VmmX64_Initialize()
|
||||
VOID MmX64_Initialize()
|
||||
{
|
||||
if(ctxVmm->MemoryModel.pfnClose) {
|
||||
ctxVmm->MemoryModel.pfnClose();
|
||||
if(ctxVmm->fnMemoryModel.pfnClose) {
|
||||
ctxVmm->fnMemoryModel.pfnClose();
|
||||
}
|
||||
ctxVmm->MemoryModel.pfnInitialize = VmmX64_Initialize;
|
||||
ctxVmm->MemoryModel.pfnClose = VmmX64_Close;
|
||||
ctxVmm->MemoryModel.pfnVirt2Phys = VmmX64_Virt2Phys;
|
||||
ctxVmm->MemoryModel.pfnVirt2PhysEx = VmmX64_Virt2PhysEx;
|
||||
ctxVmm->MemoryModel.pfnVirt2PhysGetInformation = VmmX64_Virt2PhysGetInformation;
|
||||
ctxVmm->MemoryModel.pfnMapInitialize = VmmX64_MapInitialize;
|
||||
ctxVmm->MemoryModel.pfnMapTag = VmmX64_MapTag;
|
||||
ctxVmm->MemoryModel.pfnMapGetEntry = VmmX64_MapGetEntry;
|
||||
ctxVmm->MemoryModel.pfnMapDisplayBufferGenerate = VmmX64_MapDisplayBufferGenerate;
|
||||
ctxVmm->MemoryModel.pfnTlbSpider = VmmX64_TlbSpider;
|
||||
ctxVmm->MemoryModel.pfnTlbPageTableVerify = VmmX64_TlbPageTableVerify;
|
||||
ctxVmm->MemoryModel.tp = X64;
|
||||
ctxVmm->fnMemoryModel.pfnInitialize = MmX64_Initialize;
|
||||
ctxVmm->fnMemoryModel.pfnClose = MmX64_Close;
|
||||
ctxVmm->fnMemoryModel.pfnVirt2Phys = MmX64_Virt2Phys;
|
||||
ctxVmm->fnMemoryModel.pfnVirt2PhysGetInformation = MmX64_Virt2PhysGetInformation;
|
||||
ctxVmm->fnMemoryModel.pfnMapInitialize = MmX64_MapInitialize;
|
||||
ctxVmm->fnMemoryModel.pfnMapTag = MmX64_MapTag;
|
||||
ctxVmm->fnMemoryModel.pfnMapGetEntry = MmX64_MapGetEntry;
|
||||
ctxVmm->fnMemoryModel.pfnMapDisplayBufferGenerate = MmX64_MapDisplayBufferGenerate;
|
||||
ctxVmm->fnMemoryModel.pfnTlbSpider = MmX64_TlbSpider;
|
||||
ctxVmm->fnMemoryModel.pfnTlbPageTableVerify = MmX64_TlbPageTableVerify;
|
||||
ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_X64;
|
||||
ctxVmm->f32 = FALSE;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
// vmmx64.h : definitions related to the x64 / IA32e / long-mode paging / memory model.
|
||||
// mm_x64.h : definitions related to the x64 / IA32e / long-mode paging / memory model.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __VMMX64_H__
|
||||
#define __VMMX64_H__
|
||||
#ifndef __MM_X64_H__
|
||||
#define __MM_X64_H__
|
||||
#include "vmm.h"
|
||||
|
||||
/*
|
||||
@@ -12,6 +12,6 @@
|
||||
* If a previous memory model exists that memory model is first closed before
|
||||
* the new X64 memory model is initialized.
|
||||
*/
|
||||
VOID VmmX64_Initialize();
|
||||
VOID MmX64_Initialize();
|
||||
|
||||
#endif /* __VMMX64_H__ */
|
||||
#endif /* __MM_X64_H__ */
|
||||
303
vmm/mm_x86.c
Normal file
303
vmm/mm_x86.c
Normal file
@@ -0,0 +1,303 @@
|
||||
// mm_x86.c : implementation of the x86 32-bit protected mode memory model.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "device.h"
|
||||
#include "vmm.h"
|
||||
|
||||
/*
|
||||
* Tries to verify that a loaded page table is correct. If just a bit strange
|
||||
* bytes/ptes supplied in pb will be altered to look better.
|
||||
*/
|
||||
BOOL MmX86_TlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define VMMX64_TLB_SIZE_STAGEBUF 0x400
|
||||
|
||||
typedef struct tdMMX86_TLB_SPIDER_STAGE_INTERNAL {
|
||||
QWORD c;
|
||||
PMEM_IO_SCATTER_HEADER ppDMAs[VMMX64_TLB_SIZE_STAGEBUF];
|
||||
PVMM_CACHE_ENTRY ppEntrys[VMMX64_TLB_SIZE_STAGEBUF];
|
||||
} MMX86_TLB_SPIDER_STAGE_INTERNAL, *PMMX86_TLB_SPIDER_STAGE_INTERNAL;
|
||||
|
||||
VOID MmX86_TlbSpider_ReadToCache(PMMX86_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
|
||||
{
|
||||
QWORD i;
|
||||
DeviceReadScatterMEM(pTlbSpiderStage->ppDMAs, (DWORD)pTlbSpiderStage->c, NULL);
|
||||
for(i = 0; i < pTlbSpiderStage->c; i++) {
|
||||
MmX86_TlbPageTableVerify(pTlbSpiderStage->ppEntrys[i]->h.pb, pTlbSpiderStage->ppEntrys[i]->h.qwA, FALSE);
|
||||
VmmCachePut(ctxVmm->ptTLB, pTlbSpiderStage->ppEntrys[i]);
|
||||
}
|
||||
pTlbSpiderStage->c = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over the PD to retrieve uncached PT pages and then commit them to the cache.
|
||||
*/
|
||||
VOID MmX86_TlbSpider(_In_ QWORD paDTB, _In_ BOOL fUserOnly)
|
||||
{
|
||||
PBYTE pbPD;
|
||||
DWORD i, pte;
|
||||
PMEM_IO_SCATTER_HEADER pt;
|
||||
PMMX86_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage;
|
||||
if(!(pTlbSpiderStage = (PMMX86_TLB_SPIDER_STAGE_INTERNAL)LocalAlloc(LMEM_ZEROINIT, sizeof(MMX86_TLB_SPIDER_STAGE_INTERNAL)))) { return; }
|
||||
pbPD = VmmTlbGetPageTable(paDTB & 0xfffff000, FALSE);
|
||||
for(i = 0; i < 0x1000; i += 8) {
|
||||
pte = *(PDWORD)(pbPD + i);
|
||||
if(!(pte & 0x01)) { continue; } // not valid
|
||||
if(pte & 0x80) { continue; } // not valid ptr to PT
|
||||
if(fUserOnly && !(pte & 0x04)) { continue; } // supervisor page when fUserOnly -> not valid
|
||||
pt = VmmCacheGet(ctxVmm->ptTLB, pte & 0xfffff000);
|
||||
if(!pt) {
|
||||
pTlbSpiderStage->ppEntrys[pTlbSpiderStage->c] = VmmCacheReserve(ctxVmm->ptTLB);
|
||||
pTlbSpiderStage->ppDMAs[pTlbSpiderStage->c] = &pTlbSpiderStage->ppEntrys[pTlbSpiderStage->c]->h;
|
||||
pTlbSpiderStage->ppDMAs[pTlbSpiderStage->c]->qwA = pte & 0xfffff000;
|
||||
pTlbSpiderStage->c++;
|
||||
}
|
||||
}
|
||||
MmX86_TlbSpider_ReadToCache(pTlbSpiderStage);
|
||||
LocalFree(pTlbSpiderStage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Map a tag into the sorted memory map in O(log2) operations. Supply only one
|
||||
* of szTag or wszTag.
|
||||
* -- pProcess
|
||||
* -- vaBase
|
||||
* -- vaLimit = limit == vaBase + size (== top address in range +1)
|
||||
* -- szTag
|
||||
* -- wszTag
|
||||
*/
|
||||
VOID MmX86_MapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_opt_ BOOL fWoW64)
|
||||
{
|
||||
PVMM_MEMMAP_ENTRY pMap;
|
||||
QWORD i, lvl, cMap;
|
||||
if((vaBase > 0xffffffff) || (vaLimit > 0xffffffff)) { return; }
|
||||
pMap = pProcess->pMemMap;
|
||||
cMap = pProcess->cMemMap;
|
||||
if(!pMap || !cMap) { return; }
|
||||
// 1: locate base
|
||||
lvl = 1;
|
||||
i = cMap >> lvl;
|
||||
while(TRUE) {
|
||||
lvl++;
|
||||
if((cMap >> lvl) == 0) {
|
||||
break;
|
||||
}
|
||||
if(pMap[i].AddrBase > vaBase) {
|
||||
i -= (cMap >> lvl);
|
||||
} else {
|
||||
i += (cMap >> lvl);
|
||||
}
|
||||
}
|
||||
// 2: scan back if needed
|
||||
while(i && (pMap[i].AddrBase > vaBase)) {
|
||||
i--;
|
||||
}
|
||||
// 3: fill in tag
|
||||
while((i < cMap) && (pMap[i].AddrBase + (pMap[i].cPages << 12) <= vaLimit)) {
|
||||
if(pMap[i].AddrBase >= vaBase) {
|
||||
if(wszTag) {
|
||||
snprintf(pMap[i].szTag, 31, "%S", wszTag);
|
||||
}
|
||||
if(szTag) {
|
||||
snprintf(pMap[i].szTag, 31, "%s", szTag);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
VOID MmX86_MapDisplayBufferGenerate(_In_ PVMM_PROCESS pProcess)
|
||||
{
|
||||
DWORD i, o = 0;
|
||||
PBYTE pbBuffer;
|
||||
if(!pProcess->cMemMap || !pProcess->pMemMap) { return; }
|
||||
pProcess->cbMemMapDisplayCache = 0;
|
||||
LocalFree(pProcess->pbMemMapDisplayCache);
|
||||
pProcess->pbMemMapDisplayCache = NULL;
|
||||
pbBuffer = LocalAlloc(LMEM_ZEROINIT, 70 * pProcess->cMemMap);
|
||||
if(!pbBuffer) { return; }
|
||||
for(i = 0; i < pProcess->cMemMap; i++) {
|
||||
o += snprintf(
|
||||
pbBuffer + o,
|
||||
70,
|
||||
"%04x %8x %08x-%08x %sr%sx %s\n",
|
||||
i,
|
||||
(DWORD)pProcess->pMemMap[i].cPages,
|
||||
(DWORD)pProcess->pMemMap[i].AddrBase,
|
||||
(DWORD)(pProcess->pMemMap[i].AddrBase + (pProcess->pMemMap[i].cPages << 12) - 1),
|
||||
pProcess->pMemMap[i].fPage & VMM_MEMMAP_FLAG_PAGE_NS ? "-" : "s",
|
||||
pProcess->pMemMap[i].fPage & VMM_MEMMAP_FLAG_PAGE_W ? "w" : "-",
|
||||
pProcess->pMemMap[i].szTag
|
||||
);
|
||||
}
|
||||
pProcess->pbMemMapDisplayCache = LocalAlloc(0, o);
|
||||
if(!pProcess->pbMemMapDisplayCache) { goto fail; }
|
||||
memcpy(pProcess->pbMemMapDisplayCache, pbBuffer, o);
|
||||
pProcess->cbMemMapDisplayCache = o;
|
||||
fail:
|
||||
LocalFree(pbBuffer);
|
||||
}
|
||||
|
||||
PVMM_MEMMAP_ENTRY MmX86_MapGetEntry(_In_ PVMM_PROCESS pProcess, _In_ QWORD va)
|
||||
{
|
||||
QWORD i, ce;
|
||||
PVMM_MEMMAP_ENTRY pe;
|
||||
if(!pProcess->pMemMap) { return NULL; }
|
||||
ce = pProcess->cMemMap;
|
||||
for(i = 0; i < ce; i++) {
|
||||
pe = pProcess->pMemMap + i;
|
||||
if((pe->AddrBase >= va) && (va <= pe->AddrBase + (pe->cPages << 12))) {
|
||||
return pe;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const QWORD MMX86_PAGETABLEMAP_PML_REGION_SIZE[3] = { 0, 12, 22 };
|
||||
|
||||
VOID MmX86_MapInitialize_Index(_In_ PVMM_PROCESS pProcess, _In_ DWORD vaBase, _In_ BYTE iPML, _In_ DWORD PTEs[1024], _In_ BOOL fSupervisorPML, _In_ QWORD paMax)
|
||||
{
|
||||
PBYTE pbNextPageTable;
|
||||
DWORD i, va, pte;
|
||||
BOOL fUserOnly, fNextSupervisorPML;
|
||||
QWORD cMemMap = pProcess->cMemMap;
|
||||
PVMM_MEMMAP_ENTRY pMemMap = pProcess->pMemMap;
|
||||
PVMM_MEMMAP_ENTRY pMemMapEntry = pMemMap + cMemMap - 1;
|
||||
fUserOnly = pProcess->fUserOnly;
|
||||
for(i = 0; i < 1024; i++) {
|
||||
pte = PTEs[i];
|
||||
if(!(pte & 0x01)) { continue; }
|
||||
if((pte & 0xfffff000) > paMax) { continue; }
|
||||
if(fSupervisorPML) { pte = pte & 0xfffffffb; }
|
||||
if(fUserOnly && !(pte & 0x04)) { continue; }
|
||||
va = vaBase + (i << MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
if((iPML == 1) || (pte & 0x80) /* PS */) {
|
||||
if((cMemMap == 0) ||
|
||||
(pMemMapEntry->fPage != (pte & VMM_MEMMAP_FLAG_PAGE_MASK)) ||
|
||||
(va != pMemMapEntry->AddrBase + (pMemMapEntry->cPages << 12))) {
|
||||
if(cMemMap + 1 >= VMM_MEMMAP_ENTRIES_MAX) { return; }
|
||||
pMemMapEntry = pProcess->pMemMap + cMemMap;
|
||||
pMemMapEntry->AddrBase = va;
|
||||
pMemMapEntry->fPage = pte & VMM_MEMMAP_FLAG_PAGE_MASK;
|
||||
pMemMapEntry->cPages = 1ULL << (MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
|
||||
pProcess->cMemMap++;
|
||||
cMemMap++;
|
||||
continue;
|
||||
}
|
||||
pMemMapEntry->cPages += 1ULL << (MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
|
||||
continue;
|
||||
}
|
||||
// maps page table
|
||||
fNextSupervisorPML = !(pte & 0x04);
|
||||
if(!(pbNextPageTable = VmmTlbGetPageTable(pte & 0xfffff000, FALSE))) { continue; }
|
||||
MmX86_MapInitialize_Index(pProcess, va, 1, (PDWORD)pbNextPageTable, fNextSupervisorPML, paMax);
|
||||
cMemMap = pProcess->cMemMap;
|
||||
pMemMapEntry = pProcess->pMemMap + cMemMap - 1;
|
||||
}
|
||||
}
|
||||
|
||||
VOID MmX86_MapInitialize(_In_ PVMM_PROCESS pProcess)
|
||||
{
|
||||
PBYTE pbPD;
|
||||
pProcess->cbMemMapDisplayCache = 0;
|
||||
LocalFree(pProcess->pbMemMapDisplayCache);
|
||||
pProcess->pbMemMapDisplayCache = NULL;
|
||||
LocalFree(pProcess->pMemMap);
|
||||
pProcess->cMemMap = 0;
|
||||
pProcess->pMemMap = (PVMM_MEMMAP_ENTRY)LocalAlloc(LMEM_ZEROINIT, VMM_MEMMAP_ENTRIES_MAX * sizeof(VMM_MEMMAP_ENTRY));
|
||||
if(!pProcess->pMemMap) { return; }
|
||||
if(!(pbPD = VmmTlbGetPageTable(pProcess->paDTB & 0xfffff000, FALSE))) { return; }
|
||||
MmX86_MapInitialize_Index(pProcess, 0, 2, (PDWORD)pbPD, FALSE, ctxMain->cfg.paAddrMax);
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL MmX86_Virt2Phys(_In_ QWORD paPT, _In_ BOOL fUserOnly, _In_ BYTE iPML, _In_ QWORD va, _Out_ PQWORD ppa)
|
||||
{
|
||||
DWORD pte, i;
|
||||
PBYTE pbPTEs;
|
||||
if(va > 0xffffffff) { return FALSE; }
|
||||
if(paPT > 0xffffffff) { return FALSE; }
|
||||
if(iPML == (BYTE)-1) { iPML = 2; }
|
||||
if(!(pbPTEs = VmmTlbGetPageTable(paPT & 0xfffff000, FALSE))) { return FALSE; }
|
||||
i = 0x3ff & (va >> MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
pte = ((PDWORD)pbPTEs)[i];
|
||||
if(!(pte & 0x01)) { return FALSE; } // NOT VALID
|
||||
if(fUserOnly && !(pte & 0x04)) { return FALSE; } // SUPERVISOR PAGE & USER MODE REQ
|
||||
if((iPML == 2) && !(pte & 0x80) /* PS */) {
|
||||
return MmX86_Virt2Phys(pte, fUserOnly, 1, va, ppa);
|
||||
}
|
||||
if(iPML == 1) { // 4kB PAGE
|
||||
*ppa = pte & 0xfffff000;
|
||||
return TRUE;
|
||||
}
|
||||
// 4MB PAGE
|
||||
if(pte & 0x003e0000) { return FALSE; } // RESERVED
|
||||
*ppa = (((QWORD)(pte & 0x0001e000)) << (32 - 13)) + (pte & 0xffc00000) + (va & 0x003ff000);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID MmX86_Virt2PhysGetInformation_DoWork(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo, _In_ BYTE iPML, _In_ QWORD paPT)
|
||||
{
|
||||
PDWORD PTEs;
|
||||
DWORD pte, i;
|
||||
if(!(PTEs = (PDWORD)VmmTlbGetPageTable(paPT, FALSE))) { return; }
|
||||
i = 0x3ff & (pVirt2PhysInfo->va >> MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
pte = PTEs[i];
|
||||
pVirt2PhysInfo->pas[iPML] = paPT;
|
||||
pVirt2PhysInfo->iPTEs[iPML] = (WORD)i;
|
||||
pVirt2PhysInfo->PTEs[iPML] = pte;
|
||||
if(!(pte & 0x01)) { return; } // NOT VALID
|
||||
if(pProcess->fUserOnly && !(pte & 0x04)) { return; } // SUPERVISOR PAGE & USER MODE REQ
|
||||
if(iPML == 1) { // 4kB page
|
||||
pVirt2PhysInfo->pas[0] = pte & 0xfffff000;
|
||||
return;
|
||||
}
|
||||
if(pte & 0x80) { // 4MB page
|
||||
if(pte & 0x003e0000) { return; } // RESERVED
|
||||
pVirt2PhysInfo->pas[0] = (pte & 0xffc00000) + (((QWORD)(pte & 0x0001e000)) << (32 - 13));
|
||||
return;
|
||||
}
|
||||
MmX86_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, 1, pte & 0xffff000); // PDE
|
||||
}
|
||||
|
||||
VOID MmX86_Virt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo)
|
||||
{
|
||||
QWORD va;
|
||||
if(pVirt2PhysInfo->va > 0xffffffff) { return; }
|
||||
va = pVirt2PhysInfo->va;
|
||||
ZeroMemory(pVirt2PhysInfo, sizeof(VMM_VIRT2PHYS_INFORMATION));
|
||||
pVirt2PhysInfo->tpMemoryModel = VMM_MEMORYMODEL_X86;
|
||||
pVirt2PhysInfo->va = va;
|
||||
MmX86_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, 2, pProcess->paDTB & 0xfffff000);
|
||||
}
|
||||
|
||||
VOID MmX86_Close()
|
||||
{
|
||||
ctxVmm->f32 = FALSE;
|
||||
ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_NA;
|
||||
ZeroMemory(&ctxVmm->fnMemoryModel, sizeof(VMM_MEMORYMODEL_FUNCTIONS));
|
||||
}
|
||||
|
||||
VOID MmX86_Initialize()
|
||||
{
|
||||
if(ctxVmm->fnMemoryModel.pfnClose) {
|
||||
ctxVmm->fnMemoryModel.pfnClose();
|
||||
}
|
||||
ctxVmm->fnMemoryModel.pfnInitialize = MmX86_Initialize;
|
||||
ctxVmm->fnMemoryModel.pfnClose = MmX86_Close;
|
||||
ctxVmm->fnMemoryModel.pfnVirt2Phys = MmX86_Virt2Phys;
|
||||
ctxVmm->fnMemoryModel.pfnVirt2PhysGetInformation = MmX86_Virt2PhysGetInformation;
|
||||
ctxVmm->fnMemoryModel.pfnMapInitialize = MmX86_MapInitialize;
|
||||
ctxVmm->fnMemoryModel.pfnMapTag = MmX86_MapTag;
|
||||
ctxVmm->fnMemoryModel.pfnMapGetEntry = MmX86_MapGetEntry;
|
||||
ctxVmm->fnMemoryModel.pfnMapDisplayBufferGenerate = MmX86_MapDisplayBufferGenerate;
|
||||
ctxVmm->fnMemoryModel.pfnTlbSpider = MmX86_TlbSpider;
|
||||
ctxVmm->fnMemoryModel.pfnTlbPageTableVerify = MmX86_TlbPageTableVerify;
|
||||
ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_X86;
|
||||
ctxVmm->f32 = TRUE;
|
||||
}
|
||||
17
vmm/mm_x86.h
Normal file
17
vmm/mm_x86.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// mm_x86.h : definitions related to the x86 32-bit protected mode memory model.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __MM_X86_H__
|
||||
#define __MM_X86_H__
|
||||
#include "vmm.h"
|
||||
|
||||
/*
|
||||
* Initialize the X86 32-bit protected mode memory model.
|
||||
* If a previous memory model exists that memory model is first closed before
|
||||
* the new X86 memory model is initialized.
|
||||
*/
|
||||
VOID MmX86_Initialize();
|
||||
|
||||
#endif /* __MM_X86_H__ */
|
||||
371
vmm/mm_x86pae.c
Normal file
371
vmm/mm_x86pae.c
Normal file
@@ -0,0 +1,371 @@
|
||||
// mm_x86pae.c : implementation of the x86 PAE (Physical Address Extension) 32-bit protected mode memory model.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#include "device.h"
|
||||
#include "vmm.h"
|
||||
|
||||
/*
|
||||
* Tries to verify that a loaded page table is correct. If just a bit strange
|
||||
* bytes/ptes supplied in pb will be altered to look better.
|
||||
*/
|
||||
BOOL MmX86PAE_TlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define VMMX64_TLB_SIZE_STAGEBUF 0x200
|
||||
|
||||
typedef struct tdMMX86PAE_TLB_SPIDER_STAGE_INTERNAL {
|
||||
QWORD c;
|
||||
PMEM_IO_SCATTER_HEADER ppDMAs[VMMX64_TLB_SIZE_STAGEBUF];
|
||||
PVMM_CACHE_ENTRY ppEntrys[VMMX64_TLB_SIZE_STAGEBUF];
|
||||
} MMX86PAE_TLB_SPIDER_STAGE_INTERNAL, *PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL;
|
||||
|
||||
VOID MmX86PAE_TlbSpider_ReadToCache(PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
|
||||
{
|
||||
QWORD i;
|
||||
DeviceReadScatterMEM(pTlbSpiderStage->ppDMAs, (DWORD)pTlbSpiderStage->c, NULL);
|
||||
for(i = 0; i < pTlbSpiderStage->c; i++) {
|
||||
MmX86PAE_TlbPageTableVerify(pTlbSpiderStage->ppEntrys[i]->h.pb, pTlbSpiderStage->ppEntrys[i]->h.qwA, FALSE);
|
||||
VmmCachePut(ctxVmm->ptTLB, pTlbSpiderStage->ppEntrys[i]);
|
||||
}
|
||||
pTlbSpiderStage->c = 0;
|
||||
}
|
||||
|
||||
BOOL MmX86PAE_TlbSpider_PD_PT(_In_ QWORD pa, _In_ BYTE iPML, _In_ BOOL fUserOnly, PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
|
||||
{
|
||||
BOOL fSpiderComplete = TRUE;
|
||||
PMEM_IO_SCATTER_HEADER pt;
|
||||
QWORD i, pte;
|
||||
// 1: retrieve from cache, add to staging if not found
|
||||
pt = VmmCacheGet(ctxVmm->ptTLB, pa);
|
||||
if(!pt) {
|
||||
pTlbSpiderStage->ppEntrys[pTlbSpiderStage->c] = VmmCacheReserve(ctxVmm->ptTLB);
|
||||
pTlbSpiderStage->ppDMAs[pTlbSpiderStage->c] = &pTlbSpiderStage->ppEntrys[pTlbSpiderStage->c]->h;
|
||||
pTlbSpiderStage->ppDMAs[pTlbSpiderStage->c]->qwA = pa;
|
||||
pTlbSpiderStage->c++;
|
||||
if(pTlbSpiderStage->c == VMMX64_TLB_SIZE_STAGEBUF) {
|
||||
MmX86PAE_TlbSpider_ReadToCache(pTlbSpiderStage);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if(iPML == 1) { return TRUE; }
|
||||
// 2: walk trough all entries for PD
|
||||
for(i = 0; i < 0x1000; i += 8) {
|
||||
pte = *(PQWORD)(pt->pb + i);
|
||||
if(!(pte & 0x01)) { continue; } // not valid
|
||||
if(pte & 0x80) { continue; } // not valid ptr to PT
|
||||
if(fUserOnly && !(pte & 0x04)) { continue; } // supervisor page when fUserOnly -> not valid
|
||||
fSpiderComplete = MmX86PAE_TlbSpider_PD_PT(pte & 0x0000fffffffff000, 1, fUserOnly, pTlbSpiderStage) && fSpiderComplete;
|
||||
}
|
||||
return fSpiderComplete;
|
||||
}
|
||||
|
||||
BOOL MmX86PAE_TlbSpider_PDPT(_In_ QWORD paDTB, _In_ BOOL fUserOnly, PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
|
||||
{
|
||||
BOOL fSpiderComplete = TRUE;
|
||||
QWORD i, pte;
|
||||
PBYTE pbPDPT;
|
||||
// 1: retrieve PDPT
|
||||
pbPDPT = VmmTlbGetPageTable(paDTB & 0xfffff000, FALSE);
|
||||
if(!pbPDPT) { return FALSE; }
|
||||
pbPDPT += paDTB & 0xfe0;
|
||||
// 2: walk through all four (4) PDPTEs
|
||||
for(i = 0; i < 0x20; i += 8) {
|
||||
pte = *(PQWORD)(pbPDPT + i);
|
||||
if(!(pte & 0x01)) { continue; } // not valid
|
||||
if(pte & 0xffff0000000001e6) { continue; } // RESERVED BITS IN PDPTE
|
||||
fSpiderComplete = MmX86PAE_TlbSpider_PD_PT(pte & 0x0000fffffffff000, 2, fUserOnly, pTlbSpiderStage) && fSpiderComplete;
|
||||
}
|
||||
return fSpiderComplete;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over PTPT, PD (3 times in total) to first stage uncached pages
|
||||
* and then commit them to the cache.
|
||||
*/
|
||||
VOID MmX86PAE_TlbSpider(_In_ QWORD paDTB, _In_ BOOL fUserOnly)
|
||||
{
|
||||
DWORD i = 0;
|
||||
BOOL result = FALSE;
|
||||
PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage;
|
||||
if(!(pTlbSpiderStage = (PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL)LocalAlloc(LMEM_ZEROINIT, sizeof(MMX86PAE_TLB_SPIDER_STAGE_INTERNAL)))) { return; }
|
||||
while(!result && (i < 3)) {
|
||||
result = MmX86PAE_TlbSpider_PDPT(paDTB, fUserOnly, pTlbSpiderStage);
|
||||
if(pTlbSpiderStage->c) {
|
||||
MmX86PAE_TlbSpider_ReadToCache(pTlbSpiderStage);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
LocalFree(pTlbSpiderStage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Map a tag into the sorted memory map in O(log2) operations. Supply only one
|
||||
* of szTag or wszTag.
|
||||
* -- pProcess
|
||||
* -- vaBase
|
||||
* -- vaLimit = limit == vaBase + size (== top address in range +1)
|
||||
* -- szTag
|
||||
* -- wszTag
|
||||
*/
|
||||
VOID MmX86PAE_MapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_opt_ BOOL fWoW64)
|
||||
{
|
||||
PVMM_MEMMAP_ENTRY pMap;
|
||||
QWORD i, lvl, cMap;
|
||||
if((vaBase > 0xffffffff) || (vaLimit > 0xffffffff)) { return; }
|
||||
pMap = pProcess->pMemMap;
|
||||
cMap = pProcess->cMemMap;
|
||||
if(!pMap || !cMap) { return; }
|
||||
// 1: locate base
|
||||
lvl = 1;
|
||||
i = cMap >> lvl;
|
||||
while(TRUE) {
|
||||
lvl++;
|
||||
if((cMap >> lvl) == 0) {
|
||||
break;
|
||||
}
|
||||
if(pMap[i].AddrBase > vaBase) {
|
||||
i -= (cMap >> lvl);
|
||||
} else {
|
||||
i += (cMap >> lvl);
|
||||
}
|
||||
}
|
||||
// 2: scan back if needed
|
||||
while(i && (pMap[i].AddrBase > vaBase)) {
|
||||
i--;
|
||||
}
|
||||
// 3: fill in tag
|
||||
while((i < cMap) && (pMap[i].AddrBase + (pMap[i].cPages << 12) <= vaLimit)) {
|
||||
if(pMap[i].AddrBase >= vaBase) {
|
||||
if(wszTag) {
|
||||
snprintf(pMap[i].szTag, 31, "%S", wszTag);
|
||||
}
|
||||
if(szTag) {
|
||||
snprintf(pMap[i].szTag, 31, "%s", szTag);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
VOID MmX86PAE_MapDisplayBufferGenerate(_In_ PVMM_PROCESS pProcess)
|
||||
{
|
||||
DWORD i, o = 0;
|
||||
PBYTE pbBuffer;
|
||||
if(!pProcess->cMemMap || !pProcess->pMemMap) { return; }
|
||||
pProcess->cbMemMapDisplayCache = 0;
|
||||
LocalFree(pProcess->pbMemMapDisplayCache);
|
||||
pProcess->pbMemMapDisplayCache = NULL;
|
||||
pbBuffer = LocalAlloc(LMEM_ZEROINIT, 70 * pProcess->cMemMap);
|
||||
if(!pbBuffer) { return; }
|
||||
for(i = 0; i < pProcess->cMemMap; i++) {
|
||||
o += snprintf(
|
||||
pbBuffer + o,
|
||||
70,
|
||||
"%04x %8x %08x-%08x %sr%s%s %s\n",
|
||||
i,
|
||||
(DWORD)pProcess->pMemMap[i].cPages,
|
||||
(DWORD)pProcess->pMemMap[i].AddrBase,
|
||||
(DWORD)(pProcess->pMemMap[i].AddrBase + (pProcess->pMemMap[i].cPages << 12) - 1),
|
||||
pProcess->pMemMap[i].fPage & VMM_MEMMAP_FLAG_PAGE_NS ? "-" : "s",
|
||||
pProcess->pMemMap[i].fPage & VMM_MEMMAP_FLAG_PAGE_W ? "w" : "-",
|
||||
pProcess->pMemMap[i].fPage & VMM_MEMMAP_FLAG_PAGE_NX ? "-" : "x",
|
||||
pProcess->pMemMap[i].szTag
|
||||
);
|
||||
}
|
||||
pProcess->pbMemMapDisplayCache = LocalAlloc(0, o);
|
||||
if(!pProcess->pbMemMapDisplayCache) { goto fail; }
|
||||
memcpy(pProcess->pbMemMapDisplayCache, pbBuffer, o);
|
||||
pProcess->cbMemMapDisplayCache = o;
|
||||
fail:
|
||||
LocalFree(pbBuffer);
|
||||
}
|
||||
|
||||
PVMM_MEMMAP_ENTRY MmX86PAE_MapGetEntry(_In_ PVMM_PROCESS pProcess, _In_ QWORD va)
|
||||
{
|
||||
QWORD i, ce;
|
||||
PVMM_MEMMAP_ENTRY pe;
|
||||
if(!pProcess->pMemMap) { return NULL; }
|
||||
ce = pProcess->cMemMap;
|
||||
for(i = 0; i < ce; i++) {
|
||||
pe = pProcess->pMemMap + i;
|
||||
if((pe->AddrBase >= va) && (va <= pe->AddrBase + (pe->cPages << 12))) {
|
||||
return pe;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const QWORD MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[4] = { 0, 12, 21, 30 };
|
||||
|
||||
VOID MmX86PAE_MapInitialize_Index(_In_ PVMM_PROCESS pProcess, _In_ DWORD vaBase, _In_ BYTE iPML, _In_ QWORD PTEs[512], _In_ BOOL fSupervisorPML, _In_ QWORD paMax)
|
||||
{
|
||||
PBYTE pbNextPageTable;
|
||||
DWORD i, va;
|
||||
QWORD pte;
|
||||
BOOL fUserOnly, fNextSupervisorPML;
|
||||
QWORD cMemMap = pProcess->cMemMap;
|
||||
PVMM_MEMMAP_ENTRY pMemMap = pProcess->pMemMap;
|
||||
PVMM_MEMMAP_ENTRY pMemMapEntry = pMemMap + cMemMap - 1;
|
||||
fUserOnly = pProcess->fUserOnly;
|
||||
for(i = 0; i < 512; i++) {
|
||||
if((iPML == 3) && (i > 3)) { break; } // MAX 4 ENTRIES IN PDPT
|
||||
pte = PTEs[i];
|
||||
if(!(pte & 0x01)) { continue; }
|
||||
if((pte & 0x0000fffffffff000) > paMax) { continue; }
|
||||
if(iPML == 3) {
|
||||
// PDPT: (iPML = 3)
|
||||
if(pte & 0xffff0000000001e6) { continue; } // RESERVED BITS IN PDPTE
|
||||
va = i * 0x40000000;
|
||||
} else {
|
||||
// PT or PD: (iPML = 1..2)
|
||||
if(fSupervisorPML) { pte = pte & 0xfffffffffffffffb; }
|
||||
if(fUserOnly && !(pte & 0x04)) { continue; }
|
||||
va = vaBase + (i << MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
// maps page
|
||||
if((iPML == 1) || (pte & 0x80) /* PS */) {
|
||||
if((cMemMap == 0) ||
|
||||
(pMemMapEntry->fPage != (pte & VMM_MEMMAP_FLAG_PAGE_MASK)) ||
|
||||
(va != pMemMapEntry->AddrBase + (pMemMapEntry->cPages << 12))) {
|
||||
if(cMemMap + 1 >= VMM_MEMMAP_ENTRIES_MAX) { return; }
|
||||
pMemMapEntry = pProcess->pMemMap + cMemMap;
|
||||
pMemMapEntry->AddrBase = va;
|
||||
pMemMapEntry->fPage = pte & VMM_MEMMAP_FLAG_PAGE_MASK;
|
||||
pMemMapEntry->cPages = 1ULL << (MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
|
||||
pProcess->cMemMap++;
|
||||
cMemMap++;
|
||||
continue;
|
||||
}
|
||||
pMemMapEntry->cPages += 1ULL << (MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// maps page table (PD, PT)
|
||||
fNextSupervisorPML = (iPML != 3) && !(pte & 0x04);
|
||||
if(!(pbNextPageTable = VmmTlbGetPageTable(pte & 0x0000fffffffff000, FALSE))) { continue; }
|
||||
MmX86PAE_MapInitialize_Index(pProcess, va, iPML - 1, (PQWORD)pbNextPageTable, fNextSupervisorPML, paMax);
|
||||
cMemMap = pProcess->cMemMap;
|
||||
pMemMapEntry = pProcess->pMemMap + cMemMap - 1;
|
||||
}
|
||||
}
|
||||
|
||||
VOID MmX86PAE_MapInitialize(_In_ PVMM_PROCESS pProcess)
|
||||
{
|
||||
PBYTE pbPDPT;
|
||||
pProcess->cbMemMapDisplayCache = 0;
|
||||
LocalFree(pProcess->pbMemMapDisplayCache);
|
||||
pProcess->pbMemMapDisplayCache = NULL;
|
||||
LocalFree(pProcess->pMemMap);
|
||||
pProcess->cMemMap = 0;
|
||||
pProcess->pMemMap = (PVMM_MEMMAP_ENTRY)LocalAlloc(LMEM_ZEROINIT, VMM_MEMMAP_ENTRIES_MAX * sizeof(VMM_MEMMAP_ENTRY));
|
||||
if(!pProcess->pMemMap) { return; }
|
||||
if(!(pbPDPT = VmmTlbGetPageTable(pProcess->paDTB & 0xfffff000, FALSE))) { return; }
|
||||
pbPDPT += pProcess->paDTB & 0xfe0; // ADJUST PDPT TO 32-BYTE BOUNDARY
|
||||
MmX86PAE_MapInitialize_Index(pProcess, 0, 3, (PQWORD)pbPDPT, FALSE, ctxMain->cfg.paAddrMax);
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL MmX86PAE_Virt2Phys(_In_ QWORD paPT, _In_ BOOL fUserOnly, _In_ BYTE iPML, _In_ QWORD va, _Out_ PQWORD ppa)
|
||||
{
|
||||
QWORD pte, i, qwMask;
|
||||
PBYTE pbPTEs;
|
||||
if(va > 0xffffffff) { return FALSE; }
|
||||
if(iPML == (BYTE)-1) { iPML = 3; }
|
||||
if(!(pbPTEs = VmmTlbGetPageTable(paPT & 0x0000fffffffff000, FALSE))) { return FALSE; }
|
||||
i = 0x1ff & (va >> MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
if(iPML == 3) {
|
||||
// PDPT
|
||||
if(i > 3) { return FALSE; } // MAX 4 ENTRIES IN PDPT
|
||||
pbPTEs += paPT & 0xfe0; // ADJUST PDPT TO 32-BYTE BOUNDARY
|
||||
pte = ((PQWORD)pbPTEs)[i];
|
||||
if(!(pte & 0x01)) { return FALSE; } // NOT VALID
|
||||
if(pte & 0xffff0000000001e6) { return FALSE; } // RESERVED BITS IN PDPTE
|
||||
return MmX86PAE_Virt2Phys(pte, fUserOnly, 2, va, ppa);
|
||||
}
|
||||
// PT or PD
|
||||
pte = ((PQWORD)pbPTEs)[i];
|
||||
if(!(pte & 0x01)) { return FALSE; } // NOT VALID
|
||||
if(fUserOnly && !(pte & 0x04)) { return FALSE; } // SUPERVISOR PAGE & USER MODE REQ
|
||||
if(pte & 0x000f000000000000) { return FALSE; } // RESERVED
|
||||
if((iPML == 1) || (pte & 0x80) /* PS */) {
|
||||
qwMask = 0xffffffffffffffff << MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML];
|
||||
*ppa = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB/1GB PAGES
|
||||
qwMask = qwMask ^ 0xffffffffffffffff;
|
||||
*ppa = *ppa | (qwMask & va); // FILL LOWER ADDRESS BITS
|
||||
return TRUE;
|
||||
}
|
||||
return MmX86PAE_Virt2Phys(pte, fUserOnly, 1, va, ppa);
|
||||
}
|
||||
|
||||
VOID MmX86PAE_Virt2PhysGetInformation_DoWork(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo, _In_ BYTE iPML, _In_ QWORD PTEs[512])
|
||||
{
|
||||
QWORD pte, i, qwMask;
|
||||
PBYTE pbNextPageTable;
|
||||
i = 0x1ff & (pVirt2PhysInfo->va >> MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
|
||||
if((iPML == 3) && (i > 3)) { return; } // MAX 4 ENTRIES IN PDPT
|
||||
pte = PTEs[i];
|
||||
pVirt2PhysInfo->iPTEs[iPML] = (WORD)i;
|
||||
pVirt2PhysInfo->PTEs[iPML] = pte;
|
||||
if(!(pte & 0x01)) { return; } // NOT VALID
|
||||
if(iPML == 3) {
|
||||
// PDPT: (iPML = 3)
|
||||
if(pte & 0xffff0000000001e6) { return; } // RESERVED BITS IN PDPTE
|
||||
} else {
|
||||
// PT or PD: (iPML = 1..2)
|
||||
if(pProcess->fUserOnly && !(pte & 0x04)) { return; } // SUPERVISOR PAGE & USER MODE REQ
|
||||
if(pte & 0x000f000000000000) { return; } // RESERVED
|
||||
if((iPML == 1) || (pte & 0x80) /* PS */) {
|
||||
qwMask = 0xffffffffffffffff << MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML];
|
||||
pVirt2PhysInfo->pas[0] = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB PAGES
|
||||
qwMask = qwMask ^ 0xffffffffffffffff;
|
||||
pVirt2PhysInfo->pas[0] = pVirt2PhysInfo->pas[0] | (qwMask & pVirt2PhysInfo->va); // FILL LOWER ADDRESS BITS
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!(pbNextPageTable = VmmTlbGetPageTable(pte & 0x0000fffffffff000, FALSE))) { return; }
|
||||
pVirt2PhysInfo->pas[iPML - 1] = pte & 0x0000fffffffff000;
|
||||
MmX86PAE_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, iPML - 1, (PQWORD)pbNextPageTable);
|
||||
}
|
||||
|
||||
VOID MmX86PAE_Virt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo)
|
||||
{
|
||||
QWORD va;
|
||||
PBYTE pbPDPT;
|
||||
if(pVirt2PhysInfo->va > 0xffffffff) { return; }
|
||||
va = pVirt2PhysInfo->va;
|
||||
ZeroMemory(pVirt2PhysInfo, sizeof(VMM_VIRT2PHYS_INFORMATION));
|
||||
pVirt2PhysInfo->tpMemoryModel = VMM_MEMORYMODEL_X86PAE;
|
||||
pVirt2PhysInfo->va = va;
|
||||
pVirt2PhysInfo->pas[3] = pProcess->paDTB;
|
||||
if(!(pbPDPT = VmmTlbGetPageTable(pProcess->paDTB & 0xfffff000, FALSE))) { return; }
|
||||
MmX86PAE_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, 3, (PQWORD)(pbPDPT + (pProcess->paDTB & 0xfe0)));
|
||||
}
|
||||
|
||||
VOID MmX86PAE_Close()
|
||||
{
|
||||
ctxVmm->f32 = FALSE;
|
||||
ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_NA;
|
||||
ZeroMemory(&ctxVmm->fnMemoryModel, sizeof(VMM_MEMORYMODEL_FUNCTIONS));
|
||||
}
|
||||
|
||||
VOID MmX86PAE_Initialize()
|
||||
{
|
||||
if(ctxVmm->fnMemoryModel.pfnClose) {
|
||||
ctxVmm->fnMemoryModel.pfnClose();
|
||||
}
|
||||
ctxVmm->fnMemoryModel.pfnInitialize = MmX86PAE_Initialize;
|
||||
ctxVmm->fnMemoryModel.pfnClose = MmX86PAE_Close;
|
||||
ctxVmm->fnMemoryModel.pfnVirt2Phys = MmX86PAE_Virt2Phys;
|
||||
ctxVmm->fnMemoryModel.pfnVirt2PhysGetInformation = MmX86PAE_Virt2PhysGetInformation;
|
||||
ctxVmm->fnMemoryModel.pfnMapInitialize = MmX86PAE_MapInitialize;
|
||||
ctxVmm->fnMemoryModel.pfnMapTag = MmX86PAE_MapTag;
|
||||
ctxVmm->fnMemoryModel.pfnMapGetEntry = MmX86PAE_MapGetEntry;
|
||||
ctxVmm->fnMemoryModel.pfnMapDisplayBufferGenerate = MmX86PAE_MapDisplayBufferGenerate;
|
||||
ctxVmm->fnMemoryModel.pfnTlbSpider = MmX86PAE_TlbSpider;
|
||||
ctxVmm->fnMemoryModel.pfnTlbPageTableVerify = MmX86PAE_TlbPageTableVerify;
|
||||
ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_X86PAE;
|
||||
ctxVmm->f32 = TRUE;
|
||||
}
|
||||
17
vmm/mm_x86pae.h
Normal file
17
vmm/mm_x86pae.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// mm_x86pae.h : definitions related to the x86 PAE (Physical Address Extension) 32-bit protected mode memory model.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __MM_X86PAE_H__
|
||||
#define __MM_X86PAE_H__
|
||||
#include "vmm.h"
|
||||
|
||||
/*
|
||||
* Initialize the X86 PAE 32-bit protected mode memory model.
|
||||
* If a previous memory model exists that memory model is first closed before
|
||||
* the new X86 PAE memory model is initialized.
|
||||
*/
|
||||
VOID MmX86PAE_Initialize();
|
||||
|
||||
#endif /* __MM_X86PAE_H__ */
|
||||
221
vmm/pe.c
Normal file
221
vmm/pe.c
Normal file
@@ -0,0 +1,221 @@
|
||||
// pe.c : implementation related to parsing of portable executable (PE) images
|
||||
// in virtual address space. This may mostly (but not exclusively) be
|
||||
// used by Windows functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
|
||||
#include "vmm.h"
|
||||
|
||||
PIMAGE_NT_HEADERS PE_HeaderGetVerify(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase, _Inout_ PBYTE pbModuleHeader, _Out_opt_ PBOOL pfHdr32)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dosHeader;
|
||||
PIMAGE_NT_HEADERS ntHeader;
|
||||
if(pfHdr32) { *pfHdr32 = FALSE; }
|
||||
if(vaModuleBase) {
|
||||
if(!VmmReadPage(pProcess, vaModuleBase, pbModuleHeader)) { return NULL; }
|
||||
}
|
||||
dosHeader = (PIMAGE_DOS_HEADER)pbModuleHeader; // dos header.
|
||||
if(!dosHeader || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return NULL; }
|
||||
if(dosHeader->e_lfanew > 0x800) { return NULL; }
|
||||
ntHeader = (PIMAGE_NT_HEADERS)(pbModuleHeader + dosHeader->e_lfanew); // nt header
|
||||
if(!ntHeader || ntHeader->Signature != IMAGE_NT_SIGNATURE) { return NULL; }
|
||||
if((ntHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) && (ntHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)) { return NULL; }
|
||||
if(pfHdr32) { *pfHdr32 = (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC); }
|
||||
return ntHeader;
|
||||
}
|
||||
|
||||
QWORD PE_GetSize(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase)
|
||||
{
|
||||
BYTE pbHeader[0x1000] = { 0 };
|
||||
PIMAGE_NT_HEADERS ntHeader;
|
||||
DWORD cbSize;
|
||||
BOOL f32;
|
||||
ntHeader = PE_HeaderGetVerify(pProcess, vaModuleBase, pbHeader, &f32);
|
||||
cbSize = f32 ?
|
||||
((PIMAGE_NT_HEADERS32)ntHeader)->OptionalHeader.SizeOfImage :
|
||||
((PIMAGE_NT_HEADERS64)ntHeader)->OptionalHeader.SizeOfImage;
|
||||
if(cbSize > 0x02000000) { cbSize = 0; }
|
||||
return cbSize;
|
||||
}
|
||||
|
||||
QWORD PE_GetProcAddress(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR lpProcName)
|
||||
{
|
||||
BYTE pbModuleHeader[0x1000] = { 0 };
|
||||
PIMAGE_NT_HEADERS32 ntHeader32;
|
||||
PIMAGE_NT_HEADERS64 ntHeader64;
|
||||
PDWORD pdwRVAAddrNames, pdwRVAAddrFunctions;
|
||||
PWORD pwNameOrdinals;
|
||||
DWORD i, cbProcName, cbExportDirectoryOffset;
|
||||
LPSTR sz;
|
||||
QWORD vaFnPtr;
|
||||
QWORD vaExportDirectory;
|
||||
DWORD cbExportDirectory;
|
||||
PBYTE pbExportDirectory = NULL;
|
||||
QWORD vaRVAAddrNames, vaNameOrdinals, vaRVAAddrFunctions;
|
||||
BOOL f32;
|
||||
if(!(ntHeader64 = PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32))) { goto cleanup; }
|
||||
if(f32) { // 32-bit PE
|
||||
ntHeader32 = (PIMAGE_NT_HEADERS32)ntHeader64;
|
||||
vaExportDirectory = vaModuleBase + ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
cbExportDirectory = ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
} else { // 64-bit PE
|
||||
vaExportDirectory = vaModuleBase + ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
cbExportDirectory = ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
}
|
||||
if((cbExportDirectory < sizeof(IMAGE_EXPORT_DIRECTORY)) || (cbExportDirectory > 0x01000000) || (vaExportDirectory == vaModuleBase) || (vaExportDirectory > vaModuleBase + 0x80000000)) { goto cleanup; }
|
||||
if(!(pbExportDirectory = LocalAlloc(0, cbExportDirectory))) { goto cleanup; }
|
||||
if(!VmmRead(pProcess, vaExportDirectory, pbExportDirectory, cbExportDirectory)) { goto cleanup; }
|
||||
PIMAGE_EXPORT_DIRECTORY exp = (PIMAGE_EXPORT_DIRECTORY)pbExportDirectory;
|
||||
if(!exp || !exp->NumberOfNames || !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; }
|
||||
cbProcName = (DWORD)strnlen_s(lpProcName, 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);
|
||||
for(i = 0; i < exp->NumberOfNames; i++) {
|
||||
if(pdwRVAAddrNames[i] - cbExportDirectoryOffset + cbProcName > cbExportDirectory) { continue; }
|
||||
sz = (LPSTR)(pbExportDirectory + pdwRVAAddrNames[i] - cbExportDirectoryOffset);
|
||||
if(0 == memcmp(sz, lpProcName, cbProcName)) {
|
||||
if(pwNameOrdinals[i] >= exp->NumberOfFunctions) { goto cleanup; }
|
||||
vaFnPtr = (QWORD)(vaModuleBase + pdwRVAAddrFunctions[pwNameOrdinals[i]]);
|
||||
LocalFree(pbExportDirectory);
|
||||
return vaFnPtr;
|
||||
}
|
||||
}
|
||||
cleanup:
|
||||
LocalFree(pbExportDirectory);
|
||||
return 0;
|
||||
}
|
||||
|
||||
WORD PE_SectionGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt)
|
||||
{
|
||||
BOOL f32;
|
||||
BYTE pbModuleHeader[0x1000] = { 0 };
|
||||
WORD cSections;
|
||||
PIMAGE_NT_HEADERS ntHeader;
|
||||
// load nt header either by using optionally supplied module header or by fetching from memory.
|
||||
ntHeader = pbModuleHeaderOpt ? PE_HeaderGetVerify(pProcess, 0, pbModuleHeaderOpt, &f32) : PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32);
|
||||
if(!ntHeader) { return 0; }
|
||||
cSections = f32 ? ((PIMAGE_NT_HEADERS32)ntHeader)->FileHeader.NumberOfSections : ((PIMAGE_NT_HEADERS64)ntHeader)->FileHeader.NumberOfSections;
|
||||
if(cSections > 0x40) { return 0; }
|
||||
return cSections;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL PE_SectionGetFromName(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR szSectionName, _Out_ PIMAGE_SECTION_HEADER pSection)
|
||||
{
|
||||
BOOL f32;
|
||||
BYTE pbModuleHeader[0x1000] = { 0 };
|
||||
PIMAGE_NT_HEADERS ntHeader;
|
||||
PIMAGE_SECTION_HEADER pSectionBase;
|
||||
DWORD i, cSections;
|
||||
if(!(ntHeader = PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32))) { return FALSE; }
|
||||
pSectionBase = f32 ?
|
||||
(PIMAGE_SECTION_HEADER)((QWORD)ntHeader + sizeof(IMAGE_NT_HEADERS32)) :
|
||||
(PIMAGE_SECTION_HEADER)((QWORD)ntHeader + sizeof(IMAGE_NT_HEADERS64));
|
||||
cSections = (DWORD)(((QWORD)pbModuleHeader + 0x1000 - (QWORD)pSectionBase) / sizeof(IMAGE_SECTION_HEADER)); // max section headers possible in 0x1000 module header buffer
|
||||
cSections = (DWORD)min(cSections, ntHeader->FileHeader.NumberOfSections); // FileHeader is the same in both 32/64-bit versions of struct
|
||||
for(i = 0; i < cSections; i++) {
|
||||
if(!strncmp((pSectionBase + i)->Name, szSectionName, 8)) {
|
||||
memcpy(pSection, pSectionBase + i, sizeof(IMAGE_SECTION_HEADER));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD PE_IatGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt)
|
||||
{
|
||||
BOOL f32;
|
||||
BYTE pbModuleHeader[0x1000] = { 0 };
|
||||
PIMAGE_NT_HEADERS ntHeader;
|
||||
DWORD cbImportDirectory, cbImportAddressTable, cIatEntries, cModules;
|
||||
// load nt header either by using optionally supplied module header or by fetching from memory.
|
||||
ntHeader = pbModuleHeaderOpt ? PE_HeaderGetVerify(pProcess, 0, pbModuleHeaderOpt, &f32) : PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32);
|
||||
if(!ntHeader) { return 0; }
|
||||
// Calculate the number of functions in the import address table (IAT).
|
||||
// Number of functions = # IAT entries - # Imported modules
|
||||
cbImportDirectory = f32 ?
|
||||
((PIMAGE_NT_HEADERS32)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size :
|
||||
((PIMAGE_NT_HEADERS64)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
|
||||
cbImportAddressTable = f32 ?
|
||||
((PIMAGE_NT_HEADERS32)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size :
|
||||
((PIMAGE_NT_HEADERS64)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
|
||||
cIatEntries = cbImportAddressTable / (f32 ? sizeof(DWORD) : sizeof(QWORD));
|
||||
cModules = cbImportDirectory / sizeof(IMAGE_IMPORT_DESCRIPTOR);
|
||||
return cIatEntries - cModules;
|
||||
}
|
||||
|
||||
DWORD PE_EatGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt)
|
||||
{
|
||||
BOOL f32;
|
||||
BYTE pbModuleHeader[0x1000] = { 0 };
|
||||
PIMAGE_NT_HEADERS ntHeader;
|
||||
QWORD va, vaExportDirectory;
|
||||
IMAGE_EXPORT_DIRECTORY hdrExportDirectory;
|
||||
// load both 32/64 bit ntHeader unless already supplied in parameter (only one of 32/64 bit hdr will be valid)
|
||||
// load nt header either by using optionally supplied module header or by fetching from memory.
|
||||
ntHeader = pbModuleHeaderOpt ? PE_HeaderGetVerify(pProcess, 0, pbModuleHeaderOpt, &f32) : PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32);
|
||||
if(!ntHeader) { return 0; }
|
||||
// Calculate the number of functions in the export address table (EAT).
|
||||
va = f32 ?
|
||||
((PIMAGE_NT_HEADERS32)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress :
|
||||
((PIMAGE_NT_HEADERS64)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
vaExportDirectory = va ? vaModuleBase + va : 0;
|
||||
if(vaExportDirectory && VmmRead(pProcess, vaExportDirectory, (PBYTE)&hdrExportDirectory, sizeof(IMAGE_EXPORT_DIRECTORY)) && (hdrExportDirectory.NumberOfNames < 0x00010000)) {
|
||||
return hdrExportDirectory.NumberOfNames;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL PE_GetModuleNameEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ BOOL fOnFailDummyName, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt, _Out_writes_(MAX_PATH) PCHAR szModuleName, _Out_opt_ PDWORD pdwSize)
|
||||
{
|
||||
BOOL f32;
|
||||
BYTE pbModuleHeader[0x1000] = { 0 };
|
||||
PIMAGE_NT_HEADERS ntHeader;
|
||||
PIMAGE_NT_HEADERS64 ntHeader64;
|
||||
PIMAGE_NT_HEADERS32 ntHeader32;
|
||||
PIMAGE_EXPORT_DIRECTORY exp;
|
||||
QWORD vaExportDirectory;
|
||||
DWORD cbImageSize, cbExportDirectory;
|
||||
BYTE pbExportDirectory[sizeof(IMAGE_EXPORT_DIRECTORY)];
|
||||
// load both 32/64 bit ntHeader unless already supplied in parameter (only one of 32/64 bit hdr will be valid)
|
||||
// load nt header either by using optionally supplied module header or by fetching from memory.
|
||||
ntHeader = pbModuleHeaderOpt ? PE_HeaderGetVerify(pProcess, 0, pbModuleHeaderOpt, &f32) : PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32);
|
||||
if(!ntHeader) { return FALSE; }
|
||||
if(!f32) { // 64-bit PE
|
||||
ntHeader64 = (PIMAGE_NT_HEADERS64)ntHeader;
|
||||
if(pdwSize) { *pdwSize = ntHeader64->OptionalHeader.SizeOfImage; }
|
||||
vaExportDirectory = vaModuleBase + ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
cbExportDirectory = ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
cbImageSize = ntHeader64->OptionalHeader.SizeOfImage;
|
||||
} else { // 32-bit PE
|
||||
ntHeader32 = (PIMAGE_NT_HEADERS32)ntHeader;
|
||||
if(pdwSize) { *pdwSize = ntHeader32->OptionalHeader.SizeOfImage; }
|
||||
vaExportDirectory = vaModuleBase + ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
cbExportDirectory = ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
cbImageSize = ntHeader32->OptionalHeader.SizeOfImage;
|
||||
}
|
||||
if((cbExportDirectory < sizeof(IMAGE_EXPORT_DIRECTORY)) || (vaExportDirectory == vaModuleBase) || (cbExportDirectory > cbImageSize)) { goto fail; }
|
||||
if(!VmmRead(pProcess, vaExportDirectory, pbExportDirectory, sizeof(IMAGE_EXPORT_DIRECTORY))) { goto fail; }
|
||||
exp = (PIMAGE_EXPORT_DIRECTORY)pbExportDirectory;
|
||||
if(!exp || !exp->Name || exp->Name > cbImageSize) { goto fail; }
|
||||
szModuleName[MAX_PATH - 1] = 0;
|
||||
if(!VmmRead(pProcess, vaModuleBase + exp->Name, szModuleName, MAX_PATH - 1)) { goto fail; }
|
||||
return TRUE;
|
||||
fail:
|
||||
if(fOnFailDummyName) {
|
||||
memcpy(szModuleName, "UNKNOWN", 8);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
102
vmm/pe.h
Normal file
102
vmm/pe.h
Normal file
@@ -0,0 +1,102 @@
|
||||
// pe.h : definitions related to parsing of portable executable (PE) images in
|
||||
// virtual address space. This may mostly (but not exclusively) be used
|
||||
// by Windows functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __PE_H__
|
||||
#define __PE_H__
|
||||
#include "vmm.h"
|
||||
|
||||
static const LPCSTR PE_DATA_DIRECTORIES[16] = { "EXPORT", "IMPORT", "RESOURCE", "EXCEPTION", "SECURITY", "BASERELOC", "DEBUG", "ARCHITECTURE", "GLOBALPTR", "TLS", "LOAD_CONFIG", "BOUND_IMPORT", "IAT", "DELAY_IMPORT", "COM_DESCRIPTOR", "RESERVED" };
|
||||
|
||||
/*
|
||||
* Retrieve the size of the module given its base.
|
||||
* -- pProcess
|
||||
* -- vaModuleBase = PE module base address.
|
||||
* -- return = success: size of module. fail: 0.
|
||||
*/
|
||||
QWORD PE_GetSize(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase);
|
||||
|
||||
/*
|
||||
* Lookup the virtual address of an exported function or symbol in the module supplied.
|
||||
* Similar to Windows 'GetProcAddress'.
|
||||
* -- pProcess
|
||||
* -- vaModuleBase = PE module base address.
|
||||
* -- return = success: virtual address of function / symbol. fail: 0.
|
||||
*/
|
||||
QWORD PE_GetProcAddress(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR lpProcName);
|
||||
|
||||
/*
|
||||
* Retrieve the module name and optionally the module size.
|
||||
* -- pProcess
|
||||
* -- vaModuleBase
|
||||
* -- fOnFailDummyName
|
||||
* -- pbModuleHeaderOpt
|
||||
* -- szModuleName
|
||||
* -- pdwSize
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL PE_GetModuleNameEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ BOOL fOnFailDummyName, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt, _Out_writes_(MAX_PATH) PCHAR szModuleName, _Out_opt_ PDWORD pdwSize);
|
||||
_Success_(return)
|
||||
inline BOOL PE_GetModuleName(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _Out_writes_(MAX_PATH) PCHAR szModuleName)
|
||||
{
|
||||
return PE_GetModuleNameEx(pProcess, vaModuleBase, FALSE, NULL, szModuleName, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the number of sections in the module given by either the module base
|
||||
* virtual address or a pre-retrieved pbModuleHeader of size 0x1000.
|
||||
* -- pProcess
|
||||
* -- vaModuleBase = PE module base address (unless pbModuleHeaderOpt is specified)
|
||||
* -- pbModuleHeaderOpt = Optional buffer containing module header (MZ) page.
|
||||
* -- return = success: number of sections. fail: 0.
|
||||
*/
|
||||
WORD PE_SectionGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt);
|
||||
inline WORD PE_SectionGetNumberOf(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase)
|
||||
{
|
||||
return PE_SectionGetNumberOfEx(pProcess, vaModuleBase, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a single section header given its name.
|
||||
* -- pProcess
|
||||
* -- vaModuleBase
|
||||
* -- szSectionName
|
||||
* -- pSection
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL PE_SectionGetFromName(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR szSectionName, _Out_ PIMAGE_SECTION_HEADER pSection);
|
||||
|
||||
/*
|
||||
* Retrieve the number of export address table (EAT) entries - i.e. the number
|
||||
* of functions that the module is exporting.
|
||||
* -- pProcess
|
||||
* -- vaModuleBase = PE module base address (unless pbModuleHeaderOpt is specified)
|
||||
* -- pbModuleHaderOpt = Optional buffer containing module header (MZ) page.
|
||||
* -- return = success: number of entries. fail: 0.
|
||||
*/
|
||||
DWORD PE_EatGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt);
|
||||
inline DWORD PE_EatGetNumberOf(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase)
|
||||
{
|
||||
return PE_EatGetNumberOfEx(pProcess, vaModuleBase, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the number of import address table (IAT) entries - i.e. the number
|
||||
* of functions that the module is importing.
|
||||
* -- pProcess
|
||||
* -- vaModuleBase = PE module base address (unless pbModuleHeaderOpt is specified)
|
||||
* -- pbModuleHaderOpt = Optional buffer containing module header (MZ) page.
|
||||
* -- return = success: number of entries. fail: 0.
|
||||
*/
|
||||
DWORD PE_IatGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt);
|
||||
inline DWORD PE_IatGetNumberOf(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase)
|
||||
{
|
||||
return PE_IatGetNumberOfEx(pProcess, vaModuleBase, NULL);
|
||||
}
|
||||
|
||||
#endif /* __PE_H__ */
|
||||
@@ -77,7 +77,7 @@ PHANDLE PluginManager_ProcCacheGet(_Inout_ PPLUGIN_LISTENTRY pModule, _In_ DWORD
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID PluginManager_ContextInitialize(_Inout_ PVMMDLL_PLUGIN_CONTEXT ctx, PPLUGIN_LISTENTRY pModule, _In_opt_ PVMM_PROCESS pProcess, _In_ LPSTR szPath, _In_ BOOL fDll)
|
||||
VOID PluginManager_ContextInitialize(_Out_ PVMMDLL_PLUGIN_CONTEXT ctx, PPLUGIN_LISTENTRY pModule, _In_opt_ PVMM_PROCESS pProcess, _In_ LPSTR szPath, _In_ BOOL fDll)
|
||||
{
|
||||
ctx->magic = VMMDLL_PLUGIN_CONTEXT_MAGIC;
|
||||
ctx->wVersion = VMMDLL_PLUGIN_CONTEXT_VERSION;
|
||||
@@ -289,14 +289,15 @@ VOID PluginManager_Close()
|
||||
}
|
||||
}
|
||||
|
||||
VOID PluginManager_Initialize_RegInfoInit(_Inout_ PVMMDLL_PLUGIN_REGINFO pRI, _In_opt_ HMODULE hDLL)
|
||||
VOID PluginManager_Initialize_RegInfoInit(_Out_ PVMMDLL_PLUGIN_REGINFO pRI, _In_opt_ HMODULE hDLL)
|
||||
{
|
||||
ZeroMemory(pRI, sizeof(VMMDLL_PLUGIN_REGINFO));
|
||||
pRI->magic = VMMDLL_PLUGIN_REGINFO_MAGIC;
|
||||
pRI->wVersion = VMMDLL_PLUGIN_REGINFO_VERSION;
|
||||
pRI->wSize = sizeof(VMMDLL_PLUGIN_REGINFO);
|
||||
pRI->hDLL = hDLL;
|
||||
pRI->fTargetSystem = ctxVmm->fTargetSystem;
|
||||
pRI->tpMemoryModel = ctxVmm->tpMemoryModel;
|
||||
pRI->tpSystem = ctxVmm->tpSystem;
|
||||
pRI->pfnPluginManager_Register = PluginManager_Register;
|
||||
}
|
||||
|
||||
|
||||
16
vmm/util.c
16
vmm/util.c
@@ -16,7 +16,13 @@ QWORD Util_GetNumeric(_In_ LPSTR sz)
|
||||
|
||||
#define Util_2HexChar(x) (((((x) & 0xf) <= 9) ? '0' : ('a' - 10)) + ((x) & 0xf))
|
||||
|
||||
BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Inout_ PDWORD pcsz)
|
||||
#define UTIL_PRINTASCII \
|
||||
"................................ !\"#$%&'()*+,-./0123456789:;<=>?" \
|
||||
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz`{|}~" \
|
||||
"................................................................" \
|
||||
"................................................................" \
|
||||
|
||||
BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz)
|
||||
{
|
||||
DWORD i, j, o = 0, szMax, iMod;
|
||||
// checks
|
||||
@@ -59,7 +65,7 @@ BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset,
|
||||
if(j >= cb) {
|
||||
sz[o++] = ' ';
|
||||
} else {
|
||||
sz[o++] = (isprint(pb[j]) ? (CHAR)pb[j] : '.');
|
||||
sz[o++] = UTIL_PRINTASCII[pb[j]];
|
||||
}
|
||||
}
|
||||
sz[o++] = '\n';
|
||||
@@ -84,7 +90,7 @@ VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset
|
||||
LocalFree(sz);
|
||||
}
|
||||
|
||||
VOID Util_PathSplit2(_In_ LPSTR sz, _Inout_ CHAR _szBuf[MAX_PATH], _Out_ LPSTR *psz1, _Out_ LPSTR *psz2)
|
||||
VOID Util_PathSplit2(_In_ LPSTR sz, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2)
|
||||
{
|
||||
DWORD i;
|
||||
strcpy_s(_szBuf, MAX_PATH, sz);
|
||||
@@ -102,7 +108,7 @@ VOID Util_PathSplit2(_In_ LPSTR sz, _Inout_ CHAR _szBuf[MAX_PATH], _Out_ LPSTR *
|
||||
}
|
||||
}
|
||||
|
||||
VOID Util_PathSplit2_WCHAR(_In_ LPWSTR wsz, _Inout_ CHAR _szBuf[MAX_PATH], _Out_ LPSTR *psz1, _Out_ LPSTR *psz2)
|
||||
VOID Util_PathSplit2_WCHAR(_In_ LPWSTR wsz, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2)
|
||||
{
|
||||
DWORD i;
|
||||
for(i = 0; i < MAX_PATH; i++) {
|
||||
@@ -124,7 +130,7 @@ VOID Util_PathSplit2_WCHAR(_In_ LPWSTR wsz, _Inout_ CHAR _szBuf[MAX_PATH], _Out_
|
||||
}
|
||||
}
|
||||
|
||||
VOID Util_GetPathDll(_Out_ CHAR szPath[MAX_PATH], _In_opt_ HMODULE hModule)
|
||||
VOID Util_GetPathDll(_Out_writes_(MAX_PATH) PCHAR szPath, _In_opt_ HMODULE hModule)
|
||||
{
|
||||
SIZE_T i;
|
||||
GetModuleFileNameA(hModule, szPath, MAX_PATH - 4);
|
||||
|
||||
@@ -32,7 +32,7 @@ VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset
|
||||
* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
|
||||
* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
|
||||
*/
|
||||
BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Inout_ PDWORD pcsz);
|
||||
BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
|
||||
|
||||
/*
|
||||
* Split a "path" string into two at the first '\' character. If no 2nd string
|
||||
@@ -42,7 +42,7 @@ BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset,
|
||||
* -- psz1
|
||||
* -- psz2
|
||||
*/
|
||||
VOID Util_PathSplit2(_In_ LPSTR sz, _Inout_ CHAR _szBuf[MAX_PATH], _Out_ LPSTR *psz1, _Out_ LPSTR *psz2);
|
||||
VOID Util_PathSplit2(_In_ LPSTR sz, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2);
|
||||
|
||||
/*
|
||||
* Split a "path" string into two at the first '\' character. If no 2nd string
|
||||
@@ -52,14 +52,14 @@ VOID Util_PathSplit2(_In_ LPSTR sz, _Inout_ CHAR _szBuf[MAX_PATH], _Out_ LPSTR *
|
||||
* -- psz1
|
||||
* -- psz2
|
||||
*/
|
||||
VOID Util_PathSplit2_WCHAR(_In_ LPWSTR wsz, _Inout_ CHAR _szBuf[MAX_PATH], _Out_ LPSTR *psz1, _Out_ LPSTR *psz2);
|
||||
VOID Util_PathSplit2_WCHAR(_In_ LPWSTR wsz, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2);
|
||||
|
||||
/*
|
||||
* Return the path of the specified hModule (DLL) - ending with a backslash, or current Executable.
|
||||
* -- szPath
|
||||
* -- hModule = Optional, HMODULE handle for path to DLL, NULL for path to EXE.
|
||||
*/
|
||||
VOID Util_GetPathDll(_Out_ CHAR szPath[MAX_PATH], _In_opt_ HMODULE hModule);
|
||||
VOID Util_GetPathDll(_Out_writes_(MAX_PATH) PCHAR szPath, _In_opt_ HMODULE hModule);
|
||||
|
||||
/*
|
||||
* Utility functions for read/write towards different underlying data representations.
|
||||
|
||||
74
vmm/vmm.c
74
vmm/vmm.c
@@ -5,7 +5,9 @@
|
||||
//
|
||||
|
||||
#include "vmm.h"
|
||||
#include "vmmx64.h"
|
||||
#include "mm_x86.h"
|
||||
#include "mm_x86pae.h"
|
||||
#include "mm_x64.h"
|
||||
#include "vmmproc.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "device.h"
|
||||
@@ -242,20 +244,24 @@ PVMM_PROCESS VmmProcessGet(_In_ DWORD dwPID)
|
||||
return VmmProcessGetEx(ctxVmm->ptPROC, dwPID);
|
||||
}
|
||||
|
||||
PVMM_PROCESS VmmProcessCreateEntry(_In_ DWORD dwPID, _In_ DWORD dwState, _In_ QWORD paPML4, _In_ QWORD paPML4_UserOpt, _In_ CHAR szName[16], _In_ BOOL fUserOnly, _In_ BOOL fSpiderPageTableDone)
|
||||
PVMM_PROCESS VmmProcessCreateEntry(_In_ DWORD dwPID, _In_ DWORD dwState, _In_ QWORD paDTB, _In_ QWORD paDTB_UserOpt, _In_ CHAR szName[16], _In_ BOOL fUserOnly, _In_ BOOL fSpiderPageTableDone)
|
||||
{
|
||||
QWORD i, iStart, cEmpty = 0, cValid = 0;
|
||||
PVMM_PROCESS pNewProcess;
|
||||
PBYTE pbPML4;
|
||||
PBYTE pbDTB;
|
||||
// 1: Sanity check PML4
|
||||
pbPML4 = VmmTlbGetPageTable(paPML4, FALSE);
|
||||
if(!pbPML4) { return NULL; }
|
||||
if(!VmmTlbPageTableVerify(pbPML4, paPML4, (ctxVmm->fTargetSystem & VMM_TARGET_WINDOWS_X64))) { return NULL; }
|
||||
pbDTB = VmmTlbGetPageTable(paDTB, FALSE);
|
||||
if(!pbDTB) { return NULL; }
|
||||
if(!VmmTlbPageTableVerify(pbDTB, paDTB, (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64))) { return NULL; }
|
||||
// 2: Allocate new PID table (if not already existing)
|
||||
if(ctxVmm->ptPROC->ptNew == NULL) {
|
||||
if(!(ctxVmm->ptPROC->ptNew = LocalAlloc(LMEM_ZEROINIT, sizeof(VMM_PROCESS_TABLE)))) { return NULL; }
|
||||
}
|
||||
// 3: Prepare existing item, or create new item, for new PID
|
||||
// 3: Sanity check - process to create not already in 'new' table.
|
||||
if(VmmProcessGetEx(ctxVmm->ptPROC->ptNew, dwPID)) {
|
||||
return NULL;
|
||||
}
|
||||
// 4: Prepare existing item, or create new item, for new PID
|
||||
pNewProcess = VmmProcessGetEx(ctxVmm->ptPROC, dwPID);
|
||||
if(!pNewProcess) {
|
||||
if(!(pNewProcess = LocalAlloc(LMEM_ZEROINIT, sizeof(VMM_PROCESS)))) { return NULL; }
|
||||
@@ -263,12 +269,12 @@ PVMM_PROCESS VmmProcessCreateEntry(_In_ DWORD dwPID, _In_ DWORD dwState, _In_ QW
|
||||
memcpy(pNewProcess->szName, szName, 16);
|
||||
pNewProcess->dwPID = dwPID;
|
||||
pNewProcess->dwState = dwState;
|
||||
pNewProcess->paPML4 = paPML4;
|
||||
pNewProcess->paPML4_UserOpt = paPML4_UserOpt;
|
||||
pNewProcess->paDTB = paDTB;
|
||||
pNewProcess->paDTB_UserOpt = paDTB_UserOpt;
|
||||
pNewProcess->fUserOnly = fUserOnly;
|
||||
pNewProcess->fSpiderPageTableDone = pNewProcess->fSpiderPageTableDone || fSpiderPageTableDone;
|
||||
pNewProcess->_i_fMigrated = TRUE;
|
||||
// 4: Install new PID
|
||||
// 5: Install new PID
|
||||
i = iStart = dwPID % VMM_PROCESSTABLE_ENTRIES_MAX;
|
||||
while(TRUE) {
|
||||
if(!ctxVmm->ptPROC->ptNew->M[i]) {
|
||||
@@ -339,7 +345,7 @@ VOID VmmProcessCreateFinish()
|
||||
}
|
||||
}
|
||||
|
||||
VOID VmmProcessListPIDs(_Out_ PDWORD pPIDs, _Inout_ PSIZE_T pcPIDs)
|
||||
VOID VmmProcessListPIDs(_Out_opt_ PDWORD pPIDs, _Inout_ PSIZE_T pcPIDs)
|
||||
{
|
||||
DWORD i = 0;
|
||||
WORD iProcess;
|
||||
@@ -413,7 +419,7 @@ VOID VmmWriteScatterPhysical(_Inout_ PPMEM_IO_SCATTER_HEADER ppDMAsPhys, _In_ DW
|
||||
}
|
||||
}
|
||||
|
||||
BOOL VmmWritePhysical(_In_ QWORD pa, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
BOOL VmmWritePhysical(_In_ QWORD pa, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
QWORD paPage;
|
||||
// 1: invalidate any physical pages from cache
|
||||
@@ -573,8 +579,8 @@ VOID VmmClose()
|
||||
}
|
||||
}
|
||||
VmmProcessCloseTable(ctxVmm->ptPROC, TRUE);
|
||||
if(ctxVmm->MemoryModel.pfnClose) {
|
||||
ctxVmm->MemoryModel.pfnClose();
|
||||
if(ctxVmm->fnMemoryModel.pfnClose) {
|
||||
ctxVmm->fnMemoryModel.pfnClose();
|
||||
}
|
||||
VmmCacheClose(ctxVmm->ptTLB);
|
||||
VmmCacheClose(ctxVmm->ptPHYS);
|
||||
@@ -583,7 +589,7 @@ VOID VmmClose()
|
||||
ctxVmm = NULL;
|
||||
}
|
||||
|
||||
VOID VmmWriteEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbWrite)
|
||||
VOID VmmWriteEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _In_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbWrite)
|
||||
{
|
||||
DWORD i = 0, oVA = 0, cbWrite = 0, cbP, cDMAs;
|
||||
PBYTE pbBuffer;
|
||||
@@ -598,6 +604,7 @@ VOID VmmWriteEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ PBYTE pb,
|
||||
// prepare pages
|
||||
while(oVA < cb) {
|
||||
ppDMAs[i] = &pDMAs[i];
|
||||
pDMAs[i].version = MEM_IO_SCATTER_HEADER_VERSION;
|
||||
pDMAs[i].qwA = qwVA + oVA;
|
||||
cbP = 0x1000 - ((qwVA + oVA) & 0xfff);
|
||||
cbP = min(cbP, cb - oVA);
|
||||
@@ -621,14 +628,14 @@ VOID VmmWriteEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ PBYTE pb,
|
||||
LocalFree(pbBuffer);
|
||||
}
|
||||
|
||||
BOOL VmmWrite(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
BOOL VmmWrite(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
DWORD cbWrite;
|
||||
VmmWriteEx(pProcess, qwVA, pb, cb, &cbWrite);
|
||||
return (cbWrite == cb);
|
||||
}
|
||||
|
||||
VOID VmmReadEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ QWORD flags)
|
||||
VOID VmmReadEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ QWORD flags)
|
||||
{
|
||||
DWORD cbP, cDMAs, cbRead = 0;
|
||||
PBYTE pbBuffer;
|
||||
@@ -645,6 +652,7 @@ VOID VmmReadEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Inout_ PBYTE pb
|
||||
// prepare "middle" pages
|
||||
for(i = 0; i < cDMAs; i++) {
|
||||
ppDMAs[i] = &pDMAs[i];
|
||||
pDMAs[i].version = MEM_IO_SCATTER_HEADER_VERSION;
|
||||
pDMAs[i].qwA = qwVA - oVA + (i << 12);
|
||||
pDMAs[i].cbMax = 0x1000;
|
||||
pDMAs[i].pb = pb - oVA + (i << 12);
|
||||
@@ -691,18 +699,21 @@ VOID VmmReadEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Inout_ PBYTE pb
|
||||
LocalFree(pbBuffer);
|
||||
}
|
||||
|
||||
BOOL VmmReadString_Unicode2Ansi(_In_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ LPSTR sz, _In_ DWORD cch)
|
||||
_Success_(return)
|
||||
BOOL VmmReadString_Unicode2Ansi(_In_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_writes_(cch) LPSTR sz, _In_ DWORD cch)
|
||||
{
|
||||
DWORD i = 0;
|
||||
BOOL result;
|
||||
WCHAR wsz[0x1000];
|
||||
if(cch > 0x1000) { return FALSE; }
|
||||
if(cch) { sz[0] = 0; }
|
||||
if(!cch || cch > 0x1000) { return FALSE; }
|
||||
result = VmmRead(pProcess, qwVA, (PBYTE)wsz, cch << 1);
|
||||
if(!result) { return FALSE; }
|
||||
for(i = 0; i < cch; i++) {
|
||||
sz[i] = ((WORD)wsz[i] <= 0xff) ? (CHAR)wsz[i] : '?';
|
||||
for(i = 0; i < cch - 1; i++) {
|
||||
sz[i] = (CHAR)(((WORD)wsz[i] <= 0xff) ? wsz[i] : '?');
|
||||
if(sz[i] == 0) { return TRUE; }
|
||||
}
|
||||
sz[cch - 1] = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -720,6 +731,25 @@ BOOL VmmReadPage(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwA, _Inout_bytecoun
|
||||
return cb == 0x1000;
|
||||
}
|
||||
|
||||
VOID VmmInitializeMemoryModel(_In_ VMM_MEMORYMODEL_TP tp)
|
||||
{
|
||||
switch(tp) {
|
||||
case VMM_MEMORYMODEL_X64:
|
||||
MmX64_Initialize();
|
||||
break;
|
||||
case VMM_MEMORYMODEL_X86PAE:
|
||||
MmX86PAE_Initialize();
|
||||
break;
|
||||
case VMM_MEMORYMODEL_X86:
|
||||
MmX86_Initialize();
|
||||
break;
|
||||
default:
|
||||
if(ctxVmm->fnMemoryModel.pfnClose) {
|
||||
ctxVmm->fnMemoryModel.pfnClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL VmmInitialize()
|
||||
{
|
||||
// 1: allocate & initialize
|
||||
@@ -738,8 +768,6 @@ BOOL VmmInitialize()
|
||||
// 5: OTHER INIT:
|
||||
ctxVmm->fReadOnly = (ctxMain->dev.tp == VMM_DEVICE_FILE);
|
||||
InitializeCriticalSection(&ctxVmm->MasterLock);
|
||||
// 6: MEMORY MODEL INIT: (x64)
|
||||
VmmX64_Initialize();
|
||||
return TRUE;
|
||||
fail:
|
||||
VmmClose();
|
||||
|
||||
174
vmm/vmm.h
174
vmm/vmm.h
@@ -10,6 +10,8 @@
|
||||
|
||||
typedef unsigned __int64 QWORD, *PQWORD;
|
||||
|
||||
#define MEM_IO_SCATTER_HEADER_VERSION 2
|
||||
|
||||
typedef struct tdMEM_IO_SCATTER_HEADER {
|
||||
ULONG64 qwA; // base address (DWORD boundry).
|
||||
DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pbResult must have room for this.
|
||||
@@ -17,6 +19,10 @@ typedef struct tdMEM_IO_SCATTER_HEADER {
|
||||
PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
|
||||
PVOID pvReserved1; // reserved for use by caller.
|
||||
PVOID pvReserved2; // reserved for use by caller.
|
||||
WORD version; // version of struct
|
||||
WORD Future1; // reserved for future use.
|
||||
DWORD Future2; // reserved for future use.
|
||||
ULONG64 qwDeviceA; // device-physical address (used by device layer).
|
||||
struct {
|
||||
PVOID pvReserved1;
|
||||
PVOID pvReserved2;
|
||||
@@ -49,14 +55,28 @@ typedef struct tdMEM_IO_SCATTER_HEADER {
|
||||
|
||||
#define VMM_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
|
||||
#define VMM_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
|
||||
|
||||
#define VMM_TARGET_UNKNOWN_X64 0x0001
|
||||
#define VMM_TARGET_WINDOWS_X64 0x0002
|
||||
#define VMM_FLAG_PROCESS_SHOW_TERMINATED 0x0004 // show terminated processes in the process list (if they can be found).
|
||||
|
||||
#define VMM_VERSION_MAJOR 1
|
||||
#define VMM_VERSION_MINOR 1
|
||||
#define VMM_VERSION_MINOR 2
|
||||
#define VMM_VERSION_REVISION 0
|
||||
|
||||
static const LPSTR VMM_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
|
||||
|
||||
typedef enum tdVMM_MEMORYMODEL_TP {
|
||||
VMM_MEMORYMODEL_NA = 0,
|
||||
VMM_MEMORYMODEL_X86 = 1,
|
||||
VMM_MEMORYMODEL_X86PAE = 2,
|
||||
VMM_MEMORYMODEL_X64 = 3
|
||||
} VMM_MEMORYMODEL_TP;
|
||||
|
||||
typedef enum tdVMM_SYSTEM_TP {
|
||||
VMM_SYSTEM_UNKNOWN_X64 = 1,
|
||||
VMM_SYSTEM_WINDOWS_X64 = 2,
|
||||
VMM_SYSTEM_UNKNOWN_X86 = 3,
|
||||
VMM_SYSTEM_WINDOWS_X86 = 4
|
||||
} VMM_SYSTEM_TP;
|
||||
|
||||
typedef struct tdVMM_MEMMAP_ENTRY {
|
||||
QWORD AddrBase;
|
||||
QWORD cPages;
|
||||
@@ -82,8 +102,8 @@ typedef struct tdVMM_MODULEMAP_ENTRY {
|
||||
typedef struct tdVMM_PROCESS {
|
||||
DWORD dwPID;
|
||||
DWORD dwState; // state of process, 0 = running
|
||||
QWORD paPML4;
|
||||
QWORD paPML4_UserOpt;
|
||||
QWORD paDTB;
|
||||
QWORD paDTB_UserOpt;
|
||||
CHAR szName[16];
|
||||
BOOL _i_fMigrated;
|
||||
BOOL fUserOnly;
|
||||
@@ -142,29 +162,18 @@ typedef struct tdVMM_CACHE_TABLE {
|
||||
PVMM_CACHE_ENTRY S;
|
||||
} VMM_CACHE_TABLE, *PVMM_CACHE_TABLE;
|
||||
|
||||
typedef enum tdVMM_MEMORYMODEL_TP {
|
||||
NA = 0,
|
||||
X64 = 1
|
||||
} tdVMM_MEMORYMODEL_TP;
|
||||
|
||||
typedef struct tdVMM_VIRT2PHYS_INFORMATION {
|
||||
tdVMM_MEMORYMODEL_TP tpMemoryModel;
|
||||
VMM_MEMORYMODEL_TP tpMemoryModel;
|
||||
QWORD va;
|
||||
union {
|
||||
struct {
|
||||
QWORD pas[5]; // physical addresses of pagetable[PML]/page[0]
|
||||
QWORD PTEs[5]; // PTEs[PML]
|
||||
WORD iPTEs[5]; // Index of PTE in page table
|
||||
} x64;
|
||||
};
|
||||
QWORD pas[5]; // physical addresses of pagetable[PML]/page[0]
|
||||
QWORD PTEs[5]; // PTEs[PML]
|
||||
WORD iPTEs[5]; // Index of PTE in page table
|
||||
} VMM_VIRT2PHYS_INFORMATION, *PVMM_VIRT2PHYS_INFORMATION;
|
||||
|
||||
typedef struct tdVMM_MEMORYMODEL {
|
||||
tdVMM_MEMORYMODEL_TP tp;
|
||||
typedef struct tdVMM_MEMORYMODEL_FUNCTIONS {
|
||||
VOID(*pfnInitialize)();
|
||||
VOID(*pfnClose)();
|
||||
BOOL(*pfnVirt2Phys)(_In_ PVMM_PROCESS pProcess, _In_ QWORD va, _Out_ PQWORD ppa);
|
||||
BOOL(*pfnVirt2PhysEx)(_In_ BOOL fUserOnly, _In_ QWORD va, _In_ BYTE iPML, _In_reads_(4096) PBYTE pbPTEs, _Out_ PQWORD ppa);
|
||||
BOOL(*pfnVirt2Phys)(_In_ QWORD paDTB, _In_ BOOL fUserOnly, _In_ BYTE iPML, _In_ QWORD va, _Out_ PQWORD ppa);
|
||||
VOID(*pfnVirt2PhysGetInformation)(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo);
|
||||
VOID(*pfnMapInitialize)(_In_ PVMM_PROCESS pProcess);
|
||||
VOID(*pfnMapTag)(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_opt_ BOOL fWoW64);
|
||||
@@ -172,7 +181,7 @@ typedef struct tdVMM_MEMORYMODEL {
|
||||
VOID(*pfnMapDisplayBufferGenerate)(_In_ PVMM_PROCESS pProcess);
|
||||
VOID(*pfnTlbSpider)(_In_ QWORD paDTB, _In_ BOOL fUserOnly);
|
||||
BOOL(*pfnTlbPageTableVerify)(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq);
|
||||
} VMM_MEMORYMODEL;
|
||||
} VMM_MEMORYMODEL_FUNCTIONS;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// VMM general constants and struct definitions below:
|
||||
@@ -192,17 +201,17 @@ typedef struct tdVmmConfig {
|
||||
BOOL fVerboseExtraTlp;
|
||||
} VMMCONFIG, *PVMMCONFIG;
|
||||
|
||||
typedef enum tdMPFS_DEVICE_TYPE {
|
||||
typedef enum tdVMM_DEVICE_TYPE {
|
||||
VMM_DEVICE_NA,
|
||||
VMM_DEVICE_FILE,
|
||||
VMM_DEVICE_PCILEECH_DLL,
|
||||
} MPFS_DEVICE_TYPE;
|
||||
} VMM_DEVICE_TYPE;
|
||||
|
||||
typedef struct tdVmmDeviceConfig {
|
||||
HANDLE hDevice;
|
||||
QWORD paAddrMaxNative;
|
||||
QWORD qwMaxSizeMemIo;
|
||||
MPFS_DEVICE_TYPE tp;
|
||||
VMM_DEVICE_TYPE tp;
|
||||
VOID(*pfnReadScatterMEM)(_Inout_ PPMEM_IO_SCATTER_HEADER ppDMAs, _In_ DWORD cpDMAs, _Out_opt_ PDWORD pcpDMAsRead);
|
||||
BOOL(*pfnWriteMEM)(_In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
VOID(*pfnClose)();
|
||||
@@ -224,16 +233,27 @@ typedef struct tdVMM_STATISTICS {
|
||||
QWORD cRefreshProcessFull;
|
||||
} VMM_STATISTICS, *PVMM_STATISTICS;
|
||||
|
||||
typedef struct tdVMM_KERNELINFO {
|
||||
QWORD paDTB;
|
||||
QWORD vaBase;
|
||||
QWORD cbSize;
|
||||
// optional non-required values below
|
||||
QWORD vaEntry;
|
||||
QWORD vaPsLoadedModuleList;
|
||||
QWORD vaKDBG;
|
||||
} VMM_KERNELINFO;
|
||||
|
||||
typedef struct tdVMM_CONTEXT {
|
||||
CRITICAL_SECTION MasterLock;
|
||||
PVMM_PROCESS_TABLE ptPROC;
|
||||
PVMM_CACHE_TABLE ptTLB;
|
||||
PVMM_CACHE_TABLE ptPHYS;
|
||||
BOOL fReadOnly;
|
||||
VMM_MEMORYMODEL MemoryModel;
|
||||
// os specific below:
|
||||
DWORD fTargetSystem;
|
||||
DWORD flags;
|
||||
VMM_MEMORYMODEL_FUNCTIONS fnMemoryModel;
|
||||
VMM_MEMORYMODEL_TP tpMemoryModel;
|
||||
BOOL f32;
|
||||
VMM_SYSTEM_TP tpSystem;
|
||||
DWORD flags; // VMM_FLAG_*
|
||||
struct {
|
||||
BOOL fEnabled;
|
||||
HANDLE hThread;
|
||||
@@ -244,11 +264,8 @@ typedef struct tdVMM_CONTEXT {
|
||||
DWORD cTick_ProcTotal;
|
||||
} ThreadProcCache;
|
||||
VMM_STATISTICS stat;
|
||||
VMM_KERNELINFO kernel;
|
||||
PVOID pVmmVfsModuleList;
|
||||
struct {
|
||||
QWORD paDTB;
|
||||
QWORD vaBase;
|
||||
} kernelinfo;
|
||||
} VMM_CONTEXT, *PVMM_CONTEXT;
|
||||
|
||||
typedef struct tdVMM_MAIN_CONTEXT {
|
||||
@@ -301,7 +318,7 @@ VOID VmmLockRelease();
|
||||
* -- cb
|
||||
* -- return = TRUE on success, FALSE on partial or zero write.
|
||||
*/
|
||||
BOOL VmmWrite(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
BOOL VmmWrite(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Write physical memory and clear any VMM caches that may contain data.
|
||||
@@ -310,19 +327,20 @@ BOOL VmmWrite(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ PBYTE pb, _
|
||||
* -- cb
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmWritePhysical(_In_ QWORD pa, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
BOOL VmmWritePhysical(_In_ QWORD pa, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Read a virtually contigious arbitrary amount of memory containing cch number of
|
||||
* unicode characters and convert them into ansi characters. Characters > 0xff are
|
||||
* converted into '?'.
|
||||
* converted into '?'. The result is guaranteed to be zero-terminated.
|
||||
* -- pProcess
|
||||
* -- qwVA
|
||||
* -- sz
|
||||
* -- cch
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmReadString_Unicode2Ansi(_In_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ LPSTR sz, _In_ DWORD cch);
|
||||
_Success_(return)
|
||||
BOOL VmmReadString_Unicode2Ansi(_In_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_writes_(cch) LPSTR sz, _In_ DWORD cch);
|
||||
|
||||
/*
|
||||
* Read a contigious arbitrary amount of memory, virtual or physical.
|
||||
@@ -348,7 +366,7 @@ BOOL VmmRead(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwA, _Out_ PBYTE pb, _In
|
||||
* -- pcbRead
|
||||
* -- flags = flags as in VMM_FLAG_*
|
||||
*/
|
||||
VOID VmmReadEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ QWORD flags);
|
||||
VOID VmmReadEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ QWORD flags);
|
||||
|
||||
/*
|
||||
* Read a single 4096-byte page of memory, virtual or physical.
|
||||
@@ -394,6 +412,21 @@ BOOL VmmReadPhysicalPage(_In_ QWORD qwPA, _Inout_bytecount_(4096) PBYTE pbPage);
|
||||
*/
|
||||
PBYTE VmmTlbGetPageTable(_In_ QWORD pa, _In_ BOOL fCacheOnly);
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address by walking the page tables.
|
||||
* -- paDTB
|
||||
* -- fUserOnly
|
||||
* -- va
|
||||
* -- ppa
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
inline BOOL VmmVirt2PhysEx(_In_ QWORD paDTB, _In_ BOOL fUserOnly, _In_ QWORD va, _Out_ PQWORD ppa)
|
||||
{
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return FALSE; }
|
||||
return ctxVmm->fnMemoryModel.pfnVirt2Phys(paDTB, fUserOnly, -1, va, ppa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address by walking the page tables.
|
||||
* -- pProcess
|
||||
@@ -404,25 +437,8 @@ PBYTE VmmTlbGetPageTable(_In_ QWORD pa, _In_ BOOL fCacheOnly);
|
||||
_Success_(return)
|
||||
inline BOOL VmmVirt2Phys(_In_ PVMM_PROCESS pProcess, _In_ QWORD va, _Out_ PQWORD ppa)
|
||||
{
|
||||
if(ctxVmm->MemoryModel.tp == NA) { return FALSE; }
|
||||
return ctxVmm->MemoryModel.pfnVirt2Phys(pProcess, va, ppa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address given some extra parameters as
|
||||
* as compared to the standard recommended function VmmVirt2Phys.
|
||||
* -- fUserOnly
|
||||
* -- va
|
||||
* -- iPML = index of page table (-1 = topmost) (Example: PML4 = 4, PDPT = 3 .. in X64).
|
||||
* -- PTEs
|
||||
* -- ppa
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
inline BOOL VmmVirt2PhysEx(_In_ BOOL fUserOnly, _In_ QWORD va, _In_ BYTE iPML, _In_reads_(4096) PBYTE pbPTEs, _Out_ PQWORD ppa)
|
||||
{
|
||||
if(ctxVmm->MemoryModel.tp == NA) { return FALSE; }
|
||||
return ctxVmm->MemoryModel.pfnVirt2PhysEx(fUserOnly, va, iPML, pbPTEs, ppa);
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return FALSE; }
|
||||
return ctxVmm->fnMemoryModel.pfnVirt2Phys(pProcess->paDTB, pProcess->fUserOnly, -1, va, ppa);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -435,8 +451,8 @@ inline BOOL VmmVirt2PhysEx(_In_ BOOL fUserOnly, _In_ QWORD va, _In_ BYTE iPML, _
|
||||
*/
|
||||
inline VOID VmmTlbSpider(_In_ QWORD paDTB, _In_ BOOL fUserOnly)
|
||||
{
|
||||
if(ctxVmm->MemoryModel.tp == NA) { return; }
|
||||
ctxVmm->MemoryModel.pfnTlbSpider(paDTB, fUserOnly);
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return; }
|
||||
ctxVmm->fnMemoryModel.pfnTlbSpider(paDTB, fUserOnly);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -447,8 +463,8 @@ inline VOID VmmTlbSpider(_In_ QWORD paDTB, _In_ BOOL fUserOnly)
|
||||
*/
|
||||
inline BOOL VmmTlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq)
|
||||
{
|
||||
if(ctxVmm->MemoryModel.tp == NA) { return FALSE; }
|
||||
return ctxVmm->MemoryModel.pfnTlbPageTableVerify(pb, pa, fSelfRefReq);
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return FALSE; }
|
||||
return ctxVmm->fnMemoryModel.pfnTlbPageTableVerify(pb, pa, fSelfRefReq);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -460,8 +476,8 @@ inline BOOL VmmTlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSe
|
||||
*/
|
||||
inline VOID VmmVirt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo)
|
||||
{
|
||||
if(ctxVmm->MemoryModel.tp == NA) { return; }
|
||||
ctxVmm->MemoryModel.pfnVirt2PhysGetInformation(pProcess, pVirt2PhysInfo);
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return; }
|
||||
ctxVmm->fnMemoryModel.pfnVirt2PhysGetInformation(pProcess, pVirt2PhysInfo);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -471,8 +487,8 @@ inline VOID VmmVirt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PV
|
||||
*/
|
||||
inline VOID VmmMapInitialize(_In_ PVMM_PROCESS pProcess)
|
||||
{
|
||||
if(ctxVmm->MemoryModel.tp == NA) { return; }
|
||||
ctxVmm->MemoryModel.pfnMapInitialize(pProcess);
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return; }
|
||||
ctxVmm->fnMemoryModel.pfnMapInitialize(pProcess);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -487,8 +503,8 @@ inline VOID VmmMapInitialize(_In_ PVMM_PROCESS pProcess)
|
||||
*/
|
||||
inline VOID VmmMapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_opt_ BOOL fWoW64)
|
||||
{
|
||||
if(ctxVmm->MemoryModel.tp == NA) { return; }
|
||||
ctxVmm->MemoryModel.pfnMapTag(pProcess, vaBase, vaLimit, szTag, wszTag, fWoW64);
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return; }
|
||||
ctxVmm->fnMemoryModel.pfnMapTag(pProcess, vaBase, vaLimit, szTag, wszTag, fWoW64);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -499,8 +515,8 @@ inline VOID VmmMapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD
|
||||
*/
|
||||
inline PVMM_MEMMAP_ENTRY VmmMapGetEntry(_In_ PVMM_PROCESS pProcess, _In_ QWORD va)
|
||||
{
|
||||
if(ctxVmm->MemoryModel.tp == NA) { return NULL; }
|
||||
return ctxVmm->MemoryModel.pfnMapGetEntry(pProcess, va);
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return NULL; }
|
||||
return ctxVmm->fnMemoryModel.pfnMapGetEntry(pProcess, va);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -511,11 +527,10 @@ inline PVMM_MEMMAP_ENTRY VmmMapGetEntry(_In_ PVMM_PROCESS pProcess, _In_ QWORD v
|
||||
*/
|
||||
inline VOID VmmMapDisplayBufferGenerate(_In_ PVMM_PROCESS pProcess)
|
||||
{
|
||||
if(ctxVmm->MemoryModel.tp == NA) { return; }
|
||||
ctxVmm->MemoryModel.pfnMapDisplayBufferGenerate(pProcess);
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return; }
|
||||
ctxVmm->fnMemoryModel.pfnMapDisplayBufferGenerate(pProcess);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create or re-create the entire process table. This will clean the complete and
|
||||
* all existing processes will be cleared.
|
||||
@@ -535,7 +550,7 @@ PVMM_PROCESS VmmProcessGet(_In_ DWORD dwPID);
|
||||
* structure and won't become visible to the "Process" functions until after the
|
||||
* VmmProcessCreateFinish have been called.
|
||||
*/
|
||||
PVMM_PROCESS VmmProcessCreateEntry(_In_ DWORD dwPID, _In_ DWORD dwState, _In_ QWORD paPML4, _In_ QWORD paPML4_UserOpt, _In_ CHAR szName[16], _In_ BOOL fUserOnly, _In_ BOOL fSpiderPageTableDone);
|
||||
PVMM_PROCESS VmmProcessCreateEntry(_In_ DWORD dwPID, _In_ DWORD dwState, _In_ QWORD paDTB, _In_ QWORD paDTB_UserOpt, _In_ CHAR szName[16], _In_ BOOL fUserOnly, _In_ BOOL fSpiderPageTableDone);
|
||||
|
||||
/*
|
||||
* Activate the pending, not yet active, processes added by VmmProcessCreateEntry.
|
||||
@@ -548,7 +563,7 @@ VOID VmmProcessCreateFinish();
|
||||
* -- pPIDs = user allocated DWORD array to receive result, or NULL.
|
||||
* -- pcPIDs = ptr to number of DWORDs in pPIDs on entry - number of PIDs in system on exit.
|
||||
*/
|
||||
VOID VmmProcessListPIDs(_Out_ PDWORD pPIDs, _Inout_ PSIZE_T pcPIDs);
|
||||
VOID VmmProcessListPIDs(_Out_opt_ PDWORD pPIDs, _Inout_ PSIZE_T pcPIDs);
|
||||
|
||||
/*
|
||||
* Clear the specified cache from all entries.
|
||||
@@ -563,6 +578,13 @@ VOID VmmCacheClear( _In_ BOOL fTLB, _In_ BOOL fPHYS);
|
||||
*/
|
||||
VOID VmmCacheInvalidate( _In_ QWORD pa);
|
||||
|
||||
/*
|
||||
* Initialize the memory model specified and discard any previous memory models
|
||||
* that may be in action.
|
||||
* -- tp
|
||||
*/
|
||||
VOID VmmInitializeMemoryModel(_In_ VMM_MEMORYMODEL_TP tp);
|
||||
|
||||
/*
|
||||
* Initialize a new VMM context. This must always be done before calling any
|
||||
* other VMM functions. An alternative way to do this is to call the function:
|
||||
|
||||
@@ -99,35 +99,44 @@
|
||||
<ClInclude Include="device.h" />
|
||||
<ClInclude Include="devicefile.h" />
|
||||
<ClInclude Include="devicepcileechdll.h" />
|
||||
<ClInclude Include="mm_x64.h" />
|
||||
<ClInclude Include="mm_x86.h" />
|
||||
<ClInclude Include="mm_x86pae.h" />
|
||||
<ClInclude Include="m_ldrmodules.h" />
|
||||
<ClInclude Include="m_status.h" />
|
||||
<ClInclude Include="m_virt2phys.h" />
|
||||
<ClInclude Include="pcileech_dll.h" />
|
||||
<ClInclude Include="pe.h" />
|
||||
<ClInclude Include="pluginmanager.h" />
|
||||
<ClInclude Include="statistics.h" />
|
||||
<ClInclude Include="util.h" />
|
||||
<ClInclude Include="vmm.h" />
|
||||
<ClInclude Include="vmmdll.h" />
|
||||
<ClInclude Include="vmmproc.h" />
|
||||
<ClInclude Include="vmmproc_windows.h" />
|
||||
<ClInclude Include="vmmvfs.h" />
|
||||
<ClInclude Include="vmmx64.h" />
|
||||
<ClInclude Include="vmmwin.h" />
|
||||
<ClInclude Include="vmmwininit.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="device.c" />
|
||||
<ClCompile Include="devicefile.c" />
|
||||
<ClCompile Include="devicepcileechdll.c" />
|
||||
<ClCompile Include="mm_x64.c" />
|
||||
<ClCompile Include="mm_x86.c" />
|
||||
<ClCompile Include="mm_x86pae.c" />
|
||||
<ClCompile Include="m_ldrmodules.c" />
|
||||
<ClCompile Include="m_status.c" />
|
||||
<ClCompile Include="m_virt2phys.c" />
|
||||
<ClCompile Include="pe.c" />
|
||||
<ClCompile Include="pluginmanager.c" />
|
||||
<ClCompile Include="statistics.c" />
|
||||
<ClCompile Include="util.c" />
|
||||
<ClCompile Include="vmm.c" />
|
||||
<ClCompile Include="vmmdll.c" />
|
||||
<ClCompile Include="vmmproc.c" />
|
||||
<ClCompile Include="vmmproc_windows.c" />
|
||||
<ClCompile Include="vmmvfs.c" />
|
||||
<ClCompile Include="vmmx64.c" />
|
||||
<ClCompile Include="vmmwin.c" />
|
||||
<ClCompile Include="vmmwininit.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -59,13 +59,28 @@
|
||||
<ClInclude Include="vmmproc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vmmproc_windows.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vmmvfs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vmmx64.h">
|
||||
<ClInclude Include="mm_x64.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mm_x86.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mm_x86pae.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pe.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vmmdll.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vmmwin.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vmmwininit.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
@@ -106,13 +121,25 @@
|
||||
<ClCompile Include="vmmproc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vmmproc_windows.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vmmvfs.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vmmx64.c">
|
||||
<ClCompile Include="mm_x64.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mm_x86.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mm_x86pae.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pe.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vmmwin.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vmmwininit.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
||||
135
vmm/vmmdll.c
135
vmm/vmmdll.c
@@ -9,9 +9,10 @@
|
||||
#include "device.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "util.h"
|
||||
#include "pe.h"
|
||||
#include "vmm.h"
|
||||
#include "vmmproc.h"
|
||||
#include "vmmproc_windows.h"
|
||||
#include "vmmwin.h"
|
||||
#include "vmmvfs.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -48,6 +49,7 @@
|
||||
// INITIALIZATION FUNCTIONALITY BELOW:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
_Success_(return)
|
||||
BOOL VmmDll_ConfigIntialize(_In_ DWORD argc, _In_ char* argv[])
|
||||
{
|
||||
char* argv2[3];
|
||||
@@ -142,7 +144,7 @@ VOID VmmDll_PrintHelp()
|
||||
" The recommended way to use the Memory Process File System is to specify the \n" \
|
||||
" memory acquisition device in the -device option and possibly more options. \n" \
|
||||
" Example 1: MemProcFS.exe -device c:\\temp\\memdump-win10x64.pmem \n" \
|
||||
" Example 2: MemProcFS.exe -device c:\\temp\\memdump-win10x64.pmem -v -vv \n" \
|
||||
" Example 2: MemProcFS.exe -device c:\\temp\\memdump-winXPx86.pmem -v -vv \n" \
|
||||
" Example 3: MemProcFS.exe -device FPGA \n" \
|
||||
" The Memory Process File System may also be started the memory dump file name \n" \
|
||||
" as the only option. This allows to make file extensions associated so that \n" \
|
||||
@@ -191,6 +193,7 @@ VOID VmmDll_FreeContext()
|
||||
}
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[])
|
||||
{
|
||||
ctxMain = LocalAlloc(LMEM_ZEROINIT, sizeof(VMM_MAIN_CONTEXT));
|
||||
@@ -223,21 +226,25 @@ BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[])
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBaseOpt)
|
||||
{
|
||||
return VMMDLL_InitializeReserved(5, (LPSTR[]) { "", "-device", szFileName, "-cr3", (szPageTableBaseOpt ? szPageTableBaseOpt : "0") });
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPSTR szPageTableBaseOpt)
|
||||
{
|
||||
return VMMDLL_InitializeReserved(7, (LPSTR[]) { "", "-device", "fpga", "-cr3", (szPageTableBaseOpt ? szPageTableBaseOpt : "0", "-max", szMaxPhysicalAddressOpt) });
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeTotalMeltdown()
|
||||
{
|
||||
return VMMDLL_InitializeReserved(3, (LPSTR[]) { "", "-device", "totalmeltdown" });
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_Close()
|
||||
{
|
||||
VmmDll_FreeContext();
|
||||
@@ -248,6 +255,7 @@ BOOL VMMDLL_Close()
|
||||
// CONFIGURATION SETTINGS BELOW:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigGet_VmmCore(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue)
|
||||
{
|
||||
switch(fOption) {
|
||||
@@ -278,6 +286,7 @@ BOOL VMMDLL_ConfigGet_VmmCore(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue)
|
||||
{
|
||||
if(!pqwValue) { return FALSE; }
|
||||
@@ -319,8 +328,11 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue)
|
||||
case VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE:
|
||||
*pqwValue = ctxMain->dev.qwMaxSizeMemIo;
|
||||
return TRUE;
|
||||
case VMMDLL_OPT_CORE_TARGET_SYSTEM:
|
||||
*pqwValue = ctxVmm->fTargetSystem;
|
||||
case VMMDLL_OPT_CORE_SYSTEM:
|
||||
*pqwValue = ctxVmm->tpSystem;
|
||||
return TRUE;
|
||||
case VMMDLL_OPT_CORE_MEMORYMODEL:
|
||||
*pqwValue = ctxVmm->tpMemoryModel;
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
@@ -330,6 +342,7 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue)
|
||||
return DeviceGetOption(fOption, pqwValue);
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigSet_VmmCore(_In_ ULONG64 fOption, _In_ ULONG64 qwValue)
|
||||
{
|
||||
switch(fOption) {
|
||||
@@ -357,6 +370,7 @@ BOOL VMMDLL_ConfigSet_VmmCore(_In_ ULONG64 fOption, _In_ ULONG64 qwValue)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue)
|
||||
{
|
||||
if(!ctxVmm) { return FALSE; }
|
||||
@@ -404,6 +418,7 @@ BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue)
|
||||
// VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
@@ -461,6 +476,7 @@ NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb,
|
||||
// PLUGIN MANAGER FUNCTIONALITY BELOW:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsInitializePlugins()
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
@@ -497,7 +513,8 @@ DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPVMMDLL_MEM_IO_SCATTER_HE
|
||||
return cMEMs;
|
||||
}
|
||||
|
||||
BOOL VMMDLL_MemReadEx_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadEx_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags)
|
||||
{
|
||||
PVMM_PROCESS pProcess = NULL;
|
||||
if(dwPID != -1) {
|
||||
@@ -508,26 +525,30 @@ BOOL VMMDLL_MemReadEx_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
STATISTICS_ID_VMMDLL_MemReadEx,
|
||||
VMMDLL_MemReadEx_Impl(dwPID, qwVA, pb, cb, pcbReadOpt, flags))
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
DWORD dwRead;
|
||||
return VMMDLL_MemReadEx(dwPID, qwVA, pb, cb, &dwRead, 0) && (dwRead == cb);
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage)
|
||||
{
|
||||
DWORD dwRead;
|
||||
return VMMDLL_MemReadEx(dwPID, qwVA, pbPage, 4096, &dwRead, 0) && (dwRead == 4096);
|
||||
}
|
||||
|
||||
BOOL VMMDLL_MemWrite_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemWrite_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
PVMM_PROCESS pProcess = NULL;
|
||||
if(dwPID != -1) {
|
||||
@@ -537,13 +558,15 @@ BOOL VMMDLL_MemWrite_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _
|
||||
return VmmWrite(pProcess, qwVA, pb, cb);
|
||||
}
|
||||
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
STATISTICS_ID_VMMDLL_MemWrite,
|
||||
VMMDLL_MemWrite_Impl(dwPID, qwVA, pb, cb))
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemVirt2Phys_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA)
|
||||
{
|
||||
PVMM_PROCESS pProcess = VmmProcessGet(dwPID);
|
||||
@@ -551,6 +574,7 @@ BOOL VMMDLL_MemVirt2Phys_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG6
|
||||
return VmmVirt2Phys(pProcess, qwVA, pqwPA);
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
@@ -562,13 +586,14 @@ BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqw
|
||||
// VMM PROCESS FUNCTIONALITY BELOW:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
BOOL VMMDLL_ProcessGetMemoryMap_Impl(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMap_Impl(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules)
|
||||
{
|
||||
PVMM_PROCESS pProcess = VmmProcessGet(dwPID);
|
||||
if(!pProcess) { return FALSE; }
|
||||
if(!pProcess->pMemMap || !pProcess->cMemMap) {
|
||||
if(!pProcess->fSpiderPageTableDone) {
|
||||
VmmTlbSpider(pProcess->paPML4, pProcess->fUserOnly);
|
||||
VmmTlbSpider(pProcess->paDTB, pProcess->fUserOnly);
|
||||
pProcess->fSpiderPageTableDone = TRUE;
|
||||
}
|
||||
VmmMapInitialize(pProcess);
|
||||
@@ -586,6 +611,7 @@ BOOL VMMDLL_ProcessGetMemoryMap_Impl(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTR
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
@@ -593,6 +619,7 @@ BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY
|
||||
VMMDLL_ProcessGetMemoryMap_Impl(dwPID, pMemMapEntries, pcMemMapEntries, fIdentifyModules))
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMapEntry_Impl(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules)
|
||||
{
|
||||
PVMM_PROCESS pProcess = VmmProcessGet(dwPID);
|
||||
@@ -611,6 +638,7 @@ BOOL VMMDLL_ProcessGetMemoryMapEntry_Impl(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
@@ -618,7 +646,8 @@ BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTR
|
||||
VMMDLL_ProcessGetMemoryMapEntry_Impl(dwPID, pMemMapEntry, va, fIdentifyModules))
|
||||
}
|
||||
|
||||
BOOL VMMDLL_ProcessGetModuleMap_Impl(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleMap_Impl(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries)
|
||||
{
|
||||
ULONG64 i;
|
||||
PVMM_PROCESS pProcess = VmmProcessGet(dwPID);
|
||||
@@ -626,7 +655,7 @@ BOOL VMMDLL_ProcessGetModuleMap_Impl(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_E
|
||||
if(!pcModuleEntries) { return FALSE; }
|
||||
if(!pProcess->pModuleMap || !pProcess->cModuleMap) {
|
||||
if(!pProcess->fSpiderPageTableDone) {
|
||||
VmmTlbSpider(pProcess->paPML4, pProcess->fUserOnly);
|
||||
VmmTlbSpider(pProcess->paDTB, pProcess->fUserOnly);
|
||||
pProcess->fSpiderPageTableDone = TRUE;
|
||||
}
|
||||
VmmProc_InitializeModuleNames(pProcess);
|
||||
@@ -643,17 +672,19 @@ BOOL VMMDLL_ProcessGetModuleMap_Impl(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_E
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
STATISTICS_ID_VMMDLL_ProcessGetModuleMap,
|
||||
VMMDLL_ProcessGetModuleMap_Impl(dwPID, pModuleEntries, pcModuleEntries))
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleFromName_Impl(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry)
|
||||
{
|
||||
BOOL result;
|
||||
ULONG64 i, cModuleEntries;
|
||||
ULONG64 i, cModuleEntries = 0;
|
||||
PVMMDLL_MODULEMAP_ENTRY pModuleEntries = NULL;
|
||||
result = VMMDLL_ProcessGetModuleMap_Impl(dwPID, NULL, &cModuleEntries);
|
||||
if(!result || !cModuleEntries) { return FALSE; }
|
||||
@@ -673,6 +704,7 @@ BOOL VMMDLL_ProcessGetModuleFromName_Impl(_In_ DWORD dwPID, _In_ LPSTR szModuleN
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
@@ -680,19 +712,22 @@ BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName,
|
||||
VMMDLL_ProcessGetModuleFromName_Impl(dwPID, szModuleName, pModuleEntry))
|
||||
}
|
||||
|
||||
BOOL VMMDLL_PidList_Impl(_Out_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidList_Impl(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs)
|
||||
{
|
||||
VmmProcessListPIDs(pPIDs, pcPIDs);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL VMMDLL_PidList(_Out_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
STATISTICS_ID_VMMDLL_PidList,
|
||||
VMMDLL_PidList_Impl(pPIDs, pcPIDs))
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidGetFromName_Impl(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID)
|
||||
{
|
||||
DWORD i, pdwPIDs[1024];
|
||||
@@ -710,6 +745,7 @@ BOOL VMMDLL_PidGetFromName_Impl(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
@@ -717,6 +753,7 @@ BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID)
|
||||
VMMDLL_PidGetFromName_Impl(szProcName, pdwPID))
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetInformation_Impl(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pInfo, _In_ PSIZE_T pcbProcessInfo)
|
||||
{
|
||||
PVMM_PROCESS pProcess;
|
||||
@@ -733,25 +770,33 @@ BOOL VMMDLL_ProcessGetInformation_Impl(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PRO
|
||||
// set general parameters
|
||||
pInfo->wVersion = VMMDLL_PROCESS_INFORMATION_VERSION;
|
||||
pInfo->wSize = sizeof(VMMDLL_PROCESS_INFORMATION);
|
||||
pInfo->fTargetSystem = VMMDLL_TARGET_UNKNOWN_X64;
|
||||
pInfo->tpMemoryModel = ctxVmm->tpMemoryModel;
|
||||
pInfo->tpSystem = ctxVmm->tpSystem;
|
||||
pInfo->fUserOnly = pProcess->fUserOnly;
|
||||
pInfo->dwPID = dwPID;
|
||||
pInfo->dwState = pProcess->dwState;
|
||||
pInfo->paPML4 = pProcess->paPML4;
|
||||
pInfo->paPML4_UserOpt = pProcess->paPML4_UserOpt;
|
||||
pInfo->paDTB = pProcess->paDTB;
|
||||
pInfo->paDTB_UserOpt = pProcess->paDTB_UserOpt;
|
||||
memcpy(pInfo->szName, pProcess->szName, sizeof(pInfo->szName));
|
||||
// set windows specific parameters
|
||||
if(ctxVmm->fTargetSystem == VMM_TARGET_WINDOWS_X64) {
|
||||
pInfo->fTargetSystem = VMMDLL_TARGET_WINDOWS_X64;
|
||||
pInfo->os.win.fWow64 = pProcess->os.win.fWow64;
|
||||
pInfo->os.win.vaENTRY = pProcess->os.win.vaENTRY;
|
||||
pInfo->os.win.vaEPROCESS = pProcess->os.win.vaEPROCESS;
|
||||
pInfo->os.win.vaPEB = pProcess->os.win.vaPEB;
|
||||
pInfo->os.win.vaPEB32 = pProcess->os.win.vaPEB32;
|
||||
// set operating system specific parameters
|
||||
switch(ctxVmm->tpSystem) {
|
||||
case VMM_SYSTEM_WINDOWS_X64:
|
||||
pInfo->os.win.fWow64 = pProcess->os.win.fWow64;
|
||||
pInfo->os.win.vaENTRY = pProcess->os.win.vaENTRY;
|
||||
pInfo->os.win.vaEPROCESS = pProcess->os.win.vaEPROCESS;
|
||||
pInfo->os.win.vaPEB = pProcess->os.win.vaPEB;
|
||||
pInfo->os.win.vaPEB32 = pProcess->os.win.vaPEB32;
|
||||
break;
|
||||
case VMM_SYSTEM_WINDOWS_X86:
|
||||
pInfo->os.win.vaENTRY = pProcess->os.win.vaENTRY;
|
||||
pInfo->os.win.vaEPROCESS = pProcess->os.win.vaEPROCESS;
|
||||
pInfo->os.win.vaPEB = pProcess->os.win.vaPEB;
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
@@ -759,12 +804,13 @@ BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_
|
||||
VMMDLL_ProcessGetInformation_Impl(dwPID, pProcessInformation, pcbProcessInformation))
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(
|
||||
_In_ DWORD dwPID,
|
||||
_In_ LPSTR szModule,
|
||||
_In_ DWORD cData,
|
||||
_Out_ PDWORD pcData,
|
||||
_Out_opt_ PIMAGE_DATA_DIRECTORY pDataDirectory,
|
||||
_Out_writes_opt_(16) PIMAGE_DATA_DIRECTORY pDataDirectory,
|
||||
_Out_opt_ PIMAGE_SECTION_HEADER pSections,
|
||||
_Out_opt_ PVMMDLL_EAT_ENTRY pEAT,
|
||||
_Out_opt_ PVOID pIAT,
|
||||
@@ -781,7 +827,7 @@ BOOL VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(
|
||||
// genereate module map (if required)
|
||||
if(!pProcess->pModuleMap || !pProcess->cModuleMap) {
|
||||
if(!pProcess->fSpiderPageTableDone) {
|
||||
VmmTlbSpider(pProcess->paPML4, pProcess->fUserOnly);
|
||||
VmmTlbSpider(pProcess->paDTB, pProcess->fUserOnly);
|
||||
pProcess->fSpiderPageTableDone = TRUE;
|
||||
}
|
||||
VmmProc_InitializeModuleNames(pProcess);
|
||||
@@ -798,69 +844,74 @@ BOOL VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(
|
||||
if(fDataDirectory) {
|
||||
if(!pDataDirectory) { *pcData = 16; return TRUE; }
|
||||
if(cData < 16) { return FALSE; }
|
||||
VmmProcWindows_PE_DIRECTORY_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, pDataDirectory);
|
||||
VmmWin_PE_DIRECTORY_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, pDataDirectory);
|
||||
*pcData = 16;
|
||||
return TRUE;
|
||||
}
|
||||
// sections
|
||||
if(fSections) {
|
||||
i = VmmProcWindows_PE_GetNumberOfSection(pProcess, pModule, NULL, FALSE);
|
||||
i = PE_SectionGetNumberOf(pProcess, pModule->BaseAddress);
|
||||
if(!pSections) { *pcData = i; return TRUE; }
|
||||
if(cData < i) { return FALSE; }
|
||||
VmmProcWindows_PE_SECTION_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, pSections);
|
||||
*pcData = i;
|
||||
VmmWin_PE_SECTION_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, &cData, pSections);
|
||||
*pcData = cData;
|
||||
return TRUE;
|
||||
}
|
||||
// export address table (EAT)
|
||||
if(fEAT) {
|
||||
i = VmmProcWindows_PE_GetNumberOfEAT(pProcess, pModule, NULL, FALSE);
|
||||
i = PE_EatGetNumberOf(pProcess, pModule->BaseAddress);
|
||||
if(!pEAT) { *pcData = i; return TRUE; }
|
||||
if(cData < i) { return FALSE; }
|
||||
VmmProcWindows_PE_LoadEAT_DisplayBuffer(pProcess, pModule, (PVMMPROC_WINDOWS_EAT_ENTRY)pEAT, &cData);
|
||||
VmmWin_PE_LoadEAT_DisplayBuffer(pProcess, pModule, (PVMMPROC_WINDOWS_EAT_ENTRY)pEAT, &cData);
|
||||
*pcData = cData;
|
||||
return TRUE;
|
||||
}
|
||||
// import address table (IAT)
|
||||
if(fIAT) {
|
||||
i = VmmProcWindows_PE_GetNumberOfIAT(pProcess, pModule, NULL, FALSE);
|
||||
i = PE_IatGetNumberOf(pProcess, pModule->BaseAddress);
|
||||
if(!pIAT) { *pcData = i; return TRUE; }
|
||||
if(cData < i) { return FALSE; }
|
||||
VmmProcWindows_PE_LoadIAT_DisplayBuffer(pProcess, pModule, (PVMMPROC_WINDOWS_IAT_ENTRY)pIAT, &cData);
|
||||
VmmWin_PE_LoadIAT_DisplayBuffer(pProcess, pModule, (PVMMWIN_IAT_ENTRY)pIAT, &cData);
|
||||
*pcData = cData;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
STATISTICS_ID_VMMDLL_ProcessGetDirectories,
|
||||
VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(dwPID, szModule, cData, pcData, pData, NULL, NULL, NULL, TRUE, FALSE, FALSE, FALSE))
|
||||
}
|
||||
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
STATISTICS_ID_VMMDLL_ProcessGetSections,
|
||||
VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(dwPID, szModule, cData, pcData, NULL, pData, NULL, NULL, FALSE, TRUE, FALSE, FALSE))
|
||||
}
|
||||
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
STATISTICS_ID_VMMDLL_ProcessGetEAT,
|
||||
VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(dwPID, szModule, cData, pcData, NULL, NULL, pData, NULL, FALSE, FALSE, TRUE, FALSE))
|
||||
}
|
||||
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData)
|
||||
{
|
||||
CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
|
||||
STATISTICS_ID_VMMDLL_ProcessGetIAT,
|
||||
VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(dwPID, szModule, cData, pcData, NULL, NULL, NULL, pData, FALSE, FALSE, FALSE, TRUE))
|
||||
}
|
||||
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_ LPSTR sz, _Inout_ PDWORD pcsz)
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz)
|
||||
{
|
||||
return Util_FillHexAscii(pb, cb, cbInitialOffset, sz, pcsz);
|
||||
}
|
||||
|
||||
92
vmm/vmmdll.h
92
vmm/vmmdll.h
@@ -23,6 +23,7 @@ extern "C" {
|
||||
* Call other VMMDLL_Intialize functions to initialize VMM.DLL and the memory
|
||||
* process file system.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
|
||||
/*
|
||||
@@ -37,6 +38,7 @@ BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -52,6 +54,7 @@ BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBase
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -60,6 +63,7 @@ BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPST
|
||||
* initialized in read/write mode upon success.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
|
||||
/*
|
||||
@@ -67,6 +71,7 @@ BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
* including plugins, linked PCILeech.DLL and other memory resources.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_Close();
|
||||
|
||||
|
||||
@@ -103,7 +108,8 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
|
||||
#define VMMDLL_OPT_CORE_TARGET_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
|
||||
|
||||
#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
|
||||
#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
|
||||
@@ -116,6 +122,22 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
|
||||
#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
|
||||
|
||||
static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
|
||||
|
||||
typedef enum tdVMMDLL_MEMORYMODEL_TP {
|
||||
VMMDLL_MEMORYMODEL_NA = 0,
|
||||
VMMDLL_MEMORYMODEL_X86 = 1,
|
||||
VMMDLL_MEMORYMODEL_X86PAE = 2,
|
||||
VMMDLL_MEMORYMODEL_X64 = 3
|
||||
} VMMDLL_MEMORYMODEL_TP;
|
||||
|
||||
typedef enum tdVMMDLL_SYSTEM_TP {
|
||||
VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
|
||||
VMMDLL_SYSTEM_WINDOWS_X64 = 2,
|
||||
VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
|
||||
VMMDLL_SYSTEM_WINDOWS_X86 = 4
|
||||
} VMMDLL_SYSTEM_TP;
|
||||
|
||||
/*
|
||||
* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
|
||||
* mation about valid option values. Please note that option values may overlap
|
||||
@@ -124,6 +146,7 @@ BOOL VMMDLL_Close();
|
||||
* -- pqwValue = pointer to ULONG64 to receive option value.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
|
||||
/*
|
||||
@@ -134,6 +157,7 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
* -- qwValue
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
|
||||
|
||||
|
||||
@@ -171,6 +195,7 @@ typedef struct tdVMMDLL_VFS_FILELIST {
|
||||
* -- pFileList
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
|
||||
|
||||
/*
|
||||
@@ -227,12 +252,13 @@ NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb,
|
||||
* will be unloaded on a general close of the vmm dll.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsInitializePlugins();
|
||||
|
||||
#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
|
||||
#define VMMDLL_PLUGIN_CONTEXT_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 2
|
||||
|
||||
#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
|
||||
|
||||
@@ -254,7 +280,8 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem;
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel;
|
||||
VMMDLL_SYSTEM_TP tpSystem;
|
||||
HMODULE hDLL;
|
||||
HMODULE hReservedDll; // not for general use (only used for python).
|
||||
BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
|
||||
@@ -272,7 +299,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
// function plugin registration info to be filled out by the plugin below:
|
||||
struct {
|
||||
BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
|
||||
VOID(*pfnNotify)(_Inout_opt_ PHANDLE phModulePrivate, _In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
|
||||
VOID(*pfnCloseHandleModule)(_Inout_opt_ PHANDLE phModulePrivate);
|
||||
@@ -296,8 +323,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
|
||||
#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
|
||||
|
||||
#define VMMDLL_TARGET_UNKNOWN_X64 0x0001
|
||||
#define VMMDLL_TARGET_WINDOWS_X64 0x0002
|
||||
#define VMMDLL_MEM_IO_SCATTER_HEADER_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
ULONG64 qwA; // base address (DWORD boundry).
|
||||
@@ -306,6 +332,10 @@ typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
|
||||
PVOID pvReserved1; // reserved for use by caller.
|
||||
PVOID pvReserved2; // reserved for use by caller.
|
||||
WORD version; // version of struct
|
||||
WORD Future1; // reserved for future use.
|
||||
DWORD Future2; // reserved for future use.
|
||||
ULONG64 qwDeviceA; // device-physical address (used by device layer).
|
||||
struct {
|
||||
PVOID pvReserved1;
|
||||
PVOID pvReserved2;
|
||||
@@ -335,6 +365,7 @@ DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPVMMDLL_MEM_IO_SCATTER_HE
|
||||
* -- pbPage
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
|
||||
|
||||
/*
|
||||
@@ -345,6 +376,7 @@ BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4
|
||||
* -- cb
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
@@ -358,7 +390,8 @@ BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DW
|
||||
* -- return = success/fail. NB! reads may report as success even if 0 bytes are
|
||||
* read - it's recommended to verify pcbReadOpt parameter.
|
||||
*/
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
|
||||
/*
|
||||
* Write a contigious arbitrary amount of memory. Please note some virtual memory
|
||||
@@ -373,7 +406,8 @@ BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In
|
||||
* -- cb
|
||||
* -- return = TRUE on success, FALSE on partial or zero write.
|
||||
*/
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address by walking the page tables
|
||||
@@ -383,6 +417,7 @@ BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ D
|
||||
* -- pqwPA
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
|
||||
|
||||
|
||||
@@ -401,6 +436,7 @@ BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqw
|
||||
* -- pdwPID = pointer that will receive PID on success.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
|
||||
/*
|
||||
@@ -409,7 +445,8 @@ BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_PidList(_Out_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
|
||||
// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
|
||||
#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
|
||||
@@ -437,6 +474,7 @@ typedef struct tdVMMDLL_MEMMAP_ENTRY {
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
|
||||
|
||||
/*
|
||||
@@ -448,6 +486,7 @@ BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
|
||||
|
||||
typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
@@ -469,7 +508,8 @@ typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
* -- pcModuleEntries = pointer to number of memory map entries.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
|
||||
/*
|
||||
* Retrieve a module (.exe or .dll or similar) given a module name.
|
||||
@@ -478,29 +518,31 @@ BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY
|
||||
* -- pModuleEntry
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
|
||||
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 1
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem; // as given by VMMDLL_TARGET_*
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
|
||||
VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
DWORD dwPID;
|
||||
DWORD dwState;
|
||||
CHAR szName[16];
|
||||
ULONG64 paPML4;
|
||||
ULONG64 paPML4_UserOpt; // may not exist
|
||||
ULONG64 paDTB;
|
||||
ULONG64 paDTB_UserOpt; // may not exist
|
||||
union {
|
||||
struct {
|
||||
ULONG64 vaEPROCESS;
|
||||
ULONG64 vaPEB;
|
||||
ULONG64 vaENTRY;
|
||||
BOOL fWow64;
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
} win;
|
||||
} os;
|
||||
} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
|
||||
@@ -513,6 +555,7 @@ typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
|
||||
|
||||
typedef struct tdVMMDLL_EAT_ENTRY {
|
||||
@@ -539,10 +582,14 @@ typedef struct tdVMMDLL_IAT_ENTRY {
|
||||
* -- pcData
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
|
||||
|
||||
|
||||
@@ -558,7 +605,8 @@ BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_I
|
||||
* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
|
||||
* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
|
||||
*/
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_ LPSTR sz, _Inout_ PDWORD pcsz);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
265
vmm/vmmproc.c
265
vmm/vmmproc.c
@@ -5,7 +5,8 @@
|
||||
//
|
||||
|
||||
#include "vmmproc.h"
|
||||
#include "vmmproc_windows.h"
|
||||
#include "vmmwin.h"
|
||||
#include "vmmwininit.h"
|
||||
#include "device.h"
|
||||
#include "statistics.h"
|
||||
#include "util.h"
|
||||
@@ -14,128 +15,66 @@
|
||||
// GENERIC PROCESS RELATED FUNCTIONALITY BELOW:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* see VmmProcPHYS_ScanWindowsKernel_LargePages for more information!
|
||||
* Scan a page table hierarchy between virtual addresses between vaMin and vaMax
|
||||
* for the first occurence of large 2MB pages. This is usually the ntoskrnl.exe
|
||||
* if the OS is Windows. Ntoskrnl.exe is loaded between the virtual addresses:
|
||||
* 0xFFFFF80000000000-0xFFFFF803FFFFFFFF
|
||||
* -- ctxVmm,
|
||||
* -- paTable = set to: physical address of PML4
|
||||
* -- vaBase = set to 0
|
||||
* -- vaMin = 0xFFFFF80000000000 (if windows kernel)
|
||||
* -- vaMax = 0xFFFFF803FFFFFFFF (if windows kernel)
|
||||
* -- cPML = set to 4
|
||||
* -- pvaBase
|
||||
* -- pcbSize
|
||||
*/
|
||||
VOID VmmProcPHYS_ScanWindowsKernel_LargePages_PageTableWalk(_In_ QWORD paTable, _In_ QWORD vaBase, _In_ QWORD vaMin, _In_ QWORD vaMax, _In_ BYTE cPML, _Inout_ PQWORD pvaBase, _Inout_ PQWORD pcbSize)
|
||||
{
|
||||
const QWORD PML_REGION_SIZE[5] = { 0, 12, 21, 30, 39 };
|
||||
QWORD i, pte, *ptes, vaCurrent, vaSizeRegion;
|
||||
ptes = (PQWORD)VmmTlbGetPageTable(paTable, FALSE);
|
||||
if(!ptes) { return; }
|
||||
if(cPML == 4) {
|
||||
*pvaBase = 0;
|
||||
*pcbSize = 0;
|
||||
if(!VmmTlbPageTableVerify((PBYTE)ptes, paTable, TRUE)) { return; }
|
||||
vaBase = 0;
|
||||
}
|
||||
for(i = 0; i < 512; i++) {
|
||||
// address in range
|
||||
vaSizeRegion = 1ULL << PML_REGION_SIZE[cPML];
|
||||
vaCurrent = vaBase + (i << PML_REGION_SIZE[cPML]);
|
||||
vaCurrent |= (vaCurrent & 0x0000800000000000) ? 0xffff000000000000 : 0; // sign extend
|
||||
if(*pvaBase && (vaCurrent >(*pvaBase + *pcbSize))) { return; }
|
||||
if(vaCurrent < vaMin) { continue; }
|
||||
if(vaCurrent > vaMax) { return; }
|
||||
// check PTEs
|
||||
pte = ptes[i];
|
||||
if(!(pte & 0x01)) { continue; } // NOT VALID
|
||||
if(cPML == 2) {
|
||||
if(!(pte & 0x80)) { continue; }
|
||||
if(!*pvaBase) { *pvaBase = vaCurrent; }
|
||||
*pcbSize += 0x200000;
|
||||
continue;
|
||||
} else {
|
||||
if(pte & 0x80) { continue; } // PS = 1
|
||||
VmmProcPHYS_ScanWindowsKernel_LargePages_PageTableWalk(pte & 0x0000fffffffff000, vaCurrent, vaMin, vaMax, cPML - 1, pvaBase, pcbSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sometimes the PageDirectoryBase (PML4) is known, but the kernel location may
|
||||
* be unknown. This functions walks the page table in the area in which ntoskrnl
|
||||
* is loaded (0xFFFFF80000000000-0xFFFFF803FFFFFFFF) looking for 2MB large pages
|
||||
* If an area in 2MB pages are found it is scanned for the ntoskrnl.exe base.
|
||||
* -- paPML4
|
||||
* -- return = virtual address of ntoskrnl.exe base if successful, otherwise 0.
|
||||
*/
|
||||
QWORD VmmProcPHYS_ScanWindowsKernel_LargePages(_In_ QWORD paPML4)
|
||||
{
|
||||
PBYTE pbBuffer;
|
||||
QWORD p, o, vaCurrentMin, vaBase, cbSize;
|
||||
PVMM_PROCESS pSystemProcess = NULL;
|
||||
BOOL fINITKDBG, fPOOLCODE;
|
||||
vaCurrentMin = 0xFFFFF80000000000; // base of windows kernel possible location
|
||||
while(TRUE) {
|
||||
VmmProcPHYS_ScanWindowsKernel_LargePages_PageTableWalk(paPML4, 0, vaCurrentMin, 0xFFFFF803FFFFFFFF, 4, &vaBase, &cbSize);
|
||||
if(!vaBase) { return 0; }
|
||||
vaCurrentMin = vaBase + cbSize;
|
||||
if(cbSize <= 0x00400000) { continue; } // too small
|
||||
if(cbSize >= 0x01000000) { continue; } // too big
|
||||
if(!pSystemProcess) {
|
||||
pSystemProcess = VmmProcessCreateEntry(4, 0, paPML4, 0, "System", FALSE, FALSE);
|
||||
if(!pSystemProcess) { return 0; }
|
||||
VmmProcessCreateFinish();
|
||||
}
|
||||
// try locate ntoskrnl.exe base inside suggested area
|
||||
pbBuffer = (PBYTE)LocalAlloc(0, cbSize);
|
||||
if(!pbBuffer) { return 0; }
|
||||
VmmReadEx(pSystemProcess, vaBase, pbBuffer, (DWORD)cbSize, NULL, 0);
|
||||
for(p = 0; p < cbSize; p += 0x1000) {
|
||||
if(*(PWORD)(pbBuffer + p) != 0x5a4d) { continue; }
|
||||
// check if module header contains INITKDBG and POOLCODE
|
||||
fINITKDBG = FALSE;
|
||||
fPOOLCODE = FALSE;
|
||||
for(o = 0; o < 0x1000; o += 8) {
|
||||
if(*(PQWORD)(pbBuffer + p + o) == 0x4742444B54494E49) { // INITKDBG
|
||||
fINITKDBG = TRUE;
|
||||
}
|
||||
if(*(PQWORD)(pbBuffer + p + o) == 0x45444F434C4F4F50) { // POOLCODE
|
||||
fPOOLCODE = TRUE;
|
||||
}
|
||||
if(fINITKDBG && fPOOLCODE) {
|
||||
LocalFree(pbBuffer);
|
||||
return vaBase + p;
|
||||
}
|
||||
}
|
||||
}
|
||||
LocalFree(pbBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GENERIC PROCESS RELATED FUNCTIONALITY BELOW:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Try initialize from user supplied CR3/PML4 supplied in parameter at startup.
|
||||
* -- ctx
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmProcUserCR3TryInitialize()
|
||||
BOOL VmmProcUserCR3TryInitialize64()
|
||||
{
|
||||
PVMM_PROCESS pProcess;
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_X64);
|
||||
pProcess = VmmProcessCreateEntry(0, 0, ctxMain->cfg.paCR3, 0, "unknown_process", FALSE, TRUE);
|
||||
VmmProcessCreateFinish();
|
||||
if(!pProcess) {
|
||||
vmmprintfv("VmmProc: FAIL: Initialization of Process failed from user-defined CR3 %016llx. #4.\n", ctxMain->cfg.paCR3);
|
||||
vmmprintfv("VmmProc: FAIL: Initialization of Process failed from user-defined CR3 %016llx.\n", ctxMain->cfg.paCR3);
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_NA);
|
||||
return FALSE;
|
||||
}
|
||||
VmmTlbSpider(pProcess->paPML4, FALSE);
|
||||
ctxVmm->fTargetSystem = VMM_TARGET_UNKNOWN_X64;
|
||||
VmmTlbSpider(pProcess->paDTB, FALSE);
|
||||
ctxVmm->tpSystem = VMM_SYSTEM_UNKNOWN_X64;
|
||||
ctxVmm->kernel.paDTB = ctxMain->cfg.paCR3;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL VmmProc_Refresh(_In_ BOOL fProcessList, _In_ BOOL fProcessFull)
|
||||
{
|
||||
PVMM_PROCESS pSystemProcess;
|
||||
QWORD paSystemPML4, vaSystemEPROCESS;
|
||||
if(fProcessList) {
|
||||
ctxVmm->stat.cRefreshProcessPartial++;
|
||||
// Windows OS
|
||||
if((ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) || (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86)) {
|
||||
pSystemProcess = VmmProcessGet(4);
|
||||
if(pSystemProcess) {
|
||||
VmmWin_EnumerateEPROCESS(pSystemProcess);
|
||||
vmmprintfvv("VmmProc: vmmproc.c!VmmProcCacheUpdaterThread FlushProcessList\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fProcessFull) {
|
||||
ctxVmm->stat.cRefreshProcessFull++;
|
||||
// Windows OS
|
||||
if((ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) || (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86)) {
|
||||
pSystemProcess = VmmProcessGet(4);
|
||||
if(pSystemProcess) {
|
||||
paSystemPML4 = pSystemProcess->paDTB;
|
||||
vaSystemEPROCESS = pSystemProcess->os.win.vaEPROCESS;
|
||||
// spider TLB and set up initial system process and enumerate EPROCESS
|
||||
VmmTlbSpider(paSystemPML4, FALSE);
|
||||
pSystemProcess = VmmProcessCreateEntry(4, 0, paSystemPML4, 0, "System", FALSE, TRUE);
|
||||
if(!pSystemProcess) { return FALSE; }
|
||||
pSystemProcess->os.win.vaEPROCESS = vaSystemEPROCESS;
|
||||
VmmWin_EnumerateEPROCESS(pSystemProcess);
|
||||
vmmprintfvv("vmmproc.c!VmmProc_Refresh FlushProcessListAndBuffers\n");
|
||||
}
|
||||
}
|
||||
// Single user-defined X64 process
|
||||
if(ctxVmm->tpSystem == VMM_SYSTEM_UNKNOWN_X64) {
|
||||
VmmProcessCreateTable();
|
||||
VmmProcUserCR3TryInitialize64();
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -149,8 +88,6 @@ DWORD VmmProcCacheUpdaterThread()
|
||||
{
|
||||
QWORD i = 0;
|
||||
BOOL fPHYS, fTLB, fProcList, fProcTotal;
|
||||
PVMM_PROCESS pSystemProcess;
|
||||
QWORD paSystemPML4, vaSystemEPROCESS;
|
||||
vmmprintfv("VmmProc: Start periodic cache flushing.\n");
|
||||
ctxVmm->ThreadProcCache.cMs_TickPeriod = VMMPROC_UPDATERTHREAD_PERIOD;
|
||||
ctxVmm->ThreadProcCache.cTick_Phys = VMMPROC_UPDATERTHREAD_PHYSCACHE;
|
||||
@@ -173,44 +110,16 @@ DWORD VmmProcCacheUpdaterThread()
|
||||
}
|
||||
// refresh proc list
|
||||
if(fProcList) {
|
||||
ctxVmm->stat.cRefreshProcessPartial++;
|
||||
// Windows OS
|
||||
if(ctxVmm->fTargetSystem & VMM_TARGET_WINDOWS_X64) {
|
||||
pSystemProcess = VmmProcessGet(4);
|
||||
if(pSystemProcess) {
|
||||
VmmProcWindows_EnumerateEPROCESS(pSystemProcess);
|
||||
vmmprintfvv("VmmProc: vmmproc.c!VmmProcCacheUpdaterThread FlushProcessList\n");
|
||||
}
|
||||
}
|
||||
VmmProc_Refresh(TRUE, FALSE);
|
||||
}
|
||||
// total refresh of entire proc cache
|
||||
if(fProcTotal) {
|
||||
ctxVmm->stat.cRefreshProcessFull++;
|
||||
// Windows OS
|
||||
if(ctxVmm->fTargetSystem & VMM_TARGET_WINDOWS_X64) {
|
||||
pSystemProcess = VmmProcessGet(4);
|
||||
if(pSystemProcess) {
|
||||
paSystemPML4 = pSystemProcess->paPML4;
|
||||
vaSystemEPROCESS = pSystemProcess->os.win.vaEPROCESS;
|
||||
// spider TLB and set up initial system process and enumerate EPROCESS
|
||||
VmmTlbSpider(paSystemPML4, FALSE);
|
||||
pSystemProcess = VmmProcessCreateEntry(4, 0, paSystemPML4, 0, "System", FALSE, TRUE);
|
||||
if(!pSystemProcess) {
|
||||
vmmprintf("VmmProc: Failed to refresh memory process file system - aborting.\n");
|
||||
VmmProcessCreateFinish();
|
||||
ctxVmm->ThreadProcCache.fEnabled = FALSE;
|
||||
LeaveCriticalSection(&ctxVmm->MasterLock);
|
||||
goto fail;
|
||||
}
|
||||
pSystemProcess->os.win.vaEPROCESS = vaSystemEPROCESS;
|
||||
VmmProcWindows_EnumerateEPROCESS(pSystemProcess);
|
||||
vmmprintfvv("VmmProc: vmmproc.c!VmmProcCacheUpdaterThread FlushProcessListAndBuffers\n");
|
||||
}
|
||||
}
|
||||
// Single user-defined X64 process
|
||||
if(ctxVmm->fTargetSystem & VMM_TARGET_UNKNOWN_X64) {
|
||||
VmmProcessCreateTable();
|
||||
VmmProcUserCR3TryInitialize(ctxVmm);
|
||||
if(!VmmProc_Refresh(FALSE, TRUE)) {
|
||||
vmmprintf("VmmProc: Failed to refresh memory process file system - aborting.\n");
|
||||
VmmProcessCreateFinish();
|
||||
ctxVmm->ThreadProcCache.fEnabled = FALSE;
|
||||
LeaveCriticalSection(&ctxVmm->MasterLock);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&ctxVmm->MasterLock);
|
||||
@@ -223,47 +132,27 @@ fail:
|
||||
|
||||
VOID VmmProc_InitializeModuleNames(_In_ PVMM_PROCESS pProcess)
|
||||
{
|
||||
if(ctxVmm->fTargetSystem & VMM_TARGET_WINDOWS_X64) {
|
||||
VmmProcWindows_InitializeModuleNames(pProcess);
|
||||
if((ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) || (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86)) {
|
||||
VmmWin_InitializeModuleNames(pProcess);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL VmmProcInitialize()
|
||||
{
|
||||
BOOL result;
|
||||
QWORD vaKernelBase;
|
||||
BOOL result = FALSE;
|
||||
if(!VmmInitialize()) { return FALSE; }
|
||||
// user supplied a CR3 - use it!
|
||||
if(ctxMain->cfg.paCR3) {
|
||||
// if VmmProcPHYS_ScanWindowsKernel_LargePages returns a value this is a
|
||||
// Windows system - initialize it, otherwise initialize the generic x64
|
||||
// single process more basic mode.
|
||||
result = FALSE;
|
||||
vaKernelBase = VmmProcPHYS_ScanWindowsKernel_LargePages(ctxMain->cfg.paCR3);
|
||||
if(vaKernelBase) {
|
||||
result = VmmProcWindows_TryInitialize(ctxMain->cfg.paCR3, vaKernelBase);
|
||||
}
|
||||
if(!vaKernelBase) {
|
||||
result = VmmProcUserCR3TryInitialize(ctxVmm);
|
||||
if(!result) {
|
||||
VmmInitialize(); // re-initialize VMM to clear state
|
||||
}
|
||||
}
|
||||
if(!result) {
|
||||
result = VmmProcUserCR3TryInitialize(ctxVmm);
|
||||
}
|
||||
} else {
|
||||
// no page directory was found, so try initialize it by looking if the
|
||||
// "low stub" exists on a Windows sytem and use it. Otherwise fail.
|
||||
result = VmmProcWindows_TryInitialize(0, 0);
|
||||
// 1: try initialize 'windows' with an optionally supplied CR3
|
||||
result = VmmWinInit_TryInitialize(ctxMain->cfg.paCR3);
|
||||
if(!result) {
|
||||
result = ctxMain->cfg.paCR3 && VmmProcUserCR3TryInitialize64();
|
||||
if(!result) {
|
||||
vmmprintf(
|
||||
"VmmProc: Unable to auto-identify operating system for PROC file system mount. \n" \
|
||||
" Please specify PageDirectoryBase (CR3/PML4) in the -cr3 option if value\n" \
|
||||
" Please specify PageDirectoryBase (DTB/CR3) in the -cr3 option if value \n" \
|
||||
" is known. If unknown it may be recoverable with command 'identify'. \n");
|
||||
}
|
||||
}
|
||||
// set up cache mainenance in the form of a separate worker thread in case
|
||||
// set up cache maintenance in the form of a separate worker thread in case
|
||||
// the backend is a writeable device (FPGA). File devices are read-only so
|
||||
// far so full caching is enabled since they are considered to be read-only.
|
||||
if(result && !ctxVmm->fReadOnly) {
|
||||
@@ -308,34 +197,38 @@ _Success_(return)
|
||||
BOOL VmmProcPHYS_ScanForKernel(_Out_ PQWORD ppaPML4, _In_ QWORD paBase, _In_ QWORD paMax, _In_ LPSTR szDescription)
|
||||
{
|
||||
QWORD o, i, paCurrent;
|
||||
PAGE_STATISTICS pageStat;
|
||||
PBYTE pbBuffer8M;
|
||||
PBYTE pbBuffer8M = NULL;
|
||||
PPAGE_STATISTICS pPageStat = NULL;
|
||||
BOOL result;
|
||||
// initialize / allocate memory
|
||||
if(!(pbBuffer8M = LocalAlloc(0, 0x800000))) { return FALSE; }
|
||||
ZeroMemory(&pageStat, sizeof(PAGE_STATISTICS));
|
||||
pbBuffer8M = LocalAlloc(0, 0x800000);
|
||||
pPageStat = (PPAGE_STATISTICS)LocalAlloc(LMEM_ZEROINIT, sizeof(PAGE_STATISTICS));
|
||||
if(!pbBuffer8M || !pPageStat) { goto fail; }
|
||||
paCurrent = paBase;
|
||||
PageStatInitialize(&pageStat, paCurrent, paMax, szDescription, FALSE, FALSE);
|
||||
PageStatInitialize(pPageStat, paCurrent, paMax, szDescription, FALSE, FALSE);
|
||||
// loop kmd-find
|
||||
for(; paCurrent < paMax; paCurrent += 0x00800000) {
|
||||
if(!DeviceReadMEMEx(paCurrent, pbBuffer8M, 0x00800000, &pageStat)) { continue; }
|
||||
if(!DeviceReadMEMEx(paCurrent, pbBuffer8M, 0x00800000, pPageStat)) { continue; }
|
||||
for(o = 0; o < 0x00800000; o += 0x1000) {
|
||||
// Scan for windows EPROCESS (to get DirectoryBase/PML4)
|
||||
for(i = 0; i < 0x1000; i += 8) {
|
||||
if(*(PQWORD)(pbBuffer8M + o + i) == 0x00006D6574737953) {
|
||||
result = VmmProcPHYS_VerifyWindowsEPROCESS(pbBuffer8M, 0x00800000, o + i, ppaPML4);
|
||||
if(result) {
|
||||
pageStat.szAction = "Windows System PageDirectoryBase/PML4 located";
|
||||
pPageStat->szAction = "Windows System PageDirectoryBase/PML4 located";
|
||||
PageStatClose(pPageStat);
|
||||
LocalFree(pPageStat);
|
||||
LocalFree(pbBuffer8M);
|
||||
PageStatClose(&pageStat);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fail:
|
||||
if(pPageStat) { PageStatClose(pPageStat); }
|
||||
LocalFree(pPageStat);
|
||||
LocalFree(pbBuffer8M);
|
||||
PageStatClose(&pageStat);
|
||||
*ppaPML4 = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
#define __VMMPROC_H__
|
||||
#include "vmm.h"
|
||||
|
||||
/*
|
||||
* Force a refresh of the process list.
|
||||
* -- fProcessList = partial refresh of processes should be done.
|
||||
* -- fProcessFull = full refresh of processes should be done.
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmProc_Refresh(_In_ BOOL fProcessList, _In_ BOOL fProcessFull);
|
||||
|
||||
/*
|
||||
* Load operating system dependant module names, such as parsed from PE or ELF
|
||||
* into the proper display caches, and also into the memory map.
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
// vmmproc_windows.h : definitions related to windows operating system and processes.
|
||||
// parsing of virtual memory. Windows related features only.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __VMMPROC_WINDOWS_H__
|
||||
#define __VMMPROC_WINDOWS_H__
|
||||
#include "vmm.h"
|
||||
|
||||
typedef struct tdVMMPROC_WINDOWS_EAT_ENTRY {
|
||||
QWORD vaFunction;
|
||||
DWORD vaFunctionOffset;
|
||||
CHAR szFunction[40];
|
||||
} VMMPROC_WINDOWS_EAT_ENTRY, *PVMMPROC_WINDOWS_EAT_ENTRY;
|
||||
|
||||
typedef struct tdVMMPROC_WINDOWS_IAT_ENTRY {
|
||||
ULONG64 vaFunction;
|
||||
CHAR szFunction[40];
|
||||
CHAR szModule[64];
|
||||
} VMMPROC_WINDOWS_IAT_ENTRY, *PVMMPROC_WINDOWS_IAT_ENTRY;
|
||||
|
||||
/*
|
||||
* Load the size of the required display buffer for sections, imports and export
|
||||
* into the pModule struct. The size is a direct consequence of the number of
|
||||
* functions since fixed line sizes are used for all these types. Loading is
|
||||
* done in a recource efficient way to minimize I/O as much as possible.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
*/
|
||||
VOID VmmProcWindows_PE_SetSizeSectionIATEAT_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule);
|
||||
|
||||
/*
|
||||
* Walk the export address table (EAT) from a given pProcess and store it in the
|
||||
* in the caller supplied pEATs/pcEATs structures.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
* -- pEATs
|
||||
* -- pcEATs = number max items of pEATs on entry, number of actual items of pEATs on exit
|
||||
*/
|
||||
VOID VmmProcWindows_PE_LoadEAT_DisplayBuffer(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule, _Out_ PVMMPROC_WINDOWS_EAT_ENTRY pEATs, _Inout_ PDWORD pcEATs);
|
||||
|
||||
/*
|
||||
* Walk the import address table (IAT) from a given pProcess and store it in the
|
||||
* in the caller supplied pIATs/pcIATs structures.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
* -- pIATs
|
||||
* -- pcIATs = number max items of pIATs on entry, number of actual items of pIATs on exit
|
||||
*/
|
||||
VOID VmmProcWindows_PE_LoadIAT_DisplayBuffer(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule, _Out_ PVMMPROC_WINDOWS_IAT_ENTRY pIATs, _Inout_ PDWORD pcIATs);
|
||||
|
||||
/*
|
||||
* Fill the pbDisplayBuffer with a human readable version of the data directories.
|
||||
* This is guaranteed to be exactly 864 bytes (excluding NULL terminator).
|
||||
* Alternatively copy the 16 data directories into pDataDirectoryOpt.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
* -- pbDisplayBufferOpt
|
||||
* -- cbDisplayBufferMax
|
||||
* -- pcbDisplayBuffer
|
||||
* -- pDataDirectoryOpt
|
||||
*/
|
||||
VOID VmmProcWindows_PE_DIRECTORY_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _Out_opt_ PBYTE pbDisplayBufferOpt, _In_ DWORD cbDisplayBufferMax, _Out_ PDWORD pcbDisplayBuffer, _Out_opt_ PIMAGE_DATA_DIRECTORY pDataDirectoryOpt);
|
||||
|
||||
/*
|
||||
* Fill the pbDisplayBuffer with a human readable version of the PE sections.
|
||||
* Alternatively copy the sections into the pSectionsOpt buffer.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
* -- pbDisplayBufferOpt
|
||||
* -- cbDisplayBufferMax
|
||||
* -- pcbDisplayBuffer
|
||||
* -- pSectionsOpt
|
||||
*/
|
||||
VOID VmmProcWindows_PE_SECTION_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _Out_opt_ PBYTE pbDisplayBufferOpt, _In_ DWORD cbDisplayBufferMax, _Out_ PDWORD pcbDisplayBuffer, _Out_opt_ PIMAGE_SECTION_HEADER pSectionsOpt);
|
||||
|
||||
/*
|
||||
* Retrieve the number of: sections, EAT entries or IAT entries depending on the
|
||||
* function that is called.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
* -- pbModuleHeaderOpt = optional PIMAGE_NT_HEADERS structure (either 32 or 64-bit)
|
||||
* -- fHdr32 = specified whether pbModuleHeaderOpt is a 32-bit or 64-bit header.
|
||||
* -- return = the number of entries
|
||||
*/
|
||||
WORD VmmProcWindows_PE_GetNumberOfSection(_In_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule, _In_opt_ PIMAGE_NT_HEADERS pbModuleHeaderOpt, _In_opt_ BOOL fHdr32);
|
||||
DWORD VmmProcWindows_PE_GetNumberOfEAT(_In_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule, _In_opt_ PIMAGE_NT_HEADERS pbModuleHeaderOpt, _In_opt_ BOOL fHdr32);
|
||||
DWORD VmmProcWindows_PE_GetNumberOfIAT(_In_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule, _In_opt_ PIMAGE_NT_HEADERS pbModuleHeaderOpt, _In_opt_ BOOL fHdr32);
|
||||
|
||||
/*
|
||||
* Initialize the module names into the ctxVMM. This is performed by a PEB/Ldr
|
||||
* scan of in-process memory structures. This may be unreliable of process is
|
||||
* obfuscated.
|
||||
* -- pProcess
|
||||
*/
|
||||
VOID VmmProcWindows_InitializeModuleNames(_In_ PVMM_PROCESS pProcess);
|
||||
|
||||
/*
|
||||
* Try walk the EPROCESS list in the Windows kernel to enumerate processes into
|
||||
* the VMM/PROC file system.
|
||||
* NB! This may be done to refresh an existing PID cache hence migration code.
|
||||
* -- pSystemProcess
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmProcWindows_EnumerateEPROCESS(_In_ PVMM_PROCESS pSystemProcess);
|
||||
|
||||
/*
|
||||
* Try initialize the VMM from scratch with new WINDOWS support.
|
||||
* -- paPML4Opt
|
||||
* -- vaKernelBaseOpt
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmProcWindows_TryInitialize(_In_opt_ QWORD paPML4Opt, _In_opt_ QWORD vaKernelBaseOpt);
|
||||
|
||||
#endif /* __VMMPROC_WINDOWS_H__ */
|
||||
73
vmm/vmmvfs.c
73
vmm/vmmvfs.c
@@ -7,7 +7,7 @@
|
||||
#include "vmmdll.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "vmmproc.h"
|
||||
#include "vmmproc_windows.h"
|
||||
#include "vmmwin.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef struct tdVMMVFS_PATH {
|
||||
@@ -19,7 +19,7 @@ typedef struct tdVMMVFS_PATH {
|
||||
LPSTR szPath2;
|
||||
} VMMVFS_PATH, *PVMMVFS_PATH;
|
||||
|
||||
BOOL VmmVfs_UtilVmmGetPidDirFile(_In_ LPCWSTR wcsFileName, _Inout_ PVMMVFS_PATH pPath)
|
||||
BOOL VmmVfs_UtilVmmGetPidDirFile(_In_ LPCWSTR wcsFileName, _Out_ PVMMVFS_PATH pPath)
|
||||
{
|
||||
DWORD i = 0, iPID, iPath1 = 0, iPath2 = 0;
|
||||
// 1: convert to ascii string
|
||||
@@ -78,6 +78,10 @@ NTSTATUS VmmVfsReadFileProcess(_In_ PVMMVFS_PATH pPath, _Out_ LPVOID pb, _In_ DW
|
||||
if(!pProcess) { return VMM_STATUS_FILE_INVALID; }
|
||||
// read memory from "vmem" file
|
||||
if(!_stricmp(pPath->szPath1, "vmem")) {
|
||||
if((ctxVmm->tpMemoryModel != VMM_MEMORYMODEL_X64) && (cbOffset + cb >= 0x100000000)) {
|
||||
if(cbOffset >= 0x100000000) { return VMM_STATUS_END_OF_FILE; }
|
||||
cb = (DWORD)(0x100000000 - cbOffset);
|
||||
}
|
||||
VmmReadEx(pProcess, cbOffset, pb, cb, NULL, 0);
|
||||
*pcbRead = cb;
|
||||
return VMM_STATUS_SUCCESS;
|
||||
@@ -93,11 +97,19 @@ NTSTATUS VmmVfsReadFileProcess(_In_ PVMMVFS_PATH pPath, _Out_ LPVOID pb, _In_ DW
|
||||
return Util_VfsReadFile_FromPBYTE(pProcess->pbMemMapDisplayCache, pProcess->cbMemMapDisplayCache, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
// read genereal numeric values from files, pml4, pid, name, virt
|
||||
if(!_stricmp(pPath->szPath1, "pml4")) {
|
||||
return Util_VfsReadFile_FromQWORD(pProcess->paPML4, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
if(!_stricmp(pPath->szPath1, "dtb")) {
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X64) {
|
||||
return Util_VfsReadFile_FromQWORD(pProcess->paDTB, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
} else if((ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86) || (ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86PAE)) {
|
||||
return Util_VfsReadFile_FromDWORD((DWORD)pProcess->paDTB, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
}
|
||||
}
|
||||
if(!_stricmp(pPath->szPath1, "pml4-user")) {
|
||||
return Util_VfsReadFile_FromQWORD(pProcess->paPML4_UserOpt, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
if(!_stricmp(pPath->szPath1, "dtb-user")) {
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X64) {
|
||||
return Util_VfsReadFile_FromQWORD(pProcess->paDTB_UserOpt, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
} else if((ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86) || (ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86PAE)) {
|
||||
return Util_VfsReadFile_FromDWORD((DWORD)pProcess->paDTB_UserOpt, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
}
|
||||
}
|
||||
if(!_stricmp(pPath->szPath1, "pid")) {
|
||||
cbBuffer = snprintf(pbBuffer, 32, "%i", pProcess->dwPID);
|
||||
@@ -108,7 +120,7 @@ NTSTATUS VmmVfsReadFileProcess(_In_ PVMMVFS_PATH pPath, _Out_ LPVOID pb, _In_ DW
|
||||
return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
// windows specific reads below:
|
||||
if(ctxVmm->fTargetSystem & VMM_TARGET_WINDOWS_X64) {
|
||||
if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) {
|
||||
if(!_stricmp(pPath->szPath1, "win-eprocess")) {
|
||||
return Util_VfsReadFile_FromQWORD(pProcess->os.win.vaEPROCESS, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
}
|
||||
@@ -125,6 +137,20 @@ NTSTATUS VmmVfsReadFileProcess(_In_ PVMMVFS_PATH pPath, _Out_ LPVOID pb, _In_ DW
|
||||
return Util_VfsReadFile_FromDWORD(pProcess->os.win.vaPEB32, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
}
|
||||
}
|
||||
if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86) {
|
||||
if(!_stricmp(pPath->szPath1, "win-eprocess")) {
|
||||
return Util_VfsReadFile_FromDWORD((DWORD)pProcess->os.win.vaEPROCESS, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
}
|
||||
if(!_stricmp(pPath->szPath1, "win-entry")) {
|
||||
return Util_VfsReadFile_FromDWORD((DWORD)pProcess->os.win.vaENTRY, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
}
|
||||
if(!_stricmp(pPath->szPath1, "win-peb")) {
|
||||
return Util_VfsReadFile_FromDWORD((DWORD)pProcess->os.win.vaPEB, pb, cb, pcbRead, cbOffset, FALSE);
|
||||
}
|
||||
if(!_stricmp(pPath->szPath1, "win-modules") && pProcess->os.win.pbLdrModulesDisplayCache) {
|
||||
return Util_VfsReadFile_FromPBYTE(pProcess->os.win.pbLdrModulesDisplayCache, pProcess->os.win.cbLdrModulesDisplayCache, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
}
|
||||
// no hit - call down the loadable modules chain for potential hits
|
||||
return PluginManager_Read(pProcess, pPath->szPath1, pPath->szPath2, pb, cb, pcbRead, cbOffset);
|
||||
}
|
||||
@@ -174,7 +200,7 @@ NTSTATUS VmmVfsWriteFileProcess(_In_ PVMMVFS_PATH pPath, _In_ LPVOID pb, _In_ DW
|
||||
return VMM_STATUS_SUCCESS;
|
||||
}
|
||||
// windows specific writes below:
|
||||
if(ctxVmm->fTargetSystem & VMM_TARGET_WINDOWS_X64) {
|
||||
if((ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) || (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86)) {
|
||||
fFound =
|
||||
!_stricmp(pPath->szPath1, "win-eprocess") ||
|
||||
!_stricmp(pPath->szPath1, "win-peb") ||
|
||||
@@ -227,13 +253,15 @@ NTSTATUS VmmVfs_Write(LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_
|
||||
VOID VmmVfsListFiles_OsSpecific(_In_ PVMM_PROCESS pProcess, _Inout_ PHANDLE pFileList)
|
||||
{
|
||||
// WINDOWS
|
||||
if(ctxVmm->fTargetSystem & VMM_TARGET_WINDOWS_X64) {
|
||||
if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-eprocess", 16);
|
||||
if(pProcess->os.win.vaENTRY) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-entry", 16);
|
||||
}
|
||||
// 64-bit PEB and modules
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-peb", 16);
|
||||
if(pProcess->os.win.vaPEB) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-peb", 16);
|
||||
}
|
||||
if(pProcess->os.win.cbLdrModulesDisplayCache) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-modules", pProcess->os.win.cbLdrModulesDisplayCache);
|
||||
}
|
||||
@@ -242,6 +270,19 @@ VOID VmmVfsListFiles_OsSpecific(_In_ PVMM_PROCESS pProcess, _Inout_ PHANDLE pFil
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-peb32", 8);
|
||||
}
|
||||
}
|
||||
if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-eprocess", 8);
|
||||
if(pProcess->os.win.vaENTRY) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-entry", 8);
|
||||
}
|
||||
// PEB and modules
|
||||
if(pProcess->os.win.vaPEB) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-peb", 8);
|
||||
}
|
||||
if(pProcess->os.win.cbLdrModulesDisplayCache) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "win-modules", pProcess->os.win.cbLdrModulesDisplayCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
@@ -291,10 +332,14 @@ BOOL VmmVfsListFilesProcess(_In_ PVMMVFS_PATH pPath, _Inout_ PHANDLE pFileList)
|
||||
VMMDLL_VfsList_AddFile(pFileList, "map", pProcess->cbMemMapDisplayCache);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "name", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pid", 10);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pml4", 16);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "vmem", 0x0001000000000000);
|
||||
if(pProcess->paPML4_UserOpt) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "pml4-user", 16);
|
||||
if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X64) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "vmem", 0x0001000000000000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "dtb", 16);
|
||||
if(pProcess->paDTB_UserOpt) { VMMDLL_VfsList_AddFile(pFileList, "dtb-user", 16); }
|
||||
} else if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86 || ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86PAE) {
|
||||
VMMDLL_VfsList_AddFile(pFileList, "vmem", 0x100000000);
|
||||
VMMDLL_VfsList_AddFile(pFileList, "dtb", 8);
|
||||
if(pProcess->paDTB_UserOpt) { VMMDLL_VfsList_AddFile(pFileList, "dtb-user", 8); }
|
||||
}
|
||||
VmmVfsListFiles_OsSpecific(pProcess, pFileList);
|
||||
PluginManager_ListAll(pProcess, pFileList);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
96
vmm/vmmwin.h
Normal file
96
vmm/vmmwin.h
Normal file
@@ -0,0 +1,96 @@
|
||||
// vmmwin.h : definitions related to windows operating system and processes.
|
||||
// parsing of virtual memory. Windows related features only.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
#ifndef __VMMWIN_H__
|
||||
#define __VMMWIN_H__
|
||||
#include "vmm.h"
|
||||
|
||||
typedef struct tdVMMWIN_EAT_ENTRY {
|
||||
QWORD vaFunction;
|
||||
DWORD vaFunctionOffset;
|
||||
CHAR szFunction[40];
|
||||
} VMMPROC_WINDOWS_EAT_ENTRY, *PVMMPROC_WINDOWS_EAT_ENTRY;
|
||||
|
||||
typedef struct tdVMMWIN_IAT_ENTRY {
|
||||
ULONG64 vaFunction;
|
||||
CHAR szFunction[40];
|
||||
CHAR szModule[64];
|
||||
} VMMWIN_IAT_ENTRY, *PVMMWIN_IAT_ENTRY;
|
||||
|
||||
/*
|
||||
* Load the size of the required display buffer for sections, imports and export
|
||||
* into the pModule struct. The size is a direct consequence of the number of
|
||||
* functions since fixed line sizes are used for all these types. Loading is
|
||||
* done in a recource efficient way to minimize I/O as much as possible.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
*/
|
||||
VOID VmmWin_PE_SetSizeSectionIATEAT_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule);
|
||||
|
||||
/*
|
||||
* Walk the export address table (EAT) from a given pProcess and store it in the
|
||||
* in the caller supplied pEATs/pcEATs structures.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
* -- pEATs
|
||||
* -- pcEATs = number max items of pEATs on entry, number of actual items of pEATs on exit
|
||||
*/
|
||||
VOID VmmWin_PE_LoadEAT_DisplayBuffer(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule, _Out_ PVMMPROC_WINDOWS_EAT_ENTRY pEATs, _Inout_ PDWORD pcEATs);
|
||||
|
||||
/*
|
||||
* Walk the import address table (IAT) from a given pProcess and store it in the
|
||||
* in the caller supplied pIATs/pcIATs structures.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
* -- pIATs
|
||||
* -- pcIATs = number max items of pIATs on entry, number of actual items of pIATs on exit
|
||||
*/
|
||||
VOID VmmWin_PE_LoadIAT_DisplayBuffer(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule, _Out_ PVMMWIN_IAT_ENTRY pIATs, _Inout_ PDWORD pcIATs);
|
||||
|
||||
/*
|
||||
* Fill the pbDisplayBuffer with a human readable version of the data directories.
|
||||
* This is guaranteed to be exactly 864 bytes (excluding NULL terminator).
|
||||
* Alternatively copy the 16 data directories into pDataDirectoryOpt.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
* -- pbDisplayBufferOpt
|
||||
* -- cbDisplayBufferMax
|
||||
* -- pcbDisplayBuffer
|
||||
* -- pDataDirectoryOpt
|
||||
*/
|
||||
VOID VmmWin_PE_DIRECTORY_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _Out_opt_ PBYTE pbDisplayBufferOpt, _In_ DWORD cbDisplayBufferMax, _Out_opt_ PDWORD pcbDisplayBuffer, _Out_writes_opt_(16) PIMAGE_DATA_DIRECTORY pDataDirectoryOpt);
|
||||
|
||||
/*
|
||||
* Fill the pbDisplayBuffer with a human readable version of the PE sections.
|
||||
* Alternatively copy the sections into the pSectionsOpt buffer.
|
||||
* -- pProcess
|
||||
* -- pModule
|
||||
* -- pbDisplayBufferOpt
|
||||
* -- cbDisplayBufferMax
|
||||
* -- pcbDisplayBuffer
|
||||
* -- pcSectionsOpt = size of buffer pSectionsOpt on entry, # returned entries on exit
|
||||
* -- pSectionsOpt
|
||||
*/
|
||||
VOID VmmWin_PE_SECTION_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _Out_opt_ PBYTE pbDisplayBufferOpt, _In_ DWORD cbDisplayBufferMax, _Out_opt_ PDWORD pcbDisplayBuffer, _Inout_opt_ PDWORD pcSectionsOpt, _Out_opt_ PIMAGE_SECTION_HEADER pSectionsOpt);
|
||||
|
||||
/*
|
||||
* Initialize the module names into the ctxVMM. This is performed by a PEB/Ldr
|
||||
* scan of in-process memory structures. This may be unreliable of process is
|
||||
* obfuscated.
|
||||
* -- pProcess
|
||||
*/
|
||||
VOID VmmWin_InitializeModuleNames(_In_ PVMM_PROCESS pProcess);
|
||||
|
||||
/*
|
||||
* Try walk the EPROCESS list in the Windows kernel to enumerate processes into
|
||||
* the VMM/PROC file system.
|
||||
* NB! This may be done to refresh an existing PID cache hence migration code.
|
||||
* -- pSystemProcess
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmWin_EnumerateEPROCESS(_In_ PVMM_PROCESS pSystemProcess);
|
||||
|
||||
#endif /* __VMMWIN_H__ */
|
||||
484
vmm/vmmwininit.c
Normal file
484
vmm/vmmwininit.c
Normal file
@@ -0,0 +1,484 @@
|
||||
// vmmwininit.c : implementation of detection mechanisms for Windows operating
|
||||
// systems. Contains functions for detecting DTB and Memory Model
|
||||
// as well as the Windows kernel base and core functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
|
||||
#include "vmm.h"
|
||||
#include "vmmwin.h"
|
||||
#include "device.h"
|
||||
#include "pe.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
* Scan a page table hierarchy between virtual addresses between vaMin and vaMax
|
||||
* for the first occurence of large 2MB pages. This is usually 'ntoskrnl.exe' if
|
||||
* the OS is Windows. 'ntoskrnl.exe' is loaded between the virtual addresses:
|
||||
* 0xFFFFF80000000000-0xFFFFF803FFFFFFFF
|
||||
* -- paTable = set to: physical address of PML4
|
||||
* -- vaBase = set to 0
|
||||
* -- vaMin = 0xFFFFF80000000000 (if windows kernel)
|
||||
* -- vaMax = 0xFFFFF803FFFFFFFF (if windows kernel)
|
||||
* -- cPML = set to 4
|
||||
* -- pvaBase
|
||||
* -- pcbSize
|
||||
*/
|
||||
VOID VmmWinInit_FindNtosScan64_LargePageWalk(_In_ QWORD paTable, _In_ QWORD vaBase, _In_ QWORD vaMin, _In_ QWORD vaMax, _In_ BYTE iPML, _Inout_ PQWORD pvaBase, _Inout_ PQWORD pcbSize)
|
||||
{
|
||||
const QWORD PML_REGION_SIZE[5] = { 0, 12, 21, 30, 39 };
|
||||
QWORD i, pte, *ptes, vaCurrent, vaSizeRegion;
|
||||
ptes = (PQWORD)VmmTlbGetPageTable(paTable, FALSE);
|
||||
if(!ptes) { return; }
|
||||
if(iPML == 4) {
|
||||
*pvaBase = 0;
|
||||
*pcbSize = 0;
|
||||
if(!VmmTlbPageTableVerify((PBYTE)ptes, paTable, TRUE)) { return; }
|
||||
vaBase = 0;
|
||||
}
|
||||
for(i = 0; i < 512; i++) {
|
||||
// address in range
|
||||
vaSizeRegion = 1ULL << PML_REGION_SIZE[iPML];
|
||||
vaCurrent = vaBase + (i << PML_REGION_SIZE[iPML]);
|
||||
vaCurrent |= (vaCurrent & 0x0000800000000000) ? 0xffff000000000000 : 0; // sign extend
|
||||
if(*pvaBase && (vaCurrent > (*pvaBase + *pcbSize))) { return; }
|
||||
if(vaCurrent < vaMin) { continue; }
|
||||
if(vaCurrent > vaMax) { return; }
|
||||
// check PTEs
|
||||
pte = ptes[i];
|
||||
if(!(pte & 0x01)) { continue; } // NOT VALID
|
||||
if(iPML == 2) {
|
||||
if(!(pte & 0x80)) { continue; }
|
||||
if(!*pvaBase) { *pvaBase = vaCurrent; }
|
||||
*pcbSize += 0x200000;
|
||||
continue;
|
||||
} else {
|
||||
if(pte & 0x80) { continue; } // PS = 1
|
||||
VmmWinInit_FindNtosScan64_LargePageWalk(pte & 0x0000fffffffff000, vaCurrent, vaMin, vaMax, iPML - 1, pvaBase, pcbSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sometimes the PageDirectoryBase (PML4) is known, but the kernel location may
|
||||
* be unknown. This functions walks the page table in the area in which ntoskrnl
|
||||
* is loaded (0xFFFFF80000000000-0xFFFFF803FFFFFFFF) looking for 2MB large pages
|
||||
* If an area in 2MB pages are found it is scanned for the ntoskrnl.exe base.
|
||||
* -- pSystemProcess
|
||||
* -- return = virtual address of ntoskrnl.exe base if successful, otherwise 0.
|
||||
*/
|
||||
QWORD VmmWinInit_FindNtosScan64(PVMM_PROCESS pSystemProcess)
|
||||
{
|
||||
PBYTE pb;
|
||||
QWORD p, o, vaCurrentMin, vaBase, cbSize;
|
||||
CHAR szModuleName[MAX_PATH] = { 0 };
|
||||
vaCurrentMin = 0xFFFFF80000000000;
|
||||
while(TRUE) {
|
||||
vaBase = 0;
|
||||
cbSize = 0;
|
||||
VmmWinInit_FindNtosScan64_LargePageWalk(pSystemProcess->paDTB, 0, vaCurrentMin, 0xFFFFF803FFFFFFFF, 4, &vaBase, &cbSize);
|
||||
if(!vaBase) { return 0; }
|
||||
vaCurrentMin = vaBase + cbSize;
|
||||
if(cbSize >= 0x01000000) { continue; } // too big
|
||||
if(cbSize <= 0x00400000) { continue; } // too small
|
||||
// try locate ntoskrnl.exe base inside suggested area
|
||||
if(!(pb = (PBYTE)LocalAlloc(0, cbSize))) { return 0; }
|
||||
VmmReadEx(pSystemProcess, vaBase, pb, (DWORD)cbSize, NULL, 0);
|
||||
for(p = 0; p < cbSize; p += 0x1000) {
|
||||
// check for (1) MZ header, (2) POOLCODE section, (3) ntoskrnl.exe module name
|
||||
if(*(PWORD)(pb + p) != 0x5a4d) { continue; } // MZ header
|
||||
for(o = 0; o < 0x1000; o += 8) {
|
||||
if(*(PQWORD)(pb + p + o) == 0x45444F434C4F4F50) { // POOLCODE
|
||||
PE_GetModuleNameEx(pSystemProcess, vaBase + p, FALSE, pb + p, szModuleName, NULL);
|
||||
if(!_stricmp(szModuleName, "ntoskrnl.exe")) {
|
||||
LocalFree(pb);
|
||||
return vaBase + p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LocalFree(pb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate the virtual base address of 'ntoskrnl.exe' given any address inside
|
||||
* the kernel. Localization will be done by a scan-back method. A maximum of
|
||||
* 32MB will be scanned back.
|
||||
* -- pSystemProcess
|
||||
* -- return = virtual address of ntoskrnl.exe base if successful, otherwise 0
|
||||
*/
|
||||
QWORD VmmWinInit_FindNtosScanHint64(_In_ PVMM_PROCESS pSystemProcess)
|
||||
{
|
||||
PBYTE pb;
|
||||
QWORD vaBase, o, p, vaNtosBase = 0;
|
||||
DWORD cbRead;
|
||||
QWORD vaHint = ctxVmm->kernel.vaEntry;
|
||||
CHAR szModuleName[MAX_PATH] = { 0 };
|
||||
pb = LocalAlloc(0, 0x00200000);
|
||||
if(!pb) { goto cleanup; }
|
||||
// Scan back in 2MB chunks a time, (ntoskrnl.exe is loaded in 2MB pages).
|
||||
for(vaBase = vaHint & ~0x1fffff; vaBase + 0x02000000 > vaHint; vaBase -= 0x200000) {
|
||||
VmmReadEx(pSystemProcess, vaBase, pb, 0x200000, &cbRead, 0);
|
||||
// only fail here if all virtual memory in read fails. reason is that kernel is
|
||||
// properly mapped in memory (with NX MZ header in separate page) with empty
|
||||
// space before next valid kernel pages when running Virtualization Based Security.
|
||||
if(!cbRead) { goto cleanup; }
|
||||
for(p = 0; p < 0x200000; p += 0x1000) {
|
||||
// check for (1) MZ header, (2) POOLCODE section, (3) ntoskrnl.exe module name
|
||||
if(*(PWORD)(pb + p) != 0x5a4d) { continue; } // MZ header
|
||||
for(o = 0; o < 0x1000; o += 8) {
|
||||
if(*(PQWORD)(pb + p + o) == 0x45444F434C4F4F50) { // POOLCODE
|
||||
PE_GetModuleNameEx(pSystemProcess, vaBase + p, FALSE, pb + p, szModuleName, NULL);
|
||||
if(!_stricmp(szModuleName, "ntoskrnl.exe")) {
|
||||
LocalFree(pb);
|
||||
return vaBase + p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanup:
|
||||
LocalFree(pb);
|
||||
return vaNtosBase;
|
||||
}
|
||||
|
||||
/*
|
||||
* scans the relatively limited memory space 0x80000000-0x83ffffff for the base
|
||||
* of 'ntoskrnl.exe'. NB! this is a very non-optimized way of doing things and
|
||||
* should be improved upon to increase startup performance - but 64MB is not a
|
||||
* huge amount of memory and it's only scanned at startup ...
|
||||
* -- pSystemProcess
|
||||
* -- return = virtual address of ntoskrnl.exe base if successful, otherwise 0.
|
||||
*/
|
||||
DWORD VmmWinInit_FindNtosScan32(_In_ PVMM_PROCESS pSystemProcess)
|
||||
{
|
||||
DWORD o, p;
|
||||
PBYTE pb;
|
||||
CHAR szModuleName[MAX_PATH] = { 0 };
|
||||
if(!(pb = LocalAlloc(LMEM_ZEROINIT, 0x04000000))) { return 0; }
|
||||
for(p = 0; p < 0x04000000; p += 0x1000) {
|
||||
// read 8MB chunks when required.
|
||||
if(0 == p % 0x00800000) {
|
||||
VmmReadEx(pSystemProcess, 0x80000000ULL + p, pb + p, 0x00800000, NULL, 0);
|
||||
}
|
||||
// check for (1) MZ header, (2) POOLCODE section, (3) ntoskrnl.exe module name
|
||||
if(*(PWORD)(pb + p) != 0x5a4d) { continue; } // MZ header
|
||||
for(o = 0; o < 0x1000; o += 8) {
|
||||
if(*(PQWORD)(pb + p + o) == 0x45444F434C4F4F50) { // POOLCODE
|
||||
PE_GetModuleNameEx(pSystemProcess, 0x80000000ULL + p, FALSE, pb + p, szModuleName, NULL);
|
||||
if(!_stricmp(szModuleName, "ntoskrnl.exe")) {
|
||||
LocalFree(pb);
|
||||
return 0x80000000 + p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LocalFree(pb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan for the 'ntoskrnl.exe' by using the DTB and memory model information
|
||||
* from the ctxVmm.
|
||||
* -- ppSystemProcess = ptr to receive pSystemProcess upon success.
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmWinInit_FindNtosScan(_Out_ PVMM_PROCESS *ppSystemProcess)
|
||||
{
|
||||
QWORD vaKernelBase = 0, cbKernelSize;
|
||||
PVMM_PROCESS pSystemProcess;
|
||||
*ppSystemProcess = NULL;
|
||||
// 1: Pre-initialize System PID (required by VMM)
|
||||
pSystemProcess = VmmProcessCreateEntry(4, 0, ctxVmm->kernel.paDTB, 0, "System", FALSE, TRUE);
|
||||
if(!pSystemProcess) { return FALSE; }
|
||||
VmmProcessCreateFinish();
|
||||
// 2: Spider DTB to speed things up.
|
||||
VmmTlbSpider(ctxVmm->kernel.paDTB, FALSE);
|
||||
// 3: Find the base of 'ntoskrnl.exe'
|
||||
if(VMM_MEMORYMODEL_X64 == ctxVmm->tpMemoryModel) {
|
||||
if(ctxVmm->kernel.vaEntry) {
|
||||
vaKernelBase = VmmWinInit_FindNtosScanHint64(pSystemProcess);
|
||||
}
|
||||
if(!vaKernelBase) {
|
||||
vaKernelBase = VmmWinInit_FindNtosScan64(pSystemProcess);
|
||||
}
|
||||
} else {
|
||||
vaKernelBase = VmmWinInit_FindNtosScan32(pSystemProcess);
|
||||
}
|
||||
if(!vaKernelBase) { return FALSE; }
|
||||
cbKernelSize = PE_GetSize(pSystemProcess, vaKernelBase);
|
||||
if(!cbKernelSize) { return FALSE; }
|
||||
*ppSystemProcess = pSystemProcess;
|
||||
ctxVmm->kernel.vaBase = vaKernelBase;
|
||||
ctxVmm->kernel.cbSize = cbKernelSize;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a page looks like the Windows Kernel x86 Directory Table Base (DTB)
|
||||
* in the 32-bit mode - i.e. the PD of the System process.
|
||||
* 1: self-referential entry exists at offset 0xC00
|
||||
* 2: PDE[0] is a user-mode PDE pointing to a PT.
|
||||
* 3: a minimum number of supervisor-mode PDEs must exist.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VmmWinInit_DTB_FindValidate_X86(_In_ QWORD pa, _In_reads_(0x1000) PBYTE pbPage)
|
||||
{
|
||||
DWORD c, i;
|
||||
if((*(PDWORD)(pbPage + 0xc00) & 0xfffff003) != pa + 0x03) { return FALSE; } // self-referential entry exists
|
||||
if(*pbPage != 0x67) { return FALSE; } // user-mode page table exists at 1st PTE (index 0)
|
||||
for(c = 0, i = 0x800; i < 0x1000; i += 4) { // minimum number of supervisor entries above 0x800
|
||||
if((*(pbPage + i) == 0x63) || (*(pbPage + i) == 0xe3)) { c++; }
|
||||
if(c > 16) { return TRUE; }
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a page looks like the Windows Kernel x86 Directory Table Base (DTB)
|
||||
* in the 32-bit PAE memory mode - i.e. the PDPT of the System process.
|
||||
* Also please note that this may not be the actual PDPT used by the kernel -
|
||||
* it may very well rather be the PDPT probably set up by WinLoad and then the
|
||||
* 'System' process uses another. But it works for auto-detect!
|
||||
* 1: (4) valid PDPT entries with consecutive physical addresses of the PDPT.
|
||||
* 2: all zeroes for the rest of the page.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VmmWinInit_DTB_FindValidate_X86PAE(_In_ QWORD pa, _In_reads_(0x1000) PBYTE pbPage)
|
||||
{
|
||||
for(QWORD i = 0; i < 0x1000; i += 8) {
|
||||
if((i < 0x20) && ((*(PQWORD)(pbPage + i) != pa + (i << 9) + 0x1001))) {
|
||||
return FALSE;
|
||||
} else if((i >= 0x20) && *(PQWORD)(pbPage + i)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VmmWinInit_DTB_FindValidate_X64(_In_ QWORD pa, _In_reads_(0x1000) PBYTE pbPage)
|
||||
{
|
||||
DWORD c, i;
|
||||
BOOL fSelfRef = FALSE;
|
||||
QWORD pte, paMax;
|
||||
paMax = ctxMain->cfg.paAddrMax;
|
||||
// check for user-mode page table with PDPT below max physical address and not NX.
|
||||
pte = *(PQWORD)pbPage;
|
||||
if(((pte & 0x8000000000000087) != 0x07) || ((pte & 0x0000fffffffff000) > paMax)) { return FALSE; }
|
||||
for(c = 0, i = 0x800; i < 0x1000; i += 8) { // minimum number of supervisor entries above 0x800
|
||||
pte = *(PQWORD)(pbPage + i);
|
||||
// check for user-mode page table with PDPT below max physical address and not NX.
|
||||
if(((pte & 0x8000ff0000000087) == 0x03) && ((pte & 0x0000fffffffff000) > paMax)) { c++; }
|
||||
// check for self-referential entry
|
||||
if((*(PQWORD)(pbPage + i) & 0x8000fffffffff083) == pa + 0x03) { fSelfRef = TRUE; }
|
||||
}
|
||||
return fSelfRef && (c >= 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find and validate the low stub (loaded <1MB if exists). The low stub almost
|
||||
* always exists on real hardware. It may be missing on virtual machines though.
|
||||
* Upon success both the PML4 and 'ntoskrnl.exe' KernelEntry point are located.
|
||||
* The PML4 is stored as the ctxVmm->kernel.paDTB and the KernelEntry is stored
|
||||
* as ctxVmm->kernel.vaHintOpt
|
||||
*/
|
||||
BOOL VmmWinInit_DTB_FindValidate_X64_LowStub(_In_ PBYTE pbLowStub1M)
|
||||
{
|
||||
DWORD o = 0;
|
||||
while(o < 0x100000) {
|
||||
o += 0x1000;
|
||||
if(0x00000001000600E9 != (0xffffffffffff00ff & *(PQWORD)(pbLowStub1M + o + 0x000))) { continue; } // START BYTES
|
||||
if(0xfffff80000000000 != (0xfffff80000000003 & *(PQWORD)(pbLowStub1M + o + 0x070))) { continue; } // KERNEL ENTRY
|
||||
if(0xffffff0000000fff & *(PQWORD)(pbLowStub1M + o + 0x0a0)) { continue; } // PML4
|
||||
ctxVmm->kernel.vaEntry = *(PQWORD)(pbLowStub1M + o + 0x070);
|
||||
ctxVmm->kernel.paDTB = *(PQWORD)(pbLowStub1M + o + 0x0a0);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tries to locate the Directory Table Base and the Memory Model by using various
|
||||
* detection and scanning functions. Upon success memory model and kernel DTB is
|
||||
* returned in the ctxVmm context.
|
||||
-- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VmmWinInit_DTB_FindValidate()
|
||||
{
|
||||
DWORD pa;
|
||||
QWORD paDTB = 0;
|
||||
PBYTE pb16M;
|
||||
if(!(pb16M = LocalAlloc(LMEM_ZEROINIT, 0x01000000))) { return FALSE; }
|
||||
// 1: try locate DTB via X64 low stub in lower 1MB
|
||||
DeviceReadMEMEx(0, pb16M, 0x00100000, NULL);
|
||||
if(VmmWinInit_DTB_FindValidate_X64_LowStub(pb16M)) {
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_X64);
|
||||
paDTB = ctxVmm->kernel.paDTB;
|
||||
}
|
||||
// 2: try locate DTB by scanning in lower 16MB
|
||||
// X64
|
||||
if(!paDTB) {
|
||||
for(pa = 0; pa < 0x01000000; pa += 0x1000) {
|
||||
if(pa == 0x00100000) {
|
||||
DeviceReadMEMEx(0x00100000, pb16M + 0x00100000, 0x00f00000, NULL);
|
||||
}
|
||||
if(VmmWinInit_DTB_FindValidate_X64(pa, pb16M + pa)) {
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_X64);
|
||||
paDTB = pa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// X86-PAE
|
||||
if(!paDTB) {
|
||||
for(pa = 0; pa < 0x01000000; pa += 0x1000) {
|
||||
if(VmmWinInit_DTB_FindValidate_X86PAE(pa, pb16M + pa)) {
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_X86PAE);
|
||||
paDTB = pa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// X86
|
||||
if(!paDTB) {
|
||||
for(pa = 0; pa < 0x01000000; pa += 0x1000) {
|
||||
if(VmmWinInit_DTB_FindValidate_X86(pa, pb16M + pa)) {
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_X86);
|
||||
paDTB = pa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LocalFree(pb16M);
|
||||
if(!paDTB) { return FALSE; }
|
||||
ctxVmm->kernel.paDTB = paDTB;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate a DTB supplied by the user. The memory model will be detected and
|
||||
* the result will be stored in the ctxVmm context upon success.
|
||||
* -- paDTB
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmWinInit_DTB_Validate(QWORD paDTB)
|
||||
{
|
||||
BYTE pb[0x1000];
|
||||
DeviceReadMEMEx(0, pb, 0x1000, NULL);
|
||||
if(VmmWinInit_DTB_FindValidate_X64(paDTB, pb)) {
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_X64);
|
||||
ctxVmm->kernel.paDTB = paDTB;
|
||||
return TRUE;
|
||||
}
|
||||
if(VmmWinInit_DTB_FindValidate_X86PAE(paDTB, pb)) {
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_X86PAE);
|
||||
ctxVmm->kernel.paDTB = paDTB;
|
||||
return TRUE;
|
||||
}
|
||||
if(VmmWinInit_DTB_FindValidate_X86(paDTB, pb)) {
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_X86);
|
||||
ctxVmm->kernel.paDTB = paDTB;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL VmmWinInit_FindPsLoadedModuleListKDBG(_In_ PVMM_PROCESS pSystemProcess)
|
||||
{
|
||||
PBYTE pbData = NULL, pbKDBG;
|
||||
IMAGE_SECTION_HEADER SectionHeader;
|
||||
DWORD o;
|
||||
QWORD va;
|
||||
// 1: Try locate 'PsLoadedModuleList' by exported kernel symbol. If this is
|
||||
// possible it's most probably Windows 10 and KDBG will be encrypted so
|
||||
// no need to continue looking for it.
|
||||
ctxVmm->kernel.vaPsLoadedModuleList = PE_GetProcAddress(pSystemProcess, ctxVmm->kernel.vaBase, "PsLoadedModuleList");
|
||||
if(ctxVmm->kernel.vaPsLoadedModuleList) { return TRUE; }
|
||||
// 2: Try locate 'KDBG' by looking in 'ntoskrnl.exe' '.text' section. This
|
||||
// is the normal way of finding it on 64-bit Windows below Windows 10.
|
||||
// This also works on 32-bit Windows versions - so use this method for
|
||||
// simplicity rather than using a separate 32-bit method.
|
||||
if(!ctxVmm->kernel.vaKDBG) {
|
||||
if(!PE_SectionGetFromName(pSystemProcess, ctxVmm->kernel.vaBase, ".data", &SectionHeader)) { goto fail; }
|
||||
if((SectionHeader.Misc.VirtualSize > 0x00100000) || (SectionHeader.VirtualAddress > 0x01000000)) { goto fail; }
|
||||
if(!(pbData = LocalAlloc(LMEM_ZEROINIT, SectionHeader.Misc.VirtualSize))) { goto fail; }
|
||||
VmmReadEx(pSystemProcess, ctxVmm->kernel.vaBase + SectionHeader.VirtualAddress, pbData, SectionHeader.Misc.VirtualSize, NULL, 0);
|
||||
for(o = 16; o <= SectionHeader.Misc.VirtualSize - 0x290; o += 4) {
|
||||
if(*(PDWORD)(pbData + o) == 0x4742444b) { // KDBG tag
|
||||
pbKDBG = pbData + o - 16;
|
||||
if(ctxVmm->kernel.vaBase != *(PQWORD)(pbKDBG + 0x18)) { continue; }
|
||||
// fetch PsLoadedModuleList
|
||||
va = *(PQWORD)(pbKDBG + 0x48);
|
||||
if((va < ctxVmm->kernel.vaBase) || (va > ctxVmm->kernel.vaBase + ctxVmm->kernel.cbSize)) { goto fail; }
|
||||
if(!VmmRead(pSystemProcess, va, (PBYTE)&ctxVmm->kernel.vaPsLoadedModuleList, ctxVmm->f32 ? 4 : 8)) { goto fail; }
|
||||
// finish!
|
||||
ctxVmm->kernel.vaKDBG = ctxVmm->kernel.vaBase + SectionHeader.VirtualAddress + o - 16;
|
||||
LocalFree(pbData);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
fail:
|
||||
LocalFree(pbData);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try initialize the VMM from scratch with new WINDOWS support.
|
||||
* -- paDTBOpt
|
||||
* -- return
|
||||
*/
|
||||
BOOL VmmWinInit_TryInitialize(_In_opt_ QWORD paDTBOpt)
|
||||
{
|
||||
PVMM_PROCESS pSystemProcess = NULL;
|
||||
QWORD vaPsInitialSystemProcess, vaSystemEPROCESS;
|
||||
// Fetch Directory Base (DTB (PML4)) and initialize Memory Model.
|
||||
if(paDTBOpt) {
|
||||
if(!VmmWinInit_DTB_Validate(paDTBOpt)) {
|
||||
vmmprintfv("VmmWinInit_TryInitialize: Initialization Failed. Unable to verify user-supplied DTB. #1\n");
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
if(!VmmWinInit_DTB_FindValidate()) {
|
||||
vmmprintfv("VmmWinInit_TryInitialize: Initialization Failed. Unable to locate valid DTB. #2\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
vmmprintfvv("VmmWinInit_TryInitialize: INFO: DTB located at: %016llx. MemoryModel: %s\n", ctxVmm->kernel.paDTB, VMM_MEMORYMODEL_TOSTRING[ctxVmm->tpMemoryModel]);
|
||||
// Fetch 'ntoskrnl.exe' base address
|
||||
if(!VmmWinInit_FindNtosScan(&pSystemProcess)) {
|
||||
vmmprintfv("VmmWinInit_TryInitialize: Initialization Failed. Unable to locate ntoskrnl.exe. #3\n");
|
||||
goto fail;
|
||||
}
|
||||
vmmprintfvv("VmmWinInit_TryInitialize: INFO: NTOS located at: %016llx.\n", ctxVmm->kernel.vaBase);
|
||||
// Locate System EPROCESS
|
||||
vaPsInitialSystemProcess = PE_GetProcAddress(pSystemProcess, ctxVmm->kernel.vaBase, "PsInitialSystemProcess");
|
||||
if(!VmmRead(pSystemProcess, vaPsInitialSystemProcess, (PBYTE)&vaSystemEPROCESS, 8)) {
|
||||
vmmprintfv("VmmWinInit_TryInitialize: Initialization Failed. Unable to locate EPROCESS. #4\n");
|
||||
goto fail;
|
||||
}
|
||||
if((VMM_MEMORYMODEL_X86 == ctxVmm->tpMemoryModel) || (VMM_MEMORYMODEL_X86PAE == ctxVmm->tpMemoryModel)) {
|
||||
vaSystemEPROCESS &= 0xffffffff;
|
||||
}
|
||||
pSystemProcess->os.win.vaEPROCESS = vaSystemEPROCESS;
|
||||
vmmprintfvv("VmmWinInit_TryInitialize: INFO: PsInitialSystemProcess located at %016llx.\n", vaPsInitialSystemProcess);
|
||||
vmmprintfvv("VmmWinInit_TryInitialize: INFO: EPROCESS located at %016llx.\n", vaSystemEPROCESS);
|
||||
// Enumerate processes
|
||||
if(!VmmWin_EnumerateEPROCESS(pSystemProcess)) {
|
||||
vmmprintfv("VmmWinInit: Initialization Failed. Unable to walk EPROCESS. #5\n");
|
||||
goto fail;
|
||||
}
|
||||
ctxVmm->tpSystem = (VMM_MEMORYMODEL_X64 == ctxVmm->tpMemoryModel) ? VMM_SYSTEM_WINDOWS_X64 : VMM_SYSTEM_WINDOWS_X86;
|
||||
// Optionally fetch PsLoadedModuleList / KDBG
|
||||
VmmWinInit_FindPsLoadedModuleListKDBG(pSystemProcess);
|
||||
return TRUE;
|
||||
fail:
|
||||
VmmInitializeMemoryModel(VMM_MEMORYMODEL_NA); // clean memory model
|
||||
ZeroMemory(&ctxVmm->kernel, sizeof(VMM_KERNELINFO));
|
||||
return FALSE;
|
||||
}
|
||||
21
vmm/vmmwininit.h
Normal file
21
vmm/vmmwininit.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// vmmwininit.h : declarations of detection mechanisms for Windows operating
|
||||
// systems. Contains functions for detecting DTB and Memory Model
|
||||
// as well as the Windows kernel base and core functionality.
|
||||
//
|
||||
// (c) Ulf Frisk, 2018
|
||||
// Author: Ulf Frisk, pcileech@frizk.net
|
||||
//
|
||||
|
||||
#ifndef __VMMWININIT_H__
|
||||
#define __VMMWININIT_H__
|
||||
#include "vmm.h"
|
||||
|
||||
/*
|
||||
* Try initialize the VMM from scratch with new WINDOWS support.
|
||||
* -- paDTB
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VmmWinInit_TryInitialize(_In_opt_ QWORD paDTB);
|
||||
|
||||
#endif /* __VMMWININIT_H__ */
|
||||
@@ -23,6 +23,7 @@ extern "C" {
|
||||
* Call other VMMDLL_Intialize functions to initialize VMM.DLL and the memory
|
||||
* process file system.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
|
||||
/*
|
||||
@@ -37,6 +38,7 @@ BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -52,6 +54,7 @@ BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBase
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -60,6 +63,7 @@ BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPST
|
||||
* initialized in read/write mode upon success.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
|
||||
/*
|
||||
@@ -67,6 +71,7 @@ BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
* including plugins, linked PCILeech.DLL and other memory resources.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_Close();
|
||||
|
||||
|
||||
@@ -103,7 +108,8 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
|
||||
#define VMMDLL_OPT_CORE_TARGET_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
|
||||
|
||||
#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
|
||||
#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
|
||||
@@ -116,6 +122,22 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
|
||||
#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
|
||||
|
||||
static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
|
||||
|
||||
typedef enum tdVMMDLL_MEMORYMODEL_TP {
|
||||
VMMDLL_MEMORYMODEL_NA = 0,
|
||||
VMMDLL_MEMORYMODEL_X86 = 1,
|
||||
VMMDLL_MEMORYMODEL_X86PAE = 2,
|
||||
VMMDLL_MEMORYMODEL_X64 = 3
|
||||
} VMMDLL_MEMORYMODEL_TP;
|
||||
|
||||
typedef enum tdVMMDLL_SYSTEM_TP {
|
||||
VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
|
||||
VMMDLL_SYSTEM_WINDOWS_X64 = 2,
|
||||
VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
|
||||
VMMDLL_SYSTEM_WINDOWS_X86 = 4
|
||||
} VMMDLL_SYSTEM_TP;
|
||||
|
||||
/*
|
||||
* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
|
||||
* mation about valid option values. Please note that option values may overlap
|
||||
@@ -124,6 +146,7 @@ BOOL VMMDLL_Close();
|
||||
* -- pqwValue = pointer to ULONG64 to receive option value.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
|
||||
/*
|
||||
@@ -134,6 +157,7 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
* -- qwValue
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
|
||||
|
||||
|
||||
@@ -171,6 +195,7 @@ typedef struct tdVMMDLL_VFS_FILELIST {
|
||||
* -- pFileList
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
|
||||
|
||||
/*
|
||||
@@ -227,12 +252,13 @@ NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb,
|
||||
* will be unloaded on a general close of the vmm dll.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsInitializePlugins();
|
||||
|
||||
#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
|
||||
#define VMMDLL_PLUGIN_CONTEXT_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 2
|
||||
|
||||
#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
|
||||
|
||||
@@ -254,7 +280,8 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem;
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel;
|
||||
VMMDLL_SYSTEM_TP tpSystem;
|
||||
HMODULE hDLL;
|
||||
HMODULE hReservedDll; // not for general use (only used for python).
|
||||
BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
|
||||
@@ -272,7 +299,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
// function plugin registration info to be filled out by the plugin below:
|
||||
struct {
|
||||
BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
|
||||
VOID(*pfnNotify)(_Inout_opt_ PHANDLE phModulePrivate, _In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
|
||||
VOID(*pfnCloseHandleModule)(_Inout_opt_ PHANDLE phModulePrivate);
|
||||
@@ -296,8 +323,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
|
||||
#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
|
||||
|
||||
#define VMMDLL_TARGET_UNKNOWN_X64 0x0001
|
||||
#define VMMDLL_TARGET_WINDOWS_X64 0x0002
|
||||
#define VMMDLL_MEM_IO_SCATTER_HEADER_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
ULONG64 qwA; // base address (DWORD boundry).
|
||||
@@ -306,6 +332,10 @@ typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
|
||||
PVOID pvReserved1; // reserved for use by caller.
|
||||
PVOID pvReserved2; // reserved for use by caller.
|
||||
WORD version; // version of struct
|
||||
WORD Future1; // reserved for future use.
|
||||
DWORD Future2; // reserved for future use.
|
||||
ULONG64 qwDeviceA; // device-physical address (used by device layer).
|
||||
struct {
|
||||
PVOID pvReserved1;
|
||||
PVOID pvReserved2;
|
||||
@@ -335,6 +365,7 @@ DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPVMMDLL_MEM_IO_SCATTER_HE
|
||||
* -- pbPage
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
|
||||
|
||||
/*
|
||||
@@ -345,6 +376,7 @@ BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4
|
||||
* -- cb
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
@@ -358,7 +390,8 @@ BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DW
|
||||
* -- return = success/fail. NB! reads may report as success even if 0 bytes are
|
||||
* read - it's recommended to verify pcbReadOpt parameter.
|
||||
*/
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
|
||||
/*
|
||||
* Write a contigious arbitrary amount of memory. Please note some virtual memory
|
||||
@@ -373,7 +406,8 @@ BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In
|
||||
* -- cb
|
||||
* -- return = TRUE on success, FALSE on partial or zero write.
|
||||
*/
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address by walking the page tables
|
||||
@@ -383,6 +417,7 @@ BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ D
|
||||
* -- pqwPA
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
|
||||
|
||||
|
||||
@@ -401,6 +436,7 @@ BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqw
|
||||
* -- pdwPID = pointer that will receive PID on success.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
|
||||
/*
|
||||
@@ -409,7 +445,8 @@ BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_PidList(_Out_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
|
||||
// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
|
||||
#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
|
||||
@@ -437,6 +474,7 @@ typedef struct tdVMMDLL_MEMMAP_ENTRY {
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
|
||||
|
||||
/*
|
||||
@@ -448,6 +486,7 @@ BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
|
||||
|
||||
typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
@@ -469,7 +508,8 @@ typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
* -- pcModuleEntries = pointer to number of memory map entries.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
|
||||
/*
|
||||
* Retrieve a module (.exe or .dll or similar) given a module name.
|
||||
@@ -478,29 +518,31 @@ BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY
|
||||
* -- pModuleEntry
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
|
||||
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 1
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem; // as given by VMMDLL_TARGET_*
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
|
||||
VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
DWORD dwPID;
|
||||
DWORD dwState;
|
||||
CHAR szName[16];
|
||||
ULONG64 paPML4;
|
||||
ULONG64 paPML4_UserOpt; // may not exist
|
||||
ULONG64 paDTB;
|
||||
ULONG64 paDTB_UserOpt; // may not exist
|
||||
union {
|
||||
struct {
|
||||
ULONG64 vaEPROCESS;
|
||||
ULONG64 vaPEB;
|
||||
ULONG64 vaENTRY;
|
||||
BOOL fWow64;
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
} win;
|
||||
} os;
|
||||
} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
|
||||
@@ -513,6 +555,7 @@ typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
|
||||
|
||||
typedef struct tdVMMDLL_EAT_ENTRY {
|
||||
@@ -539,10 +582,14 @@ typedef struct tdVMMDLL_IAT_ENTRY {
|
||||
* -- pcData
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
|
||||
|
||||
|
||||
@@ -558,7 +605,8 @@ BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_I
|
||||
* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
|
||||
* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
|
||||
*/
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_ LPSTR sz, _Inout_ PDWORD pcsz);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -194,8 +194,8 @@ int main(_In_ int argc, _In_ char* argv[])
|
||||
if(result) {
|
||||
printf("SUCCESS: VMMDLL_ProcessGetInformation\n");
|
||||
printf(" Name = %s\n", ProcessInformation.szName);
|
||||
printf(" PageDirectoryBase = 0x%016llx\n", ProcessInformation.paPML4);
|
||||
printf(" PageDirectoryBaseUser = 0x%016llx\n", ProcessInformation.paPML4_UserOpt);
|
||||
printf(" PageDirectoryBase = 0x%016llx\n", ProcessInformation.paDTB);
|
||||
printf(" PageDirectoryBaseUser = 0x%016llx\n", ProcessInformation.paDTB_UserOpt);
|
||||
printf(" ProcessState = 0x%08x\n", ProcessInformation.dwState);
|
||||
} else {
|
||||
printf("FAIL: VMMDLL_ProcessGetInformation\n");
|
||||
|
||||
@@ -23,6 +23,7 @@ extern "C" {
|
||||
* Call other VMMDLL_Intialize functions to initialize VMM.DLL and the memory
|
||||
* process file system.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
|
||||
/*
|
||||
@@ -37,6 +38,7 @@ BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -52,6 +54,7 @@ BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBase
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -60,6 +63,7 @@ BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPST
|
||||
* initialized in read/write mode upon success.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
|
||||
/*
|
||||
@@ -67,6 +71,7 @@ BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
* including plugins, linked PCILeech.DLL and other memory resources.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_Close();
|
||||
|
||||
|
||||
@@ -103,7 +108,8 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
|
||||
#define VMMDLL_OPT_CORE_TARGET_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
|
||||
|
||||
#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
|
||||
#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
|
||||
@@ -116,6 +122,22 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
|
||||
#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
|
||||
|
||||
static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
|
||||
|
||||
typedef enum tdVMMDLL_MEMORYMODEL_TP {
|
||||
VMMDLL_MEMORYMODEL_NA = 0,
|
||||
VMMDLL_MEMORYMODEL_X86 = 1,
|
||||
VMMDLL_MEMORYMODEL_X86PAE = 2,
|
||||
VMMDLL_MEMORYMODEL_X64 = 3
|
||||
} VMMDLL_MEMORYMODEL_TP;
|
||||
|
||||
typedef enum tdVMMDLL_SYSTEM_TP {
|
||||
VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
|
||||
VMMDLL_SYSTEM_WINDOWS_X64 = 2,
|
||||
VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
|
||||
VMMDLL_SYSTEM_WINDOWS_X86 = 4
|
||||
} VMMDLL_SYSTEM_TP;
|
||||
|
||||
/*
|
||||
* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
|
||||
* mation about valid option values. Please note that option values may overlap
|
||||
@@ -124,6 +146,7 @@ BOOL VMMDLL_Close();
|
||||
* -- pqwValue = pointer to ULONG64 to receive option value.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
|
||||
/*
|
||||
@@ -134,6 +157,7 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
* -- qwValue
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
|
||||
|
||||
|
||||
@@ -171,6 +195,7 @@ typedef struct tdVMMDLL_VFS_FILELIST {
|
||||
* -- pFileList
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
|
||||
|
||||
/*
|
||||
@@ -227,12 +252,13 @@ NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb,
|
||||
* will be unloaded on a general close of the vmm dll.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsInitializePlugins();
|
||||
|
||||
#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
|
||||
#define VMMDLL_PLUGIN_CONTEXT_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 2
|
||||
|
||||
#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
|
||||
|
||||
@@ -254,7 +280,8 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem;
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel;
|
||||
VMMDLL_SYSTEM_TP tpSystem;
|
||||
HMODULE hDLL;
|
||||
HMODULE hReservedDll; // not for general use (only used for python).
|
||||
BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
|
||||
@@ -272,7 +299,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
// function plugin registration info to be filled out by the plugin below:
|
||||
struct {
|
||||
BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
|
||||
VOID(*pfnNotify)(_Inout_opt_ PHANDLE phModulePrivate, _In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
|
||||
VOID(*pfnCloseHandleModule)(_Inout_opt_ PHANDLE phModulePrivate);
|
||||
@@ -296,8 +323,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
|
||||
#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
|
||||
|
||||
#define VMMDLL_TARGET_UNKNOWN_X64 0x0001
|
||||
#define VMMDLL_TARGET_WINDOWS_X64 0x0002
|
||||
#define VMMDLL_MEM_IO_SCATTER_HEADER_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
ULONG64 qwA; // base address (DWORD boundry).
|
||||
@@ -306,6 +332,10 @@ typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
|
||||
PVOID pvReserved1; // reserved for use by caller.
|
||||
PVOID pvReserved2; // reserved for use by caller.
|
||||
WORD version; // version of struct
|
||||
WORD Future1; // reserved for future use.
|
||||
DWORD Future2; // reserved for future use.
|
||||
ULONG64 qwDeviceA; // device-physical address (used by device layer).
|
||||
struct {
|
||||
PVOID pvReserved1;
|
||||
PVOID pvReserved2;
|
||||
@@ -335,6 +365,7 @@ DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPVMMDLL_MEM_IO_SCATTER_HE
|
||||
* -- pbPage
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
|
||||
|
||||
/*
|
||||
@@ -345,6 +376,7 @@ BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4
|
||||
* -- cb
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
@@ -358,7 +390,8 @@ BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DW
|
||||
* -- return = success/fail. NB! reads may report as success even if 0 bytes are
|
||||
* read - it's recommended to verify pcbReadOpt parameter.
|
||||
*/
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
|
||||
/*
|
||||
* Write a contigious arbitrary amount of memory. Please note some virtual memory
|
||||
@@ -373,7 +406,8 @@ BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In
|
||||
* -- cb
|
||||
* -- return = TRUE on success, FALSE on partial or zero write.
|
||||
*/
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address by walking the page tables
|
||||
@@ -383,6 +417,7 @@ BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ D
|
||||
* -- pqwPA
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
|
||||
|
||||
|
||||
@@ -401,6 +436,7 @@ BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqw
|
||||
* -- pdwPID = pointer that will receive PID on success.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
|
||||
/*
|
||||
@@ -409,7 +445,8 @@ BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_PidList(_Out_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
|
||||
// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
|
||||
#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
|
||||
@@ -437,6 +474,7 @@ typedef struct tdVMMDLL_MEMMAP_ENTRY {
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
|
||||
|
||||
/*
|
||||
@@ -448,6 +486,7 @@ BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
|
||||
|
||||
typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
@@ -469,7 +508,8 @@ typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
* -- pcModuleEntries = pointer to number of memory map entries.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
|
||||
/*
|
||||
* Retrieve a module (.exe or .dll or similar) given a module name.
|
||||
@@ -478,29 +518,31 @@ BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY
|
||||
* -- pModuleEntry
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
|
||||
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 1
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem; // as given by VMMDLL_TARGET_*
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
|
||||
VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
DWORD dwPID;
|
||||
DWORD dwState;
|
||||
CHAR szName[16];
|
||||
ULONG64 paPML4;
|
||||
ULONG64 paPML4_UserOpt; // may not exist
|
||||
ULONG64 paDTB;
|
||||
ULONG64 paDTB_UserOpt; // may not exist
|
||||
union {
|
||||
struct {
|
||||
ULONG64 vaEPROCESS;
|
||||
ULONG64 vaPEB;
|
||||
ULONG64 vaENTRY;
|
||||
BOOL fWow64;
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
} win;
|
||||
} os;
|
||||
} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
|
||||
@@ -513,6 +555,7 @@ typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
|
||||
|
||||
typedef struct tdVMMDLL_EAT_ENTRY {
|
||||
@@ -539,10 +582,14 @@ typedef struct tdVMMDLL_IAT_ENTRY {
|
||||
* -- pcData
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
|
||||
|
||||
|
||||
@@ -558,7 +605,8 @@ BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_I
|
||||
* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
|
||||
* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
|
||||
*/
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_ LPSTR sz, _Inout_ PDWORD pcsz);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -96,8 +96,8 @@ VMMPYC_MemReadScatter(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *pyListSrc, *pyListItemSrc, *pyListDst, *pyDict;
|
||||
BOOL result;
|
||||
DWORD dwPID, cMEMs, i, flags = 0;
|
||||
ULONG64 qwA;
|
||||
DWORD dwPID, cMEMs, flags = 0;
|
||||
ULONG64 i, qwA;
|
||||
PVMMDLL_MEM_IO_SCATTER_HEADER pMEM, pMEMs;
|
||||
PPVMMDLL_MEM_IO_SCATTER_HEADER ppMEMs;
|
||||
PBYTE pb, pbDataBuffer;
|
||||
@@ -243,7 +243,7 @@ VMMPYC_ProcessGetMemoryMap(PyObject *self, PyObject *args)
|
||||
PyObject *pyList, *pyDict;
|
||||
BOOL result, fIdentifyModules;
|
||||
DWORD dwPID, i;
|
||||
ULONG64 cMemMapEntries;
|
||||
ULONG64 cMemMapEntries = 0;
|
||||
PVMMDLL_MEMMAP_ENTRY pe, pMemMapEntries = NULL;
|
||||
CHAR sz[5];
|
||||
if(!PyArg_ParseTuple(args, "k|p", &dwPID, &fIdentifyModules)) { return NULL; }
|
||||
@@ -323,7 +323,7 @@ VMMPYC_ProcessGetModuleMap(PyObject *self, PyObject *args)
|
||||
PyObject *pyList, *pyDict;
|
||||
BOOL result;
|
||||
DWORD dwPID;
|
||||
ULONG64 i, cModuleEntries;
|
||||
ULONG64 i, cModuleEntries = 0;
|
||||
PVMMDLL_MODULEMAP_ENTRY pe, pModuleEntries = NULL;
|
||||
if(!PyArg_ParseTuple(args, "k", &dwPID)) { return NULL; }
|
||||
if(!(pyList = PyList_New(0))) { return PyErr_NoMemory(); }
|
||||
@@ -402,7 +402,7 @@ VMMPYC_PidList(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *pyList;
|
||||
BOOL result;
|
||||
ULONG64 cPIDs;
|
||||
ULONG64 cPIDs = 0;
|
||||
DWORD i, *pPIDs = NULL;
|
||||
if(!(pyList = PyList_New(0))) { return PyErr_NoMemory(); }
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
@@ -445,18 +445,26 @@ VMMPYC_ProcessGetInformation(PyObject *self, PyObject *args)
|
||||
return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetInformation: Failed.");
|
||||
}
|
||||
PyDict_SetItemString(pyDict, "pid", PyLong_FromUnsignedLong(info.dwPID));
|
||||
PyDict_SetItemString(pyDict, "pa-pml4", PyLong_FromUnsignedLongLong(info.paPML4));
|
||||
PyDict_SetItemString(pyDict, "pa-pml4-user", PyLong_FromUnsignedLongLong(info.paPML4_UserOpt));
|
||||
PyDict_SetItemString(pyDict, "pa-dtb", PyLong_FromUnsignedLongLong(info.paDTB));
|
||||
PyDict_SetItemString(pyDict, "pa-dtb-user", PyLong_FromUnsignedLongLong(info.paDTB_UserOpt));
|
||||
PyDict_SetItemString(pyDict, "state", PyLong_FromUnsignedLong(info.dwState));
|
||||
PyDict_SetItemString(pyDict, "target", PyLong_FromUnsignedLong(info.fTargetSystem));
|
||||
PyDict_SetItemString(pyDict, "tp-memorymodel", PyLong_FromUnsignedLong(info.tpMemoryModel));
|
||||
PyDict_SetItemString(pyDict, "tp-system", PyLong_FromUnsignedLong(info.tpSystem));
|
||||
PyDict_SetItemString(pyDict, "usermode", PyBool_FromLong(info.fUserOnly));
|
||||
PyDict_SetItemString(pyDict, "name", PyUnicode_FromString(info.szName));
|
||||
if(info.fTargetSystem == VMMDLL_TARGET_WINDOWS_X64) {
|
||||
PyDict_SetItemString(pyDict, "wow64", PyBool_FromLong((long)info.os.win.fWow64));
|
||||
PyDict_SetItemString(pyDict, "va-entry", PyLong_FromUnsignedLongLong(info.os.win.vaENTRY));
|
||||
PyDict_SetItemString(pyDict, "va-eprocess", PyLong_FromUnsignedLongLong(info.os.win.vaEPROCESS));
|
||||
PyDict_SetItemString(pyDict, "va-peb", PyLong_FromUnsignedLongLong(info.os.win.vaPEB));
|
||||
PyDict_SetItemString(pyDict, "va-peb32", PyLong_FromUnsignedLongLong(info.os.win.vaPEB32));
|
||||
switch(info.tpSystem) {
|
||||
case VMMDLL_SYSTEM_WINDOWS_X64:
|
||||
PyDict_SetItemString(pyDict, "wow64", PyBool_FromLong((long)info.os.win.fWow64));
|
||||
PyDict_SetItemString(pyDict, "va-entry", PyLong_FromUnsignedLongLong(info.os.win.vaENTRY));
|
||||
PyDict_SetItemString(pyDict, "va-eprocess", PyLong_FromUnsignedLongLong(info.os.win.vaEPROCESS));
|
||||
PyDict_SetItemString(pyDict, "va-peb", PyLong_FromUnsignedLongLong(info.os.win.vaPEB));
|
||||
PyDict_SetItemString(pyDict, "va-peb32", PyLong_FromUnsignedLongLong(info.os.win.vaPEB32));
|
||||
break;
|
||||
case VMMDLL_SYSTEM_WINDOWS_X86:
|
||||
PyDict_SetItemString(pyDict, "va-entry", PyLong_FromUnsignedLongLong(info.os.win.vaENTRY));
|
||||
PyDict_SetItemString(pyDict, "va-eprocess", PyLong_FromUnsignedLongLong(info.os.win.vaEPROCESS));
|
||||
PyDict_SetItemString(pyDict, "va-peb", PyLong_FromUnsignedLongLong(info.os.win.vaPEB));
|
||||
break;
|
||||
}
|
||||
return pyDict;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ extern "C" {
|
||||
* Call other VMMDLL_Intialize functions to initialize VMM.DLL and the memory
|
||||
* process file system.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
|
||||
/*
|
||||
@@ -37,6 +38,7 @@ BOOL VMMDLL_InitializeReserved(_In_ DWORD argc, _In_ LPSTR argv[]);
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -52,6 +54,7 @@ BOOL VMMDLL_InitializeFile(_In_ LPSTR szFileName, _In_opt_ LPSTR szPageTableBase
|
||||
* as hex string. NB! this is usally not required. Example: "0x1ab000".
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPSTR szPageTableBaseOpt);
|
||||
|
||||
/*
|
||||
@@ -60,6 +63,7 @@ BOOL VMMDLL_InitializeFPGA(_In_opt_ LPSTR szMaxPhysicalAddressOpt, _In_opt_ LPST
|
||||
* initialized in read/write mode upon success.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
|
||||
/*
|
||||
@@ -67,6 +71,7 @@ BOOL VMMDLL_InitializeTotalMeltdown();
|
||||
* including plugins, linked PCILeech.DLL and other memory resources.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_Close();
|
||||
|
||||
|
||||
@@ -103,7 +108,8 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
|
||||
#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
|
||||
#define VMMDLL_OPT_CORE_TARGET_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
|
||||
#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
|
||||
|
||||
#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
|
||||
#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
|
||||
@@ -116,6 +122,22 @@ BOOL VMMDLL_Close();
|
||||
#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
|
||||
#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
|
||||
|
||||
static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
|
||||
|
||||
typedef enum tdVMMDLL_MEMORYMODEL_TP {
|
||||
VMMDLL_MEMORYMODEL_NA = 0,
|
||||
VMMDLL_MEMORYMODEL_X86 = 1,
|
||||
VMMDLL_MEMORYMODEL_X86PAE = 2,
|
||||
VMMDLL_MEMORYMODEL_X64 = 3
|
||||
} VMMDLL_MEMORYMODEL_TP;
|
||||
|
||||
typedef enum tdVMMDLL_SYSTEM_TP {
|
||||
VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
|
||||
VMMDLL_SYSTEM_WINDOWS_X64 = 2,
|
||||
VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
|
||||
VMMDLL_SYSTEM_WINDOWS_X86 = 4
|
||||
} VMMDLL_SYSTEM_TP;
|
||||
|
||||
/*
|
||||
* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
|
||||
* mation about valid option values. Please note that option values may overlap
|
||||
@@ -124,6 +146,7 @@ BOOL VMMDLL_Close();
|
||||
* -- pqwValue = pointer to ULONG64 to receive option value.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
|
||||
/*
|
||||
@@ -134,6 +157,7 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
|
||||
* -- qwValue
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
|
||||
|
||||
|
||||
@@ -171,6 +195,7 @@ typedef struct tdVMMDLL_VFS_FILELIST {
|
||||
* -- pFileList
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
|
||||
|
||||
/*
|
||||
@@ -227,12 +252,13 @@ NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb,
|
||||
* will be unloaded on a general close of the vmm dll.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_VfsInitializePlugins();
|
||||
|
||||
#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
|
||||
#define VMMDLL_PLUGIN_CONTEXT_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 1
|
||||
#define VMMDLL_PLUGIN_REGINFO_VERSION 2
|
||||
|
||||
#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
|
||||
|
||||
@@ -254,7 +280,8 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem;
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel;
|
||||
VMMDLL_SYSTEM_TP tpSystem;
|
||||
HMODULE hDLL;
|
||||
HMODULE hReservedDll; // not for general use (only used for python).
|
||||
BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
|
||||
@@ -272,7 +299,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
// function plugin registration info to be filled out by the plugin below:
|
||||
struct {
|
||||
BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
|
||||
NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
|
||||
VOID(*pfnNotify)(_Inout_opt_ PHANDLE phModulePrivate, _In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
|
||||
VOID(*pfnCloseHandleModule)(_Inout_opt_ PHANDLE phModulePrivate);
|
||||
@@ -296,8 +323,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO {
|
||||
#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
|
||||
#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
|
||||
|
||||
#define VMMDLL_TARGET_UNKNOWN_X64 0x0001
|
||||
#define VMMDLL_TARGET_WINDOWS_X64 0x0002
|
||||
#define VMMDLL_MEM_IO_SCATTER_HEADER_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
ULONG64 qwA; // base address (DWORD boundry).
|
||||
@@ -306,6 +332,10 @@ typedef struct tdVMMDLL_MEM_IO_SCATTER_HEADER {
|
||||
PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
|
||||
PVOID pvReserved1; // reserved for use by caller.
|
||||
PVOID pvReserved2; // reserved for use by caller.
|
||||
WORD version; // version of struct
|
||||
WORD Future1; // reserved for future use.
|
||||
DWORD Future2; // reserved for future use.
|
||||
ULONG64 qwDeviceA; // device-physical address (used by device layer).
|
||||
struct {
|
||||
PVOID pvReserved1;
|
||||
PVOID pvReserved2;
|
||||
@@ -335,6 +365,7 @@ DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPVMMDLL_MEM_IO_SCATTER_HE
|
||||
* -- pbPage
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
|
||||
|
||||
/*
|
||||
@@ -345,6 +376,7 @@ BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4
|
||||
* -- cb
|
||||
* -- return = success/fail (depending if all requested bytes are read or not).
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
@@ -358,7 +390,8 @@ BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DW
|
||||
* -- return = success/fail. NB! reads may report as success even if 0 bytes are
|
||||
* read - it's recommended to verify pcbReadOpt parameter.
|
||||
*/
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
|
||||
|
||||
/*
|
||||
* Write a contigious arbitrary amount of memory. Please note some virtual memory
|
||||
@@ -373,7 +406,8 @@ BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_ PBYTE pb, _In
|
||||
* -- cb
|
||||
* -- return = TRUE on success, FALSE on partial or zero write.
|
||||
*/
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
|
||||
|
||||
/*
|
||||
* Translate a virtual address to a physical address by walking the page tables
|
||||
@@ -383,6 +417,7 @@ BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ D
|
||||
* -- pqwPA
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
|
||||
|
||||
|
||||
@@ -401,6 +436,7 @@ BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqw
|
||||
* -- pdwPID = pointer that will receive PID on success.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
|
||||
/*
|
||||
@@ -409,7 +445,8 @@ BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
|
||||
* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_PidList(_Out_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
|
||||
|
||||
// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
|
||||
#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
|
||||
@@ -437,6 +474,7 @@ typedef struct tdVMMDLL_MEMMAP_ENTRY {
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
|
||||
|
||||
/*
|
||||
@@ -448,6 +486,7 @@ BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY
|
||||
* -- fIdentifyModules = try identify modules as well (= slower)
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
|
||||
|
||||
typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
@@ -469,7 +508,8 @@ typedef struct tdVMMDLL_MODULEMAP_ENTRY {
|
||||
* -- pcModuleEntries = pointer to number of memory map entries.
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
|
||||
|
||||
/*
|
||||
* Retrieve a module (.exe or .dll or similar) given a module name.
|
||||
@@ -478,29 +518,31 @@ BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_ PVMMDLL_MODULEMAP_ENTRY
|
||||
* -- pModuleEntry
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
|
||||
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301d
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 1
|
||||
#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
|
||||
#define VMMDLL_PROCESS_INFORMATION_VERSION 2
|
||||
|
||||
typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
ULONG64 magic;
|
||||
WORD wVersion;
|
||||
WORD wSize;
|
||||
DWORD fTargetSystem; // as given by VMMDLL_TARGET_*
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
|
||||
VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
|
||||
BOOL fUserOnly; // only user mode pages listed
|
||||
DWORD dwPID;
|
||||
DWORD dwState;
|
||||
CHAR szName[16];
|
||||
ULONG64 paPML4;
|
||||
ULONG64 paPML4_UserOpt; // may not exist
|
||||
ULONG64 paDTB;
|
||||
ULONG64 paDTB_UserOpt; // may not exist
|
||||
union {
|
||||
struct {
|
||||
ULONG64 vaEPROCESS;
|
||||
ULONG64 vaPEB;
|
||||
ULONG64 vaENTRY;
|
||||
BOOL fWow64;
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
DWORD vaPEB32; // WoW64 only
|
||||
} win;
|
||||
} os;
|
||||
} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
|
||||
@@ -513,6 +555,7 @@ typedef struct tdVMMDLL_PROCESS_INFORMATION {
|
||||
* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
|
||||
|
||||
typedef struct tdVMMDLL_EAT_ENTRY {
|
||||
@@ -539,10 +582,14 @@ typedef struct tdVMMDLL_IAT_ENTRY {
|
||||
* -- pcData
|
||||
* -- return = success/fail.
|
||||
*/
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
|
||||
|
||||
|
||||
|
||||
@@ -558,7 +605,8 @@ BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_ PVMMDLL_I
|
||||
* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
|
||||
* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
|
||||
*/
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_ LPSTR sz, _Inout_ PDWORD pcsz);
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ PY2C_CallbackRegister(PyObject *self, PyObject *args)
|
||||
return Py_BuildValue("s", NULL); // None returned on success.
|
||||
}
|
||||
|
||||
BOOL PY2C_Util_TranslatePathDelimiter(_Inout_ CHAR dst[MAX_PATH], LPSTR src)
|
||||
BOOL PY2C_Util_TranslatePathDelimiter(_Out_writes_(MAX_PATH) PCHAR dst, LPSTR src)
|
||||
{
|
||||
DWORD i;
|
||||
for(i = 0; i < MAX_PATH; i++) {
|
||||
@@ -248,7 +248,7 @@ void PY2C_InitializeModuleVMMPYCC()
|
||||
// CORE NATIVE MODULE FUNCTIONALITY BELOW:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
VOID Util_GetPathDll(_Out_ WCHAR wszPath[MAX_PATH], _In_opt_ HMODULE hModule)
|
||||
VOID Util_GetPathDll(_Out_writes_(MAX_PATH) PWCHAR wszPath, _In_opt_ HMODULE hModule)
|
||||
{
|
||||
SIZE_T i;
|
||||
GetModuleFileNameW(hModule, wszPath, MAX_PATH - 4);
|
||||
@@ -348,7 +348,7 @@ VOID PYTHON_Close(_Inout_ PHANDLE phModulePrivate)
|
||||
__declspec(dllexport)
|
||||
VOID InitializeVmmPlugin(_In_ PVMMDLL_PLUGIN_REGINFO pRegInfo)
|
||||
{
|
||||
if(0 == (pRegInfo->fTargetSystem & (VMMDLL_TARGET_UNKNOWN_X64 | VMMDLL_TARGET_WINDOWS_X64))) { return; }
|
||||
if((pRegInfo->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRegInfo->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
|
||||
if(VmmPyPlugin_PythonInitialize(pRegInfo->hReservedDll)) {
|
||||
strcpy_s(pRegInfo->reg_info.szModuleName, 32, "py"); // module name - 'py'.
|
||||
pRegInfo->reg_info.fRootModule = TRUE; // module shows in root directory.
|
||||
|
||||
Reference in New Issue
Block a user