Skip to content

Commit

Permalink
Version 5.8.14
Browse files Browse the repository at this point in the history
  • Loading branch information
ufrisk committed Oct 19, 2023
1 parent 9de3f14 commit b753c20
Show file tree
Hide file tree
Showing 14 changed files with 142 additions and 27 deletions.
21 changes: 18 additions & 3 deletions includes/vmmdll.h
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ BOOL VMMDLL_Scatter_Prepare(_In_ VMMDLL_SCATTER_HANDLE hS, _In_ QWORD va, _In_ D
* -- va = start address of the memory range to read.
* -- cb = size of memory range to read.
* -- pb = buffer to populate with read memory when calling VMMDLL_Scatter_ExecuteRead()
* -- pcbRead = pointer to be populated with number of bytes successfully read.
* -- pcbRead = optional pointer to be populated with number of bytes successfully read.
* -- return
*/
EXPORTED_FUNCTION _Success_(return)
Expand Down Expand Up @@ -1961,7 +1961,7 @@ typedef BOOL(*VMMYARA_SCAN_MEMORY_CALLBACK)(
_In_ PVMMYARA_RULE_MATCH pRuleMatch,
_In_reads_bytes_(cbBuffer) PBYTE pbBuffer,
_In_ SIZE_T cbBuffer
);
);

#endif /* VMMYARA_SCAN_MEMORY_CALLBACK_DEFINED */
// =========== END SHARED STRUCTS WITH <vmmdll.h/vmmyara.h> ===========
Expand All @@ -1970,6 +1970,21 @@ typedef BOOL(*VMMYARA_SCAN_MEMORY_CALLBACK)(
#define VMMDLL_YARA_MEMORY_CALLBACK_CONTEXT_VERSION 0xdec40002
#define VMMDLL_YARA_CONFIG_MAX_RESULT 0x00010000 // max 65k results.

typedef struct tdVMMDLL_YARA_CONFIG *PVMMDLL_YARA_CONFIG; // forward declaration.

/*
* Callback function to tell whether a section of memory should be scanned or not.
* -- ctx = pointer to PVMMDLL_YARA_CONFIG context.
* -- pePte = pointer to PTE entry if the memory region is backed by PTE map. Otherwise NULL.
* -- peVad = pointer to VAD entry if the memory region is backed by VAD map. Otherwise NULL.
* -- return = return TRUE to scan the memory region, FALSE to skip it.
*/
typedef BOOL(*VMMYARA_SCAN_FILTER_CALLBACK)(
_In_ PVMMDLL_YARA_CONFIG ctx,
_In_opt_ PVMMDLL_MAP_PTEENTRY pePte,
_In_opt_ PVMMDLL_MAP_VADENTRY peVad
);

/*
* Yara search configuration struct.
*/
Expand Down Expand Up @@ -1997,7 +2012,7 @@ typedef struct tdVMMDLL_YARA_CONFIG {
// optional filter callback function for virtual address reads:
// for ranges inbetween vaMin:vaMax callback with pte or vad entry.
// return: read from range(TRUE), do not read from range(FALSE).
BOOL(*pfnFilterOptCB)(_In_ struct tdVMMDLL_YARA_CONFIG *ctx, _In_opt_ PVMMDLL_MAP_PTEENTRY pePte, _In_opt_ PVMMDLL_MAP_VADENTRY peVad);
VMMYARA_SCAN_FILTER_CALLBACK pfnFilterOptCB;
PVOID pvUserPtrOpt2; // optional pointer set by caller (not used by MemProcFS).
QWORD _Reserved;
} VMMDLL_YARA_CONFIG, *PVMMDLL_YARA_CONFIG;
Expand Down
4 changes: 2 additions & 2 deletions m_vmemd/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#define VERSION_MAJOR 5
#define VERSION_MINOR 8
#define VERSION_REVISION 13
#define VERSION_BUILD 132
#define VERSION_REVISION 14
#define VERSION_BUILD 134

#define VER_FILE_DESCRIPTION_STR "MemProcFS : Plugin vmemd"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
Expand Down
4 changes: 2 additions & 2 deletions memprocfs/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#define VERSION_MAJOR 5
#define VERSION_MINOR 8
#define VERSION_REVISION 13
#define VERSION_BUILD 132
#define VERSION_REVISION 14
#define VERSION_BUILD 134

#define VER_FILE_DESCRIPTION_STR "MemProcFS"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
Expand Down
2 changes: 1 addition & 1 deletion vmm/modules/m_evil_av1.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ VOID MEvilAV1_DoWork_WinDefend_MPLog(_In_ VMM_HANDLE H, _In_ VMMDLL_MODULE_ID MI
LPSTR uszText = NULL, uszLine, szTokenizerContext;
DWORD cProtect = 0;
// read file:
cbFile = min(MEVILAV1_MAX_FILE_SIZE, pFile->cb);
cbFile = min(MEVILAV1_MAX_FILE_SIZE, (SIZE_T)pFile->cb);
if(!cbFile || !(pbFile = LocalAlloc(0, cbFile + 1))) { goto fail; }
if(0 == VmmWinObjFile_Read(H, pFile, 0, pbFile, (DWORD)cbFile, VMMDLL_FLAG_ZEROPAD_ON_FAIL)) { goto fail; }
pbFile[cbFile] = 0;
Expand Down
4 changes: 2 additions & 2 deletions vmm/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#define VERSION_MAJOR 5
#define VERSION_MINOR 8
#define VERSION_REVISION 13
#define VERSION_BUILD 132
#define VERSION_REVISION 14
#define VERSION_BUILD 134

#define VER_FILE_DESCRIPTION_STR "MemProcFS : Core"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
Expand Down
21 changes: 18 additions & 3 deletions vmm/vmmdll.h
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ BOOL VMMDLL_Scatter_Prepare(_In_ VMMDLL_SCATTER_HANDLE hS, _In_ QWORD va, _In_ D
* -- va = start address of the memory range to read.
* -- cb = size of memory range to read.
* -- pb = buffer to populate with read memory when calling VMMDLL_Scatter_ExecuteRead()
* -- pcbRead = pointer to be populated with number of bytes successfully read.
* -- pcbRead = optional pointer to be populated with number of bytes successfully read.
* -- return
*/
EXPORTED_FUNCTION _Success_(return)
Expand Down Expand Up @@ -1961,7 +1961,7 @@ typedef BOOL(*VMMYARA_SCAN_MEMORY_CALLBACK)(
_In_ PVMMYARA_RULE_MATCH pRuleMatch,
_In_reads_bytes_(cbBuffer) PBYTE pbBuffer,
_In_ SIZE_T cbBuffer
);
);

#endif /* VMMYARA_SCAN_MEMORY_CALLBACK_DEFINED */
// =========== END SHARED STRUCTS WITH <vmmdll.h/vmmyara.h> ===========
Expand All @@ -1970,6 +1970,21 @@ typedef BOOL(*VMMYARA_SCAN_MEMORY_CALLBACK)(
#define VMMDLL_YARA_MEMORY_CALLBACK_CONTEXT_VERSION 0xdec40002
#define VMMDLL_YARA_CONFIG_MAX_RESULT 0x00010000 // max 65k results.

typedef struct tdVMMDLL_YARA_CONFIG *PVMMDLL_YARA_CONFIG; // forward declaration.

/*
* Callback function to tell whether a section of memory should be scanned or not.
* -- ctx = pointer to PVMMDLL_YARA_CONFIG context.
* -- pePte = pointer to PTE entry if the memory region is backed by PTE map. Otherwise NULL.
* -- peVad = pointer to VAD entry if the memory region is backed by VAD map. Otherwise NULL.
* -- return = return TRUE to scan the memory region, FALSE to skip it.
*/
typedef BOOL(*VMMYARA_SCAN_FILTER_CALLBACK)(
_In_ PVMMDLL_YARA_CONFIG ctx,
_In_opt_ PVMMDLL_MAP_PTEENTRY pePte,
_In_opt_ PVMMDLL_MAP_VADENTRY peVad
);

/*
* Yara search configuration struct.
*/
Expand Down Expand Up @@ -1997,7 +2012,7 @@ typedef struct tdVMMDLL_YARA_CONFIG {
// optional filter callback function for virtual address reads:
// for ranges inbetween vaMin:vaMax callback with pte or vad entry.
// return: read from range(TRUE), do not read from range(FALSE).
BOOL(*pfnFilterOptCB)(_In_ struct tdVMMDLL_YARA_CONFIG *ctx, _In_opt_ PVMMDLL_MAP_PTEENTRY pePte, _In_opt_ PVMMDLL_MAP_VADENTRY peVad);
VMMYARA_SCAN_FILTER_CALLBACK pfnFilterOptCB;
PVOID pvUserPtrOpt2; // optional pointer set by caller (not used by MemProcFS).
QWORD _Reserved;
} VMMDLL_YARA_CONFIG, *PVMMDLL_YARA_CONFIG;
Expand Down
13 changes: 8 additions & 5 deletions vmm/vmmyarautil.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,10 @@ BOOL VmmYaraUtil_MatchCB(_In_ PVMMYARAUTIL_SCAN_CONTEXT ctxScan, _In_ PVMMYARA_R
return TRUE;
}

int VmmYaraUtil_MatchCmpSort(void const *pv1, void const *pv2)
int VmmYaraUtil_MatchCmpSort(_In_ POB_MAP_ENTRY pv1, _In_ POB_MAP_ENTRY pv2)
{
PVMMYARAUTIL_MATCH e1 = ((POB_MAP_ENTRY)pv1)->v;
PVMMYARAUTIL_MATCH e2 = ((POB_MAP_ENTRY)pv2)->v;
PVMMYARAUTIL_MATCH e1 = (PVMMYARAUTIL_MATCH)pv1->v;
PVMMYARAUTIL_MATCH e2 = (PVMMYARAUTIL_MATCH)pv2->v;
if(e1->dwPID < e2->dwPID) { return 1; }
if(e1->dwPID > e2->dwPID) { return -1; }
if(e1->vaBase < e2->vaBase) { return 1; }
Expand Down Expand Up @@ -502,7 +502,7 @@ BOOL VmmSearch_SearchRegion_YaraCB(_In_ PVOID pvContext, _In_ PVMMYARA_RULE_MATC
}
}
ctxs->cResult = ObSet_Size(ctxi->psvaResult);
if(ctxs->cResult > ctxs->cMaxResult) {
if(ctxs->cResult >= ctxs->cMaxResult) {
ctxs->fAbortRequested = TRUE;
return FALSE;
}
Expand All @@ -529,7 +529,9 @@ BOOL VmmYaraUtil_SearchRegion(_In_ VMM_HANDLE H, _In_ PVMMYARAUTIL_SEARCH_INTERN
if(!cbRead || Util_IsZeroBuffer(ctxi->pb, ctxi->cb)) {
return TRUE;
}
if(Util_IsZeroBuffer(ctxi->pb, ctxi->cb)) { return TRUE; }
if(Util_IsZeroBuffer(ctxi->pb, ctxi->cb)) {
return TRUE;
}
yrerr = VmmYara_ScanMemory(
ctxi->hVmmYaraRules,
ctxi->pb,
Expand Down Expand Up @@ -667,6 +669,7 @@ BOOL VmmYaraUtil_SearchSingleProcess(_In_ VMM_HANDLE H, _In_opt_ PVMM_PROCESS pP
ctxs->vaCurrent = ctxs->vaMin;
fResult = VmmYaraUtil_SearchRange(H, ctxi, ctxs, ctxs->vaMax);
}
fResult = fResult || (ctxs->cResult && (ctxs->cResult == ctxs->cMaxResult));
// 5: finish
if(fResult && ppObAddressResult) {
*ppObAddressResult = ObSet_GetAll(ctxi->psvaResult);
Expand Down
78 changes: 76 additions & 2 deletions vmm_example/vmmdll_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,40 @@ LPSTR VadMap_Type(_In_ PVMMDLL_MAP_VADENTRY pVad)
}
}


// ----------------------------------------------------------------------------
// Callback functions (YARA SEARCH) functionality below:
// ----------------------------------------------------------------------------

BOOL CallbackSearchYaraMatch(_In_ PVOID pvContext, _In_ PVMMYARA_RULE_MATCH pRuleMatch, _In_reads_bytes_(cbBuffer) PBYTE pbBuffer, _In_ SIZE_T cbBuffer)
{
PVMMDLL_YARA_CONFIG ctx = (PVMMDLL_YARA_CONFIG)pvContext; // We pass the PVMMDLL_YARA_CONFIG into the user-set context pointer (ctx->pvUserPtrOpt)
// This is done so we'll get the base address of the buffer being scanned.
// if one wish to use another user-context the field ctx->pvUserPtrOpt2 may be used.
if(pRuleMatch->dwVersion != VMMYARA_RULE_MATCH_VERSION) { return FALSE; }
if((pRuleMatch->cStrings > 0) && (pRuleMatch->Strings[0].cMatch > 0)) { // ensure at least one string match exists - only print the address of the first occurence.
printf(" rule: %s address: %llx string: %s\n", pRuleMatch->szRuleIdentifier, ctx->vaCurrent + pRuleMatch->Strings[0].cbMatchOffset[0], pRuleMatch->Strings[0].szString);
}
return TRUE; // TRUE = continue search, FALSE = abort search
}

/*
* Optional filter callback. Tell whether a memory region should be scanned or not.
* User-mode applications predominantely use vad entries, whilst kernel use pte entries.
* -- ctx = Pointer to the VMMDLL_YARA_CONFIG structure.
* -- pePte = Pointer to the VMMDLL_MAP_PTEENTRY structure. NULL if not available.
* -- peVad = Pointer to the VMMDLL_MAP_VADENTRY structure. NULL if not available.
* -- return = TRUE to scan the memory region, FALSE to skip it.
*/
BOOL CallbackSearchYaraFilter(_In_ PVMMDLL_YARA_CONFIG ctx, _In_opt_ PVMMDLL_MAP_PTEENTRY pePte, _In_opt_ PVMMDLL_MAP_VADENTRY peVad)
{
if(ctx->dwVersion != VMMDLL_YARA_CONFIG_VERSION) { return FALSE; }
// only scan VAD-backed image memory regions since we're scanning for PE headers.
// this may miss out on PE headers in other memory regions commonly used by malware.
return peVad && peVad->fImage;
}


// ----------------------------------------------------------------------------
// Main entry point which contains various sample code how to use MemProcFS DLL.
// Please walk though for different API usage examples. To select device ensure
Expand Down Expand Up @@ -753,13 +787,53 @@ int main(_In_ int argc, _In_ char* argv[])
printf(" 0x%016llx", pvaSearchResult[i]);
}
printf("\n");
LocalFree(pvaSearchResult); // free any function-allocated memory containing results.
VMMDLL_MemFree(pvaSearchResult); // free any function-allocated memory containing results.
} else {
printf("FAIL: VMMDLL_MemSearch\n");
LocalFree(pvaSearchResult); // free any function-allocated memory containing results.
VMMDLL_MemFree(pvaSearchResult); // free any function-allocated memory containing results.
return 1;
}


// YARA SEARCH for process PE header signatures.
// NB! YARA SEARCH REQUIRES 'vmmyara.dll'/'vmmyara.so' to be present in the vmm directory.
// The search is performed at offset 0x0in each scanned memory region (VAD or PTE).
// Only search virtual memory above 4GB. For more information see vmmdll.h.
// The search will return a maximum number of 32 results.
printf("------------------------------------------------------------\n");
printf("# YARA Search for PE header signatures in 'explorer.exe'. \n");
ShowKeyPress();
VMMDLL_YARA_CONFIG ctxYara = { 0 };
ctxYara.dwVersion = VMMDLL_YARA_CONFIG_VERSION; // required struct version.
// YARA rules: Yara rules may be in the form of any number of strings as
// given in the below example.
// Yara rules may also be given in the form of one (1) file (including path)
// containing one or more YARA rules or index rules.
LPSTR szYaraRule1 = " rule mz_header { strings: $mz = \"MZ\" condition: $mz at 0 } ";
LPSTR szYaraRules[] = { szYaraRule1 };
ctxYara.pszRules = szYaraRules; // required YARA rules array.
ctxYara.cRules = 1; // required number of YARA rules.
ctxYara.pvUserPtrOpt = &ctxYara; // optional user pointer passed to callback functions
// here ctxYara is passed since we need to read the base address of the memory region.
// any other user-defined pointer may be set in ctxYara.pvUserPtrOpt2
ctxYara.cMaxResult = 16; // optional max number of results to return.
ctxYara.ReadFlags = VMMDLL_FLAG_NOCACHE; // optional read flags are possible to use.
ctxYara.vaMin = 0x100000000; // optional start searching at 4GB in virtual memory
ctxYara.pfnFilterOptCB = CallbackSearchYaraFilter; // optional callback function for filtering which memory ranges to scan.
ctxYara.pfnScanMemoryCB = CallbackSearchYaraMatch; // optional callback function for handling search results
// perform the actual search:
// Note that the the two last arguments works the same as in the VMMDLL_MemSearch() function.
// These are not used in this example though since a callback is used instead (it's possible to use both or just one of them).
printf("CALL: VMMDLL_YaraSearch\n");
result = VMMDLL_YaraSearch(hVMM, dwPID, &ctxYara, NULL, NULL);
if(result) {
printf("SUCCESS: VMMDLL_YaraSearch\n");
printf(" Number of search results: %u\n", ctxYara.cResult);
} else {
printf("FAIL: VMMDLL_YaraSearch\n");
// YARA search will fail if 'vmmyara.dll'/'vmmyara.so' is not present in the vmm directory.
}


// Write virtual memory at PE header of Explorer.EXE and display the first
// 0x80 bytes on-screen - afterwards. Maybe result of write is in there?
Expand Down
4 changes: 2 additions & 2 deletions vmmpyc/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#define VERSION_MAJOR 5
#define VERSION_MINOR 8
#define VERSION_REVISION 13
#define VERSION_BUILD 132
#define VERSION_REVISION 14
#define VERSION_BUILD 134

#define VER_FILE_DESCRIPTION_STR "MemProcFS : Python API"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
Expand Down
2 changes: 1 addition & 1 deletion vmmrust/leechcore_example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "leechcore_example"
version = "5.8.13"
version = "5.8.14"
edition = "2021"
publish = false

Expand Down
2 changes: 1 addition & 1 deletion vmmrust/m_example_plugin/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "m_example_plugin"
version = "5.8.13"
version = "5.8.14"
edition = "2021"
publish = false

Expand Down
2 changes: 1 addition & 1 deletion vmmrust/memprocfs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "memprocfs"
version = "5.8.13"
version = "5.8.14"
edition = "2021"
description = "MemProcFS - Physical Memory Analysis Framework"
homepage = "https://github.com/ufrisk/MemProcFS"
Expand Down
10 changes: 9 additions & 1 deletion vmmrust/memprocfs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@ purposes. Analysis may also take place on live memory - either captured by
using [PCILeech PCIe DMA devices](https://github.com/ufrisk/pcileech-fpga)
or by using drivers - such as WinPMEM, LiveCloudKd, VMware or similar.

The MemProcFS API base is the [`Vmm`](https://docs.rs/memprocfs/latest/memprocfs/struct.Vmm.html)
<b>Rust API Versioning follows MemProcFS major.minor versioning.</b>
Always use the matching MemProcFS Native library version for the major.minor
number. <b>Revision numbers</b> may however be higher (but not lower) in the
Native library than in the Rust API. Bug fixes often takes place in the Native
library without the Rust API being updated. It's possible to use Rust API
version 5.8.1 with MemProcFS 5.8.10 for example. It is not supported to use
Rust API version 5.8.1 with MemProcFS 5.7.x or MemProcFS 5.9.x.

<b>Base of the MemProcFS API</b> is the [`Vmm`](https://docs.rs/memprocfs/latest/memprocfs/struct.Vmm.html)
struct. Once the native vmm has been initialized it's possible to retrieve
processes in the form of the [`VmmProcess`](https://docs.rs/memprocfs/latest/memprocfs/struct.VmmProcess.html) struct.
Using the `Vmm` and `VmmProcess` it's possible to undertake a wide range of
Expand Down
2 changes: 1 addition & 1 deletion vmmrust/memprocfs_example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "memprocfs_example"
version = "5.8.13"
version = "5.8.14"
edition = "2021"
publish = false

Expand Down

0 comments on commit b753c20

Please sign in to comment.