Version 5.18.3

This commit is contained in:
Ulf Frisk
2026-08-08 13:53:09 +02:00
parent cb7a09f4f2
commit 6cd5bedb93
21 changed files with 381 additions and 244 deletions
+1
View File
@@ -265,3 +265,4 @@ Latest:
* Bug fixes.
* Fix: Heap recovery now works on Windows 11 24H2 and later.
* Fix: Pool and Heap parsing improved.
* Fix: Compressed memory recovery rates improved.
+11 -11
View File
@@ -292,17 +292,17 @@ BOOL LcRead(
* request to the target.
*/
typedef DWORD LC_READ_PAGE_RESULT, *PLC_READ_PAGE_RESULT;
#define LC_READ_PAGE_RESULT_NONE 0
#define LC_READ_PAGE_RESULT_SUCCESS 1
#define LC_READ_PAGE_RESULT_SUCCESS_AFTER_RETRY 2
#define LC_READ_PAGE_RESULT_UNSUPPORTED_REQUEST 3
#define LC_READ_PAGE_RESULT_COMPLETER_ABORT 4
#define LC_READ_PAGE_RESULT_NO_COMPLETION 5
#define LC_READ_PAGE_RESULT_PARTIAL_COMPLETION 6
#define LC_READ_PAGE_RESULT_TRANSPORT_ERROR 7
#define LC_READ_PAGE_RESULT_PROTOCOL_ERROR 8
#define LC_READ_PAGE_RESULT_UNSPECIFIED_ERROR 9
#define LC_READ_PAGE_RESULT_NOT_ISSUED 10
#define LC_READ_PAGE_RESULT_NONE 0x00
#define LC_READ_PAGE_RESULT_SUCCESS 0x01
#define LC_READ_PAGE_RESULT_SUCCESS_AFTER_RETRY 0x02
#define LC_READ_PAGE_RESULT_UNSUPPORTED_REQUEST 0x03
#define LC_READ_PAGE_RESULT_COMPLETER_ABORT 0x04
#define LC_READ_PAGE_RESULT_NO_COMPLETION 0x05
#define LC_READ_PAGE_RESULT_PARTIAL_COMPLETION 0x06
#define LC_READ_PAGE_RESULT_TRANSPORT_ERROR 0x07
#define LC_READ_PAGE_RESULT_PROTOCOL_ERROR 0x08
#define LC_READ_PAGE_RESULT_UNSPECIFIED_ERROR 0x09
#define LC_READ_PAGE_RESULT_NOT_ISSUED 0x0A
/*
* Read memory in a scattered non-contiguous way and return a typed result for
+2 -2
View File
@@ -3,8 +3,8 @@
#define VERSION_MAJOR 5
#define VERSION_MINOR 18
#define VERSION_REVISION 2
#define VERSION_BUILD 241
#define VERSION_REVISION 3
#define VERSION_BUILD 242
#define VER_FILE_DESCRIPTION_STR "MemProcFS : Plugin vmemd"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
+2 -2
View File
@@ -3,8 +3,8 @@
#define VERSION_MAJOR 5
#define VERSION_MINOR 18
#define VERSION_REVISION 2
#define VERSION_BUILD 241
#define VERSION_REVISION 3
#define VERSION_BUILD 242
#define VER_FILE_DESCRIPTION_STR "MemProcFS"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
+8 -5
View File
@@ -1039,9 +1039,6 @@ VOID MmVad_ExtendedInfoFetch(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pSystemProcess
PVMMOB_SCATTER hObScatter = NULL;
DWORD cbRead, cb32 = f32 ? 4 : 8;
pVadMap = pProcess->Map.pObVad;
if(tp == VMM_VADMAP_TP_FULL) {
if(!(psmOb = ObStrMap_New(H, 0))) { goto cleanup; }
}
// count max potential vads and allocate.
{
for(i = 0, cMax = pVadMap->cMap; i < cMax; i++) {
@@ -1125,6 +1122,10 @@ VOID MmVad_ExtendedInfoFetch(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pSystemProcess
pVadMap->tp = tp;
goto cleanup;
}
// [ alloc strmap for full VAD parse ]
if(!(psmOb = ObStrMap_New(H, 0))) {
goto cleanup;
}
// [ heap map parse ]
if(VmmMap_GetHeap(H, pProcess, &pObHeapMap)) {
for(i = 0; i < pObHeapMap->cSegments; i++) {
@@ -1172,14 +1173,16 @@ VOID MmVad_ExtendedInfoFetch(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pSystemProcess
);
}
}
// cleanup
// Finalize all strings before publishing the full map.
f = ObStrMap_FinalizeAllocU_DECREF_NULL(&psmOb, &pVadMap->pbMultiText, &pVadMap->cbMultiText);
if(!f) { goto cleanup; }
pVadMap->tp = tp;
cleanup:
ObStrMap_FinalizeAllocU_DECREF_NULL(&psmOb, &pVadMap->pbMultiText, &pVadMap->cbMultiText);
Ob_DECREF(pObThreadMap);
Ob_DECREF(pObHeapMap);
Ob_DECREF(pObPteMap);
Ob_DECREF(hObScatter);
Ob_DECREF(psmOb);
LocalFree(pva);
}
+164 -125
View File
@@ -25,7 +25,7 @@
#define MMWINX86PAE_PTE_TRANSITION(pte) (((pte & 0x0c01) == 0x0800) ? ((pte & 0x0000003ffffff000) | 0x005) : 0)
#define MMWINX86PAE_PTE_PROTOTYPE(pte) (((pte & 0x8000000700000401) == 0x8000000000000400) ? (pte >> 32) : 0)
#define MMWINX86PAE_PTE_PAGE_FILE_NUMBER(H, pte) ((pte >> (((H->vmm.kernel.dwVersionBuild >= 17134) ? 12 : 1))) & 0x0f)
#define MMWINX86PAE_PTE_PAGE_FILE_OFFSET(pte) ((pte >> 32) ^ (!(pte & PTE_SWIZZLE_BIT) ? PTE_SWIZZLE_MASK : 0))
#define MMWINX86PAE_PTE_PAGE_FILE_OFFSET(pte) ((DWORD)(pte >> 32) & ~(((H->vmm.kernel.dwVersionBuild >= 17134) && !(pte & PTE_SWIZZLE_BIT)) ? PTE_SWIZZLE_MASK : 0))
#define MMWINX86PAE_PTE_PAGE_KEY_COMPRESSED(H, pte) (DWORD)(((MMWINX86PAE_PTE_PAGE_FILE_NUMBER(H, pte) << 0x1c) | MMWINX86PAE_PTE_PAGE_FILE_OFFSET(pte)))
#define MMWINX64_PTE_IS_HARDWARE(pte) (pte & 0x01)
@@ -33,7 +33,7 @@
#define MMWINX64_PTE_TRANSITION(pte) (((pte & 0x0c01) == 0x0800) ? ((pte & 0xffffdffffffff000) | 0x005) : 0)
#define MMWINX64_PTE_PROTOTYPE(pte) (((pte & 0x8000000000070401) == 0x8000000000000400) ? ((pte >> 16) | 0xffff000000000000) : 0)
#define MMWINX64_PTE_PAGE_FILE_NUMBER(H, pte) ((pte >> (((H->vmm.kernel.dwVersionBuild >= 17134) ? 12 : 1))) & 0x0f)
#define MMWINX64_PTE_PAGE_FILE_OFFSET(pte) ((pte >> 32) ^ (!(pte & PTE_SWIZZLE_BIT) ? PTE_SWIZZLE_MASK : 0))
#define MMWINX64_PTE_PAGE_FILE_OFFSET(pte) ((DWORD)(pte >> 32) & ~(((H->vmm.kernel.dwVersionBuild >= 17134) && !(pte & PTE_SWIZZLE_BIT)) ? PTE_SWIZZLE_MASK : 0))
#define MMWINX64_PTE_PAGE_KEY_COMPRESSED(H, pte) (DWORD)(((MMWINX64_PTE_PAGE_FILE_NUMBER(H, pte) << 0x1c) | MMWINX64_PTE_PAGE_FILE_OFFSET(pte)))
typedef struct tdMMWIN_MEMCOMPRESS_OFFSET {
@@ -124,67 +124,39 @@ BOOL MmWin_BTree64_Search(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _In_ QW
_Success_(return)
BOOL MmWin_BTree32_SearchLeaf(_In_ PVMM_PROCESS pSystemProcess, _In_ P_BTREE32 pT, _In_ DWORD dwKey, _Out_ PDWORD pdwValue, _In_ QWORD fVmmRead)
{
BOOL fSearchPreFail = FALSE;
DWORD i, dwSearchStep, dwSearchIndex = 1;
// 2: search tree for leaf
for(i = 1; (i < 12) && ((pT->cEntries - 1) >> i); i++);
dwSearchIndex = dwSearchStep = min(1 << (i - 1), pT->cEntries);
while(TRUE) {
dwSearchStep = dwSearchStep >> 1;
if(pT->LeafEntries[dwSearchIndex].k == dwKey) {
*pdwValue = pT->LeafEntries[dwSearchIndex].v;
DWORD i, iMin = 0, iMax = pT->cEntries;
while(iMin < iMax) {
i = iMin + ((iMax - iMin) >> 1);
if(pT->LeafEntries[i].k == dwKey) {
*pdwValue = pT->LeafEntries[i].v;
return TRUE;
}
if(dwSearchStep == 0) {
if(fSearchPreFail) {
return FALSE;
}
fSearchPreFail = TRUE;
dwSearchStep = 1;
}
if(pT->LeafEntries[dwSearchIndex].k < dwKey) {
if(dwSearchIndex + dwSearchStep < pT->cEntries) {
dwSearchIndex += dwSearchStep;
}
if(pT->LeafEntries[i].k < dwKey) {
iMin = i + 1;
} else {
if(dwSearchStep <= dwSearchIndex) {
dwSearchIndex -= dwSearchStep;
}
iMax = i;
}
}
return FALSE;
}
_Success_(return)
BOOL MmWin_BTree64_SearchLeaf(_In_ PVMM_PROCESS pSystemProcess, _In_ P_BTREE64 pT, _In_ DWORD dwKey, _Out_ PDWORD pdwValue, _In_ QWORD fVmmRead)
{
BOOL fSearchPreFail = FALSE;
DWORD i, dwSearchStep, dwSearchIndex = 1;
// 2: search tree for leaf
for(i = 1; (i < 12) && ((pT->cEntries - 1) >> i); i++);
dwSearchIndex = dwSearchStep = min(1 << (i - 1), pT->cEntries);
while(TRUE) {
dwSearchStep = dwSearchStep >> 1;
if(pT->LeafEntries[dwSearchIndex].k == dwKey) {
*pdwValue = pT->LeafEntries[dwSearchIndex].v;
DWORD i, iMin = 0, iMax = pT->cEntries;
while(iMin < iMax) {
i = iMin + ((iMax - iMin) >> 1);
if(pT->LeafEntries[i].k == dwKey) {
*pdwValue = pT->LeafEntries[i].v;
return TRUE;
}
if(dwSearchStep == 0) {
if(fSearchPreFail) {
return FALSE;
}
fSearchPreFail = TRUE;
dwSearchStep = 1;
}
if(pT->LeafEntries[dwSearchIndex].k < dwKey) {
if(dwSearchIndex + dwSearchStep < pT->cEntries) {
dwSearchIndex += dwSearchStep;
}
if(pT->LeafEntries[i].k < dwKey) {
iMin = i + 1;
} else {
if(dwSearchStep <= dwSearchIndex) {
dwSearchIndex -= dwSearchStep;
}
iMax = i;
}
}
return FALSE;
}
_Success_(return)
@@ -292,7 +264,7 @@ BOOL MmWin_BTree64_Search(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _In_ QW
if(!f) { return FALSE; }
if(pT->fLeaf) {
// Leaf
if(pT->cEntries > 0x1ff) { return FALSE; }
if(pT->cEntries > 0x1fe) { return FALSE; }
return MmWin_BTree64_SearchLeaf(pProcess, pT, dwKey, pdwValue, fVmmRead);
} else {
// Node
@@ -737,10 +709,16 @@ typedef struct td_SMHP_CHUNK_METADATA64 {
typedef struct td_ST_PAGE_RECORD {
DWORD Key;
DWORD CompressedSize;
DWORD NextKey;
// Normal records store a WORD size at +4; redirects store a DWORD key at +4.
union {
WORD CompressedSize;
DWORD NextKey;
} u;
DWORD Reserved;
} _ST_PAGE_RECORD, *P_ST_PAGE_RECORD;
#define MMWIN_MEMCOMPRESS_MAX_PAGE_RECORD_REDIRECTS 0x20
/*
* Log a memory compression error.
* -- H
@@ -825,6 +803,60 @@ BOOL MmWin_MemCompress2_SmkmStoreMetadata64(_In_ VMM_HANDLE H, _In_ PMMWINX64_CO
return TRUE;
}
/*
* Retrieve the PageRecord address from the region key and the already loaded
* SmkmStore. Page records with Key == 0xffffffff may redirect to another
* region key, so this calculation is also used while following redirects.
* -- H
* -- ctx
* -- return
*/
_Success_(return)
BOOL MmWin_MemCompress3_PageRecordAddress32(_In_ VMM_HANDLE H, _In_ PMMWINX64_COMPRESS_CONTEXT ctx)
{
QWORD cbChunkEntry;
DWORD vaPageRecordArray;
DWORD i, dwEncodedMetadata, iChunkPtr = 0, iChunkArray, dwPoolHdr = 0;
P_SMHP_CHUNK_METADATA32 pc;
PMMWIN_MEMCOMPRESS_OFFSET po = &H->vmm.pMmContext->MemCompress.O;
// Get page record and calculate:
// - chunk "encoded metadata"
// - index into chunk metadata array (= highest non-zero bit position of encoded_metadata)
// - index into chunk array (pointed to by chunk metadata array)
pc = (P_SMHP_CHUNK_METADATA32)(ctx->e.pbSmkm + po->SMKM_STORE.ChunkMetaData);
if((pc->dwBitValue & 0xff) >= 32) {
return MmWin_MemCompress_LogError(H, ctx, "#35 InvalidChunkMetadata");
}
dwEncodedMetadata = ctx->e.dwRegionKey >> (pc->dwBitValue & 0xff);
if(!dwEncodedMetadata) {
return MmWin_MemCompress_LogError(H, ctx, "#35 InvalidChunkMetadata");
}
for(i = 0; i < 32; i++) {
if(!(dwEncodedMetadata >> i)) { break; }
iChunkPtr = i;
}
iChunkArray = (1U << iChunkPtr) ^ dwEncodedMetadata;
// Validate and fetch page record address
if(iChunkArray > 0x400) {
return MmWin_MemCompress_LogError(H, ctx, "#35 ChunkArrayTooLarge");
}
if(!VMM_KADDR32_8(pc->avaChunkPtr[iChunkPtr])) {
return MmWin_MemCompress_LogError(H, ctx, "#36 ChunkPtrNoKADDR");
}
if(pc->avaChunkPtr[iChunkPtr] & 0xfff) {
if(!VmmRead2(H, ctx->pSystemProcess, pc->avaChunkPtr[iChunkPtr] - 4, (PBYTE)&dwPoolHdr, 4, ctx->fVmmRead) || (dwPoolHdr != 'ABms')) {
return MmWin_MemCompress_LogError(H, ctx, "#37 ChunkBadPoolHdr");
}
}
// Windows 10 1607 uses two DWORDs per chunk entry; 1703+ uses three.
cbChunkEntry = (H->vmm.kernel.dwVersionBuild >= 15063) ? 0x0cULL : 0x08ULL;
if(!VmmRead2(H, ctx->pSystemProcess, pc->avaChunkPtr[iChunkPtr] + cbChunkEntry * iChunkArray, (PBYTE)&vaPageRecordArray, sizeof(DWORD), ctx->fVmmRead) || !VMM_KADDR32_PAGE(vaPageRecordArray)) {
return MmWin_MemCompress_LogError(H, ctx, "#38 PageRecordArray");
}
ctx->e.vaPageRecord = (DWORD)((QWORD)vaPageRecordArray + pc->dwChunkPageHeaderSize + ((QWORD)pc->dwPageRecordSize * (ctx->e.dwRegionKey & pc->dwPageRecordsPerChunkMask)));
return TRUE;
}
/*
* Retrieve the SmkmStore and the PageRecord.
* -- H
@@ -834,9 +866,6 @@ BOOL MmWin_MemCompress2_SmkmStoreMetadata64(_In_ VMM_HANDLE H, _In_ PMMWINX64_CO
_Success_(return)
BOOL MmWin_MemCompress3_SmkmStoreAndPageRecord32(_In_ VMM_HANDLE H, _In_ PMMWINX64_COMPRESS_CONTEXT ctx)
{
DWORD vaPageRecordArray;
DWORD i, dwEncodedMetadata, iChunkPtr = 0, iChunkArray, dwPoolHdr = 0;
P_SMHP_CHUNK_METADATA32 pc;
PMMWIN_MEMCOMPRESS_OFFSET po = &H->vmm.pMmContext->MemCompress.O;
// 1: Load SmkmStore
if(!VmmRead2(H, ctx->pSystemProcess, ctx->e.vaSmkmStore, ctx->e.pbSmkm, sizeof(ctx->e.pbSmkm), ctx->fVmmRead)) {
@@ -853,34 +882,9 @@ BOOL MmWin_MemCompress3_SmkmStoreAndPageRecord32(_In_ VMM_HANDLE H, _In_ PMMWINX
if(!MmWin_BTree_Search(H, ctx->pSystemProcess, *(PDWORD)(ctx->e.pbSmkm + po->SMKM_STORE.PagesTree), ctx->e.dwPageKey, &ctx->e.dwRegionKey, ctx->fVmmRead)) {
return MmWin_MemCompress_LogError(H, ctx, "#34 RegionKeyBTreeSearch");
}
// 4: Get page record and calculate:
// - chunk "encoded metadata"
// - index into chunk metadata array (= highest non-zero bit position of encoded_metadata)
// - index into chunk array (pointed to by chunk metadata array)
pc = (P_SMHP_CHUNK_METADATA32)(ctx->e.pbSmkm + po->SMKM_STORE.ChunkMetaData);
dwEncodedMetadata = ctx->e.dwRegionKey >> (pc->dwBitValue & 0xff);
for(i = 0; i < 32; i++) {
if(!(dwEncodedMetadata >> i)) { break; }
iChunkPtr = i;
}
iChunkArray = (1 << iChunkPtr) ^ dwEncodedMetadata;
// 5: Validate and fetch page record address
if(iChunkArray > 0x400) {
return MmWin_MemCompress_LogError(H, ctx, "#35 ChunkArrayTooLarge");
}
if(!VMM_KADDR32_8(pc->avaChunkPtr[iChunkPtr])) {
return MmWin_MemCompress_LogError(H, ctx, "#36 ChunkPtrNoKADDR");
}
if(pc->avaChunkPtr[iChunkPtr] & 0xfff) {
if(!VmmRead2(H, ctx->pSystemProcess, pc->avaChunkPtr[iChunkPtr] - 4, (PBYTE)&dwPoolHdr, 4, ctx->fVmmRead) || (dwPoolHdr != 'ABms')) {
return MmWin_MemCompress_LogError(H, ctx, "#37 ChunkBadPoolHdr");
}
}
if(!VmmRead2(H, ctx->pSystemProcess, pc->avaChunkPtr[iChunkPtr] + 0x0cULL * iChunkArray, (PBYTE)&vaPageRecordArray, sizeof(DWORD), ctx->fVmmRead) || !VMM_KADDR32_PAGE(vaPageRecordArray)) {
return MmWin_MemCompress_LogError(H, ctx, "#38 PageRecordArray");
}
ctx->e.vaPageRecord = (DWORD)((QWORD)vaPageRecordArray + pc->dwChunkPageHeaderSize + ((QWORD)pc->dwPageRecordSize * (ctx->e.dwRegionKey & pc->dwPageRecordsPerChunkMask)));
// 6: Get owner EPROCESS
// 4: Get page record address
if(!MmWin_MemCompress3_PageRecordAddress32(H, ctx)) { return FALSE; }
// 5: Get owner EPROCESS
ctx->e.vaOwnerEPROCESS = *(PDWORD)(ctx->e.pbSmkm + po->SMKM_STORE.OwnerProcess);
if(ctx->e.vaOwnerEPROCESS != H->vmm.pMmContext->MemCompress.vaEPROCESS) {
return MmWin_MemCompress_LogError(H, ctx, "#39 OwnerEPROCESS");
@@ -888,6 +892,55 @@ BOOL MmWin_MemCompress3_SmkmStoreAndPageRecord32(_In_ VMM_HANDLE H, _In_ PMMWINX
return TRUE;
}
/*
* Retrieve the PageRecord address from the region key and the already loaded SmkmStore.
* -- H
* -- ctx
* -- return
*/
_Success_(return)
BOOL MmWin_MemCompress3_PageRecordAddress64(_In_ VMM_HANDLE H, _In_ PMMWINX64_COMPRESS_CONTEXT ctx)
{
QWORD vaPageRecordArray;
DWORD i, dwEncodedMetadata, iChunkPtr = 0, iChunkArray, dwPoolHdr = 0;
P_SMHP_CHUNK_METADATA64 pc;
PMMWIN_MEMCOMPRESS_OFFSET po = &H->vmm.pMmContext->MemCompress.O;
// Get page record and calculate:
// - chunk "encoded metadata"
// - index into chunk metadata array (= highest non-zero bit position of encoded_metadata)
// - index into chunk array (pointed to by chunk metadata array)
pc = (P_SMHP_CHUNK_METADATA64)(ctx->e.pbSmkm + po->SMKM_STORE.ChunkMetaData);
if((pc->dwBitValue & 0xff) >= 32) {
return MmWin_MemCompress_LogError(H, ctx, "#35 InvalidChunkMetadata");
}
dwEncodedMetadata = ctx->e.dwRegionKey >> (pc->dwBitValue & 0xff);
if(!dwEncodedMetadata) {
return MmWin_MemCompress_LogError(H, ctx, "#35 InvalidChunkMetadata");
}
for(i = 0; i < 32; i++) {
if(!(dwEncodedMetadata >> i)) { break; }
iChunkPtr = i;
}
iChunkArray = (1U << iChunkPtr) ^ dwEncodedMetadata;
// Validate and fetch page record address
if(iChunkArray > 0x400) {
return MmWin_MemCompress_LogError(H, ctx, "#35 ChunkArrayTooLarge");
}
if(!VMM_KADDR64_16(pc->avaChunkPtr[iChunkPtr])) {
return MmWin_MemCompress_LogError(H, ctx, "#36 ChunkPtrNoKADDR");
}
if(pc->avaChunkPtr[iChunkPtr] & 0xfff) {
if(!VmmRead2(H, ctx->pSystemProcess, pc->avaChunkPtr[iChunkPtr] - 12, (PBYTE)&dwPoolHdr, 4, ctx->fVmmRead) || (dwPoolHdr != 'ABms')) {
return MmWin_MemCompress_LogError(H, ctx, "#37 ChunkBadPoolHdr");
}
}
if(!VmmRead2(H, ctx->pSystemProcess, pc->avaChunkPtr[iChunkPtr] + 0x10ULL * iChunkArray, (PBYTE)&vaPageRecordArray, sizeof(QWORD), ctx->fVmmRead) || !VMM_KADDR64_PAGE(vaPageRecordArray)) {
return MmWin_MemCompress_LogError(H, ctx, "#38 PageRecordArray");
}
ctx->e.vaPageRecord = (QWORD)(vaPageRecordArray + pc->dwChunkPageHeaderSize + ((QWORD)pc->dwPageRecordSize * (ctx->e.dwRegionKey & pc->dwPageRecordsPerChunkMask)));
return TRUE;
}
/*
* Retrieve the SmkmStore and the PageRecord.
* -- H
@@ -897,9 +950,6 @@ BOOL MmWin_MemCompress3_SmkmStoreAndPageRecord32(_In_ VMM_HANDLE H, _In_ PMMWINX
_Success_(return)
BOOL MmWin_MemCompress3_SmkmStoreAndPageRecord64(_In_ VMM_HANDLE H, _In_ PMMWINX64_COMPRESS_CONTEXT ctx)
{
QWORD vaPageRecordArray;
DWORD i, dwEncodedMetadata, iChunkPtr = 0, iChunkArray, dwPoolHdr = 0;
P_SMHP_CHUNK_METADATA64 pc;
PMMWIN_MEMCOMPRESS_OFFSET po = &H->vmm.pMmContext->MemCompress.O;
// 1: Load SmkmStore
if(!VmmRead2(H, ctx->pSystemProcess, ctx->e.vaSmkmStore, ctx->e.pbSmkm, sizeof(ctx->e.pbSmkm), ctx->fVmmRead)) {
@@ -916,34 +966,9 @@ BOOL MmWin_MemCompress3_SmkmStoreAndPageRecord64(_In_ VMM_HANDLE H, _In_ PMMWINX
if(!MmWin_BTree_Search(H, ctx->pSystemProcess, *(PQWORD)(ctx->e.pbSmkm + po->SMKM_STORE.PagesTree), ctx->e.dwPageKey, &ctx->e.dwRegionKey, ctx->fVmmRead)) {
return MmWin_MemCompress_LogError(H, ctx, "#34 RegionKeyBTreeSearch");
}
// 4: Get page record and calculate:
// - chunk "encoded metadata"
// - index into chunk metadata array (= highest non-zero bit position of encoded_metadata)
// - index into chunk array (pointed to by chunk metadata array)
pc = (P_SMHP_CHUNK_METADATA64)(ctx->e.pbSmkm + po->SMKM_STORE.ChunkMetaData);
dwEncodedMetadata = ctx->e.dwRegionKey >> (pc->dwBitValue & 0xff);
for(i = 0; i < 32; i++) {
if(!(dwEncodedMetadata >> i)) { break; }
iChunkPtr = i;
}
iChunkArray = (1 << iChunkPtr) ^ dwEncodedMetadata;
// 5: Validate and fetch page record address
if(iChunkArray > 0x400) {
return MmWin_MemCompress_LogError(H, ctx, "#35 ChunkArrayTooLarge");
}
if(!VMM_KADDR64_16(pc->avaChunkPtr[iChunkPtr])) {
return MmWin_MemCompress_LogError(H, ctx, "#36 ChunkPtrNoKADDR");
}
if(pc->avaChunkPtr[iChunkPtr] & 0xfff) {
if(!VmmRead2(H, ctx->pSystemProcess, pc->avaChunkPtr[iChunkPtr] - 12, (PBYTE)&dwPoolHdr, 4, ctx->fVmmRead) || (dwPoolHdr != 'ABms')) {
return MmWin_MemCompress_LogError(H, ctx, "#37 ChunkBadPoolHdr");
}
}
if(!VmmRead2(H, ctx->pSystemProcess, pc->avaChunkPtr[iChunkPtr] + 0x10ULL * iChunkArray, (PBYTE)&vaPageRecordArray, sizeof(QWORD), ctx->fVmmRead) || !VMM_KADDR64_PAGE(vaPageRecordArray)) {
return MmWin_MemCompress_LogError(H, ctx, "#38 PageRecordArray");
}
ctx->e.vaPageRecord = (QWORD)(vaPageRecordArray + pc->dwChunkPageHeaderSize + ((QWORD)pc->dwPageRecordSize * (ctx->e.dwRegionKey & pc->dwPageRecordsPerChunkMask)));
// 6: Get owner EPROCESS
// 4: Get page record address
if(!MmWin_MemCompress3_PageRecordAddress64(H, ctx)) { return FALSE; }
// 5: Get owner EPROCESS
ctx->e.vaOwnerEPROCESS = *(PQWORD)(ctx->e.pbSmkm + po->SMKM_STORE.OwnerProcess);
if(ctx->e.vaOwnerEPROCESS != H->vmm.pMmContext->MemCompress.vaEPROCESS) {
return MmWin_MemCompress_LogError(H, ctx, "#39 OwnerEPROCESS");
@@ -960,40 +985,54 @@ _Success_(return)
BOOL MmWin_MemCompress4_CompressedRegionData(_In_ VMM_HANDLE H, _In_ PMMWINX64_COMPRESS_CONTEXT ctx)
{
QWORD vaRegionPtr = 0;
DWORD dwRegionIndexMask, dwRegionIndex;
DWORD i, dwRegionIndexMask, dwRegionIndex;
_ST_PAGE_RECORD PageRecord;
PMMWIN_MEMCOMPRESS_OFFSET po = &H->vmm.pMmContext->MemCompress.O;
// 1: Read page record
if(!VmmRead2(H, ctx->pSystemProcess, ctx->e.vaPageRecord, (PBYTE)&PageRecord, sizeof(PageRecord), ctx->fVmmRead)) {
return MmWin_MemCompress_LogError(H, ctx, "#41 ReadPageRecord");
// 1: Read page record and follow any redirect records.
for(i = 0; i <= MMWIN_MEMCOMPRESS_MAX_PAGE_RECORD_REDIRECTS; i++) {
if(!VmmRead2(H, ctx->pSystemProcess, ctx->e.vaPageRecord, (PBYTE)&PageRecord, sizeof(PageRecord), ctx->fVmmRead)) {
return MmWin_MemCompress_LogError(H, ctx, "#41 ReadPageRecord");
}
if(PageRecord.Key != 0xffffffff) { break; }
if((i == MMWIN_MEMCOMPRESS_MAX_PAGE_RECORD_REDIRECTS) || (PageRecord.u.NextKey == ctx->e.dwRegionKey)) {
return MmWin_MemCompress_LogError(H, ctx, "#42 InvalidPageRecordRedirect");
}
ctx->e.dwRegionKey = PageRecord.u.NextKey;
if(H->vmm.f32) {
if(!MmWin_MemCompress3_PageRecordAddress32(H, ctx)) { return FALSE; }
} else {
if(!MmWin_MemCompress3_PageRecordAddress64(H, ctx)) { return FALSE; }
}
}
if(PageRecord.Key == 0xffffffff) {
// TODO: implement support
return MmWin_MemCompress_LogError(H, ctx, "#42 UnsupportedPageRecord");
ctx->e.cbCompressedData = (PageRecord.u.CompressedSize == 0x1000) ? 0x1000 : PageRecord.u.CompressedSize & 0xfff;
dwRegionIndexMask = *(PDWORD)(ctx->e.pbSmkm + po->SMKM_STORE.RegionIndexMask) & 0xff;
if(dwRegionIndexMask >= 32) {
return MmWin_MemCompress_LogError(H, ctx, "#47 InvalidRegionIndexMask");
}
ctx->e.cbCompressedData = (PageRecord.CompressedSize == 0x1000) ? 0x1000 : PageRecord.CompressedSize & 0xfff;
if(H->vmm.f32) {
// 2: Get pointer to region (32-bit)
dwRegionIndexMask = *(PDWORD)(ctx->e.pbSmkm + po->SMKM_STORE.RegionIndexMask) & 0xff;
dwRegionIndex = PageRecord.Key >> dwRegionIndexMask;
vaRegionPtr = *(PDWORD)(ctx->e.pbSmkm + po->SMKM_STORE.CompressedRegionPtrArray) + dwRegionIndex * sizeof(DWORD);
// 3: Get region and offset (32-bit)
if(!VmmRead2(H, ctx->pSystemProcess, vaRegionPtr, (PBYTE)&ctx->e.vaRegion, sizeof(DWORD), ctx->fVmmRead)) {
return MmWin_MemCompress_LogError(H, ctx, "#43 ReadRegionVA");
}
if(!ctx->e.vaRegion || (ctx->e.vaRegion & 0x8000ffff)) {
// High bit and low 16 bits contain entry state; regions are 64KB aligned.
ctx->e.vaRegion &= 0x7fff0000;
if(!VMM_UADDR32(ctx->e.vaRegion)) {
return MmWin_MemCompress_LogError(H, ctx, "#44 InvalidRegionVA");
}
} else {
// 2: Get pointer to region (64-bit)
dwRegionIndexMask = *(PDWORD)(ctx->e.pbSmkm + po->SMKM_STORE.RegionIndexMask) & 0xff;
dwRegionIndex = PageRecord.Key >> dwRegionIndexMask;
vaRegionPtr = *(PQWORD)(ctx->e.pbSmkm + po->SMKM_STORE.CompressedRegionPtrArray) + dwRegionIndex * sizeof(QWORD);
// 3: Get region and offset (64-bit)
if(!VmmRead2(H, ctx->pSystemProcess, vaRegionPtr, (PBYTE)&ctx->e.vaRegion, sizeof(QWORD), ctx->fVmmRead)) {
return MmWin_MemCompress_LogError(H, ctx, "#45 ReadRegionVA");
}
if(!ctx->e.vaRegion || (ctx->e.vaRegion & 0xffff80000000ffff)) {
// High bit and low 16 bits contain entry state; regions are 64KB aligned.
ctx->e.vaRegion &= 0x7fffffffffff0000;
if(!VMM_UADDR64(ctx->e.vaRegion)) {
return MmWin_MemCompress_LogError(H, ctx, "#46 InvalidRegionVA");
}
}
+1 -1
View File
@@ -377,7 +377,7 @@ next_check:
peVadEx->pte = pte;
peVadEx->iPML = iPML;
*piVadEx = *piVadEx + 1;
if((iPML == 1) && (iPte < 0x3ff) && (iVadEx + 1 < pVadEx->cMap) && (peVadEx->va + 0x1000 == pVadEx->pMap[iVadEx + 1].va)) { goto next_entry; }
if((iPML == 1) && (iPte < 0x1ff) && (iVadEx + 1 < pVadEx->cMap) && (peVadEx->va + 0x1000 == pVadEx->pMap[iVadEx + 1].va)) { goto next_entry; }
Ob_DECREF(pObPTEs);
}
+2 -2
View File
@@ -3,8 +3,8 @@
#define VERSION_MAJOR 5
#define VERSION_MINOR 18
#define VERSION_REVISION 2
#define VERSION_BUILD 241
#define VERSION_REVISION 3
#define VERSION_BUILD 242
#define VER_FILE_DESCRIPTION_STR "MemProcFS : Core"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
+1 -1
View File
@@ -649,7 +649,7 @@ DWORD VmmWinInit_FindNtosScan32(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pSystemProc
if(pNtHeader->Signature != IMAGE_NT_SIGNATURE) { continue; } // NT header signature
for(o = 0; o < 0x800; o += 8) {
if(*(PQWORD)(pb + ova + o) == 0x45444F434C4F4F50) { // POOLCODE
if(!PE_GetModuleNameEx(H, pSystemProcess, (QWORD)vaBase + ova, FALSE, pb + ova, szModuleName, _countof(szModuleName), NULL)) {
if(!PE_GetModuleNameEx(H, pSystemProcess, vaBase, FALSE, pb + ova, szModuleName, _countof(szModuleName), NULL)) {
vaNtosTry = vaBase;
continue;
}
+1 -1
View File
@@ -1284,7 +1284,7 @@ BOOL VmmWinObjFile_ReadAlloc(_In_ VMM_HANDLE H, _In_ POB_VMMWINOBJ_FILE pFile, _
cbFile = VmmWinObjFile_Size(H, pFile, tp);
if(!cbFile || (cbFile > 0x80000000)) { return FALSE; }
if(cbFileMaxSize && (cbFile > cbFileMaxSize)) { return FALSE; }
if(!(pbFile = LocalAlloc(LMEM_ZEROINIT, cbFile))) { return FALSE; }
if(!(pbFile = LocalAlloc(LMEM_ZEROINIT, (SIZE_T)cbFile))) { return FALSE; }
// read file:
if(!(cbRead = VmmWinObjFile_Read(H, pFile, 0, pbFile, (DWORD)cbFile, fVmmRead, tp))) {
LocalFree(pbFile);
+98 -35
View File
@@ -15,7 +15,8 @@
#include "vmmwin.h"
#include "vmmwinobj.h"
#define REG_SIGNATURE_HBIN 0x6e696268
#define REG_SIGNATURE_HBIN 0x6e696268
#define VMMWINREG_KEY_MAX_DEPTH 0x200
typedef struct tdVMMWIN_REGISTRY_OFFSET {
QWORD vaHintCMHIVE;
@@ -214,7 +215,7 @@ VOID VmmWinReg_ReadScatter(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessRegistry
for(i = 0; i < cpMEMsReg; i++) {
pMEM = ppMEMsReg[i];
MEM_SCATTER_STACK_PUSH(pMEM, pMEM->qwA);
if(pMEM->f || !VmmWinReg_Reg2Virt(H, pProcessRegistry, pRegistryHive, (DWORD)pMEM->qwA, &pMEM->qwA)) {
if(pMEM->f || (pMEM->qwA > 0xffffffff) || !VmmWinReg_Reg2Virt(H, pProcessRegistry, pRegistryHive, (DWORD)pMEM->qwA, &pMEM->qwA)) {
pMEM->qwA = -1;
}
}
@@ -248,7 +249,7 @@ VOID VmmWinReg_ReadScatter(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessRegistry
}
ctxHiveFileScatterRead.pFile = pObHiveFile;
ctxHiveFileScatterRead.tp = VMMWINOBJ_FILE_TP_DATA | VMMWINOBJ_FILE_TP_CACHE;
VmmWinObjFile_ReadScatter(H, &ctxHiveFileScatterRead, ppMEMsReg, cpMEMsReg, flags);
VmmWinObjFile_ReadScatter(H, &ctxHiveFileScatterRead, ppMEMsFile, cMEMsFile, flags);
for(i = 0; i < cMEMsFile; i++) {
pMEM = ppMEMsFile[i];
pMEM->qwA = MEM_SCATTER_STACK_POP(pMEM);
@@ -279,7 +280,7 @@ VOID VmmWinReg_HiveReadEx(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pRegistryHiv
PMEM_SCATTER pMEMs, *ppMEMs;
QWORD i, oVA;
if(pcbReadOpt) { *pcbReadOpt = 0; }
if(!cb) { return; }
if(!cb || (cb >= 0x80000000) || ((QWORD)cb > 0x100000000ULL - ra)) { return; }
cMEMs = (DWORD)(((ra & 0xfff) + cb + 0xfff) >> 12);
pbBuffer = (PBYTE)LocalAlloc(LMEM_ZEROINIT, 0x2000 + cMEMs * (sizeof(MEM_SCATTER) + sizeof(PMEM_SCATTER)));
if(!pbBuffer) {
@@ -365,7 +366,7 @@ BOOL VmmWinReg_HiveWrite(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pRegistryHive
DWORD cbWrite;
BOOL fSuccess = TRUE;
PVMM_PROCESS pObProcessRegistry = NULL;
if(!cb || !(pObProcessRegistry = VmmWinReg_GetRegistryProcess(H))) { return FALSE; }
if(!cb || ((QWORD)cb > 0x100000000ULL - ra) || !(pObProcessRegistry = VmmWinReg_GetRegistryProcess(H))) { return FALSE; }
while(cb) {
cbWrite = min(cb, 0x1000 - (ra & 0xfff));
if(VmmWinReg_Reg2Virt(H, pObProcessRegistry, pRegistryHive, ra, &vaWrite) && vaWrite) {
@@ -690,6 +691,8 @@ BOOL VmmWinReg_LocateRegistryHive(_In_ VMM_HANDLE H)
}
}
}
LcMemFree(ppMEMs);
ppMEMs = NULL;
}
}
// 2: As a fallback - try locate registry by scanning lower physical memory.
@@ -887,7 +890,7 @@ VOID VmmWinReg_EnumHive32_Post(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _I
pHiveMap &&
(*(PDWORD)(pbData + po->CM.Signature) == 0xBEE0BEE0) && // Signature match
!(*(PDWORD)(pbData + po->CM.BaseBlock) & 0xfff) && // _CMHIVE.BaseBlock on page boundary
(*(PQWORD)(pbData + po->CM.StorageMap0)) && // _CMHIVE.Hive.Storage.Map
(*(PDWORD)(pbData + po->CM.StorageMap0)) && // _CMHIVE.Hive.Storage.Map
(*(PDWORD)(pbData + po->CM.Length0)) && // Length > 0
(*(PDWORD)(pbData + po->CM.Length0) <= 0x40000000); // Length < 1GB
if(!f) { return; }
@@ -960,8 +963,9 @@ VOID VmmWinReg_EnumHive32_Post(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _I
(szHiveFileNameShort[0] ? szHiveFileNameShort : "unknown"),
(szHiveFileNameLong[0] ? szHiveFileNameLong : "unknown"));
// 4: Attach and Return
ObMap_Push(pHiveMap, pObHive->vaCMHIVE, pObHive); // pRegistry->pmHive takes responsibility for pObHive reference
ObMap_Push(pHiveMap, pObHive->vaCMHIVE, pObHive);
VmmLog(H, MID_REGISTRY, LOGLEVEL_DEBUG, "HIVE_ENUM: %04i: %s", ObMap_Size(pHiveMap), pObHive->uszName);
Ob_DECREF(pObHive);
}
/*
@@ -1071,6 +1075,8 @@ BOOL VmmWinReg_HiveSnapshotEnsure(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHiv
if(!pHive) { return FALSE; }
if(pHive->Snapshot.fInitialized) { return TRUE; }
if(pHive->cbLength > 0x10000000) { return FALSE; } // max 256MB hive
if((pHive->_DUAL[0].cb & 0xfff) || (pHive->_DUAL[0].cb > 0x10000000) || (pHive->_DUAL[0].cb < 0x1000)) { return FALSE; }
if((pHive->_DUAL[1].cb & 0xfff) || (pHive->_DUAL[1].cb > 0x10000000)) { return FALSE; }
// 2: lock and retry retrieve cached
EnterCriticalSection(&pHive->LockUpdate);
if(pHive->Snapshot.fInitialized) {
@@ -1323,7 +1329,7 @@ DWORD VmmWinReg_KeyHashName(_In_ PREG_CM_KEY_NODE pnk, _In_ DWORD iSuffix)
CharUtil_FixFsName(uszBuffer, sizeof(uszBuffer), NULL, NULL, pnk->wszName, pnk->NameLength, iSuffix, TRUE);
if(c) { c--; }
for(i = 0; i < c; i++) {
dwHash = ((dwHash >> 13) | (dwHash << 19)) + uszBuffer[i];
dwHash = ((dwHash >> 13) | (dwHash << 19)) + (UCHAR)uszBuffer[i];
}
return dwHash;
}
@@ -1417,7 +1423,7 @@ POB_REGISTRY_KEY VmmWinReg_KeyInitializeCreateKey(_In_ VMM_HANDLE H, _In_ POB_RE
// 3: get parent key
pObKeyParent = ObMap_GetByKey(pHive->Snapshot.pmKeyOffset, pnk->Parent);
if(!pObKeyParent) {
if(iLevel < 0x10) {
if(iLevel < VMMWINREG_KEY_MAX_DEPTH - 1) {
pObKeyParent = VmmWinReg_KeyInitializeCreateKey(H, pHive, pnk->Parent, iLevel + 1);
}
if(!pObKeyParent) {
@@ -1508,17 +1514,25 @@ POB_REGISTRY_KEY VmmWinReg_KeyInitializeRootKeyDummy(_In_ VMM_HANDLE H, _In_ POB
_Success_(return)
BOOL VmmWinReg_KeyInitializeRootKey(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHive)
{
BOOL f;
PREG_CM_KEY_NODE pnk;
DWORD i, oRootKey = -1, cbCell, cbKey;
DWORD i, oRootKey = -1, cbCell, cbKey, cbSnapshot, cbFirstPage;
QWORD qwKeyRootHash = 0;
cbSnapshot = pHive->Snapshot._DUAL[0].cb;
cbFirstPage = min(cbSnapshot, 0x1000);
// 1: get root key offset from regf-header (this is most often 0x20)
if(!VmmRead(H, PVMM_PROCESS_SYSTEM, pHive->vaHBASE_BLOCK + 0x24, (PBYTE)&oRootKey, sizeof(DWORD)) || !oRootKey || (oRootKey > pHive->Snapshot._DUAL[0].cb - REG_CM_KEY_NODE_SIZEOF)) {
f = !VmmRead(H, PVMM_PROCESS_SYSTEM, pHive->vaHBASE_BLOCK + 0x24, (PBYTE)&oRootKey, sizeof(DWORD)) ||
!oRootKey ||
(cbSnapshot < sizeof(DWORD) + REG_CM_KEY_NODE_SIZEOF) ||
(oRootKey > cbSnapshot - sizeof(DWORD) - REG_CM_KEY_NODE_SIZEOF);
if(f) {
// regf base block unreadable or corrupt - try locate root key in 1st hive page
oRootKey = -1;
i = 0x20;
while(TRUE) {
while((i <= cbFirstPage) && (sizeof(DWORD) <= cbFirstPage - i)) {
cbCell = REG_CELL_SIZE_EX(pHive->Snapshot._DUAL[0].pb, i);
cbKey = (cbCell > 4) ? cbCell - 4 : 0;
if((cbKey < sizeof(REG_CM_KEY_NODE)) || (i + cbCell > 0x1000)) { break; }
if((cbKey < sizeof(REG_CM_KEY_NODE)) || (cbCell > cbFirstPage - i)) { break; }
pnk = (PREG_CM_KEY_NODE)(pHive->Snapshot._DUAL[0].pb + i + 4);
if((pnk->Signature != REG_CM_KEY_SIGNATURE_KEYNODE) || !(pnk->Flags & REG_CM_KEY_NODE_FLAGS_HIVE_ENTRY) || !(pnk->Flags & REG_CM_KEY_NODE_FLAGS_COMP_NAME)) {
i += cbCell;
@@ -1562,7 +1576,7 @@ BOOL VmmWinReg_KeyInitialize(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHive)
}
cbHbin = *(PDWORD)(pHive->Snapshot._DUAL[iSV].pb + iHbin + 8);
cbHbin = min(cbHbin, pHive->Snapshot._DUAL[iSV].cb - iHbin);
if((cbHbin & 0xfff) || (cbHbin > 0x10000)) { cbHbin = 0x1000; }
if((cbHbin < 0x1000) || (cbHbin & 0xfff) || (cbHbin > 0x10000)) { cbHbin = 0x1000; }
oCell = 0x20;
while(oCell + 4 < cbHbin) {
cbCell = REG_CELL_SIZE_EX(pHive->Snapshot._DUAL[iSV].pb, (QWORD)iHbin + oCell);
@@ -1672,7 +1686,7 @@ VOID VmmWinReg_ValueQueryInternal_BigDataCell(_In_ POB_REGISTRY_HIVE pHive, _In_
cbDataCell = REG_CELL_SIZE_EX(pbSnapshot, oDataCellRaw);
f = (cbDataCell <= cbSnapshot - oDataCellRaw) &&
(cbDataCell <= REG_CM_BIGDATA_SEGMENT_CELL_SIZE) &&
(cbDataCell > 8) &&
(cbDataCell >= 8) &&
!(!fDataCellLast && (cbDataCell != REG_CM_BIGDATA_SEGMENT_CELL_SIZE));
if(!f) { return; }
cbDataCellPayload = cbDataCell - 4;
@@ -1734,7 +1748,7 @@ BOOL VmmWinReg_ValueQueryInternal_BigDataList(_In_ POB_REGISTRY_HIVE pHive, _In_
);
if(pbData) { pbData += cbReadDataCell; }
cbData -= cbReadDataCell;
cbDataOffset -= min(cbReadDataCell, cbDataOffset);
cbDataOffset = 0;
}
return TRUE;
}
@@ -1757,7 +1771,10 @@ BOOL VmmWinReg_ValueQueryInternal(_In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTR
*pdwLength = cbDataLength;
}
if(!pbData) { goto success; }
if(!cbData || (cbDataOffset >= cbDataLength)) { return FALSE; }
if(!cbData || (cbDataOffset >= cbDataLength)) {
if(cbDataOffset == cbDataLength) { goto success; }
return FALSE;
}
cbDataRead = min(cbData, cbDataLength - cbDataOffset);
if(pKeyValue->pValue->DataLength & 0x80000000) {
// "small data" stored within keyvalue
@@ -1772,11 +1789,13 @@ BOOL VmmWinReg_ValueQueryInternal(_In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTR
if(cbCell < 8) { return FALSE; }
// "big data" table
if(*(PWORD)(pHive->Snapshot._DUAL[iCellSV].pb + oCellRaw + 4) == REG_CM_KEY_SIGNATURE_BIGDATA) {
return VmmWinReg_ValueQueryInternal_BigDataList(
pHive,
*(PWORD)(pHive->Snapshot._DUAL[iCellSV].pb + oCellRaw + 4 + 2),
*(PDWORD)(pHive->Snapshot._DUAL[iCellSV].pb + oCellRaw + 4 + 4),
pbData, cbDataRead, pcbDataRead, cbDataOffset);
if((cbDataLength > REG_CM_BIGDATA_SEGMENT_DATA_SIZE) && (cbCell >= 4 + sizeof(WORD) + sizeof(WORD) + sizeof(DWORD))) {
return VmmWinReg_ValueQueryInternal_BigDataList(
pHive,
*(PWORD)(pHive->Snapshot._DUAL[iCellSV].pb + oCellRaw + 4 + 2),
*(PDWORD)(pHive->Snapshot._DUAL[iCellSV].pb + oCellRaw + 4 + 4),
pbData, cbDataRead, pcbDataRead, cbDataOffset);
}
}
// "ordinary" data
if(cbDataOffset > cbCell - 4) { return FALSE; }
@@ -1794,6 +1813,24 @@ success:
// EXTERNAL REGISTRY KEY AND VALUE FUNCTIONALITY:
//-----------------------------------------------------------------------------
/*
* Check whether a string contains an exact '-' delimited token.
*/
BOOL VmmWinReg_StrContainsDelimitedToken(_In_ LPCSTR usz, _In_ LPCSTR uszToken)
{
LPCSTR uszStart = usz;
SIZE_T cchToken = strlen(uszToken);
while(*usz) {
if(((usz == uszStart) || (usz[-1] == '-')) &&
!_strnicmp(usz, uszToken, cchToken) &&
(!usz[cchToken] || (usz[cchToken] == '-'))) {
return TRUE;
}
usz++;
}
return FALSE;
}
/*
* Retrieve registry hive and key/value path from a "full" path starting with:
* '0x...', 'by-hive\0x...' or 'HKLM\'
@@ -1809,7 +1846,7 @@ BOOL VmmWinReg_PathHiveGetByFullPath(_In_ VMM_HANDLE H, _In_ LPCSTR uszPathFull,
{
BOOL fHKLM = FALSE, fUser = FALSE, fUserSystem = FALSE, fOrphan = FALSE;
DWORD i;
LPCSTR usz, uszPath2;
LPCSTR usz, uszPath2, uszHiveNameLast;
CHAR uszPath1[MAX_PATH];
POB_REGISTRY_HIVE pObHive = NULL;
POB_REGISTRY_KEY pObKey = NULL;
@@ -1849,13 +1886,15 @@ BOOL VmmWinReg_PathHiveGetByFullPath(_In_ VMM_HANDLE H, _In_ LPCSTR uszPathFull,
}
if(fHKLM) {
while((pObHive = VmmWinReg_HiveGetNext(H, pObHive))) {
if(CharUtil_StrContains(pObHive->uszNameShort, uszPath1, TRUE)) {
uszHiveNameLast = CharUtil_PathSplitLast(pObHive->uszNameShort);
if(CharUtil_StrEquals(uszHiveNameLast, uszPath1, TRUE)) {
*ppHive = pObHive;
return TRUE; // CALLER DECREF: *ppHive
}
}
while((pObHive = VmmWinReg_HiveGetNext(H, pObHive))) {
if(CharUtil_StrContains(pObHive->uszHiveRootPath, uszPath1, TRUE)) {
uszHiveNameLast = CharUtil_PathSplitLast(pObHive->uszHiveRootPath);
if(CharUtil_StrEquals(uszHiveNameLast, uszPath1, TRUE)) {
*ppHive = pObHive;
return TRUE; // CALLER DECREF: *ppHive
}
@@ -2021,7 +2060,7 @@ VOID VmmWinReg_KeyInfo2(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHive, _In_ PO
int status;
DWORD cuszPath = 0;
CHAR szHiveShortName[33] = { 0 };
CHAR uszPath[MAX_PATH] = { 0 };
CHAR uszPath[MAX_PATH*2] = { 0 };
VmmWinReg_KeyInfo(pHive, pKey, pKeyInfo);
if(!(ps = ObSet_New(H))) { return; }
ObSet_Push(ps, (QWORD)Ob_INCREF(pKey));
@@ -2046,6 +2085,9 @@ VOID VmmWinReg_KeyInfo2(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHive, _In_ PO
cuszPath += status;
}
}
while((pObKey = (POB_REGISTRY_KEY)ObSet_Pop(ps))) {
Ob_DECREF(pObKey);
}
Ob_DECREF(ps);
if(cuszPath) {
pKeyInfo->cbuName = cuszPath + 1;
@@ -2158,6 +2200,7 @@ BOOL VmmWinReg_ValueQuery1(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHive, _In_
POB_REGISTRY_KEY pObKey = NULL;
POB_REGISTRY_VALUE pObKeyValue = NULL;
if(pcbRead) { *pcbRead = 0; }
if(pb && (cbOffset > 0xffffffff)) { return FALSE; }
f = VmmWinReg_HiveSnapshotEnsure(H, pHive) &&
(uszValueName = CharUtil_PathSplitLastEx(uszPathKeyValue, uszPathKey, sizeof(uszPathKey))) &&
(pObKey = VmmWinReg_KeyGetByPath(H, pHive, uszPathKey)) &&
@@ -2222,7 +2265,9 @@ _Success_(return)
BOOL VmmWinReg_ValueQuery4(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTRY_VALUE pKeyValue, _Out_opt_ PDWORD pdwType, _Out_writes_opt_(cbData) PBYTE pbData, _In_ DWORD cbData, _Out_opt_ PDWORD pcbData)
{
if(VmmWinReg_HiveSnapshotEnsure(H, pHive)) {
return VmmWinReg_ValueQueryInternal(pHive, pKeyValue, pdwType, NULL, NULL, pbData, cbData, pcbData, 0);
return pbData
? VmmWinReg_ValueQueryInternal(pHive, pKeyValue, pdwType, NULL, NULL, pbData, cbData, pcbData, 0)
: VmmWinReg_ValueQueryInternal(pHive, pKeyValue, pdwType, NULL, pcbData, NULL, 0, NULL, 0);
}
if(pdwType) { *pdwType = 0; }
if(pcbData) { *pcbData = 0; }
@@ -2272,10 +2317,11 @@ BOOL VmmWinReg_ValueQueryString4(_In_ VMM_HANDLE H, _In_ POB_REGISTRY_HIVE pHive
DWORD cbRegData = 0, cbRegDataRead = 0;
if(!cbuData) { goto fail; }
uszData[0] = 0;
if(sizeof(pbRegDataBuffer) < cbuData * 2) {
if(cbuData <= sizeof(pbRegDataBuffer) / 2) {
cbRegData = sizeof(pbRegDataBuffer);
pbRegData = pbRegDataBuffer;
} else {
if(cbuData > 0x01000000) { goto fail; }
cbRegData = cbuData * 2;
pbRegData = LocalAlloc(0, cbRegData);
if(!pbRegData) { goto fail; }
@@ -2305,10 +2351,11 @@ BOOL VmmWinReg_ValueQueryString2(_In_ VMM_HANDLE H, _In_ LPCSTR uszFullPathKeyVa
DWORD cbRegData = 0, cbRegDataRead = 0;
if(!cbuData) { goto fail; }
uszData[0] = 0;
if(sizeof(pbRegDataBuffer) < cbuData * 2) {
if(cbuData <= sizeof(pbRegDataBuffer) / 2) {
cbRegData = sizeof(pbRegDataBuffer);
pbRegData = pbRegDataBuffer;
} else {
if(cbuData > 0x01000000) { goto fail; }
cbRegData = cbuData * 2;
pbRegData = LocalAlloc(0, cbRegData);
if(!pbRegData) { goto fail; }
@@ -2328,18 +2375,30 @@ fail:
* -- uszHivePrefix
* -- uszHiveName
* -- uszFullPath
* -- return
*/
VOID VmmWinReg_KeyFullPath(_In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTRY_KEY pKey, _In_ LPSTR uszHivePrefix, _In_ LPSTR uszHiveName, _Out_writes_(1024) LPSTR uszFullPath)
_Success_(return)
BOOL VmmWinReg_KeyFullPath(_In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTRY_KEY pKey, _In_ LPSTR uszHivePrefix, _In_ LPSTR uszHiveName, _Out_writes_(1024) LPSTR uszFullPath)
{
CONST BYTE pbTEXT_ROOT[] = { '\\', 0, 'R', 0, 'O', 0, 'O', 0, 'T', 0 };
BOOL fResult = TRUE, fSkip = TRUE;
SIZE_T cch;
DWORD o = 0, iKey = 0, cbName;
POB_REGISTRY_KEY pk, ppObKey[0x40];
// fetch parents (max depth: 0x40)
POB_REGISTRY_KEY pk, pObKeyParent, ppObKey[VMMWINREG_KEY_MAX_DEPTH + 1];
// fetch parents (max registry depth + synthetic ROOT)
ppObKey[iKey++] = Ob_INCREF(pKey);
while((iKey < 0x40) && (ppObKey[iKey] = ObMap_GetByKey(pHive->Snapshot.pmKeyHash, ppObKey[iKey - 1]->qwHashKeyParent))) {
iKey++;
while(iKey < _countof(ppObKey)) {
pObKeyParent = ObMap_GetByKey(pHive->Snapshot.pmKeyHash, ppObKey[iKey - 1]->qwHashKeyParent);
if(!pObKeyParent) { break; }
ppObKey[iKey++] = pObKeyParent;
}
// reject malformed paths deeper than the supported registry maximum
if(iKey == _countof(ppObKey)) {
pObKeyParent = ObMap_GetByKey(pHive->Snapshot.pmKeyHash, ppObKey[iKey - 1]->qwHashKeyParent);
if(pObKeyParent) {
Ob_DECREF(pObKeyParent);
fResult = FALSE;
}
}
// unwind, copy name
cch = strlen(uszHivePrefix);
@@ -2368,6 +2427,7 @@ VOID VmmWinReg_KeyFullPath(_In_ POB_REGISTRY_HIVE pHive, _In_ POB_REGISTRY_KEY p
fSkip = FALSE;
}
uszFullPath[fResult ? o : 0] = 0;
return fResult;
}
/*
@@ -2419,7 +2479,10 @@ VOID VmmWinReg_ForensicGetAllKeysAndValues(
c = ObMap_Size(pHive->Snapshot.pmKeyOffset);
for(i = 0; ((i < c) && !H->fAbort); i++) {
if((pObKey = ObMap_GetByIndex(pHive->Snapshot.pmKeyOffset, i))) {
VmmWinReg_KeyFullPath(pHive, pObKey, uszHivePrefix, pHive->uszHiveRootPath + oHive, uszFullPath);
if(!VmmWinReg_KeyFullPath(pHive, pObKey, uszHivePrefix, pHive->uszHiveRootPath + oHive, uszFullPath)) {
Ob_DECREF(pObKey);
continue;
}
// registry timeline:
pfnKeyCB(H, hCallback1, hCallback2, uszFullPath, pHive->vaCMHIVE, pObKey->oCell, pObKey->pKey->Parent, pObKey->pKey->LastWriteTime);
// registry json data:
+73 -42
View File
@@ -150,7 +150,10 @@ VOID VmmWinSvc_ListHeadFromPDB(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pSvcProcess,
if(!VmmRead(H, pSvcProcess, peModuleServices->vaBase + dwoSymSvcDB, pbSymSvcDB, sizeof(pbSymSvcDB))) { goto fail; }
pvaListHead[0] = (QWORD)VMM_PTR_OFFSET_DUAL(f32, pbSymSvcDB, 4, 8);
pvaListHead[1] = (QWORD)VMM_PTR_OFFSET_DUAL(f32, pbSymSvcDB, 8, 16);
if(!VMM_UADDR_4_8(f32, pvaListHead[0]) || !VMM_UADDR_4_8(f32, pvaListHead[1])) { goto fail; }
if(!VMM_UADDR_4_8(f32, pvaListHead[0]) || !VMM_UADDR_4_8(f32, pvaListHead[1])) {
pvaListHead[0] = 0;
pvaListHead[1] = 0;
}
fail:
Ob_DECREF(pObModuleMap);
}
@@ -165,7 +168,7 @@ fail:
VOID VmmWinSvc_ListHeadFromVAD(_In_ VMM_HANDLE H, _In_ PVMMWINSVC_CONTEXT ctx, _In_ PVMM_PROCESS pSvcProcess, _Inout_updates_(2) PQWORD pvaListHead)
{
BOOL f32 = H->vmm.f32;
QWORD va1, va2;
QWORD va1, va2, cbVad64;
DWORD i, o, dwTag, cbVad;
BYTE pb2[0x10], *pb = NULL;
PVMM_MAP_VADENTRY pe;
@@ -173,8 +176,9 @@ VOID VmmWinSvc_ListHeadFromVAD(_In_ VMM_HANDLE H, _In_ PVMMWINSVC_CONTEXT ctx, _
if(!VmmMap_GetVad(H, pSvcProcess, &pObVadMap, VMM_VADMAP_TP_CORE)) { goto finish; }
// 1: if address exist -> prefetch vad and finish
if(pvaListHead[0] && (pe = VmmMap_GetVadEntry(H, pObVadMap, pvaListHead[0]))) {
cbVad = (DWORD)(pe->vaEnd + 1 - pe->vaStart);
if(cbVad <= 0x00200000) {
if((pe->vaEnd >= pe->vaStart) && ((pe->vaEnd - pe->vaStart) < 0x00200000)) {
cbVad64 = pe->vaEnd - pe->vaStart + 1;
cbVad = (DWORD)cbVad64;
VmmCachePrefetchPages4(H, pSvcProcess, 1, &pe->vaStart, cbVad, 0);
}
goto finish;
@@ -184,16 +188,21 @@ VOID VmmWinSvc_ListHeadFromVAD(_In_ VMM_HANDLE H, _In_ PVMMWINSVC_CONTEXT ctx, _
for(i = 0; i < pObVadMap->cMap; i++) {
pe = pObVadMap->pMap + i;
if(!pe->fPrivateMemory || (pe->CommitCharge < 0x10)) { continue; }
cbVad = (DWORD)(pe->vaEnd + 1 - pe->vaStart);
if((cbVad > 0x00200000) || (cbVad < 0x00010000)) { continue; }
if(pe->vaEnd < pe->vaStart) { continue; }
if((pe->vaEnd - pe->vaStart) >= 0x00200000) { continue; }
cbVad64 = pe->vaEnd - pe->vaStart + 1;
if(cbVad64 < 0x00010000) { continue; }
cbVad = (DWORD)cbVad64;
VmmReadEx(H, pSvcProcess, pe->vaStart, pb, cbVad, NULL, VMM_FLAG_ZEROPAD_ON_FAIL);
dwTag = _byteswap_ulong(ctx->dwTag);
for(o = 0x1000; o < 0x00200000; o += 4) {
for(o = 0x1000; o <= cbVad - sizeof(DWORD); o += 4) {
if(dwTag == *(PDWORD)(pb + o)) {
if(ctx->fSc19) { // sErv / Sc19 entry - Win8.0+
if((ctx->oSc19._Size > cbVad) || (o < ctx->oSc19.Tag) || ((o - ctx->oSc19.Tag) > cbVad - ctx->oSc19._Size)) { continue; }
va1 = VMM_PTR_OFFSET(f32, pb + o - ctx->oSc19.Tag, ctx->oSc19.BLink);
va2 = VMM_PTR_OFFSET(f32, pb + o - ctx->oSc19.Tag, ctx->oSc19.FLink);
} else { // serH entry
if(o > cbVad - (f32 ? 0x10 : 0x18)) { continue; }
va1 = VMM_PTR_OFFSET_DUAL(f32, pb + o, 0x0c, 0x10); // TODO: verify 32-bit version
if(!VMM_UADDR_4_8(f32, va1)) { continue; }
if(!VmmRead(H, pSvcProcess, va1, pb2, 0x10)) { continue; }
@@ -228,22 +237,23 @@ POB_MAP VmmWinSvc_MainListWalk(_In_ VMM_HANDLE H, _In_ PVMMWINSVC_CONTEXT ctx, _
DWORD dwOrdinal, dwStartType;
QWORD i, va, va1, va2, va3;
BYTE pb[0x200] = { 0 };
POB_SET psA = NULL;
POB_SET psA = NULL, psSeen = NULL;
POB_MAP pmSvc = NULL;
PVMM_MAP_SERVICEENTRY pe;
PVMMWINSVC_OFFSET_SC19 o = &ctx->oSc19;
if(!(psA = ObSet_New(H))) { goto fail; }
if(!(psSeen = ObSet_New(H))) { goto fail; }
if(!(pmSvc = ObMap_New(H, OB_MAP_FLAGS_OBJECT_LOCALFREE))) { goto fail; }
for(i = 0; i < cVaListHead; i++) {
ObSet_Push(psA, pvaListHead[i]);
}
while((va = ObSet_Pop(psA))) {
// read & sanity check
if(ObMap_ExistsKey(pmSvc, va)) { continue; }
if(!ObSet_Push(psSeen, va)) { continue; }
if(!VmmRead(H, pProcessSvc, va, pb, o->_Size)) { continue; }
if(o->fTag && !VMM_POOLTAG(*(PDWORD)(pb + o->Tag), o->TagV)) { continue; }
if((dwOrdinal = *(PDWORD)(pb + o->Ordinal)) > 0xffff) { continue; }
if((dwStartType = *(PDWORD)(pb + o->SvcTp)) > SERVICE_TYPE_ALL) { continue; }
if((dwStartType = *(PDWORD)(pb + o->SvcTp)) > SERVICE_DISABLED) { continue; }
// BLink / FLink
va1 = VMM_PTR_OFFSET(f32, pb, o->BLink);
va2 = VMM_PTR_OFFSET(f32, pb, o->FLink);
@@ -252,15 +262,19 @@ POB_MAP VmmWinSvc_MainListWalk(_In_ VMM_HANDLE H, _In_ PVMMWINSVC_CONTEXT ctx, _
if(!va1 && !va2) { continue; }
ObSet_Push(psA, va1);
ObSet_Push(psA, va2);
if(!VMM_UADDR(f32, VMM_PTR_OFFSET(f32, pb, o->NmShort))) { continue; }
va3 = VMM_PTR_OFFSET(f32, pb, o->NmShort);
if((va3 < 0x10000) || !VMM_UADDR(f32, va3)) { continue; }
// allocate & assign
if(!(pe = LocalAlloc(LMEM_ZEROINIT, sizeof(VMM_MAP_SERVICEENTRY)))) { continue; }
ObMap_Push(pmSvc, va, pe);
if(!ObMap_Push(pmSvc, va, pe)) {
LocalFree(pe);
goto fail;
}
pe->vaObj = va;
pe->dwOrdinal = dwOrdinal;
pe->dwStartType = dwStartType;
memcpy(&pe->ServiceStatus, pb + o->SvcStatus, sizeof(SERVICE_STATUS));
pe->_vaReservedServiceName = VMM_PTR_OFFSET(f32, pb, o->NmShort);
pe->_vaReservedServiceName = va3;
pe->_vaReservedDisplayName = VMM_PTR_OFFSET(f32, pb, o->NmLong);
if((pe->ServiceStatus.dwServiceType & SERVICE_KERNEL_DRIVER) || (pe->ServiceStatus.dwServiceType & SERVICE_FILE_SYSTEM_DRIVER)) {
pe->_vaReservedPath = VMM_PTR_OFFSET(f32, pb, o->ExtInfo);
@@ -272,6 +286,7 @@ POB_MAP VmmWinSvc_MainListWalk(_In_ VMM_HANDLE H, _In_ PVMMWINSVC_CONTEXT ctx, _
Ob_INCREF(pmSvc);
fail:
Ob_DECREF(psA);
Ob_DECREF(psSeen);
return Ob_DECREF(pmSvc);
}
@@ -323,26 +338,26 @@ VOID VmmWinSvc_GetExtendedInfo(_In_ VMM_HANDLE H, _In_ PVMMWINSVC_CONTEXT ctx, _
* -- psm
* -- puszText
* -- qwA
* -- fNullOnFail = set pwszText to NULL on fail (i.e. don't include in OB_STRMAP psm)
* -- fNullOnFail = set puszText to NULL on fail (i.e. don't include in OB_STRMAP psm)
* -- return
*/
VOID VmmWinSvc_ResolveStrAddSingle(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessSvc, _In_ POB_STRMAP psm, _Out_ LPSTR *puszText, _In_ QWORD qwA, _In_ BOOL fNullOnFail)
_Success_(return)
BOOL VmmWinSvc_ResolveStrAddSingle(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessSvc, _In_ POB_STRMAP psm, _Out_ LPSTR *puszText, _In_ QWORD qwA, _In_ BOOL fNullOnFail)
{
WCHAR wsz[2048] = { 0 };
*puszText = NULL;
if((qwA < 0x10000) || !VMM_UADDR(H->vmm.f32, qwA)) { goto fail; }
VmmRead2(H, pProcessSvc, qwA, (PBYTE)wsz, sizeof(wsz) - 2, VMM_FLAG_FORCECACHE_READ);
if(!VmmRead2(H, pProcessSvc, qwA, (PBYTE)wsz, sizeof(wsz) - 2, VMM_FLAG_FORCECACHE_READ)) { goto fail; }
if(!wsz[0]) { goto fail; }
if(wsz[0] > 0xff || wsz[1] > 0xff || wsz[2] > 0xff) { goto fail; }
ObStrMap_PushPtrWU(psm, wsz, puszText, NULL);
return;
return ObStrMap_PushPtrWU(psm, wsz, puszText, NULL);
fail:
if(fNullOnFail) {
*puszText = NULL;
} else {
ObStrMap_PushPtrWU(psm, NULL, puszText, NULL);
}
if(fNullOnFail) { return TRUE; }
return ObStrMap_PushPtrWU(psm, NULL, puszText, NULL);
}
VOID VmmWinSvc_ResolveStrRegistry(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessSvc, _In_ PVMMOB_MAP_SERVICE pSvcMap, _In_ POB_STRMAP psm)
_Success_(return)
BOOL VmmWinSvc_ResolveStrRegistry(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessSvc, _In_ PVMMOB_MAP_SERVICE pSvcMap, _In_ POB_STRMAP psm)
{
DWORD i, dwType, cbData = 0;
PVMM_MAP_SERVICEENTRY pe;
@@ -355,17 +370,21 @@ VOID VmmWinSvc_ResolveStrRegistry(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessS
cbData = 0;
if(pObHive) {
_snprintf_s(usz, MAX_PATH, _TRUNCATE, "ROOT\\ControlSet001\\Services\\%s\\parameters\\ServiceDll", pe->uszServiceName);
if(!VmmWinReg_ValueQuery3(H, pObHive, usz, &dwType, (PBYTE)wsz, MAX_PATH * 2, &cbData) || (dwType != REG_EXPAND_SZ)) {
if(!VmmWinReg_ValueQuery3(H, pObHive, usz, &dwType, (PBYTE)wsz, MAX_PATH * 2, &cbData) || ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ))) {
_snprintf_s(usz, MAX_PATH, _TRUNCATE, "ROOT\\ControlSet001\\Services\\%s\\ImagePath", pe->uszServiceName);
if(!VmmWinReg_ValueQuery3(H, pObHive, usz, &dwType, (PBYTE)wsz, MAX_PATH * 2, &cbData) || (dwType != REG_EXPAND_SZ)) {
if(!VmmWinReg_ValueQuery3(H, pObHive, usz, &dwType, (PBYTE)wsz, MAX_PATH * 2, &cbData) || ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ))) {
cbData = 0;
}
}
}
wsz[cbData >> 1] = 0;
ObStrMap_PushPtrWU(psm, wsz, &pe->uszImagePath, NULL);
if(!ObStrMap_PushPtrWU(psm, wsz, &pe->uszImagePath, NULL)) {
Ob_DECREF(pObHive);
return FALSE;
}
}
Ob_DECREF(pObHive);
return TRUE;
}
/*
@@ -379,7 +398,7 @@ _Success_(return)
BOOL VmmWinSvc_ResolveStrAll(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessSvc, _In_ PVMMOB_MAP_SERVICE pSvcMap)
{
DWORD i;
BOOL fProcessUser;
BOOL fFail, fProcessUser;
CHAR usz[MAX_PATH];
PVMM_PROCESS pObProcessUser = NULL;
PVMM_MAP_SERVICEENTRY pe;
@@ -403,11 +422,16 @@ BOOL VmmWinSvc_ResolveStrAll(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessSvc, _
// 3.1: fetch strings - general
for(i = 0; i < pSvcMap->cMap; i++) {
pe = pSvcMap->pMap + i;
VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszServiceName, pe->_vaReservedServiceName, FALSE);
VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszDisplayName, pe->_vaReservedDisplayName, FALSE);
VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszPath, pe->_vaReservedPath, FALSE);
VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszUserTp, pe->_vaReservedUserTp, FALSE);
VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszUserAcct, pe->_vaReservedUserAcct, TRUE);
fFail =
!VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszServiceName, pe->_vaReservedServiceName, FALSE) ||
!VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszDisplayName, pe->_vaReservedDisplayName, FALSE) ||
!VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszPath, pe->_vaReservedPath, FALSE) ||
!VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszUserTp, pe->_vaReservedUserTp, FALSE) ||
!VmmWinSvc_ResolveStrAddSingle(H, pProcessSvc, pObStrMap, &pe->uszUserAcct, pe->_vaReservedUserAcct, TRUE);
if(fFail) {
Ob_DECREF(pObStrMap);
return FALSE;
}
}
// 3.2: fetch strings - user (if does not exist already)
for(i = 0; i < pSvcMap->cMap; i++) {
@@ -418,15 +442,21 @@ BOOL VmmWinSvc_ResolveStrAll(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcessSvc, _
(pObProcessUser = VmmProcessGetEx(H, NULL, pe->dwPID, VMM_FLAG_PROCESS_TOKEN)) &&
pObProcessUser->win.Token && pObProcessUser->win.Token->fSidUserValid &&
VmmWinUser_GetName(H, &pObProcessUser->win.Token->SidUser.SID, usz, sizeof(usz), NULL);
ObStrMap_PushPtrUU(pObStrMap, fProcessUser ? usz : NULL, &pe->uszUserAcct, NULL);
fFail = !ObStrMap_PushPtrUU(pObStrMap, fProcessUser ? usz : NULL, &pe->uszUserAcct, NULL);
Ob_DECREF_NULL(&pObProcessUser);
if(fFail) {
Ob_DECREF(pObStrMap);
return FALSE;
}
}
}
// 3.3: fetch strings - image path from registry
VmmWinSvc_ResolveStrRegistry(H, pProcessSvc, pSvcMap, pObStrMap);
if(!VmmWinSvc_ResolveStrRegistry(H, pProcessSvc, pSvcMap, pObStrMap)) {
Ob_DECREF(pObStrMap);
return FALSE;
}
// 4: resolve strmap and return
ObStrMap_FinalizeAllocU_DECREF_NULL(&pObStrMap, &pSvcMap->pbMultiText, &pSvcMap->cbMultiText);
return TRUE;
return ObStrMap_FinalizeAllocU_DECREF_NULL(&pObStrMap, &pSvcMap->pbMultiText, &pSvcMap->cbMultiText);
}
/*
@@ -444,10 +474,11 @@ VOID VmmWinSvc_CloseObCallback(_In_ PVOID pVmmServiceMap)
*/
int VmmWinSvc_CmpSort(PVMM_MAP_SERVICEENTRY a, PVMM_MAP_SERVICEENTRY b)
{
if(a->dwOrdinal != b->dwOrdinal) {
return a->dwOrdinal - b->dwOrdinal;
}
return (int)(a->vaObj - b->vaObj);
if(a->dwOrdinal < b->dwOrdinal) { return -1; }
if(a->dwOrdinal > b->dwOrdinal) { return 1; }
if(a->vaObj < b->vaObj) { return -1; }
if(a->vaObj > b->vaObj) { return 1; }
return 0;
}
/*
@@ -491,7 +522,7 @@ PVMMOB_MAP_SERVICE VmmWinSvc_Initialize_DoWork(_In_ VMM_HANDLE H)
VmmWinSvc_GetExtendedInfo(H, &InitCtx, pObSvcProcess, pmObSvc);
// 3: allocate, assign and sort services map
cSvc = ObMap_Size(pmObSvc);
if(!(pObServiceMap = Ob_AllocEx(H, OB_TAG_MAP_SERVICE, 0, sizeof(VMMOB_MAP_SERVICE) + cSvc * sizeof(VMM_MAP_SERVICEENTRY), VmmWinSvc_CloseObCallback, NULL))) { goto fail; }
if(!(pObServiceMap = Ob_AllocEx(H, OB_TAG_MAP_SERVICE, LMEM_ZEROINIT, sizeof(VMMOB_MAP_SERVICE) + cSvc * sizeof(VMM_MAP_SERVICEENTRY), VmmWinSvc_CloseObCallback, NULL))) { goto fail; }
pObServiceMap->cMap = cSvc;
for(i = 0; i < cSvc; i++) {
if((pe = ObMap_GetByIndex(pmObSvc, i))) {
+7 -7
View File
@@ -491,6 +491,7 @@ BOOL VmmWinThreadCs_RspUnwinder(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _
//Restoring former stack allocation, (the number of bytes is given by new slot and carried by FrameOffset)
case UWOP_ALLOC_LARGE:
if(pUnwindCodes[dwUnwdIter].OpInfo == 0x00) {
if(dwNbslot - dwUnwdIter < 2) { goto end; }
offset = (PFRAME_OFFSET_SH)&pUnwindCodes[dwUnwdIter + 1];
FrameOffset = (offset->FrameOffset)*8;
qwCurrentRSP = qwCurrentRSP + FrameOffset;
@@ -499,6 +500,7 @@ BOOL VmmWinThreadCs_RspUnwinder(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _
break;
}
else if(pUnwindCodes[dwUnwdIter].OpInfo == 0x01) {
if(dwNbslot - dwUnwdIter < 3) { goto end; }
offset_l = (PFRAME_OFFSET_L)&pUnwindCodes[dwUnwdIter + 1];
FrameOffset = (USHORT)offset_l->FrameOffset;
printf("Frame offset is %02x\n", FrameOffset);
@@ -517,18 +519,16 @@ BOOL VmmWinThreadCs_RspUnwinder(_In_ VMM_HANDLE H, _In_ PVMM_PROCESS pProcess, _
// vaRSP is left untouched
case UWOP_SET_FPREG:
break;
// the save is only made on stack space already allocated, RSP is left untouched but next slot is used for this register so we go over it
// the save is only made on stack space already allocated, RSP is left untouched but the offset slots must be skipped
case UWOP_SAVE_NONVOL:
case UWOP_SAVE_XMM128:
if(dwNbslot - dwUnwdIter < 2) { goto end; }
dwUnwdIter++;
break;
// the save is only made on stack already allocated, RSP is left untouched
case UWOP_SAVE_NONVOL_FAR:
break;
// the save is only made on stack already allocated, RSP is left untouched
case UWOP_SAVE_XMM128:
break;
// the save is only made on stack already allocated, RSP is left untouched
case UWOP_SAVE_XMM128_FAR:
if(dwNbslot - dwUnwdIter < 3) { goto end; }
dwUnwdIter += 2;
break;
case UWOP_PUSH_MACHFRAME:
if(pUnwindCodes[dwUnwdIter].OpInfo == 0x00) {
+1 -1
View File
@@ -331,7 +331,7 @@ BOOL VmmWork_ProcessActionForeachParallel_Void(
// 1: select processes to queue using criteria function
if(!(pObProcessSelectedSet = ObSet_New(H))) { goto fail; }
while((pObProcess = VmmProcessGetNext(H, pObProcess, VMM_FLAG_PROCESS_SHOW_TERMINATED))) {
if(!pfnCriteria || pfnCriteria(H, pObProcess, ctxOb)) {
if(!pfnCriteria || pfnCriteria(H, pObProcess, ctxAction)) {
ObSet_Push(pObProcessSelectedSet, pObProcess->dwPID);
}
}
+2 -2
View File
@@ -3,8 +3,8 @@
#define VERSION_MAJOR 5
#define VERSION_MINOR 18
#define VERSION_REVISION 2
#define VERSION_BUILD 241
#define VERSION_REVISION 3
#define VERSION_BUILD 242
#define VER_FILE_DESCRIPTION_STR "MemProcFS : Python API"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "leechcore_example"
version = "5.18.2"
version = "5.18.3"
edition = "2021"
publish = false
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "m_example_plugin"
version = "5.18.2"
version = "5.18.3"
edition = "2021"
publish = false
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "memprocfs"
version = "5.18.2"
version = "5.18.3"
edition = "2021"
description = "MemProcFS - Physical Memory Analysis Framework"
documentation = "https://docs.rs/memprocfs"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "memprocfs_example"
version = "5.18.2"
version = "5.18.3"
edition = "2021"
publish = false
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.Versioning;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.18.2.241")]
[assembly: AssemblyFileVersion("5.18.2.241")]
[assembly: AssemblyVersion("5.18.3.242")]
[assembly: AssemblyFileVersion("5.18.3.242")]
+1 -1
View File
@@ -109,7 +109,7 @@
<None Include="logo.png" Pack="true" Visible="true" PackagePath="" />
</ItemGroup>
<PropertyGroup>
<Version>5.18.2</Version>
<Version>5.18.3</Version>
<RepositoryUrl>https://github.com/ufrisk/MemProcFS</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseFile>LICENSE</PackageLicenseFile>