Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions capemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ void init_private_heap(void)
}

extern CRITICAL_SECTION readfile_critsec, g_mutex, g_writing_log_buffer_mutex, g_interactive_debugger_lock;
lookup_t g_wmi_locator_lookup;
BOOLEAN g_dll_main_complete;
OSVERSIONINFOA g_osverinfo;

Expand Down Expand Up @@ -608,6 +609,9 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
// read the config settings
read_config();

// initialize dynamic polymorphic WMI spoofing strings
InitWmiSpoofStrings();

if (g_config.standalone) {
// initialize these because some hooks behave badly when they are empty
if (!g_config.w_analyzer[0]) {
Expand Down
35 changes: 35 additions & 0 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,34 @@ void parse_config_line(char* line)
if (g_config.hook_watch)
DebugOutput("Config: Hook watch enabled.\n");
}
else if (!stricmp(key, "wmi-board-vendor")) {
strncpy_s(g_config.board_vendor, _countof(g_config.board_vendor), value, _TRUNCATE);
DebugOutput("Config: WMI board vendor set to %s.\n", g_config.board_vendor);
}
else if (!stricmp(key, "wmi-board-product")) {
strncpy_s(g_config.board_product, _countof(g_config.board_product), value, _TRUNCATE);
DebugOutput("Config: WMI board product set to %s.\n", g_config.board_product);
}
else if (!stricmp(key, "wmi-board-serial")) {
strncpy_s(g_config.board_serial, _countof(g_config.board_serial), value, _TRUNCATE);
DebugOutput("Config: WMI board serial set to %s.\n", g_config.board_serial);
}
else if (!stricmp(key, "wmi-disk-model")) {
strncpy_s(g_config.disk_model, _countof(g_config.disk_model), value, _TRUNCATE);
DebugOutput("Config: WMI disk model set to %s.\n", g_config.disk_model);
}
else if (!stricmp(key, "wmi-disk-serial")) {
strncpy_s(g_config.disk_serial, _countof(g_config.disk_serial), value, _TRUNCATE);
DebugOutput("Config: WMI disk serial set to %s.\n", g_config.disk_serial);
}
else if (!stricmp(key, "wmi-bios-vendor")) {
strncpy_s(g_config.bios_vendor, _countof(g_config.bios_vendor), value, _TRUNCATE);
DebugOutput("Config: WMI BIOS vendor set to %s.\n", g_config.bios_vendor);
}
else if (!stricmp(key, "wmi-bios-serial")) {
strncpy_s(g_config.bios_serial, _countof(g_config.bios_serial), value, _TRUNCATE);
DebugOutput("Config: WMI BIOS serial set to %s.\n", g_config.bios_serial);
}
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);
Expand Down Expand Up @@ -1504,6 +1532,13 @@ void read_config(void)
g_config.loaderlock_scans = 1;
g_config.spoofed_cpu_count = SPOOFED_CPU_CORE_NUM;
g_config.syscall = 1;
strncpy_s(g_config.board_vendor, _countof(g_config.board_vendor), "ASUSTeK COMPUTER INC.", _TRUNCATE);
strncpy_s(g_config.board_product, _countof(g_config.board_product), "PRIME Z390-A", _TRUNCATE);
strncpy_s(g_config.board_serial, _countof(g_config.board_serial), "190442345001294", _TRUNCATE);
strncpy_s(g_config.disk_model, _countof(g_config.disk_model), "Samsung SSD 860 EVO 500GB", _TRUNCATE);
strncpy_s(g_config.disk_serial, _countof(g_config.disk_serial), "S3Y1NX0K412941X", _TRUNCATE);
strncpy_s(g_config.bios_vendor, _countof(g_config.bios_vendor), "American Megatrends Inc.", _TRUNCATE);
strncpy_s(g_config.bios_serial, _countof(g_config.bios_serial), "System Serial Number", _TRUNCATE);
g_config.sleep_skip_seconds = 10;

StepLimit = SINGLE_STEP_LIMIT;
Expand Down
7 changes: 7 additions & 0 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,13 @@ struct _g_config {
int trace_times;
char *trace_into_api[EXCLUSION_MAX];
int hook_watch;
char board_vendor[128];
char board_product[128];
char board_serial[128];
char disk_model[128];
char disk_serial[128];
char bios_vendor[128];
char bios_serial[128];
int sleep_skip_seconds;
};

Expand Down
7 changes: 7 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ 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-board-vendor` | String | Spoof the motherboard manufacturer returned via WMI Win32_BaseBoard queries (default: "ASUSTeK COMPUTER INC."). |
| `wmi-board-product` | String | Spoof the motherboard product model returned via WMI Win32_BaseBoard queries (default: "PRIME Z390-A"). |
| `wmi-board-serial` | String | Spoof the motherboard serial number returned via WMI Win32_BaseBoard queries (default: "190442345001294"). |
| `wmi-disk-model` | String | Spoof the physical disk drive model returned via WMI Win32_DiskDrive queries (default: "Samsung SSD 860 EVO 500GB"). |
| `wmi-disk-serial` | String | Spoof the physical disk drive serial number returned via WMI Win32_DiskDrive queries (default: "S3Y1NX0K412941X"). |
| `wmi-bios-vendor` | String | Spoof the BIOS manufacturer returned via WMI Win32_BIOS queries (default: "American Megatrends Inc."). |
| `wmi-bios-serial` | String | Spoof the BIOS serial number returned via WMI Win32_BIOS queries (default: "System Serial Number"). |
| `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. |
Expand Down
6 changes: 3 additions & 3 deletions hook_com.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
Expand Down
92 changes: 92 additions & 0 deletions hook_wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,60 @@
#include "config.h"
#include <Wbemidl.h>

static BSTR g_wmi_board_vendor = NULL;
static BSTR g_wmi_board_product = NULL;
static BSTR g_wmi_board_serial = NULL;
static BSTR g_wmi_disk_model = NULL;
static BSTR g_wmi_disk_serial = NULL;
static BSTR g_wmi_bios_vendor = NULL;
static BSTR g_wmi_bios_serial = NULL;

void InitWmiSpoofStrings(void) {
int len;

len = MultiByteToWideChar(CP_ACP, 0, g_config.board_vendor, -1, NULL, 0);
if (len > 0) {
g_wmi_board_vendor = SysAllocStringLen(NULL, len - 1);
MultiByteToWideChar(CP_ACP, 0, g_config.board_vendor, -1, g_wmi_board_vendor, len);
}

len = MultiByteToWideChar(CP_ACP, 0, g_config.board_product, -1, NULL, 0);
if (len > 0) {
g_wmi_board_product = SysAllocStringLen(NULL, len - 1);
MultiByteToWideChar(CP_ACP, 0, g_config.board_product, -1, g_wmi_board_product, len);
}

len = MultiByteToWideChar(CP_ACP, 0, g_config.board_serial, -1, NULL, 0);
if (len > 0) {
g_wmi_board_serial = SysAllocStringLen(NULL, len - 1);
MultiByteToWideChar(CP_ACP, 0, g_config.board_serial, -1, g_wmi_board_serial, len);
}

len = MultiByteToWideChar(CP_ACP, 0, g_config.disk_model, -1, NULL, 0);
if (len > 0) {
g_wmi_disk_model = SysAllocStringLen(NULL, len - 1);
MultiByteToWideChar(CP_ACP, 0, g_config.disk_model, -1, g_wmi_disk_model, len);
}

len = MultiByteToWideChar(CP_ACP, 0, g_config.disk_serial, -1, NULL, 0);
if (len > 0) {
g_wmi_disk_serial = SysAllocStringLen(NULL, len - 1);
MultiByteToWideChar(CP_ACP, 0, g_config.disk_serial, -1, g_wmi_disk_serial, len);
}

len = MultiByteToWideChar(CP_ACP, 0, g_config.bios_vendor, -1, NULL, 0);
if (len > 0) {
g_wmi_bios_vendor = SysAllocStringLen(NULL, len - 1);
MultiByteToWideChar(CP_ACP, 0, g_config.bios_vendor, -1, g_wmi_bios_vendor, len);
}

len = MultiByteToWideChar(CP_ACP, 0, g_config.bios_serial, -1, NULL, 0);
if (len > 0) {
g_wmi_bios_serial = SysAllocStringLen(NULL, len - 1);
MultiByteToWideChar(CP_ACP, 0, g_config.bios_serial, -1, g_wmi_bios_serial, len);
}
}

void SpoofWmiData(const wchar_t* szClassName, const wchar_t* wszName, VARIANT* pVal) {
if (g_config.no_stealth)
return;
Expand Down Expand Up @@ -50,6 +104,44 @@ void SpoofWmiData(const wchar_t* szClassName, const wchar_t* wszName, VARIANT* p
pVal->bstrVal = SysAllocString(WIDE_SPOOFED_RAM);
}
}
else if (!_wcsicmp(szClassName, L"Win32_BaseBoard")) {
if (!_wcsicmp(wszName, L"Manufacturer") && g_wmi_board_vendor) {
SysFreeString(pVal->bstrVal);
pVal->bstrVal = SysAllocString(g_wmi_board_vendor);
}
else if (!_wcsicmp(wszName, L"Product") && g_wmi_board_product) {
SysFreeString(pVal->bstrVal);
pVal->bstrVal = SysAllocString(g_wmi_board_product);
}
else if (!_wcsicmp(wszName, L"SerialNumber") && g_wmi_board_serial) {
SysFreeString(pVal->bstrVal);
pVal->bstrVal = SysAllocString(g_wmi_board_serial);
}
}
else if (!_wcsicmp(szClassName, L"Win32_DiskDrive")) {
if (!_wcsicmp(wszName, L"Model") && g_wmi_disk_model) {
SysFreeString(pVal->bstrVal);
pVal->bstrVal = SysAllocString(g_wmi_disk_model);
}
else if (!_wcsicmp(wszName, L"SerialNumber") && g_wmi_disk_serial) {
SysFreeString(pVal->bstrVal);
pVal->bstrVal = SysAllocString(g_wmi_disk_serial);
}
}
else if (!_wcsicmp(szClassName, L"Win32_BIOS")) {
if (!_wcsicmp(wszName, L"Manufacturer") && g_wmi_bios_vendor) {
SysFreeString(pVal->bstrVal);
pVal->bstrVal = SysAllocString(g_wmi_bios_vendor);
}
else if (!_wcsicmp(wszName, L"SerialNumber") && g_wmi_bios_serial) {
SysFreeString(pVal->bstrVal);
pVal->bstrVal = SysAllocString(g_wmi_bios_serial);
}
else if (!_wcsicmp(wszName, L"ReleaseDate")) {
SysFreeString(pVal->bstrVal);
pVal->bstrVal = SysAllocString(L"20220412000000.000000+000");
}
}
}
//
// Spoofery logic for I4 (Signed 32-bit integer)
Expand Down
1 change: 0 additions & 1 deletion hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -1949,7 +1949,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();
Expand Down
11 changes: 10 additions & 1 deletion hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <tlhelp32.h>
#include <ncrypt.h>
#include "hook_trace.h"
#include "lookup.h"
#include <Wbemidl.h>

#pragma comment(lib, "wbemuuid.lib")
Expand Down Expand Up @@ -1331,7 +1332,7 @@ HOOKDEF(HRESULT, WINAPI, WMI_Get,
HOOKDEF(HRESULT, WINAPI, WMI_Next,
_In_ PVOID _this,
_In_ LONG lFlags,
_Out_ BSTR wszName,
_Out_ BSTR *strName,
_Out_ VARIANT *pVal,
_Out_opt_ CIMTYPE *pType,
_Out_opt_ LONG *plFlavor
Expand Down Expand Up @@ -4224,4 +4225,12 @@ HOOKDEF(DWORD, WINAPI, MapFileAndCheckSumA,
_Out_ PDWORD CheckSum
);

void InitWmiSpoofStrings(void);

// Per-thread "hooking via IWbemLocator" flag. Uses the lock-free lookup table
// (LOOKUP_THREAD idiom) instead of TLS, matching the SafeLookup convention.
extern lookup_t g_wmi_locator_lookup;
#define bHookViaWbemLocator (*(BOOL *)LOOKUP_THREAD(&g_wmi_locator_lookup, BOOL))
#define SetHookViaWbemLocator(val) (bHookViaWbemLocator = (BOOL)(val))

#include "hook_vbscript.h"