Files
MemProcFS/vmm/modules/m_sys_sysinfo.c
2026-01-04 15:00:03 +01:00

231 lines
11 KiB
C

// m_sys_sysinfo.c : implementation of easy-to-read system information.
//
// (c) Ulf Frisk, 2024-2026
// Author: Ulf Frisk, pcileech@frizk.net
//
#include "modules.h"
#include "../sysquery.h"
#include "../vmmwinreg.h"
#include "../version.h"
/*
* Helper information to display network interface information:
*/
VOID MSysInfo_GetContext_Network(_In_ VMM_HANDLE H, _In_ POB_MEMFILE pmfOb, POB_REGISTRY_HIVE pHive, _In_ POB_REGISTRY_KEY pInterfaceKey, _In_ DWORD iInterface)
{
static LPSTR szVALUES_STRING[] = { "Domain", "NameServer", "DefaultGateway", "IPAddress", "SubnetMask", "DhcpIPAddress", "DhcpSubnetMask", "DhcpServer", "DhcpDefaultGateway", "DhcpNameServer", "DhcpDomain", "DhcpSubnetMaskOpt" };
DWORD i;
CHAR szData[128];
BOOL fInterface = FALSE;
POB_REGISTRY_VALUE pObValue = NULL;
POB_MAP pmObInterfaceRegValues = NULL;
VMM_REGISTRY_VALUE_INFO ValueInfo = { 0 };
pmObInterfaceRegValues = VmmWinReg_KeyValueList(H, pHive, pInterfaceKey);
while((pObValue = ObMap_Pop(pmObInterfaceRegValues))) {
VmmWinReg_ValueInfo(pHive, pObValue, &ValueInfo);
for(i = 0; i < sizeof(szVALUES_STRING) / sizeof(LPSTR); i++) {
if(CharUtil_StrEquals(szVALUES_STRING[i], ValueInfo.uszName, FALSE)) {
if(VmmWinReg_ValueQueryString4(H, pHive, pObValue, NULL, szData, sizeof(szData)) && (strlen(szData) > 2)) {
if(!fInterface) {
ObMemFile_AppendStringEx(pmfOb, " Interface #%i:\n", iInterface);
fInterface = TRUE;
}
ObMemFile_AppendStringEx(pmfOb, " %s:%*s%s\n", szVALUES_STRING[i], (DWORD)(19 - strlen(szVALUES_STRING[i])), "", szData);
}
break;
}
}
Ob_DECREF(pObValue);
}
Ob_DECREF(pmObInterfaceRegValues);
}
/*
* Retrieve the info file.
* CALLER DECREF: return
* -- H
* -- ctxP
* -- return
*/
_Success_(return != NULL)
POB_MEMFILE MSysinfo_GetContext(_In_ VMM_HANDLE H, _In_ PVMMDLL_PLUGIN_CONTEXT ctxP)
{
static SRWLOCK LockSRW = SRWLOCK_INIT;
PVMM_MAP_PHYSMEMENTRY pePhysMem = NULL;
PVMMOB_MAP_PHYSMEM pObMapPhysMem = NULL;
PVMM_MAP_USERENTRY peUser = NULL;
PVMMOB_MAP_USER pObMapUser = NULL;
PVMM_PROCESS pObProcess = NULL;
POB_REGISTRY_HIVE pObHive = NULL;
POB_REGISTRY_KEY pObKey = NULL, pObInterfaceKey = NULL;
POB_MAP pmObInterfaceRegKey = NULL;
POB_MEMFILE pmfOb = NULL;
QWORD cbPhysMem = 0;
DWORD i, cProcActive = 0, cProcInactive = 0, cRegKey = 0;
CHAR szTimeBoot[24] = { 0 }, szTimeNow[24] = { 0 }, szTime[24] = { 0 }, szTimeZone[64] = { 0 }, szComputername[64] = { 0 };
CHAR uszHwCPU[128] = { 0 }, uszHwMBVendor[128] = { 0 }, uszHwMBProduct[128] = { 0 }, uszHwBIOS[128] = { 0 }, uszHwSystem[128] = { 0 };
// Re-use context if already created:
if((pmfOb = ObContainer_GetOb((POB_CONTAINER)ctxP->ctxM))) { return pmfOb; }
AcquireSRWLockExclusive(&LockSRW);
if((pmfOb = ObContainer_GetOb((POB_CONTAINER)ctxP->ctxM))) { goto finish; }
if(!(pmfOb = ObMemFile_New(H, H->vmm.pObCacheMapObCompressedShared))) { goto finish; }
// Windows info:
Util_FileTime2String(H->vmm.kernel.opt.ftBootTime, szTimeBoot);
Util_FileTime2String(SysQuery_TimeCurrent(H), szTimeNow);
SysQuery_TimeZoneEx(H, szTimeZone, TRUE);
SysQuery_ComputerName(H, szComputername, sizeof(szComputername));
ObMemFile_AppendString(pmfOb, "Windows Information:\n");
ObMemFile_AppendStringEx(pmfOb, " Computer Name: %s\n", szComputername);
ObMemFile_AppendStringEx(pmfOb, " Current Time: %s\n", szTimeNow);
ObMemFile_AppendStringEx(pmfOb, " Boot Time: %s\n", szTimeBoot);
ObMemFile_AppendStringEx(pmfOb, " Time Zone: %s", szTimeZone);
ObMemFile_AppendStringEx(pmfOb, " Version: %i.%i (build %i)\n", H->vmm.kernel.dwVersionMajor, H->vmm.kernel.dwVersionMinor, H->vmm.kernel.dwVersionBuild);
// Memory & CPU: (size and architectore)
VmmWinReg_ValueQueryString2(H, "HKLM\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\ProcessorNameString", NULL, uszHwCPU, sizeof(uszHwCPU));
VmmWinReg_ValueQueryString2(H, "HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BaseBoardManufacturer", NULL, uszHwMBVendor, sizeof(uszHwMBVendor));
VmmWinReg_ValueQueryString2(H, "HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BaseBoardProduct", NULL, uszHwMBProduct, sizeof(uszHwMBProduct));
VmmWinReg_ValueQueryString2(H, "HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BIOSVendor", NULL, uszHwBIOS, sizeof(uszHwBIOS));
VmmWinReg_ValueQueryString2(H, "HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS\\SystemManufacturer", NULL, uszHwSystem, sizeof(uszHwSystem));
ObMemFile_AppendString(pmfOb, "\nHardware Information:\n");
ObMemFile_AppendStringEx(pmfOb, " Architecture: %s\n", VMM_MEMORYMODEL_TOSTRING[H->vmm.tpMemoryModel]);
if((VmmMap_GetPhysMem(H, &pObMapPhysMem) && pObMapPhysMem->cMap)) {
for(i = 0; i < pObMapPhysMem->cMap; i++) {
pePhysMem = &pObMapPhysMem->pMap[i];
cbPhysMem += pePhysMem->cb;
}
ObMemFile_AppendStringEx(pmfOb, " Physical Memory: %llu GB\n", ((cbPhysMem + 0x20000000) / (1024 * 1024 * 1024)));
ObMemFile_AppendStringEx(pmfOb, " Max Address: 0x%llx\n", pePhysMem->pa + pePhysMem->cb - 1);
}
if(uszHwCPU[0]) { ObMemFile_AppendStringEx(pmfOb, " CPU: %s\n", uszHwCPU); }
if(uszHwMBVendor[0]) { ObMemFile_AppendStringEx(pmfOb, " MB Vendor: %s\n", uszHwMBVendor); }
if(uszHwMBProduct[0]) { ObMemFile_AppendStringEx(pmfOb, " MB Product: %s\n", uszHwMBProduct); }
if(uszHwBIOS[0]) { ObMemFile_AppendStringEx(pmfOb, " BIOS Vendor: %s\n", uszHwBIOS); }
if(uszHwSystem[0]) { ObMemFile_AppendStringEx(pmfOb, " System Vendor: %s\n", uszHwSystem); }
// Users:
if((VmmMap_GetUser(H, &pObMapUser) && pObMapUser->cMap)) {
ObMemFile_AppendString(pmfOb, "\nUsers:\n");
for(i = 0; i < pObMapUser->cMap; i++) {
peUser = &pObMapUser->pMap[i];
ObMemFile_AppendStringEx(pmfOb, " %s (%s)\n", peUser->uszText, peUser->szSID);
}
}
// Processes:
ObMemFile_AppendString(pmfOb, "\nProcess Information:\n");
while((pObProcess = VmmProcessGetNext(H, pObProcess, VMM_FLAG_PROCESS_SHOW_TERMINATED))) {
if(pObProcess->dwState) {
cProcInactive++;
} else {
cProcActive++;
}
}
ObMemFile_AppendStringEx(pmfOb, " Active: %u\n", cProcActive);
ObMemFile_AppendStringEx(pmfOb, " Inactive: %u\n", cProcInactive);
// Network:
if(VmmWinReg_KeyHiveGetByFullPath(H, "HKLM\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces", &pObHive, &pObKey) && (pmObInterfaceRegKey = VmmWinReg_KeyList(H, pObHive, pObKey)) && ObMap_Size(pmObInterfaceRegKey)) {
ObMemFile_AppendString(pmfOb, "\nNetwork Interfaces:\n");
while((pObInterfaceKey = ObMap_Pop(pmObInterfaceRegKey))) {
MSysInfo_GetContext_Network(H, pmfOb, pObHive, pObInterfaceKey, ++cRegKey);
Ob_DECREF(pObInterfaceKey);
}
}
// MemProcFS info:
Util_FileTime2String(Util_FileTimeNow(), szTime);
ObMemFile_AppendString(pmfOb, "\nMemProcFS Information:\n");
ObMemFile_AppendStringEx(pmfOb, " Version: %i.%i.%i (build %i)\n", VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD);
ObMemFile_AppendStringEx(pmfOb, " Parse Time: %s\n", szTime);
ObMemFile_AppendStringEx(pmfOb, " Memory Source: %s, %s\n", (H->dev.fWritable ? "Read/Write" : "Read-only"), (H->dev.fVolatile ? "Volatile" : "Static"));
ObMemFile_AppendStringEx(pmfOb, " Unique Tag: %s\n", H->vmm.szSystemUniqueTag);
ObMemFile_AppendStringEx(pmfOb, " Forensic Mode: %s\n", (H->cfg.tpForensicMode ? "Enabled" : "Disabled"));
ObMemFile_AppendStringEx(pmfOb, " VM Parsing: %s\n", (H->cfg.fVM ? "Enabled" : "Disabled"));
// Finish:
ObContainer_SetOb((POB_CONTAINER)ctxP->ctxM, pmfOb);
finish:
ReleaseSRWLockExclusive(&LockSRW);
Ob_DECREF(pmObInterfaceRegKey);
Ob_DECREF(pObMapPhysMem);
Ob_DECREF(pObMapUser);
Ob_DECREF(pObHive);
Ob_DECREF(pObKey);
return pmfOb;
}
/*
* Read : function as specified by the module manager. The module manager will
* call into this callback function whenever a read shall occur from a "file".
* -- H
* -- ctxP
* -- pb
* -- cb
* -- pcbRead
* -- cbOffset
* -- return
*/
_Success_(return == 0)
NTSTATUS MSysinfo_Read(_In_ VMM_HANDLE H, _In_ PVMMDLL_PLUGIN_CONTEXT ctxP, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
{
NTSTATUS nt;
POB_MEMFILE pmfOb = NULL;
if(CharUtil_StrEquals(ctxP->uszPath, "sysinfo.txt", TRUE)) {
if((pmfOb = MSysinfo_GetContext(H, ctxP))) {
nt = ObMemFile_ReadFile(pmfOb, pb, cb, pcbRead, cbOffset);
Ob_DECREF(pmfOb);
return nt;
}
}
return VMMDLL_STATUS_FILE_INVALID;
}
/*
* List : function as specified by the module manager. The module manager will
* call into this callback function whenever a list directory shall occur from
* the given module.
* -- H
* -- ctxP
* -- pFileList
* -- return
*/
BOOL MSysinfo_List(_In_ VMM_HANDLE H, _In_ PVMMDLL_PLUGIN_CONTEXT ctxP, _Inout_ PHANDLE pFileList)
{
POB_MEMFILE pmfOb = NULL;
if(!ctxP->uszPath[0] && (pmfOb = MSysinfo_GetContext(H, ctxP))) {
VMMDLL_VfsList_AddFile(pFileList, "sysinfo.txt", ObMemFile_Size(pmfOb), NULL);
}
Ob_DECREF(pmfOb);
return TRUE;
}
VOID MSysinfo_Notify(_In_ VMM_HANDLE H, _In_ PVMMDLL_PLUGIN_CONTEXT ctxP, _In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent)
{
if(fEvent == VMMDLL_PLUGIN_NOTIFY_REFRESH_SLOW) {
ObContainer_SetOb((POB_CONTAINER)ctxP->ctxM, NULL);
}
}
VOID MSysinfo_Close(_In_ VMM_HANDLE H, _In_ PVMMDLL_PLUGIN_CONTEXT ctxP)
{
Ob_DECREF(ctxP->ctxM);
}
VOID M_SysSysinfo_Initialize(_In_ VMM_HANDLE H, _Inout_ PVMMDLL_PLUGIN_REGINFO pRI)
{
if((pRI->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRI->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
if((pRI->tpSystem != VMMDLL_SYSTEM_WINDOWS_64) && (pRI->tpSystem != VMMDLL_SYSTEM_WINDOWS_32)) { return; }
if(!(pRI->reg_info.ctxM = (PVMMDLL_PLUGIN_INTERNAL_CONTEXT)ObContainer_New())) { return; } // internal module context
strcpy_s(pRI->reg_info.uszPathName, 128, "\\sys\\sysinfo"); // module name
pRI->reg_info.fRootModule = TRUE; // module shows in root directory
pRI->reg_fn.pfnList = MSysinfo_List; // List function supported
pRI->reg_fn.pfnRead = MSysinfo_Read; // Read function supported
pRI->reg_fn.pfnNotify = MSysinfo_Notify; // Notify function supported
pRI->reg_fn.pfnClose = MSysinfo_Close; // Close function supported
pRI->pfnPluginManager_Register(H, pRI);
}