diff --git a/pafish/Makefile.linux b/pafish/Makefile.linux index 635b470..9178461 100644 --- a/pafish/Makefile.linux +++ b/pafish/Makefile.linux @@ -6,7 +6,7 @@ OBJ = Objects/MingW/main.o Objects/MingW/common.o Objects/MingW/utils.o Ob Objects/MingW/vbox.o Objects/MingW/gensandbox.o Objects/MingW/wine.o Objects/MingW/vmware.o \ Objects/MingW/qemu.o Objects/MingW/hooks.o Objects/MingW/cpu.o Objects/MingW/pafish_private.res LINKOBJ = $(OBJ) -LIBS = -lwsock32 -liphlpapi -lsetupapi -lmpr -s +LIBS = -lwsock32 -liphlpapi -lsetupapi -lmpr -lole32 -lwbemuuid -loleaut32 -s INCS = BIN = Output/MingW/pafish.exe CFLAGS = $(INCS) -Wall -Wextra -O0 diff --git a/pafish/Makefile.win b/pafish/Makefile.win index 92a6673..d1aed09 100644 --- a/pafish/Makefile.win +++ b/pafish/Makefile.win @@ -6,7 +6,7 @@ OBJ = Objects/MingW/main.o Objects/MingW/common.o Objects/MingW/utils.o Ob Objects/MingW/vbox.o Objects/MingW/gensandbox.o Objects/MingW/wine.o Objects/MingW/vmware.o \ Objects/MingW/qemu.o Objects/MingW/hooks.o Objects/MingW/cpu.o Objects/MingW/pafish_private.res LINKOBJ = $(OBJ) -LIBS = -lwsock32 -liphlpapi -lsetupapi -lmpr -s +LIBS = -lwsock32 -liphlpapi -lsetupapi -lmpr -lole32 -lwbemuuid -loleaut32 -s INCS = BIN = Output/MingW/pafish.exe CFLAGS = $(INCS) -Wall -Wextra -O0 diff --git a/pafish/gensandbox.c b/pafish/gensandbox.c index c4edca0..19f4023 100644 --- a/pafish/gensandbox.c +++ b/pafish/gensandbox.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "types.h" #include "gensandbox.h" diff --git a/pafish/main.c b/pafish/main.c index 630dfae..40fee64 100644 --- a/pafish/main.c +++ b/pafish/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "types.h" #include "common.h" @@ -367,6 +368,14 @@ int main(void) } else print_not_traced(); + printf("[*] Looking for VBox devices using WMI ... "); + if (vbox_wmi_devices() == TRUE) { + write_log("VirtualBox device identifiers traced using WMI"); + print_traced(); + write_trace("hi_virtualbox_wmi"); + } + else print_not_traced(); + /* VMware detection tricks */ printf("\n[-] VMware detection\n"); printf("[*] Scsi port 0,1,2 ->bus->target id->logical unit id-> 0 identifier ... "); @@ -417,6 +426,14 @@ int main(void) } else print_not_traced(); + printf("[*] Looking for VMware serial number ... "); + if (vmware_wmi_serial() == TRUE) { + write_log("VMware serial number traced using WMI"); + print_traced(); + write_trace("hi_vmware_wmi"); + } + else print_not_traced(); + /* Qemu detection tricks */ printf("\n[-] Qemu detection\n"); printf("[*] Scsi port->bus->target id->logical unit id-> 0 identifier ... "); diff --git a/pafish/qemu.c b/pafish/qemu.c index 9367612..0c40ae5 100644 --- a/pafish/qemu.c +++ b/pafish/qemu.c @@ -1,6 +1,7 @@ #include #include +#include #include "qemu.h" #include "types.h" diff --git a/pafish/utils.c b/pafish/utils.c index bace44e..c741c9d 100644 --- a/pafish/utils.c +++ b/pafish/utils.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "utils.h" #include "types.h" @@ -177,3 +178,106 @@ int pafish_check_mac_vendor(char * mac_vendor) { return res; } +/** + * Initialise the WMI client that will connect to the local machine WMI + * namespace. It will return TRUE if the connection was successful, FALSE + * otherwise. + */ +int wmi_initialize(const wchar_t *query_namespace, IWbemServices **services) { + BSTR namespace; + IWbemLocator *locator = NULL; + int result; + + HRESULT hresult = CoInitializeEx(0, COINIT_MULTITHREADED); + + if (FAILED(hresult)) { + return FALSE; + } + + hresult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, + RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); + + if (FAILED(hresult)) { + CoUninitialize(); + + return FALSE; + } + + hresult = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, + &IID_IWbemLocator, (LPVOID *) & locator); + + if (FAILED(hresult)) { + CoUninitialize(); + + return FALSE; + } + + namespace = SysAllocString(query_namespace); + + // Connect to the namespace with the current user and obtain pointer + // services to make IWbemServices calls. + hresult = locator->lpVtbl->ConnectServer(locator, namespace, NULL, NULL, NULL, 0, + NULL, NULL, services); + + result = FAILED(hresult) ? FALSE : TRUE; + + SysFreeString(namespace); + locator->lpVtbl->Release(locator); + + return result; +} + +/** + * Execute the suplied WMI query and call the row checking function for each row returned. + */ +int wmi_check_query(IWbemServices *services, const wchar_t *language, const wchar_t *query, + wmi_check_row check_row) { + int status = FALSE; + IEnumWbemClassObject *queryrows = NULL; + IWbemClassObject * batchrows[10]; + BSTR wmilang = SysAllocString(language); + BSTR wmiquery = SysAllocString(query); + + // Execute the query. + HRESULT result = services->lpVtbl->ExecQuery( + services, wmilang, wmiquery, WBEM_FLAG_BIDIRECTIONAL, NULL, &queryrows); + + if (!FAILED(result) && (queryrows != NULL)) { + ULONG index, count = 0; + result = WBEM_S_NO_ERROR; + + while (WBEM_S_NO_ERROR == result && status == FALSE) { + // Retrieve 10 rows (instances) each time. + result = queryrows->lpVtbl->Next(queryrows, WBEM_INFINITE, 10, + batchrows, &count); + + if (!SUCCEEDED(result)) { + continue; + } + + for (index = 0; index < count && status == FALSE; index++) { + status = check_row(batchrows[index]); + + batchrows[index]->lpVtbl->Release(batchrows[index]); + } + } + + queryrows->lpVtbl->Release(queryrows); + } + + SysFreeString(wmiquery); + SysFreeString(wmilang); + + return status; +} + +/** + * Cleanup WMI. + */ +void wmi_cleanup(IWbemServices *services) { + if (services != NULL) { + services->lpVtbl->Release(services); + } + + CoUninitialize(); +} diff --git a/pafish/utils.h b/pafish/utils.h index 5dc4cc6..7e8dda0 100644 --- a/pafish/utils.h +++ b/pafish/utils.h @@ -16,4 +16,17 @@ inline int pafish_exists_file(char * filename); int pafish_check_mac_vendor(char * mac_vendor); +/** + * Prototype for the WMI caller implemented function for checking the + * WMI query results. + */ +typedef int (*wmi_check_row) (IWbemClassObject *); + +int wmi_initialize(const wchar_t *, IWbemServices **); + +int wmi_check_query(IWbemServices *, const wchar_t *, const wchar_t *, + wmi_check_row check_row); + +void wmi_cleanup(IWbemServices *); + #endif diff --git a/pafish/vbox.c b/pafish/vbox.c index 85ed12c..84b0463 100644 --- a/pafish/vbox.c +++ b/pafish/vbox.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "vbox.h" #include "utils.h" @@ -251,3 +252,36 @@ int vbox_processes(int writelogs) { return res; } +/** + * Check if the device identifier ("PCI\\VEN_80EE&DEV_CAFE") in the returned rows. + */ +int vbox_wmi_check_row(IWbemClassObject *row) { + CIMTYPE type = CIM_ILLEGAL; + VARIANT value; + + HRESULT hresult = row->lpVtbl->Get(row, L"DeviceId", 0, &value, &type, 0); + + if (FAILED(hresult) || V_VT(&value) == VT_NULL || type != CIM_STRING) { + return FALSE; + } + + return (wcsstr(V_BSTR(&value), L"PCI\\VEN_80EE&DEV_CAFE") != NULL) ? TRUE : FALSE; +} + +/** + * Check for devices VirtualBox devices using WMI. + */ +int vbox_wmi_devices() { + IWbemServices *services = NULL; + + if (wmi_initialize(L"root\\cimv2", &services) != TRUE) { + return FALSE; + } + + int result = wmi_check_query(services, L"WQL", L"SELECT DeviceId FROM Win32_PnPEntity", + &vbox_wmi_check_row); + + wmi_cleanup(services); + + return result; +} diff --git a/pafish/vbox.h b/pafish/vbox.h index 7721220..1da7df0 100644 --- a/pafish/vbox.h +++ b/pafish/vbox.h @@ -25,4 +25,6 @@ int vbox_network_share(); int vbox_processes(int writelogs); +int vbox_wmi_devices(); + #endif diff --git a/pafish/vmware.c b/pafish/vmware.c index cda2a3c..f6feb0e 100644 --- a/pafish/vmware.c +++ b/pafish/vmware.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "vmware.h" #include "types.h" @@ -74,3 +75,37 @@ int vmware_devices(int writelogs) { } return res; } + +/** + * Check the serial number ("VMware") in the returned rows. + */ +int vmware_wmi_check_row(IWbemClassObject *row) { + CIMTYPE type = CIM_ILLEGAL; + VARIANT value; + + HRESULT hresult = row->lpVtbl->Get(row, L"SerialNumber", 0, &value, &type, 0); + + if (FAILED(hresult) || V_VT(&value) == VT_NULL || type != CIM_STRING) { + return FALSE; + } + + return (wcsstr(V_BSTR(&value), L"VMware") != NULL) ? TRUE : FALSE; +} + +/** + * Check for the computer serial using WMI. + */ +int vmware_wmi_serial() { + IWbemServices *services = NULL; + + if (wmi_initialize(L"root\\cimv2", &services) != TRUE) { + return FALSE; + } + + int result = wmi_check_query(services, L"WQL", L"SELECT SerialNumber FROM Win32_Bios", + &vmware_wmi_check_row); + + wmi_cleanup(services); + + return result; +} diff --git a/pafish/vmware.h b/pafish/vmware.h index 0802019..e75be74 100644 --- a/pafish/vmware.h +++ b/pafish/vmware.h @@ -14,4 +14,6 @@ int vmware_mac(); int vmware_devices(); +int vmware_wmi_serial(); + #endif diff --git a/pafish/wine.c b/pafish/wine.c index 8ec08c5..f2c2e8e 100644 --- a/pafish/wine.c +++ b/pafish/wine.c @@ -1,5 +1,6 @@ #include +#include #include "wine.h" #include "types.h"