diff --git a/capemon.c b/capemon.c index 8cb30234..9a42764d 100644 --- a/capemon.c +++ b/capemon.c @@ -562,6 +562,8 @@ void init_private_heap(void) } extern CRITICAL_SECTION readfile_critsec, g_mutex, g_writing_log_buffer_mutex, g_interactive_debugger_lock; +DWORD g_wmi_tls_index = TLS_OUT_OF_INDEXES; +DWORD g_wmi_tracker_tls_index = TLS_OUT_OF_INDEXES; BOOLEAN g_dll_main_complete; OSVERSIONINFOA g_osverinfo; @@ -604,6 +606,8 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) InitializeCriticalSection(&g_mutex); InitializeCriticalSection(&g_writing_log_buffer_mutex); + g_wmi_tls_index = TlsAlloc(); + g_wmi_tracker_tls_index = TlsAlloc(); // read the config settings read_config(); @@ -690,7 +694,19 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) if (!g_config.tlsdump && !g_config.interactive) notify_successful_load(); } + else if (dwReason == DLL_THREAD_DETACH) { + extern void TlsWmiThreadCleanup(void); + TlsWmiThreadCleanup(); + } else if(dwReason == DLL_PROCESS_DETACH) { + if (g_wmi_tls_index != TLS_OUT_OF_INDEXES) { + TlsFree(g_wmi_tls_index); + g_wmi_tls_index = TLS_OUT_OF_INDEXES; + } + if (g_wmi_tracker_tls_index != TLS_OUT_OF_INDEXES) { + TlsFree(g_wmi_tracker_tls_index); + g_wmi_tracker_tls_index = TLS_OUT_OF_INDEXES; + } // in production, we shouldn't ever get called in this way since we // unlink ourselves from the module list in the PEB // so don't call log_free(), as it'll have side-effects diff --git a/config.c b/config.c index 6255ecb7..00dd836d 100644 --- a/config.c +++ b/config.c @@ -1453,6 +1453,18 @@ void parse_config_line(char* line) if (g_config.hook_watch) DebugOutput("Config: Hook watch enabled.\n"); } + else if (!stricmp(key, "wmi-cache-size")) { + g_config.wmi_cache_size = (int)strtoul(value, NULL, 10); + DebugOutput("Config: WMI cache size set to %d.\n", g_config.wmi_cache_size); + } + else if (!stricmp(key, "wmi-voltage-reading")) { + g_config.wmi_voltage_reading = (int)strtoul(value, NULL, 10); + DebugOutput("Config: WMI voltage reading set to %d.\n", g_config.wmi_voltage_reading); + } + else if (!stricmp(key, "wmi-temperature-reading")) { + g_config.wmi_temperature_reading = (int)strtoul(value, NULL, 10); + DebugOutput("Config: WMI temperature reading set to %d.\n", g_config.wmi_temperature_reading); + } else if (!stricmp(key, "sleep-skip-seconds")) { g_config.sleep_skip_seconds = (int)strtoul(value, NULL, 10); DebugOutput("Config: Sleep skip seconds set to %d.\n", g_config.sleep_skip_seconds); @@ -1504,6 +1516,9 @@ void read_config(void) g_config.loaderlock_scans = 1; g_config.spoofed_cpu_count = SPOOFED_CPU_CORE_NUM; g_config.syscall = 1; + g_config.wmi_cache_size = 32768; + g_config.wmi_voltage_reading = 12000; + g_config.wmi_temperature_reading = 3000; g_config.sleep_skip_seconds = 10; StepLimit = SINGLE_STEP_LIMIT; diff --git a/config.h b/config.h index 047be9de..3bb285ba 100644 --- a/config.h +++ b/config.h @@ -336,6 +336,9 @@ struct _g_config { int trace_times; char *trace_into_api[EXCLUSION_MAX]; int hook_watch; + int wmi_cache_size; + int wmi_voltage_reading; + int wmi_temperature_reading; int sleep_skip_seconds; }; diff --git a/docs/configuration.md b/docs/configuration.md index 561ad164..aecb1d55 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -75,6 +75,9 @@ They are typically defined in the analysis configuration file (e.g., `config.ini | `fake-rdtsc` | Boolean | Enable fake RDTSC (Read Time-Stamp Counter) results. | | `nop-rdtscp` | Boolean | NOP (No Operation) the RDTSCP instruction. | | `cpu-count` | Integer | Spoof the number of CPU cores (default: 4). | +| `wmi-cache-size` | Integer | Spoof the L1/L2/L3 cache memory size in bytes returned via Win32_CacheMemory queries (default: 32768). | +| `wmi-voltage-reading` | Integer | Spoof the voltage reading in millivolts returned via Win32_VoltageProbe queries (default: 12000). | +| `wmi-temperature-reading` | Integer | Spoof the thermal zone sensor temperature in tenths of Kelvins returned via Win32_ThermalZoneInfo queries (default: 3000). | | `ntdll-protect` | Boolean | Enable write protection on `ntdll.dll` code (enabled by default). | | `ntdll-unhook` | Boolean | Enable protection against `ntdll` unhooking (via `NtReadFile`). | | `ntdll-remap` | Boolean | Enable `ntdll` remapping protection. | diff --git a/hook_com.c b/hook_com.c index e3a41019..9ad5da3c 100644 --- a/hook_com.c +++ b/hook_com.c @@ -40,7 +40,7 @@ BOOL ContainsNamespace(const wchar_t* resource, const wchar_t* target) { return FALSE; } -__declspec(thread) BOOL bHookViaWbemLocator; +#include "hooks.h" HOOKDEF(HRESULT, WINAPI, WbemLocator_ConnectServer, _In_ PVOID _this, _In_ const BSTR strNetworkResource, @@ -63,9 +63,9 @@ HOOKDEF(HRESULT, WINAPI, WbemLocator_ConnectServer, ContainsNamespace(strNetworkResource, L"ROOT\\Microsoft\\Windows\\TaskScheduler") )) { - bHookViaWbemLocator = TRUE; + SetHookViaWbemLocator(TRUE); set_com_hooks(NULL, NULL, *ppNamespace); - bHookViaWbemLocator = FALSE; + SetHookViaWbemLocator(FALSE); } LOQ_hresult("com", "uu", "NetworkResource", strNetworkResource, "User", strUser); diff --git a/hook_wmi.c b/hook_wmi.c index 4591c20f..f6416e41 100644 --- a/hook_wmi.c +++ b/hook_wmi.c @@ -1,12 +1,75 @@ +#include #include "log.h" #include "misc.h" #include "config.h" +#include "hooks.h" #include -__declspec(thread) static int g_last_seen_disk_query = 0; -__declspec(thread) static int g_last_seen_physicalmemory = 0; +enum { + WMI_FAKE_CLASS_NONE = 0, + WMI_FAKE_CLASS_FAN, + WMI_FAKE_CLASS_CACHEMEMORY, + WMI_FAKE_CLASS_VOLTAGEPROBE, + WMI_FAKE_CLASS_PORTCONNECTOR, + WMI_FAKE_CLASS_THERMALZONEINFO, + WMI_FAKE_CLASS_CIM_MEMORY, + WMI_FAKE_CLASS_CIM_SENSOR, + WMI_FAKE_CLASS_CIM_NUMERICSENSOR, + WMI_FAKE_CLASS_CIM_TEMPERATURESENSOR, + WMI_FAKE_CLASS_CIM_VOLTAGESENSOR, + WMI_FAKE_CLASS_CIM_PHYSICALCONNECTOR, + WMI_FAKE_CLASS_CIM_SLOT +}; + +typedef struct { + int last_seen_disk_query; + int last_seen_physicalmemory; + int last_seen_fake_class; +} wmi_thread_context_t; + +extern DWORD g_wmi_tracker_tls_index; + +// Fallback context if TLS allocation fails (shared across threads as last resort) +static wmi_thread_context_t g_wmi_fallback_context = {0}; + +static wmi_thread_context_t* GetWmiThreadContext(void) { + wmi_thread_context_t* pCtx = NULL; + if (g_wmi_tracker_tls_index != TLS_OUT_OF_INDEXES) { + pCtx = (wmi_thread_context_t*)TlsGetValue(g_wmi_tracker_tls_index); + if (!pCtx) { + pCtx = (wmi_thread_context_t*)calloc(1, sizeof(wmi_thread_context_t)); + if (pCtx) { + TlsSetValue(g_wmi_tracker_tls_index, pCtx); + } else { + // calloc failed - use fallback (not thread-safe but prevents crash) + pCtx = &g_wmi_fallback_context; + } + } + } else { + // TLS not initialized - use fallback + pCtx = &g_wmi_fallback_context; + } + return pCtx; +} + +// Accessor macros: GetWmiThreadContext now guaranteed to return non-NULL +#define g_last_seen_disk_query (GetWmiThreadContext()->last_seen_disk_query) +#define g_last_seen_physicalmemory (GetWmiThreadContext()->last_seen_physicalmemory) +#define g_last_seen_fake_class (GetWmiThreadContext()->last_seen_fake_class) + +void TlsWmiThreadCleanup(void) { + if (g_wmi_tracker_tls_index != TLS_OUT_OF_INDEXES) { + wmi_thread_context_t* pCtx = (wmi_thread_context_t*)TlsGetValue(g_wmi_tracker_tls_index); + if (pCtx) { + free(pCtx); + TlsSetValue(g_wmi_tracker_tls_index, NULL); + } + } +} + +void SpoofWmiData(const void* pObject, const wchar_t* szClassName, const wchar_t* wszName, VARIANT* pVal) { + int pointer_idx = (pObject != NULL) ? (int)(((ULONG_PTR)pObject >> 4) % 3) : 0; -void SpoofWmiData(const wchar_t* szClassName, const wchar_t* wszName, VARIANT* pVal) { if (g_config.no_stealth) return; @@ -57,6 +120,40 @@ void SpoofWmiData(const wchar_t* szClassName, const wchar_t* wszName, VARIANT* p } } } + else if (!_wcsicmp(wszName, L"DeviceID") && g_last_seen_fake_class != WMI_FAKE_CLASS_NONE) { + SysFreeString(pVal->bstrVal); + switch (g_last_seen_fake_class) { + case WMI_FAKE_CLASS_FAN: pVal->bstrVal = SysAllocString(L"Fan0"); break; + case WMI_FAKE_CLASS_CACHEMEMORY: { + wchar_t fName[32]; + swprintf_s(fName, _countof(fName), L"Cache%d", pointer_idx); + pVal->bstrVal = SysAllocString(fName); + break; + } + case WMI_FAKE_CLASS_VOLTAGEPROBE: pVal->bstrVal = SysAllocString(L"Voltage0"); break; + case WMI_FAKE_CLASS_PORTCONNECTOR: pVal->bstrVal = SysAllocString(L"Port0"); break; + case WMI_FAKE_CLASS_THERMALZONEINFO: pVal->bstrVal = SysAllocString(L"Thermal0"); break; + case WMI_FAKE_CLASS_CIM_MEMORY: pVal->bstrVal = SysAllocString(L"CIMMemory0"); break; + case WMI_FAKE_CLASS_CIM_SENSOR: pVal->bstrVal = SysAllocString(L"CIMSensor0"); break; + case WMI_FAKE_CLASS_CIM_NUMERICSENSOR: pVal->bstrVal = SysAllocString(L"CIMNumeric0"); break; + case WMI_FAKE_CLASS_CIM_TEMPERATURESENSOR: pVal->bstrVal = SysAllocString(L"CIMTemp0"); break; + case WMI_FAKE_CLASS_CIM_VOLTAGESENSOR: pVal->bstrVal = SysAllocString(L"CIMVoltage0"); break; + case WMI_FAKE_CLASS_CIM_PHYSICALCONNECTOR: pVal->bstrVal = SysAllocString(L"CIMConnector0"); break; + case WMI_FAKE_CLASS_CIM_SLOT: pVal->bstrVal = SysAllocString(L"CIMSlot0"); break; + } + } + else if (!_wcsicmp(wszName, L"Status") && g_last_seen_fake_class != WMI_FAKE_CLASS_NONE) { + SysFreeString(pVal->bstrVal); + pVal->bstrVal = SysAllocString(L"OK"); + } + else if (!_wcsicmp(wszName, L"Purpose") && g_last_seen_fake_class == WMI_FAKE_CLASS_CACHEMEMORY) { + SysFreeString(pVal->bstrVal); + switch (pointer_idx) { + case 0: pVal->bstrVal = SysAllocString(L"Internal L1 Cache"); break; + case 1: pVal->bstrVal = SysAllocString(L"Internal L2 Cache"); break; + case 2: pVal->bstrVal = SysAllocString(L"External L3 Cache"); break; + } + } } // // Spoofery logic for I4 (Signed 32-bit integer) @@ -88,10 +185,41 @@ void SpoofWmiData(const wchar_t* szClassName, const wchar_t* wszName, VARIANT* p pVal->lVal = SPOOFED_REFRESH_RATE; } } + else if (g_last_seen_fake_class != WMI_FAKE_CLASS_NONE) { + if (!_wcsicmp(wszName, L"InstalledSize")) { + switch (pointer_idx) { + case 0: pVal->lVal = 32768; break; // L1: 32KB + case 1: pVal->lVal = 262144; break; // L2: 256KB + case 2: pVal->lVal = (LONG)g_config.wmi_cache_size; break; // L3: User Configurable + } + } + else if (!_wcsicmp(wszName, L"Level")) { + switch (pointer_idx) { + case 0: pVal->lVal = 3; break; // L1 (3) + case 1: pVal->lVal = 4; break; // L2 (4) + case 2: pVal->lVal = 5; break; // L3 (5) + } + } + else if (!_wcsicmp(wszName, L"CurrentReading")) { + pVal->lVal = (LONG)g_config.wmi_voltage_reading; + } + else if (!_wcsicmp(wszName, L"ConnectorType")) { + pVal->lVal = 3; // DB9 Male + } + else if (!_wcsicmp(wszName, L"PortType")) { + pVal->lVal = 2; // Serial Port + } + else if (!_wcsicmp(wszName, L"CurrentTemperature")) { + pVal->lVal = (LONG)g_config.wmi_temperature_reading; + } + } } else if (pVal->vt == VT_BOOL) { if ((!_wcsicmp(szClassName, L"Win32_ComputerSystem") && (!_wcsicmp(wszName, L"PartOfDomain")))) pVal->boolVal = VARIANT_TRUE; + else if (g_last_seen_fake_class == WMI_FAKE_CLASS_FAN && !_wcsicmp(wszName, L"ActiveCooling")) { + pVal->boolVal = VARIANT_TRUE; + } } // // Spoofery logic for NULL @@ -104,16 +232,63 @@ void SpoofWmiData(const wchar_t* szClassName, const wchar_t* wszName, VARIANT* p } } +static BOOL IsPropertyValidForFakeClass(int fakeClass, const wchar_t* wszName) { + if (!wszName) + return FALSE; + + // Core properties common to almost all faked classes + if (!_wcsicmp(wszName, L"DeviceID") || !_wcsicmp(wszName, L"Status") || !_wcsicmp(wszName, L"__CLASS")) + return TRUE; + + switch (fakeClass) { + case WMI_FAKE_CLASS_FAN: + return !_wcsicmp(wszName, L"ActiveCooling"); + case WMI_FAKE_CLASS_CACHEMEMORY: + return !_wcsicmp(wszName, L"InstalledSize") || !_wcsicmp(wszName, L"Level") || !_wcsicmp(wszName, L"Purpose"); + case WMI_FAKE_CLASS_VOLTAGEPROBE: + return !_wcsicmp(wszName, L"CurrentReading"); + case WMI_FAKE_CLASS_PORTCONNECTOR: + return !_wcsicmp(wszName, L"ConnectorType") || !_wcsicmp(wszName, L"PortType"); + case WMI_FAKE_CLASS_THERMALZONEINFO: + return !_wcsicmp(wszName, L"CurrentTemperature"); + } + + return FALSE; +} + HOOKDEF(HRESULT, WINAPI, WMI_Get, _In_ PVOID _this, _In_ LPCWSTR wszName, _In_ LONG lFlags, - _Out_ VARIANT *pVal, + _Inout_ VARIANT *pVal, _Out_opt_ CIMTYPE *pType, _Out_opt_ LONG *plFlavor ) { HRESULT ret; WCHAR szClassName[256] = L""; + + if (wszName && _wcsicmp(wszName, L"__CLASS") == 0 && g_last_seen_fake_class != WMI_FAKE_CLASS_NONE) { + VariantInit(pVal); + pVal->vt = VT_BSTR; + switch (g_last_seen_fake_class) { + case WMI_FAKE_CLASS_FAN: pVal->bstrVal = SysAllocString(L"Win32_Fan"); break; + case WMI_FAKE_CLASS_CACHEMEMORY: pVal->bstrVal = SysAllocString(L"Win32_CacheMemory"); break; + case WMI_FAKE_CLASS_VOLTAGEPROBE: pVal->bstrVal = SysAllocString(L"Win32_VoltageProbe"); break; + case WMI_FAKE_CLASS_PORTCONNECTOR: pVal->bstrVal = SysAllocString(L"Win32_PortConnector"); break; + case WMI_FAKE_CLASS_THERMALZONEINFO: pVal->bstrVal = SysAllocString(L"Win32_ThermalZoneInfo"); break; + case WMI_FAKE_CLASS_CIM_MEMORY: pVal->bstrVal = SysAllocString(L"CIM_Memory"); break; + case WMI_FAKE_CLASS_CIM_SENSOR: pVal->bstrVal = SysAllocString(L"CIM_Sensor"); break; + case WMI_FAKE_CLASS_CIM_NUMERICSENSOR: pVal->bstrVal = SysAllocString(L"CIM_NumericSensor"); break; + case WMI_FAKE_CLASS_CIM_TEMPERATURESENSOR: pVal->bstrVal = SysAllocString(L"CIM_TemperatureSensor"); break; + case WMI_FAKE_CLASS_CIM_VOLTAGESENSOR: pVal->bstrVal = SysAllocString(L"CIM_VoltageSensor"); break; + case WMI_FAKE_CLASS_CIM_PHYSICALCONNECTOR: pVal->bstrVal = SysAllocString(L"CIM_PhysicalConnector"); break; + case WMI_FAKE_CLASS_CIM_SLOT: pVal->bstrVal = SysAllocString(L"CIM_Slot"); break; + } + if (pType) *pType = CIM_STRING; + if (plFlavor) *plFlavor = 0; + return S_OK; + } + if (wszName && _wcsicmp(wszName, L"__CLASS") != 0) { VARIANT classVariant; VariantInit(&classVariant); @@ -126,7 +301,30 @@ HOOKDEF(HRESULT, WINAPI, WMI_Get, } ret = Old_WMI_Get(_this, wszName, lFlags, pVal, pType, plFlavor); - SpoofWmiData(szClassName, wszName, pVal); + + if (ret == WBEM_E_NOT_FOUND && g_last_seen_fake_class != WMI_FAKE_CLASS_NONE && IsPropertyValidForFakeClass(g_last_seen_fake_class, wszName)) { + VariantInit(pVal); + ret = S_OK; + } + + if (g_last_seen_fake_class != WMI_FAKE_CLASS_NONE) { + switch (g_last_seen_fake_class) { + case WMI_FAKE_CLASS_FAN: wcscpy_s(szClassName, _countof(szClassName), L"Win32_Fan"); break; + case WMI_FAKE_CLASS_CACHEMEMORY: wcscpy_s(szClassName, _countof(szClassName), L"Win32_CacheMemory"); break; + case WMI_FAKE_CLASS_VOLTAGEPROBE: wcscpy_s(szClassName, _countof(szClassName), L"Win32_VoltageProbe"); break; + case WMI_FAKE_CLASS_PORTCONNECTOR: wcscpy_s(szClassName, _countof(szClassName), L"Win32_PortConnector"); break; + case WMI_FAKE_CLASS_THERMALZONEINFO: wcscpy_s(szClassName, _countof(szClassName), L"Win32_ThermalZoneInfo"); break; + case WMI_FAKE_CLASS_CIM_MEMORY: wcscpy_s(szClassName, _countof(szClassName), L"CIM_Memory"); break; + case WMI_FAKE_CLASS_CIM_SENSOR: wcscpy_s(szClassName, _countof(szClassName), L"CIM_Sensor"); break; + case WMI_FAKE_CLASS_CIM_NUMERICSENSOR: wcscpy_s(szClassName, _countof(szClassName), L"CIM_NumericSensor"); break; + case WMI_FAKE_CLASS_CIM_TEMPERATURESENSOR: wcscpy_s(szClassName, _countof(szClassName), L"CIM_TemperatureSensor"); break; + case WMI_FAKE_CLASS_CIM_VOLTAGESENSOR: wcscpy_s(szClassName, _countof(szClassName), L"CIM_VoltageSensor"); break; + case WMI_FAKE_CLASS_CIM_PHYSICALCONNECTOR: wcscpy_s(szClassName, _countof(szClassName), L"CIM_PhysicalConnector"); break; + case WMI_FAKE_CLASS_CIM_SLOT: wcscpy_s(szClassName, _countof(szClassName), L"CIM_Slot"); break; + } + } + + SpoofWmiData(_this, szClassName, wszName, pVal); // Short circuit, return early for things we don't want to log if (!ret && !g_config.full_logs && wszName) { @@ -184,7 +382,7 @@ HOOKDEF(HRESULT, WINAPI, WMI_Next, if (SUCCEEDED(hr) && classVariant.vt == VT_BSTR) { wcscpy_s(szClassName, _countof(szClassName), classVariant.bstrVal); } - SpoofWmiData(szClassName, *strName, pVal); + SpoofWmiData(_this, szClassName, *strName, pVal); LOQ_hresult("system", "unu", "Name", *strName, "Value", pVal, "Class", szClassName); } __except (EXCEPTION_EXECUTE_HANDLER) { @@ -205,8 +403,10 @@ HOOKDEF(HRESULT, WINAPI, WMI_ExecQuery, _Out_ IEnumWbemClassObject **ppEnum ) { HRESULT ret; + BSTR queryToExecute = (BSTR)strQuery; g_last_seen_disk_query = 0; g_last_seen_physicalmemory = 0; + g_last_seen_fake_class = WMI_FAKE_CLASS_NONE; if (strQuery) { if (!_wcsnicmp(strQuery, L"SELECT ", 7)) { @@ -216,9 +416,60 @@ HOOKDEF(HRESULT, WINAPI, WMI_ExecQuery, else if (wcsistr(strQuery, L" FROM Win32_PhysicalMemory")) { g_last_seen_physicalmemory = 1; } + else if (wcsistr(strQuery, L" FROM Win32_Fan")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_FAN; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM Win32_CacheMemory")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CACHEMEMORY; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_Processor"); + } + else if (wcsistr(strQuery, L" FROM Win32_VoltageProbe")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_VOLTAGEPROBE; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM Win32_PortConnector")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_PORTCONNECTOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM Win32_ThermalZoneInfo")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_THERMALZONEINFO; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_Memory")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_MEMORY; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_Sensor")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_SENSOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_NumericSensor")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_NUMERICSENSOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_TemperatureSensor")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_TEMPERATURESENSOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_VoltageSensor")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_VOLTAGESENSOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_PhysicalConnector")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_PHYSICALCONNECTOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_Slot")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_SLOT; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } } } - ret = Old_WMI_ExecQuery(_this, strQueryLanguage, strQuery, lFlags, pCtx, ppEnum); + ret = Old_WMI_ExecQuery(_this, strQueryLanguage, queryToExecute, lFlags, pCtx, ppEnum); + if (queryToExecute != strQuery) { + SysFreeString(queryToExecute); + } LOQ_hresult("system", "uu", "Query", strQuery, "QueryLanguage", strQueryLanguage); return ret; } @@ -232,8 +483,10 @@ HOOKDEF(HRESULT, WINAPI, WMI_ExecQueryAsync, _In_ IWbemObjectSink *pResponseHandler ) { HRESULT ret; + BSTR queryToExecute = (BSTR)strQuery; g_last_seen_disk_query = 0; g_last_seen_physicalmemory = 0; + g_last_seen_fake_class = WMI_FAKE_CLASS_NONE; if (strQuery) { if (!_wcsnicmp(strQuery, L"SELECT ", 7)) { @@ -243,9 +496,60 @@ HOOKDEF(HRESULT, WINAPI, WMI_ExecQueryAsync, else if (wcsistr(strQuery, L" FROM Win32_PhysicalMemory")) { g_last_seen_physicalmemory = 1; } + else if (wcsistr(strQuery, L" FROM Win32_Fan")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_FAN; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM Win32_CacheMemory")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CACHEMEMORY; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_Processor"); + } + else if (wcsistr(strQuery, L" FROM Win32_VoltageProbe")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_VOLTAGEPROBE; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM Win32_PortConnector")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_PORTCONNECTOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM Win32_ThermalZoneInfo")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_THERMALZONEINFO; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_Memory")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_MEMORY; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_Sensor")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_SENSOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_NumericSensor")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_NUMERICSENSOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_TemperatureSensor")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_TEMPERATURESENSOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_VoltageSensor")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_VOLTAGESENSOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_PhysicalConnector")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_PHYSICALCONNECTOR; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } + else if (wcsistr(strQuery, L" FROM CIM_Slot")) { + g_last_seen_fake_class = WMI_FAKE_CLASS_CIM_SLOT; + queryToExecute = SysAllocString(L"SELECT * FROM Win32_ComputerSystem"); + } } } - ret = Old_WMI_ExecQueryAsync(_this, strQueryLanguage, strQuery, lFlags, pCtx, pResponseHandler); + ret = Old_WMI_ExecQueryAsync(_this, strQueryLanguage, queryToExecute, lFlags, pCtx, pResponseHandler); + if (queryToExecute != strQuery) { + SysFreeString(queryToExecute); + } LOQ_hresult("system", "uu", "Query", strQuery, "QueryLanguage", strQueryLanguage); return ret; } diff --git a/hooks.c b/hooks.c index a23fb12b..29b3e3ce 100644 --- a/hooks.c +++ b/hooks.c @@ -1945,7 +1945,6 @@ int set_IWbemServices_hooks(PVOID pComObject, hook_t* hook) { return -1; } -extern __declspec(thread) BOOL bHookViaWbemLocator; void set_com_hooks(REFCLSID rclsid, REFIID riid, PVOID pComObject) { if (!com_hooks_initialized) { init_com_hooks(); diff --git a/hooks.h b/hooks.h index 7aaa0498..58edbcba 100644 --- a/hooks.h +++ b/hooks.h @@ -4211,4 +4211,8 @@ HOOKDEF(DWORD, WINAPI, MapFileAndCheckSumA, _Out_ PDWORD CheckSum ); +extern DWORD g_wmi_tls_index; +#define bHookViaWbemLocator ((BOOL)(ULONG_PTR)TlsGetValue(g_wmi_tls_index)) +#define SetHookViaWbemLocator(val) TlsSetValue(g_wmi_tls_index, (PVOID)(ULONG_PTR)(val)) + #include "hook_vbscript.h"