mirror of
https://github.com/ufrisk/MemProcFS.git
synced 2026-10-11 22:40:01 +00:00
Version 5.18.10
This commit is contained in:
@@ -269,3 +269,4 @@ Latest:
|
||||
* New module: /sys/eventlog (Windows event log recovery).
|
||||
* New module: /sys/proc/cpu - process CPU usage, current and total.
|
||||
* New API function: VMMDLL_MemVirtualQuery.
|
||||
* New API function: VMMDLL_WinReg_QueryNameOriginalU.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+35
-1
@@ -11,7 +11,7 @@
|
||||
// (c) Ulf Frisk, 2018-2026
|
||||
// Author: Ulf Frisk, [email protected]
|
||||
//
|
||||
// Header Version: 5.18.9
|
||||
// Header Version: 5.18.10
|
||||
//
|
||||
|
||||
#include "leechcore.h"
|
||||
@@ -2842,6 +2842,23 @@ BOOL VMMDLL_WinReg_EnumValueU(
|
||||
_Inout_opt_ LPDWORD lpcbData
|
||||
);
|
||||
|
||||
/*
|
||||
* Retrieve the original UTF-8 name of a registry key or value.
|
||||
* -- uszFullPath = existing file-system path, including the value name if fValue.
|
||||
* -- fValue = TRUE for a value, FALSE for a key.
|
||||
* -- uszName = output buffer, or NULL to query the required size.
|
||||
* -- pcbName = buffer capacity on input.
|
||||
* -- return
|
||||
*/
|
||||
EXPORTED_FUNCTION _Success_(return)
|
||||
BOOL VMMDLL_WinReg_QueryNameOriginalU(
|
||||
_In_ VMM_HANDLE hVMM,
|
||||
_In_ LPCSTR uszFullPath,
|
||||
_In_ BOOL fValue,
|
||||
_Out_writes_opt_(*pcbName) LPSTR uszName,
|
||||
_When_(uszName == NULL, _Out_) _When_(uszName != NULL, _Inout_) PDWORD pcbName
|
||||
);
|
||||
|
||||
/*
|
||||
* Query a registry value given a registry key/value path - similar to WINAPI
|
||||
* function 'RegQueryValueEx'.
|
||||
@@ -2924,6 +2941,23 @@ BOOL VMMDLL_WinReg_EnumValueW(
|
||||
_Inout_opt_ LPDWORD lpcbData
|
||||
);
|
||||
|
||||
/*
|
||||
* Retrieve the original UTF-16 name of a registry key or value.
|
||||
* -- wszFullPath = existing file-system path, including the value name if fValue.
|
||||
* -- fValue = TRUE for a value, FALSE for a key.
|
||||
* -- wszName = output buffer, or NULL to query the required size.
|
||||
* -- pcchName = buffer capacity on input.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_WinReg_QueryNameOriginalW(
|
||||
_In_ VMM_HANDLE hVMM,
|
||||
_In_ LPCWSTR wszFullPath,
|
||||
_In_ BOOL fValue,
|
||||
_Out_writes_opt_(*pcchName) LPWSTR wszName,
|
||||
_When_(wszName == NULL, _Out_) _When_(wszName != NULL, _Inout_) PDWORD pcchName
|
||||
);
|
||||
|
||||
/*
|
||||
* Query a registry value given a registry key/value path - similar to WINAPI
|
||||
* function 'RegQueryValueEx'.
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 18
|
||||
#define VERSION_REVISION 9
|
||||
#define VERSION_BUILD 248
|
||||
#define VERSION_REVISION 10
|
||||
#define VERSION_BUILD 249
|
||||
|
||||
#define VER_FILE_DESCRIPTION_STR "MemProcFS : Plugin vmemd"
|
||||
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 18
|
||||
#define VERSION_REVISION 9
|
||||
#define VERSION_BUILD 248
|
||||
#define VERSION_REVISION 10
|
||||
#define VERSION_BUILD 249
|
||||
|
||||
#define VER_FILE_DESCRIPTION_STR "MemProcFS"
|
||||
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
|
||||
|
||||
@@ -89,6 +89,8 @@ typedef enum tdSTATISTICS_ID {
|
||||
STATISTICS_ID_VMMDLL_WinRegHive_Write,
|
||||
STATISTICS_ID_VMMDLL_WinReg_EnumKeyExW,
|
||||
STATISTICS_ID_VMMDLL_WinReg_EnumValueW,
|
||||
STATISTICS_ID_VMMDLL_WinReg_QueryNameOriginalU,
|
||||
STATISTICS_ID_VMMDLL_WinReg_QueryNameOriginalW,
|
||||
STATISTICS_ID_VMMDLL_WinReg_QueryValueEx,
|
||||
STATISTICS_ID_VMMDLL_YaraSearch,
|
||||
STATISTICS_ID_VMMDLL_PdbLoad,
|
||||
@@ -176,6 +178,8 @@ static LPCSTR STATISTICS_ID_STR[STATISTICS_ID_MAX] = {
|
||||
[STATISTICS_ID_VMMDLL_WinRegHive_Write] = "VMMDLL_WinRegHive_Write",
|
||||
[STATISTICS_ID_VMMDLL_WinReg_EnumKeyExW] = "VMMDLL_WinReg_EnumKeyExW",
|
||||
[STATISTICS_ID_VMMDLL_WinReg_EnumValueW] = "VMMDLL_WinReg_EnumValueW",
|
||||
[STATISTICS_ID_VMMDLL_WinReg_QueryNameOriginalU] = "VMMDLL_WinReg_QueryNameOriginalU",
|
||||
[STATISTICS_ID_VMMDLL_WinReg_QueryNameOriginalW] = "VMMDLL_WinReg_QueryNameOriginalW",
|
||||
[STATISTICS_ID_VMMDLL_WinReg_QueryValueEx] = "VMMDLL_WinReg_QueryValueEx",
|
||||
[STATISTICS_ID_VMMDLL_VmGetVmmHandle] = "VMMDLL_VmGetVmmHandle",
|
||||
[STATISTICS_ID_VMMDLL_VmMemTranslateGPA] = "VMMDLL_VmMemTranslateGPA",
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 18
|
||||
#define VERSION_REVISION 9
|
||||
#define VERSION_BUILD 248
|
||||
#define VERSION_REVISION 10
|
||||
#define VERSION_BUILD 249
|
||||
|
||||
#define VER_FILE_DESCRIPTION_STR "MemProcFS : Core"
|
||||
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
|
||||
|
||||
@@ -3075,6 +3075,47 @@ _Success_(return) BOOL VMMDLL_WinReg_EnumValueW(_In_ VMM_HANDLE H, _In_ LPCWSTR
|
||||
CALL_IMPLEMENTATION_VMM(H, STATISTICS_ID_VMMDLL_WinReg_EnumValueW, VMMDLL_WinReg_EnumValue_Impl(H, NULL, wszFullPathKey, dwIndex, (PBYTE)lpValueName, *lpcchValueName << 1, lpcchValueName, lpType, lpData, lpcbData))
|
||||
}
|
||||
|
||||
_Success_(return) BOOL VMMDLL_WinReg_QueryNameOriginalU(_In_ VMM_HANDLE H, _In_ LPCSTR uszFullPath, _In_ BOOL fValue, _Out_writes_opt_(*pcbName) LPSTR uszName, _When_(uszName == NULL, _Out_) _When_(uszName != NULL, _Inout_) PDWORD pcbName)
|
||||
{
|
||||
if(!pcbName) { return FALSE; }
|
||||
CALL_IMPLEMENTATION_VMM(H, STATISTICS_ID_VMMDLL_WinReg_QueryNameOriginalU, VmmWinReg_QueryNameOriginal(H, uszFullPath, fValue, (PBYTE)uszName, uszName ? *pcbName : 0, pcbName))
|
||||
}
|
||||
|
||||
_Success_(return) BOOL VMMDLL_WinReg_QueryNameOriginalW(_In_ VMM_HANDLE H, _In_ LPCWSTR wszFullPath, _In_ BOOL fValue, _Out_writes_opt_(*pcchName) LPWSTR wszName, _When_(wszName == NULL, _Out_) _When_(wszName != NULL, _Inout_) PDWORD pcchName)
|
||||
{
|
||||
BOOL f = FALSE;
|
||||
QWORD tm;
|
||||
DWORD cchName, cbuName = 0, cbwName = 0, cbwPart, o;
|
||||
LPSTR uszFullPath, uszName = NULL;
|
||||
PBYTE pbName = NULL;
|
||||
BYTE pbBuffer[2 * MAX_PATH];
|
||||
if(!pcchName) { return FALSE; }
|
||||
cchName = wszName ? *pcchName : 0;
|
||||
*pcchName = 0;
|
||||
if(!wszFullPath || !CharUtil_WtoU(wszFullPath, -1, pbBuffer, sizeof(pbBuffer), &uszFullPath, NULL, 0)) { return FALSE; }
|
||||
if(!VmmDllCore_HandleReserveExternal(H)) { return FALSE; }
|
||||
tm = Statistics_CallStart(H);
|
||||
if(!VmmWinReg_QueryNameOriginal(H, uszFullPath, fValue, NULL, 0, &cbuName)) { goto finish; }
|
||||
if(!(uszName = LocalAlloc(0, cbuName))) { goto finish; }
|
||||
if(!VmmWinReg_QueryNameOriginal(H, uszFullPath, fValue, (PBYTE)uszName, cbuName, &cbuName)) { goto finish; }
|
||||
if(!(pbName = LocalAlloc(0, 2 * cbuName))) { goto finish; }
|
||||
// Convert each null-delimited part to preserve embedded nulls in the name.
|
||||
for(o = 0; o < cbuName; o += (DWORD)strlen(uszName + o) + 1) {
|
||||
if(!CharUtil_UtoW(uszName + o, cbuName - o, pbName + cbwName, 2 * cbuName - cbwName, NULL, &cbwPart, CHARUTIL_FLAG_STR_BUFONLY)) { goto finish; }
|
||||
cbwName += cbwPart;
|
||||
}
|
||||
*pcchName = cbwName / 2;
|
||||
if(wszName && (cchName < *pcchName)) { goto finish; }
|
||||
if(wszName) { memcpy(wszName, pbName, cbwName); }
|
||||
f = TRUE;
|
||||
finish:
|
||||
LocalFree(pbName);
|
||||
LocalFree(uszName);
|
||||
Statistics_CallEnd(H, STATISTICS_ID_VMMDLL_WinReg_QueryNameOriginalW, tm);
|
||||
VmmDllCore_HandleReturnExternal(H);
|
||||
return f;
|
||||
}
|
||||
|
||||
_Success_(return) BOOL VMMDLL_WinReg_QueryValueExU(_In_ VMM_HANDLE H, _In_ LPCSTR uszFullPathKeyValue, _Out_opt_ LPDWORD lpType, _Out_writes_opt_(*lpcbData) LPBYTE lpData, _When_(lpData == NULL, _Out_opt_) _When_(lpData != NULL, _Inout_opt_) LPDWORD lpcbData)
|
||||
{
|
||||
CALL_IMPLEMENTATION_VMM(H, STATISTICS_ID_VMMDLL_WinReg_QueryValueEx, VmmWinReg_ValueQuery2(H, uszFullPathKeyValue, lpType, lpData, lpcbData ? *lpcbData : 0, lpcbData))
|
||||
|
||||
@@ -119,6 +119,8 @@ EXPORTS
|
||||
VMMDLL_WinReg_EnumKeyExW
|
||||
VMMDLL_WinReg_EnumValueU
|
||||
VMMDLL_WinReg_EnumValueW
|
||||
VMMDLL_WinReg_QueryNameOriginalU
|
||||
VMMDLL_WinReg_QueryNameOriginalW
|
||||
VMMDLL_WinReg_QueryValueExU
|
||||
VMMDLL_WinReg_QueryValueExW
|
||||
|
||||
|
||||
+35
-1
@@ -11,7 +11,7 @@
|
||||
// (c) Ulf Frisk, 2018-2026
|
||||
// Author: Ulf Frisk, [email protected]
|
||||
//
|
||||
// Header Version: 5.18.9
|
||||
// Header Version: 5.18.10
|
||||
//
|
||||
|
||||
#include "leechcore.h"
|
||||
@@ -2842,6 +2842,23 @@ BOOL VMMDLL_WinReg_EnumValueU(
|
||||
_Inout_opt_ LPDWORD lpcbData
|
||||
);
|
||||
|
||||
/*
|
||||
* Retrieve the original UTF-8 name of a registry key or value.
|
||||
* -- uszFullPath = existing file-system path, including the value name if fValue.
|
||||
* -- fValue = TRUE for a value, FALSE for a key.
|
||||
* -- uszName = output buffer, or NULL to query the required size.
|
||||
* -- pcbName = buffer capacity on input.
|
||||
* -- return
|
||||
*/
|
||||
EXPORTED_FUNCTION _Success_(return)
|
||||
BOOL VMMDLL_WinReg_QueryNameOriginalU(
|
||||
_In_ VMM_HANDLE hVMM,
|
||||
_In_ LPCSTR uszFullPath,
|
||||
_In_ BOOL fValue,
|
||||
_Out_writes_opt_(*pcbName) LPSTR uszName,
|
||||
_When_(uszName == NULL, _Out_) _When_(uszName != NULL, _Inout_) PDWORD pcbName
|
||||
);
|
||||
|
||||
/*
|
||||
* Query a registry value given a registry key/value path - similar to WINAPI
|
||||
* function 'RegQueryValueEx'.
|
||||
@@ -2924,6 +2941,23 @@ BOOL VMMDLL_WinReg_EnumValueW(
|
||||
_Inout_opt_ LPDWORD lpcbData
|
||||
);
|
||||
|
||||
/*
|
||||
* Retrieve the original UTF-16 name of a registry key or value.
|
||||
* -- wszFullPath = existing file-system path, including the value name if fValue.
|
||||
* -- fValue = TRUE for a value, FALSE for a key.
|
||||
* -- wszName = output buffer, or NULL to query the required size.
|
||||
* -- pcchName = buffer capacity on input.
|
||||
* -- return
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VMMDLL_WinReg_QueryNameOriginalW(
|
||||
_In_ VMM_HANDLE hVMM,
|
||||
_In_ LPCWSTR wszFullPath,
|
||||
_In_ BOOL fValue,
|
||||
_Out_writes_opt_(*pcchName) LPWSTR wszName,
|
||||
_When_(wszName == NULL, _Out_) _When_(wszName != NULL, _Inout_) PDWORD pcchName
|
||||
);
|
||||
|
||||
/*
|
||||
* Query a registry value given a registry key/value path - similar to WINAPI
|
||||
* function 'RegQueryValueEx'.
|
||||
|
||||
+88
-9
@@ -1243,7 +1243,7 @@ typedef struct tdREG_CM_KEY_NODE {
|
||||
DWORD MaxValueNameLen; // +0x03c MaxValueNameLen : Uint4B
|
||||
DWORD MaxValueDataLen; // +0x040 MaxValueDataLen : Uint4B
|
||||
DWORD WorkVar; // +0x044 WorkVar : Uint4B
|
||||
WORD NameLength; // +0x048 NameLength : Uint2B
|
||||
WORD NameLength; // +0x048 NameLength : Uint2B (bytes)
|
||||
WORD ClassLength; // +0x04a ClassLength : Uint2B
|
||||
union {
|
||||
CHAR szName[1]; // +0x04c Name : [1] Wchar
|
||||
@@ -1254,7 +1254,7 @@ typedef struct tdREG_CM_KEY_NODE {
|
||||
// "vk-key-value"
|
||||
typedef struct tdREG_CM_KEY_VALUE {
|
||||
WORD Signature; // 0x000 Signature : Uint2B
|
||||
WORD NameLength; // 0x002 NameLength : Uint2B
|
||||
WORD NameLength; // 0x002 NameLength : Uint2B (bytes)
|
||||
DWORD DataLength; // 0x004 DataLength : Uint4B
|
||||
DWORD Data; // 0x008 Data : Uint4B
|
||||
DWORD Type; // 0x00c Type : Uint4B
|
||||
@@ -1326,7 +1326,7 @@ DWORD VmmWinReg_KeyHashName(_In_ PREG_CM_KEY_NODE pnk, _In_ DWORD iSuffix)
|
||||
CHAR uszBuffer[2 * MAX_PATH];
|
||||
c = (pnk->Flags & REG_CM_KEY_NODE_FLAGS_COMP_NAME) ?
|
||||
CharUtil_FixFsName(uszBuffer, sizeof(uszBuffer), NULL, pnk->szName, NULL, pnk->NameLength, iSuffix, TRUE) :
|
||||
CharUtil_FixFsName(uszBuffer, sizeof(uszBuffer), NULL, NULL, pnk->wszName, pnk->NameLength, iSuffix, TRUE);
|
||||
CharUtil_FixFsName(uszBuffer, sizeof(uszBuffer), NULL, NULL, pnk->wszName, pnk->NameLength / 2, iSuffix, TRUE);
|
||||
if(c) { c--; }
|
||||
for(i = 0; i < c; i++) {
|
||||
dwHash = ((dwHash >> 13) | (dwHash << 19)) + (UCHAR)uszBuffer[i];
|
||||
@@ -1418,7 +1418,7 @@ POB_REGISTRY_KEY VmmWinReg_KeyInitializeCreateKey(_In_ VMM_HANDLE H, _In_ POB_RE
|
||||
cbKey = cbCell - 4;
|
||||
pnk = (PREG_CM_KEY_NODE)(pHive->Snapshot._DUAL[iSV].pb + oCellRaw + 4);
|
||||
if(pnk->Signature != REG_CM_KEY_SIGNATURE_KEYNODE) { goto fail; }
|
||||
if(((QWORD)pnk->NameLength << ((pnk->Flags & REG_CM_KEY_NODE_FLAGS_COMP_NAME) ? 0 : 1)) > (cbKey - REG_CM_KEY_NODE_SIZEOF)) { goto fail; }
|
||||
if((pnk->NameLength > cbKey - REG_CM_KEY_NODE_SIZEOF) || (!(pnk->Flags & REG_CM_KEY_NODE_FLAGS_COMP_NAME) && (pnk->NameLength & 1))) { goto fail; }
|
||||
if(pnk->Parent == oCell) { goto fail; }
|
||||
// 3: get parent key
|
||||
pObKeyParent = ObMap_GetByKey(pHive->Snapshot.pmKeyOffset, pnk->Parent);
|
||||
@@ -1495,7 +1495,7 @@ POB_REGISTRY_KEY VmmWinReg_KeyInitializeRootKeyDummy(_In_ VMM_HANDLE H, _In_ POB
|
||||
pObKey->dwCellHead = pObKey->oCell + (fActive ? 0x80000000 : 0);
|
||||
pObKey->pKey = (PREG_CM_KEY_NODE)((PBYTE)pObKey + sizeof(OB_REGISTRY_KEY));
|
||||
CharUtil_UtoW(uszName, -1, (PBYTE)&pObKey->pKey->wszName, 2 * cbuName, NULL, &cbw, CHARUTIL_FLAG_TRUNCATE_ONFAIL_NULLSTR | CHARUTIL_FLAG_STR_BUFONLY);
|
||||
pObKey->pKey->NameLength = cbw ? (WORD)(cbw >> 1) - 1 : 0;
|
||||
pObKey->pKey->NameLength = cbw ? (WORD)(cbw - 2) : 0;
|
||||
// 2: calculate lookup hashes
|
||||
pObKey->qwHashKeyParent = qwKeyParentHash;
|
||||
pObKey->qwHashKeyThis = CharUtil_HashNameFsU(uszName, 0) + ((pObKey->qwHashKeyParent >> 13) | (pObKey->qwHashKeyParent << 51));
|
||||
@@ -1618,7 +1618,7 @@ POB_REGISTRY_VALUE VmmWinReg_KeyValueGetByOffset(_In_ VMM_HANDLE H, _In_ POB_REG
|
||||
cbKeyValue = cbCell - 4;
|
||||
pvk = (PREG_CM_KEY_VALUE)(pHive->Snapshot._DUAL[REG_CELL_SV(oCell)].pb + REG_CELL_ORAW(oCell) + 4);
|
||||
if(pvk->Signature != REG_CM_KEY_SIGNATURE_KEYVALUE) { return NULL; }
|
||||
if(((QWORD)pvk->NameLength << ((pvk->Flags & REG_CM_KEY_VALUE_FLAGS_COMP_NAME) ? 0 : 1)) > (cbKeyValue - REG_CM_KEY_VALUE_SIZEOF)) { return NULL; }
|
||||
if((pvk->NameLength > cbKeyValue - REG_CM_KEY_VALUE_SIZEOF) || (!(pvk->Flags & REG_CM_KEY_VALUE_FLAGS_COMP_NAME) && (pvk->NameLength & 1))) { return NULL; }
|
||||
// 2: allocate and prepare
|
||||
pObKeyValue = Ob_AllocEx(H, OB_TAG_REG_KEYVALUE, LMEM_ZEROINIT, sizeof(OB_REGISTRY_VALUE), NULL, NULL);
|
||||
if(!pObKeyValue) { return NULL; }
|
||||
@@ -2025,6 +2025,85 @@ POB_MAP VmmWinReg_KeyList(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHive, _In_o
|
||||
return pmObSubkeys;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a counted hive name without file-system substitutions or truncation.
|
||||
* NameLength in both nk and vk cells is in bytes, including compressed names.
|
||||
* Preserve embedded nulls; pcbName includes the additional terminating null.
|
||||
*/
|
||||
_Success_(return)
|
||||
static BOOL VmmWinReg_NameOriginal(_In_reads_(cbName) PBYTE pbName, _In_ DWORD cbName, _In_ BOOL fCompressed, _Out_writes_opt_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbName)
|
||||
{
|
||||
static const BYTE pbPrefix[5] = { 0, 0, 0xc0, 0xe0, 0xf0 };
|
||||
DWORD i, j, iPass, cch, cp, cpLow, cbOut, cbChar;
|
||||
*pcbName = 0;
|
||||
if(!fCompressed && (cbName & 1)) { return FALSE; }
|
||||
cch = fCompressed ? cbName : cbName / 2;
|
||||
// Validate and size first, then encode without stopping at embedded nulls.
|
||||
for(iPass = 0; iPass < 2; iPass++) {
|
||||
cbOut = 0;
|
||||
for(i = 0; i < cch; i++) {
|
||||
cp = fCompressed ? pbName[i] : pbName[2 * i] | ((DWORD)pbName[2 * i + 1] << 8);
|
||||
if((cp >= 0xd800) && (cp <= 0xdfff)) {
|
||||
if((cp >= 0xdc00) || (++i == cch)) { return FALSE; }
|
||||
cpLow = pbName[2 * i] | ((DWORD)pbName[2 * i + 1] << 8);
|
||||
if((cpLow < 0xdc00) || (cpLow > 0xdfff)) { return FALSE; }
|
||||
cp = 0x10000 + ((cp - 0xd800) << 10) + (cpLow - 0xdc00);
|
||||
}
|
||||
cbChar = 1 + (cp > 0x7f) + (cp > 0x7ff) + (cp > 0xffff);
|
||||
if(iPass) {
|
||||
for(j = cbChar - 1; j; j--) { pb[cbOut + j] = 0x80 | (cp & 0x3f); cp >>= 6; }
|
||||
pb[cbOut] = (BYTE)cp | pbPrefix[cbChar];
|
||||
}
|
||||
cbOut += cbChar;
|
||||
}
|
||||
if(!iPass) {
|
||||
*pcbName = cbOut + 1;
|
||||
if(!pb) { return TRUE; }
|
||||
if(cb <= cbOut) { return FALSE; }
|
||||
}
|
||||
}
|
||||
pb[cbOut] = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL VmmWinReg_QueryNameOriginal(_In_ VMM_HANDLE H, _In_ LPCSTR uszFullPath, _In_ BOOL fValue, _Out_writes_opt_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbName)
|
||||
{
|
||||
BOOL f = FALSE;
|
||||
CHAR uszPath[MAX_PATH], uszParent[MAX_PATH];
|
||||
LPSTR uszName = NULL;
|
||||
PBYTE pbCell;
|
||||
PREG_CM_KEY_NODE pnk, pnkRoot;
|
||||
POB_REGISTRY_HIVE pObHive = NULL;
|
||||
POB_REGISTRY_KEY pObKey = NULL;
|
||||
POB_REGISTRY_VALUE pObValue = NULL;
|
||||
*pcbName = 0;
|
||||
if(!uszFullPath || !VmmWinReg_PathHiveGetByFullPath(H, uszFullPath, &pObHive, uszPath)) { goto finish; }
|
||||
if(fValue && !(uszName = CharUtil_PathSplitLastEx(uszPath, uszParent, sizeof(uszParent)))) { goto finish; }
|
||||
if(!(pObKey = VmmWinReg_KeyGetByPath(H, pObHive, fValue ? uszParent : uszPath))) { goto finish; }
|
||||
if(fValue) {
|
||||
if(!(pObValue = VmmWinReg_ValueByKeyAndName(H, pObHive, pObKey, uszName))) { goto finish; }
|
||||
f = VmmWinReg_NameOriginal((PBYTE)pObValue->pValue->szName, pObValue->pValue->NameLength,
|
||||
pObValue->pValue->Flags & REG_CM_KEY_VALUE_FLAGS_COMP_NAME, pb, cb, pcbName);
|
||||
} else {
|
||||
pnk = pObKey->pKey;
|
||||
// Use the backing nk cell for synthetic ROOT, when available.
|
||||
if(!pnk->Signature && VmmWinReg_KeyValidateCellSize(pObHive, pObKey->oCell, REG_CM_KEY_NODE_SIZEOF + 4, 0x1000)) {
|
||||
pbCell = pObHive->Snapshot._DUAL[REG_CELL_SV(pObKey->oCell)].pb + REG_CELL_ORAW(pObKey->oCell);
|
||||
pnkRoot = (PREG_CM_KEY_NODE)(pbCell + 4);
|
||||
f = pnkRoot->Signature == REG_CM_KEY_SIGNATURE_KEYNODE;
|
||||
f = f && (pnkRoot->NameLength <= REG_CELL_SIZE(*(PDWORD)pbCell) - 4 - REG_CM_KEY_NODE_SIZEOF);
|
||||
if(f) { pnk = pnkRoot; }
|
||||
}
|
||||
f = VmmWinReg_NameOriginal((PBYTE)pnk->szName, pnk->NameLength, pnk->Flags & REG_CM_KEY_NODE_FLAGS_COMP_NAME, pb, cb, pcbName);
|
||||
}
|
||||
finish:
|
||||
Ob_DECREF(pObValue);
|
||||
Ob_DECREF(pObKey);
|
||||
Ob_DECREF(pObHive);
|
||||
return f;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve information about a registry key.
|
||||
* -- pHive
|
||||
@@ -2040,7 +2119,7 @@ VOID VmmWinReg_KeyInfo(_In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTRY_KEY pKey,
|
||||
if(pKey->pKey->Flags & REG_CM_KEY_NODE_FLAGS_COMP_NAME) {
|
||||
pKeyInfo->cbuName = CharUtil_FixFsName(pKeyInfo->uszName, sizeof(pKeyInfo->uszName), NULL, pKey->pKey->szName, NULL, pKey->pKey->NameLength, pKey->iSuffix, FALSE);
|
||||
} else {
|
||||
pKeyInfo->cbuName = CharUtil_FixFsName(pKeyInfo->uszName, sizeof(pKeyInfo->uszName), NULL, NULL, pKey->pKey->wszName, pKey->pKey->NameLength, pKey->iSuffix, FALSE);
|
||||
pKeyInfo->cbuName = CharUtil_FixFsName(pKeyInfo->uszName, sizeof(pKeyInfo->uszName), NULL, NULL, pKey->pKey->wszName, pKey->pKey->NameLength / 2, pKey->iSuffix, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2182,7 +2261,7 @@ VOID VmmWinReg_ValueInfo(_In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTRY_VALUE p
|
||||
} else if(pValue->pValue->Flags & REG_CM_KEY_VALUE_FLAGS_COMP_NAME) {
|
||||
pValueInfo->cbuName = CharUtil_FixFsName(pValueInfo->uszName, sizeof(pValueInfo->uszName), NULL, pValue->pValue->szName, NULL, pValue->pValue->NameLength, 0, FALSE);
|
||||
} else {
|
||||
pValueInfo->cbuName = CharUtil_FixFsName(pValueInfo->uszName, sizeof(pValueInfo->uszName), NULL, NULL, pValue->pValue->wszName, pValue->pValue->NameLength, 0, FALSE);
|
||||
pValueInfo->cbuName = CharUtil_FixFsName(pValueInfo->uszName, sizeof(pValueInfo->uszName), NULL, NULL, pValue->pValue->wszName, pValue->pValue->NameLength / 2, 0, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2425,7 +2504,7 @@ BOOL VmmWinReg_KeyFullPath(_In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTRY_KEY p
|
||||
if(pk->pKey->Flags & REG_CM_KEY_NODE_FLAGS_COMP_NAME) {
|
||||
CharUtil_AtoU(pk->pKey->szName, pk->pKey->NameLength, uszFullPath + o, 1024 - o, NULL, &cbName, CHARUTIL_FLAG_TRUNCATE_ONFAIL_NULLSTR | CHARUTIL_FLAG_STR_BUFONLY);
|
||||
} else {
|
||||
CharUtil_WtoU(pk->pKey->wszName, pk->pKey->NameLength, uszFullPath + o, 1024 - o, NULL, &cbName, CHARUTIL_FLAG_TRUNCATE_ONFAIL_NULLSTR | CHARUTIL_FLAG_STR_BUFONLY);
|
||||
CharUtil_WtoU(pk->pKey->wszName, pk->pKey->NameLength / 2, uszFullPath + o, 1024 - o, NULL, &cbName, CHARUTIL_FLAG_TRUNCATE_ONFAIL_NULLSTR | CHARUTIL_FLAG_STR_BUFONLY);
|
||||
}
|
||||
if(cbName) {
|
||||
o += cbName - 1;
|
||||
|
||||
@@ -216,6 +216,19 @@ POB_MAP VmmWinReg_KeyList(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHive, _In_o
|
||||
*/
|
||||
VOID VmmWinReg_KeyInfo(_In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTRY_KEY pKey, _Out_ PVMM_REGISTRY_KEY_INFO pKeyInfo);
|
||||
|
||||
/*
|
||||
* Retrieve the original UTF-8 name of a registry key or value.
|
||||
* -- H
|
||||
* -- uszFullPath = existing file-system path to the registry key or value.
|
||||
* -- fValue = TRUE for a value, FALSE for a key.
|
||||
* -- pb = output buffer, or NULL to query the required size.
|
||||
* -- cb = size of the output buffer in bytes.
|
||||
* -- pcbName = required byte size, including the terminating null.
|
||||
* -- return = success. An insufficient buffer fails without truncation.
|
||||
*/
|
||||
_Success_(return)
|
||||
BOOL VmmWinReg_QueryNameOriginal(_In_ VMM_HANDLE H, _In_ LPCSTR uszFullPath, _In_ BOOL fValue, _Out_writes_opt_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbName);
|
||||
|
||||
/*
|
||||
* Retrieve information about a registry key - pKeyInfo->wszName = set to full path.
|
||||
* -- H
|
||||
|
||||
@@ -1416,6 +1416,30 @@ int main(_In_ int argc, _In_ char* argv[])
|
||||
}
|
||||
|
||||
|
||||
// Query original names of common Windows registry entries using their mangled paths.
|
||||
// The '*' class key is exposed as '_', and '\DosDevices\C:' as '_DosDevices_C_'.
|
||||
printf("------------------------------------------------------------\n");
|
||||
printf("# Registry: Query original key and value names \n");
|
||||
ShowKeyPress();
|
||||
// The buffer capacity and returned size are UTF-8 bytes, including the final null.
|
||||
cch = sizeof(usz);
|
||||
printf("CALL: VMMDLL_WinReg_QueryNameOriginalU (key)\n");
|
||||
result = VMMDLL_WinReg_QueryNameOriginalU(hVMM, "HKLM\\SOFTWARE\\Classes\\_", FALSE, usz, &cch);
|
||||
if(result) {
|
||||
printf("SUCCESS: Key name: '_' -> '%s'\n", usz);
|
||||
} else {
|
||||
printf("FAIL: VMMDLL_WinReg_QueryNameOriginalU (key)\n");
|
||||
}
|
||||
cch = sizeof(usz);
|
||||
printf("CALL: VMMDLL_WinReg_QueryNameOriginalU (value)\n");
|
||||
result = VMMDLL_WinReg_QueryNameOriginalU(hVMM, "HKLM\\SYSTEM\\MountedDevices\\_DosDevices_C_", TRUE, usz, &cch);
|
||||
if(result) {
|
||||
printf("SUCCESS: Value name: '_DosDevices_C_' -> '%s'\n", usz);
|
||||
} else {
|
||||
printf("FAIL: VMMDLL_WinReg_QueryNameOriginalU (value)\n");
|
||||
}
|
||||
|
||||
|
||||
// Retrieve Physical Memory Map
|
||||
printf("------------------------------------------------------------\n");
|
||||
printf("# Retrieve Physical Memory Map \n");
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 18
|
||||
#define VERSION_REVISION 9
|
||||
#define VERSION_BUILD 248
|
||||
#define VERSION_REVISION 10
|
||||
#define VERSION_BUILD 249
|
||||
|
||||
#define VER_FILE_DESCRIPTION_STR "MemProcFS : Python API"
|
||||
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
|
||||
|
||||
@@ -364,6 +364,7 @@ PyObj_RegHive* VmmPycRegHive_InitializeInternal(_In_ PyObj_Vmm *pyVMM, _In_ PVMM
|
||||
PyObj_RegMemory* VmmPycRegMemory_InitializeInternal(_In_ PyObj_Vmm *pyVMM, _In_ QWORD vaCMHive);
|
||||
PyObj_RegKey* VmmPycRegKey_InitializeInternal(_In_ PyObj_Vmm *pyVMM, _In_ LPSTR uszFullPathKey, _In_ BOOL fVerify);
|
||||
PyObj_RegValue* VmmPycRegValue_InitializeInternal(_In_ PyObj_Vmm *pyVMM, _In_ LPSTR uszFullPathKeyValue, _In_ BOOL fVerify);
|
||||
_Success_(return != NULL) PyObject* VmmPycReg_NameOriginal(_In_ PyObj_Vmm *pyVMM, _In_ LPSTR uszPath, _In_ BOOL fValue);
|
||||
PyObj_Vmm *VmmPycVmm_InitializeInternal2(_In_ PyObj_Vmm *pyVMM, _In_ VMM_HANDLE hVMM);
|
||||
PyObj_Search *VmmPycSearch_InitializeInternal(_In_ PyObj_Vmm *pyVMM, _In_opt_ DWORD dwPID, _In_ PyObject *args);
|
||||
PyObj_Yara *VmmPycYara_InitializeInternal(_In_ PyObj_Vmm *pyVMM, _In_opt_ DWORD dwPID, _In_ PyObject *args);
|
||||
|
||||
+31
-1
@@ -7,6 +7,27 @@
|
||||
|
||||
PyObject *g_pPyType_RegKey = NULL;
|
||||
|
||||
_Success_(return != NULL)
|
||||
PyObject* VmmPycReg_NameOriginal(_In_ PyObj_Vmm *pyVMM, _In_ LPSTR uszPath, _In_ BOOL fValue)
|
||||
{
|
||||
BOOL fResult;
|
||||
DWORD cbu = 0;
|
||||
LPSTR usz;
|
||||
PyObject *pyName;
|
||||
if(!pyVMM->fValid) { return PyErr_Format(PyExc_RuntimeError, "Registry.name_original: Not initialized."); }
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
fResult = VMMDLL_WinReg_QueryNameOriginalU(pyVMM->hVMM, uszPath, fValue, NULL, &cbu);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if(!fResult || !cbu || !pyVMM->fValid) { return PyErr_Format(PyExc_RuntimeError, "Registry.name_original: Failed."); }
|
||||
if(!(usz = LocalAlloc(0, cbu))) { return PyErr_NoMemory(); }
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
fResult = VMMDLL_WinReg_QueryNameOriginalU(pyVMM->hVMM, uszPath, fValue, usz, &cbu);
|
||||
Py_END_ALLOW_THREADS;
|
||||
pyName = fResult && cbu && pyVMM->fValid ? PyUnicode_DecodeUTF8(usz, cbu - 1, NULL) : PyErr_Format(PyExc_RuntimeError, "Registry.name_original: Failed.");
|
||||
LocalFree(usz);
|
||||
return pyName;
|
||||
}
|
||||
|
||||
static BOOL VmmPycRegKey_EnsureLastWrite(PyObj_RegKey *self)
|
||||
{
|
||||
DWORD cch = 0;
|
||||
@@ -170,6 +191,14 @@ VmmPycRegKey_name(PyObj_RegKey *self, void *closure)
|
||||
return self->pyName;
|
||||
}
|
||||
|
||||
// -> STR
|
||||
_Success_(return != NULL)
|
||||
static PyObject* VmmPycRegKey_name_original(_In_ PyObj_RegKey *self, _In_opt_ void *closure)
|
||||
{
|
||||
if(!self->fValid) { return PyErr_Format(PyExc_RuntimeError, "RegKey.name_original: Not initialized."); }
|
||||
return VmmPycReg_NameOriginal(self->pyVMM, self->uszPath, FALSE);
|
||||
}
|
||||
|
||||
// -> STR
|
||||
static PyObject*
|
||||
VmmPycRegKey_path(PyObj_RegKey *self, void *closure)
|
||||
@@ -236,7 +265,8 @@ BOOL VmmPycRegKey_InitializeType(PyObject *pModule)
|
||||
{NULL}
|
||||
};
|
||||
static PyGetSetDef PyGetSet[] = {
|
||||
{"name", (getter)VmmPycRegKey_name, (setter)NULL, "Key name.", NULL},
|
||||
{"name", (getter)VmmPycRegKey_name, (setter)NULL, "File-system-safe key name.", NULL},
|
||||
{"name_original", (getter)VmmPycRegKey_name_original, (setter)NULL, "Original key name stored in the hive.", NULL},
|
||||
{"path", (getter)VmmPycRegKey_path, (setter)NULL, "Key path.", NULL},
|
||||
{"parent", (getter)VmmPycRegKey_parent, (setter)NULL, "Parent key.", NULL},
|
||||
{"time_int", (getter)VmmPycRegKey_time_int, (setter)NULL, "LastWrite timestamp in numeric format.", NULL},
|
||||
|
||||
@@ -216,6 +216,14 @@ VmmPycRegValue_name(PyObj_RegValue *self, void *closure)
|
||||
return self->pyName;
|
||||
}
|
||||
|
||||
// -> STR
|
||||
_Success_(return != NULL)
|
||||
static PyObject* VmmPycRegValue_name_original(_In_ PyObj_RegValue *self, _In_opt_ void *closure)
|
||||
{
|
||||
if(!self->fValid) { return PyErr_Format(PyExc_RuntimeError, "RegValue.name_original: Not initialized."); }
|
||||
return VmmPycReg_NameOriginal(self->pyVMM, self->uszPath, TRUE);
|
||||
}
|
||||
|
||||
// -> STR
|
||||
static PyObject*
|
||||
VmmPycRegValue_path(PyObj_RegValue *self, void *closure)
|
||||
@@ -285,7 +293,8 @@ BOOL VmmPycRegValue_InitializeType(PyObject *pModule)
|
||||
{NULL}
|
||||
};
|
||||
static PyGetSetDef PyGetSet[] = {
|
||||
{"name", (getter)VmmPycRegValue_name, (setter)NULL, "Value name.", NULL},
|
||||
{"name", (getter)VmmPycRegValue_name, (setter)NULL, "File-system-safe value name.", NULL},
|
||||
{"name_original", (getter)VmmPycRegValue_name_original, (setter)NULL, "Original value name stored in the hive; empty for the unnamed value.", NULL},
|
||||
{"path", (getter)VmmPycRegValue_path, (setter)NULL, "Value path.", NULL},
|
||||
{"parent", (getter)VmmPycRegValue_parent, (setter)NULL, "Parent key.", NULL},
|
||||
{"size", (getter)VmmPycRegValue_size, (setter)NULL, "Value byte size.", NULL},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leechcore_example"
|
||||
version = "5.18.9"
|
||||
version = "5.18.10"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "m_example_plugin"
|
||||
version = "5.18.9"
|
||||
version = "5.18.10"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "memprocfs"
|
||||
version = "5.18.9"
|
||||
version = "5.18.10"
|
||||
edition = "2021"
|
||||
description = "MemProcFS - Physical Memory Analysis Framework"
|
||||
documentation = "https://docs.rs/memprocfs"
|
||||
|
||||
@@ -3071,6 +3071,23 @@ pub struct VmmRegKey<'a> {
|
||||
}
|
||||
|
||||
impl VmmRegKey<'_> {
|
||||
/// Retrieve the original key name stored in the hive.
|
||||
///
|
||||
/// Use `path` for lookups; the original name may contain backslashes or
|
||||
/// embedded nulls.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```no_run
|
||||
/// # fn example(vmm : &memprocfs::Vmm<'_>) -> memprocfs::ResultEx<()> {
|
||||
/// let regkey = vmm.reg_key(r"HKLM\SOFTWARE\Classes\_")?;
|
||||
/// println!("{} -> {:?}", regkey.name, regkey.name_original()?);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn name_original(&self) -> ResultEx<String> {
|
||||
return self.vmm.impl_reg_name_original(self.path.as_str(), false);
|
||||
}
|
||||
|
||||
/// Retrieve the parent registry key of this registry key.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -3212,6 +3229,23 @@ pub struct VmmRegValue<'a> {
|
||||
}
|
||||
|
||||
impl VmmRegValue<'_> {
|
||||
/// Retrieve the original value name stored in the hive.
|
||||
///
|
||||
/// The unnamed value returns an empty string. Use `path` for lookups; the
|
||||
/// original name may contain backslashes or embedded nulls.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```no_run
|
||||
/// # fn example(vmm : &memprocfs::Vmm<'_>) -> memprocfs::ResultEx<()> {
|
||||
/// let regvalue = vmm.reg_value(r"HKLM\SYSTEM\MountedDevices\_DosDevices_C_")?;
|
||||
/// println!("{} -> {:?}", regvalue.name, regvalue.name_original()?);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn name_original(&self) -> ResultEx<String> {
|
||||
return self.vmm.impl_reg_name_original(self.path.as_str(), true);
|
||||
}
|
||||
|
||||
/// Retrieve the parent registry key.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -4623,6 +4657,7 @@ struct VmmNative {
|
||||
VMMDLL_WinReg_HiveWrite : extern "C" fn(hVMM : usize, vaCMHive : u64, ra : u32, pb : *const u8, cb : u32) -> bool,
|
||||
VMMDLL_WinReg_EnumKeyExU : extern "C" fn(hVMM : usize, uszFullPathKey : *const c_char, dwIndex : u32, lpcchName : *mut c_char, lpcchName : *mut u32, lpftLastWriteTime : *mut u64) -> bool,
|
||||
VMMDLL_WinReg_EnumValueU : extern "C" fn(hVMM : usize, uszFullPathKey : *const c_char, dwIndex : u32, lpValueName : *mut c_char, lpcchValueName : *mut u32, lpType : *mut u32, lpcbData : *mut u32) -> bool,
|
||||
VMMDLL_WinReg_QueryNameOriginalU : extern "C" fn(hVMM : usize, uszFullPath : *const c_char, fValue : c_int, uszName : *mut c_char, pcbName : *mut u32) -> c_int,
|
||||
VMMDLL_WinReg_QueryValueExU : extern "C" fn(hVMM : usize, uszFullPathKeyValue : *const c_char, lpType : *mut u32, lpData : *mut u8, lpcbData : *mut u32) -> bool,
|
||||
|
||||
VMMDLL_ProcessGetModuleBaseU : extern "C" fn(hVMM : usize, pid : u32, uszModuleName : *const c_char) -> u64,
|
||||
@@ -4721,6 +4756,7 @@ fn impl_new<'a>(vmm_lib_path : &str, lc_existing_opt : Option<&LeechCore>, h_vmm
|
||||
let VMMDLL_WinReg_HiveWrite = *lib.get(b"VMMDLL_WinReg_HiveWrite")?;
|
||||
let VMMDLL_WinReg_EnumKeyExU = *lib.get(b"VMMDLL_WinReg_EnumKeyExU")?;
|
||||
let VMMDLL_WinReg_EnumValueU = *lib.get(b"VMMDLL_WinReg_EnumValueU")?;
|
||||
let VMMDLL_WinReg_QueryNameOriginalU = *lib.get(b"VMMDLL_WinReg_QueryNameOriginalU")?;
|
||||
let VMMDLL_WinReg_QueryValueExU = *lib.get(b"VMMDLL_WinReg_QueryValueExU")?;
|
||||
let VMMDLL_ProcessGetModuleBaseU = *lib.get(b"VMMDLL_ProcessGetModuleBaseU")?;
|
||||
let VMMDLL_ProcessGetProcAddressU = *lib.get(b"VMMDLL_ProcessGetProcAddressU")?;
|
||||
@@ -4818,6 +4854,7 @@ fn impl_new<'a>(vmm_lib_path : &str, lc_existing_opt : Option<&LeechCore>, h_vmm
|
||||
VMMDLL_WinReg_HiveWrite,
|
||||
VMMDLL_WinReg_EnumKeyExU,
|
||||
VMMDLL_WinReg_EnumValueU,
|
||||
VMMDLL_WinReg_QueryNameOriginalU,
|
||||
VMMDLL_WinReg_QueryValueExU,
|
||||
VMMDLL_ProcessGetModuleBaseU,
|
||||
VMMDLL_ProcessGetProcAddressU,
|
||||
@@ -6075,6 +6112,23 @@ impl Vmm<'_> {
|
||||
return Err(anyhow!("[err]"));
|
||||
}
|
||||
|
||||
fn impl_reg_name_original(&self, path : &str, is_value : bool) -> ResultEx<String> {
|
||||
let c_path = CString::new(path)?;
|
||||
let mut cb = 0;
|
||||
let r = (self.native.VMMDLL_WinReg_QueryNameOriginalU)(self.native.h, c_path.as_ptr(), is_value as c_int, std::ptr::null_mut(), &mut cb);
|
||||
if r == 0 || cb == 0 {
|
||||
return Err(anyhow!("VMMDLL_WinReg_QueryNameOriginalU: fail."));
|
||||
}
|
||||
let mut bytes = vec![0u8; cb as usize];
|
||||
let r = (self.native.VMMDLL_WinReg_QueryNameOriginalU)(self.native.h, c_path.as_ptr(), is_value as c_int, bytes.as_mut_ptr() as *mut c_char, &mut cb);
|
||||
if r == 0 || cb == 0 || cb as usize > bytes.len() || bytes[cb as usize - 1] != 0 {
|
||||
return Err(anyhow!("VMMDLL_WinReg_QueryNameOriginalU: fail."));
|
||||
}
|
||||
// Remove only the final terminator, retaining embedded and trailing nulls.
|
||||
bytes.truncate(cb as usize - 1);
|
||||
return Ok(String::from_utf8(bytes)?);
|
||||
}
|
||||
|
||||
fn impl_reg_key(&self, path : &str) -> ResultEx<VmmRegKey> {
|
||||
let mut ftLastWrite = 0;
|
||||
let mut cch = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "memprocfs_example"
|
||||
version = "5.18.9"
|
||||
version = "5.18.10"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
||||
@@ -564,6 +564,15 @@ pub fn main_example() -> ResultEx<()> {
|
||||
}
|
||||
|
||||
|
||||
// Example: vmmregkey.name_original()
|
||||
// The common '*' class key is exposed as '_' in file-system paths.
|
||||
println!("========================================");
|
||||
println!("vmmregkey.name_original():");
|
||||
if let Ok(regkey) = vmm.reg_key(r"HKLM\SOFTWARE\Classes\_") {
|
||||
println!("{} -> {:?}", regkey.name, regkey.name_original()?);
|
||||
}
|
||||
|
||||
|
||||
// Example: vmmregkey.parent()
|
||||
println!("========================================");
|
||||
println!("vmmregkey.parent():");
|
||||
@@ -605,6 +614,15 @@ pub fn main_example() -> ResultEx<()> {
|
||||
println!("{vmmregvalue} raw_type={} raw_size={}", vmmregvalue.raw_type, vmmregvalue.raw_size);
|
||||
|
||||
|
||||
// Example: vmmregvalue.name_original()
|
||||
// The common '\DosDevices\C:' value is exposed as '_DosDevices_C_'.
|
||||
println!("========================================");
|
||||
println!("vmmregvalue.name_original():");
|
||||
if let Ok(regvalue) = vmm.reg_value(r"HKLM\SYSTEM\MountedDevices\_DosDevices_C_") {
|
||||
println!("{} -> {:?}", regvalue.name, regvalue.name_original()?);
|
||||
}
|
||||
|
||||
|
||||
// Example: vmmregvalue.raw_value()
|
||||
// Retrieve the raw underlying data backing the actual value.
|
||||
println!("========================================");
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.Versioning;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("5.18.9.248")]
|
||||
[assembly: AssemblyFileVersion("5.18.9.248")]
|
||||
[assembly: AssemblyVersion("5.18.10.249")]
|
||||
[assembly: AssemblyFileVersion("5.18.10.249")]
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
<None Include="logo.png" Pack="true" Visible="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<Version>5.18.9</Version>
|
||||
<Version>5.18.10</Version>
|
||||
<RepositoryUrl>https://github.com/ufrisk/MemProcFS</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace Vmmsharp.Internal
|
||||
internal const string VMMDLL_Map_GetServicesX = "VMMDLL_Map_GetServicesU";
|
||||
internal const string VMMDLL_WinReg_EnumKeyExX = "VMMDLL_WinReg_EnumKeyExU";
|
||||
internal const string VMMDLL_WinReg_EnumValueX = "VMMDLL_WinReg_EnumValueU";
|
||||
internal const string VMMDLL_WinReg_QueryNameOriginalX = "VMMDLL_WinReg_QueryNameOriginalU";
|
||||
internal const string VMMDLL_WinReg_QueryValueExX = "VMMDLL_WinReg_QueryValueExU";
|
||||
#else
|
||||
internal const UnmanagedType VmmString = UnmanagedType.LPWStr;
|
||||
@@ -98,6 +99,7 @@ namespace Vmmsharp.Internal
|
||||
internal const string VMMDLL_Map_GetServicesX = "VMMDLL_Map_GetServicesW";
|
||||
internal const string VMMDLL_WinReg_EnumKeyExX = "VMMDLL_WinReg_EnumKeyExW";
|
||||
internal const string VMMDLL_WinReg_EnumValueX = "VMMDLL_WinReg_EnumValueW";
|
||||
internal const string VMMDLL_WinReg_QueryNameOriginalX = "VMMDLL_WinReg_QueryNameOriginalW";
|
||||
internal const string VMMDLL_WinReg_QueryValueExX = "VMMDLL_WinReg_QueryValueExW";
|
||||
#endif
|
||||
|
||||
@@ -1443,6 +1445,15 @@ namespace Vmmsharp.Internal
|
||||
byte* lpData,
|
||||
ref uint lpcbData);
|
||||
|
||||
[LibraryImport("vmm", EntryPoint = "VMMDLL_WinReg_QueryNameOriginalU")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static unsafe partial bool VMMDLL_WinReg_QueryNameOriginal(
|
||||
IntPtr hVMM,
|
||||
[MarshalAs(UnmanagedType.LPUTF8Str)] string uszFullPath,
|
||||
[MarshalAs(UnmanagedType.Bool)] bool fValue,
|
||||
byte* lpName,
|
||||
ref uint lpcchName);
|
||||
|
||||
[LibraryImport("vmm", EntryPoint = "VMMDLL_WinReg_QueryValueExU")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static unsafe partial bool VMMDLL_WinReg_QueryValueEx(
|
||||
@@ -1961,6 +1972,15 @@ namespace Vmmsharp.Internal
|
||||
byte* lpData,
|
||||
ref uint lpcbData);
|
||||
|
||||
[DllImport("vmm", EntryPoint = VMMDLL_WinReg_QueryNameOriginalX)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern unsafe bool VMMDLL_WinReg_QueryNameOriginal(
|
||||
IntPtr hVMM,
|
||||
[MarshalAs(VmmString)] string uszFullPath,
|
||||
[MarshalAs(UnmanagedType.Bool)] bool fValue,
|
||||
byte* lpName,
|
||||
ref uint lpcchName);
|
||||
|
||||
[DllImport("vmm", EntryPoint = VMMDLL_WinReg_QueryValueExX)]
|
||||
internal static extern unsafe bool VMMDLL_WinReg_QueryValueEx(
|
||||
IntPtr hVMM,
|
||||
|
||||
@@ -1136,6 +1136,36 @@ namespace Vmmsharp
|
||||
return re;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the original name of a registry key or value stored in the hive.
|
||||
/// Use the file-system-safe path for lookups; original names may contain backslashes or embedded nulls.
|
||||
/// </summary>
|
||||
/// <param name="sFullPath">Existing file-system path, including the value name if isValue is true.</param>
|
||||
/// <param name="isValue">True for a value, false for a key.</param>
|
||||
/// <returns>Original name on success, empty string for the unnamed value, or null on failure.</returns>
|
||||
public unsafe string RegNameOriginal(string sFullPath, bool isValue = false)
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
const int cbChar = 1;
|
||||
Encoding encoding = Encoding.UTF8;
|
||||
#else
|
||||
const int cbChar = 2;
|
||||
Encoding encoding = Encoding.Unicode;
|
||||
#endif
|
||||
uint cchName = 0;
|
||||
if (string.IsNullOrEmpty(sFullPath) || sFullPath.IndexOf('\0') >= 0) { return null; }
|
||||
if (!Vmmi.VMMDLL_WinReg_QueryNameOriginal(hVMM, sFullPath, isValue, null, ref cchName)) { return null; }
|
||||
if (cchName == 0 || cchName > int.MaxValue / cbChar) { return null; }
|
||||
byte[] data = new byte[(int)cchName * cbChar];
|
||||
fixed (byte* pb = data)
|
||||
{
|
||||
if (!Vmmi.VMMDLL_WinReg_QueryNameOriginal(hVMM, sFullPath, isValue, pb, ref cchName)) { return null; }
|
||||
}
|
||||
if (cchName == 0 || cchName > data.Length / cbChar) { return null; }
|
||||
// Exclude only the final terminator, retaining embedded and trailing nulls.
|
||||
return encoding.GetString(data, 0, ((int)cchName - 1) * cbChar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a registry value.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user