diff --git a/.github/workflows/build_run_win_32_debug.bat b/.github/workflows/build_run_win_32_debug.bat index 57d07df..ffa0176 100644 --- a/.github/workflows/build_run_win_32_debug.bat +++ b/.github/workflows/build_run_win_32_debug.bat @@ -8,5 +8,4 @@ copy "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\VC\Redist\M copy "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\VC\Redist\MSVC\14.30.30704\debug_nonredist\x86\Microsoft.VC143.DebugCRT\vcruntime140d.dll" Debug\ copy "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\VC\Redist\MSVC\14.30.30704\debug_nonredist\x86\Microsoft.VC143.DebugCRT\msvcp140d.dll" Debug\ cd Debug -vmaware.exe -vmaware.exe --disable-hyperv-host \ No newline at end of file +vmaware.exe \ No newline at end of file diff --git a/.github/workflows/build_run_win_64_debug.bat b/.github/workflows/build_run_win_64_debug.bat index 1c6154a..f3b0c05 100644 --- a/.github/workflows/build_run_win_64_debug.bat +++ b/.github/workflows/build_run_win_64_debug.bat @@ -8,5 +8,4 @@ copy "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\VC\Redist\M copy "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\VC\Redist\MSVC\14.30.30704\debug_nonredist\x86\Microsoft.VC143.DebugCRT\vcruntime140d.dll" Debug\ copy "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\VC\Redist\MSVC\14.30.30704\debug_nonredist\x86\Microsoft.VC143.DebugCRT\msvcp140d.dll" Debug\ cd Debug -vmaware.exe -vmaware.exe --disable-hyperv-host \ No newline at end of file +vmaware.exe \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index ff2963d..81f9543 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Od") elseif(CMAKE_BUILD_TYPE MATCHES "Release") MESSAGE(STATUS "Build set to release mode") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O3") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2") endif() elseif(LINUX) if(CMAKE_BUILD_TYPE MATCHES "Debug") diff --git a/TODO.md b/TODO.md index 41982f0..245ae0d 100644 --- a/TODO.md +++ b/TODO.md @@ -41,6 +41,7 @@ - [ ] maybe add internal is_cached functionalities in the cache fetchers - [ ] make the whole cache table into a mutex so i can claim it's thread-safe - [ ] make a medium post about it +- [ ] test the VM::modify_score() function # Distant plans - add the library to conan.io when released diff --git a/assets/hyperv_fucker.png b/assets/hyperv_fucker.png new file mode 100644 index 0000000..d7f6178 Binary files /dev/null and b/assets/hyperv_fucker.png differ diff --git a/docs/documentation.md b/docs/documentation.md index 5cda705..c16d236 100644 --- a/docs/documentation.md +++ b/docs/documentation.md @@ -199,6 +199,8 @@ This will essentially return the VM brand as a `std::string`. The exact possible - `Intel KGT (Trusty)` - `Microsoft Azure Hyper-V` - `Xbox NanoVisor (Hyper-V)` +- `SimpleVisor` +- `Hyper-V artifact (not an actual VM)` If none were detected, it will return `Unknown`. It's often NOT going to produce a satisfying result due to technical difficulties with accomplishing this, on top of being highly dependent on what mechanisms detected a VM. This is especially true for VMware sub-versions (ESX, GSX, Fusion, etc...) Don't rely on this function for critical operations as if it's your golden bullet. It's arguably unreliable and it'll most likely return `Unknown` (assuming it is actually running under a VM). @@ -322,108 +324,108 @@ VM::add_custom(50, new_technique); VMAware provides a convenient way to not only check for VMs, but also have the flexibility and freedom for the end-user to choose what techniques are used with complete control over what gets executed or not. This is handled with a flag system. -| Flag alias | Description | Cross-platform? (empty = yes) | Certainty | Admin? | GPL-3.0? | 32-bit? | -| ---------- | ----------- | --------------- | --------- | ------ | -------- | ------- | -| `VM::VMID` | Check CPUID output of manufacturer ID for known VMs/hypervisors at leaf 0 | | 100% | | | | -| `VM::CPU_BRAND` | Check if CPU brand model contains any VM-specific string snippets | | 50% | | | | -| `VM::HYPERVISOR_BIT` | Check if hypervisor feature bit in CPUID eax bit 31 is enabled (always false for physical CPUs) | | 100% | | | | -| `VM::HYPERVISOR_STR` | Check for hypervisor brand string length (would be around 2 characters in a host machine) | | 45% | | | | -| `VM::RDTSC` | Benchmark RDTSC and evaluate its speed, usually it's very slow in VMs | Linux and Windows | 10% | | | | -| `VM::THREADCOUNT` | Check if there are only 1 or 2 threads, which is a common pattern in VMs with default settings (nowadays physical CPUs should have at least 4 threads for modern CPUs) | | 35% | | | | -| `VM::MAC` | Check if mac address starts with certain VM designated values | Linux and Windows | 60% | | | | -| `VM::TEMPERATURE` | Check if thermal directory in linux is present, might not be present in VMs | Linux | 15% | | | -| `VM::SYSTEMD` | Check result from systemd-detect-virt tool | Linux | 70% | | | | -| `VM::CVENDOR` | Check if the chassis vendor is a VM vendor | Linux | 65% | | | | -| `VM::CTYPE` | Check if the chassis type is valid (it's very often invalid in VMs) | Linux | 10% | | | | -| `VM::DOCKERENV` | Check if /.dockerenv or /.dockerinit file is present | Linux | 80% | | | | -| `VM::DMIDECODE` | Check if dmidecode output matches a VM brand | Linux | 55% | Admin | | | -| `VM::DMESG` | Check if dmesg output matches a VM brand | Linux | 55% | Admin | | | -| `VM::HWMON` | Check if /sys/class/hwmon/ directory is present. If not, likely a VM | Linux | 75% | | | | -| `VM::SIDT5` | Check if the 5th byte after sidt is null | Linux | 45% | | | | -| `VM::CURSOR` | Check if cursor isn't active for 5 seconds (sign of automated VM environment) | Windows | 5% | | | | -| `VM::VMWARE_REG` | Check for VBox RdrDN | Windows | 65% | | | | -| `VM::VBOX_REG` | Look for any VirtualBox-specific registry data | Windows | 65% | | | | -| `VM::USER` | checks for default usernames, often a sign of a VM | Windows | 35% | | | | -| `VM::DLL` | Check for VM-specific DLLs | Windows | 50% | | | | -| `VM::REGISTRY` | Check for VM-specific registry values | Windows | 75% | | | | -| `VM::CWSANDBOX_VM` | Check if CWSandbox-specific file exists | Windows | 10% | | | | -| `VM::VM_FILES` | Find for VMware and VBox specific files | Windows | 10% | | | | -| `VM::HWMODEL` | Check if the sysctl for the hwmodel does not contain the "Mac" string | MacOS | 75% | | | | -| `VM::DISK_SIZE` | Check if disk size is under or equal to 50GB | Linux | 60% | | | | -| `VM::VBOX_DEFAULT` | Check for default RAM and DISK sizes set by VirtualBox | Linux and Windows | 55% | Admin | | | -| `VM::VBOX_NETWORK` | Check for VirtualBox network provider string | Windows | 70% | | | | -| `VM::COMPUTER_NAME` | Check if the computer name (not username to be clear) is VM-specific | Windows | 40% | | GPL | | -| `VM::WINE_CHECK` | Check wine_get_unix_file_name file for Wine | Windows | 85% | | GPL | | -| `VM::HOSTNAME` | Check if hostname is specific | Windows | 25% | | GPL | | -| `VM::MEMORY` | Check if memory space is far too low for a physical machine | Windows | 35% | | GPL | | -| `VM::VBOX_WINDOW_CLASS` | Check for the window class for VirtualBox | Windows | 10% | | GPL | | -| `VM::LOADED_DLLS` | Check for loaded DLLs in the process | Windows | 75% | | GPL | | -| `VM::KVM_REG` | Check for KVM-specific registry strings | Windows | 75% | | GPL | | -| `VM::KVM_DRIVERS` | Check for KVM-specific .sys files in system driver directory | Windows | 55% | | GPL | | -| `VM::KVM_DIRS` | Check for KVM directory "Virtio-Win" | Windows | 55% | | GPL | | -| `VM::AUDIO` | Check if audio device is present | Windows | 35% | | GPL | | -| `VM::QEMU_DIR` | Check for QEMU-specific blacklisted directories | Windows | 45% | | GPL | | -| `VM::MOUSE_DEVICE` | Check for the presence of a mouse device | Windows | 20% | | GPL | | -| `VM::VM_PROCESSES` | Check for any VM processes that are active | Windows | 30% | | | | -| `VM::LINUX_USER_HOST` | Check for default VM username and hostname for linux | Linux | 25% | | | | -| `VM::GAMARUE` | Check for Gamarue ransomware technique which compares VM-specific Window product IDs | Windows | 40% | | | | -| `VM::VMID_0X4` | Check if the CPU manufacturer ID matches that of a VM brand with leaf 0x40000000 | | 100% | | | | -| `VM::PARALLELS_VM` | Check for any indication of Parallels VM through BIOS data | Windows | 50% | | | | -| `VM::RDTSC_VMEXIT` | check through alternative RDTSC technique with VMEXIT | | 25% | | | | -| `VM::QEMU_BRAND` | Match for QEMU CPU brands with "QEMU Virtual CPU" string | | 100% | | | | -| `VM::BOCHS_CPU` | Check for various Bochs-related emulation oversights through CPU checks | | 95% | | | | -| `VM::VPC_BOARD` | Check through the motherboard and match for VirtualPC-specific string | Windows | 20% | | | | -| `VM::HYPERV_WMI` | Check WMI query for "Hyper-V RAW" string | Windows | 80% | | | | -| `VM::HYPERV_REG` | Check presence for Hyper-V specific string in registry | Windows | 80% | | | | -| `VM::BIOS_SERIAL` | Check if the BIOS serial is valid (null = VM) | Windows | 60% | | | | -| `VM::VBOX_FOLDERS` | Check for VirtualBox-specific string for shared folder ID | Windows | 45% | | | | -| `VM::MSSMBIOS` | Check MSSMBIOS registry for VM-specific strings | Windows | 75% | | | | -| `VM::MAC_MEMSIZE` | Check if memory is too low for MacOS system | MacOS | 30% | | | | -| `VM::MAC_IOKIT` | Check MacOS' IO kit registry for VM-specific strings | MacOS | 80% | | | | -| `VM::IOREG_GREP` | Check for VM-strings in ioreg commands for MacOS | MacOS | 75% | | | | -| `VM::MAC_SIP` | Check if System Integrity Protection is disabled (likely a VM if it is) | MacOS | 85% | | | | -| `VM::HKLM_REGISTRIES` | Check HKLM registries for specific VM strings | Windows | 70% | | | | -| `VM::QEMU_GA` | Check for "qemu-ga" process | Linux | 20% | | | | -| `VM::VALID_MSR` | check for valid MSR value 0x40000000 | Windows | 35% | | | | -| `VM::QEMU_PROC` | Check for QEMU processes | Windows | 30% | | | | -| `VM::VPC_PROC` | Check for VPC processes | Windows | 30% | | | | -| `VM::VPC_INVALID` | Check for official VPC method | Windows | 75% | | | 32-bit | -| `VM::SIDT` | Check for sidt instruction method | Linux, Windows | 30% | | | | -| `VM::SGDT` | Check for sgdt instruction method | Windows | 30% | | | 32-bit | -| `VM::SLDT` | Check for sldt instruction method | Windows | 15% | | | 32-bit | -| `VM::OFFSEC_SIDT` | Check for Offensive Security SIDT method | Windows | 60% | | | 32-bit | -| `VM::OFFSEC_SGDT` | Check for Offensive Security SGDT method | Windows | 60% | | | 32-bit | -| `VM::OFFSEC_SLDT` | Check for Offensive Security SLDT method | Windows | 20% | | | 32-bit | -| `VM::HYPERV_BOARD` | Check for Hyper-V specific string in motherboard | Windows | 45% | | | | -| `VM::VM_FILES_EXTRA` | Check for VPC and Parallels files | Windows | 70% | | | | -| `VM::VPC_SIDT` | Check for sidt method with VPC's 0xE8XXXXXX range | Windows | 15% | | | 32-bit | -| `VM::VMWARE_IOMEM` | Check for VMware string in /proc/iomem | Linux | 65% | | | | -| `VM::VMWARE_IOPORTS` | Check for VMware string in /proc/ioports | Linux | 70% | | | | -| `VM::VMWARE_SCSI` | Check for VMware string in /proc/scsi/scsi | Linux | 40% | | | | -| `VM::VMWARE_DMESG` | Check for VMware-specific device name in dmesg output | Linux | 65% | Admin | | | -| `VM::VMWARE_STR` | Check str assembly instruction method for VMware | Windows | 35% | | | | -| `VM::VMWARE_BACKDOOR` | Check for official VMware io port backdoor technique | Windows | 100% | | | 32-bit | -| `VM::VMWARE_PORT_MEM` | Check for VMware memory using IO port backdoor | Windows | 85% | | | 32-bit | -| `VM::SMSW` | Check for SMSW assembly instruction technique | Windows | 30% | | | 32-bit | -| `VM::MUTEX` | Check for mutex strings of VM brands | Windows | 85% | | | | -| `VM::UPTIME` | Check if uptime is less than or equal to 2 minutes | | 10% | | | | -| `VM::ODD_CPU_THREADS` | Check for odd CPU threads, usually a sign of modification through VM setting because 99% of CPUs have even numbers of threads | | 80% | | | | -| `VM::INTEL_THREAD_MISMATCH` | Check for Intel CPU thread count database if it matches the system's thread count | | 85% | | | | -| `VM::XEON_THREAD_MISMATCH` | Same as above, but for Xeon Intel CPUs | | 85% | | | | -| `VM::NETTITUDE_VM_MEMORY` | Check for memory regions to detect VM-specific brands | Windows | 75% | | | | -| `VM::CPUID_BITSET` | Check for CPUID technique by checking whether all the bits equate to more than 4000 | | 20% | | | | -| `VM::CUCKOO_DIR` | Check for cuckoo directory using crt and WIN API directory functions | Windows | 15% | | | | -| `VM::CUCKOO_PIPE` | Check for Cuckoo specific piping mechanism | Windows | 20% | | | | -| `VM::HYPERV_HOSTNAME` | Check for default Azure hostname format regex (Azure uses Hyper-V as their base VM brand) | Windows, Linux | 50% | | | | -| `VM::GENERAL_HOSTNAME` | Check for commonly set hostnames by certain VM brands | Windows, Linux | 20% | | | | -| `VM::SCREEN_RESOLUTION` | Check for pre-set screen resolutions commonly found in VMs | Windows | 10% | | | | -| `VM::DEVICE_STRING` | Check if bogus device string would be accepted | Windows | 25% | | | | -| `VM::BLUESTACKS_FOLDERS` | Check for the presence of BlueStacks-specific folders | Linux | 15% | | | | -| `VM::CPUID_SIGNATURE` | Check for signatures in leaf 0x40000001 in CPUID | | 95% | | | | -| `VM::HYPERV_BITMASK` | Check for Hyper-V CPUID bitmask range for reserved values | | 20% | | | | -| `VM::KVM_BITMASK` | Check for KVM CPUID bitmask range for reserved values | | 40% | | | | -| `VM::KGT_SIGNATURE` | Check for Intel KGT (Trusty branch) hypervisor signature in CPUID | | 80% | | | | -| `VM::VMWARE_DMI` | Check for VMware DMI strings in BIOS serial number | Windows | 30% | | | | +| Flag alias | Description | Cross-platform? (empty = yes) | Certainty | Admin? | GPL-3.0? | 32-bit? | Notes | +| ---------- | ----------- | ----------------------------- | --------- | ------ | -------- | ------- | ----- | +| `VM::VMID` | Check CPUID output of manufacturer ID for known VMs/hypervisors at leaf 0 | | 100% | | | | | +| `VM::CPU_BRAND` | Check if CPU brand model contains any VM-specific string snippets | | 50% | | | | | +| `VM::HYPERVISOR_BIT` | Check if hypervisor feature bit in CPUID eax bit 31 is enabled (always false for physical CPUs) | | 100% | | | | | +| `VM::HYPERVISOR_STR` | Check for hypervisor brand string length (would be around 2 characters in a host machine) | | 45% | | | | | +| `VM::RDTSC` | Benchmark RDTSC and evaluate its speed, usually it's very slow in VMs | Linux and Windows | 10% | | | | Disabled by default | +| `VM::THREADCOUNT` | Check if there are only 1 or 2 threads, which is a common pattern in VMs with default settings (nowadays physical CPUs should have at least 4 threads for modern CPUs) | | 35% | | | | | +| `VM::MAC` | Check if mac address starts with certain VM designated values | Linux and Windows | 60% | | | | | +| `VM::TEMPERATURE` | Check if thermal directory in linux is present, might not be present in VMs | Linux | 15% | | | | +| `VM::SYSTEMD` | Check result from systemd-detect-virt tool | Linux | 70% | | | | | +| `VM::CVENDOR` | Check if the chassis vendor is a VM vendor | Linux | 65% | | | | | +| `VM::CTYPE` | Check if the chassis type is valid (it's very often invalid in VMs) | Linux | 10% | | | | | +| `VM::DOCKERENV` | Check if /.dockerenv or /.dockerinit file is present | Linux | 80% | | | | | +| `VM::DMIDECODE` | Check if dmidecode output matches a VM brand | Linux | 55% | Admin | | | | +| `VM::DMESG` | Check if dmesg output matches a VM brand | Linux | 55% | Admin | | | | +| `VM::HWMON` | Check if /sys/class/hwmon/ directory is present. If not, likely a VM | Linux | 75% | | | | | +| `VM::SIDT5` | Check if the 5th byte after sidt is null | Linux | 45% | | | | | +| `VM::CURSOR` | Check if cursor isn't active for 5 seconds (sign of automated VM environment) | Windows | 5% | | | | Disabled by default | +| `VM::VMWARE_REG` | Check for VBox RdrDN | Windows | 65% | | | | | +| `VM::VBOX_REG` | Look for any VirtualBox-specific registry data | Windows | 65% | | | | | +| `VM::USER` | checks for default usernames, often a sign of a VM | Windows | 35% | | | | | +| `VM::DLL` | Check for VM-specific DLLs | Windows | 50% | | | | | +| `VM::REGISTRY` | Check for VM-specific registry values | Windows | 75% | | | | | +| `VM::CWSANDBOX_VM` | Check if CWSandbox-specific file exists | Windows | 10% | | | | | +| `VM::VM_FILES` | Find for VMware and VBox specific files | Windows | 10% | | | | | +| `VM::HWMODEL` | Check if the sysctl for the hwmodel does not contain the "Mac" string | MacOS | 75% | | | | | +| `VM::DISK_SIZE` | Check if disk size is under or equal to 50GB | Linux | 60% | | | | | +| `VM::VBOX_DEFAULT` | Check for default RAM and DISK sizes set by VirtualBox | Linux and Windows | 55% | Admin | | | | +| `VM::VBOX_NETWORK` | Check for VirtualBox network provider string | Windows | 70% | | | | | +| `VM::COMPUTER_NAME` | Check if the computer name (not username to be clear) is VM-specific | Windows | 40% | | GPL | | | +| `VM::WINE_CHECK` | Check wine_get_unix_file_name file for Wine | Windows | 85% | | GPL | | | +| `VM::HOSTNAME` | Check if hostname is specific | Windows | 25% | | GPL | | | +| `VM::MEMORY` | Check if memory space is far too low for a physical machine | Windows | 35% | | GPL | | | +| `VM::VBOX_WINDOW_CLASS` | Check for the window class for VirtualBox | Windows | 10% | | GPL | | | +| `VM::LOADED_DLLS` | Check for loaded DLLs in the process | Windows | 75% | | GPL | | | +| `VM::KVM_REG` | Check for KVM-specific registry strings | Windows | 75% | | GPL | | | +| `VM::KVM_DRIVERS` | Check for KVM-specific .sys files in system driver directory | Windows | 55% | | GPL | | | +| `VM::KVM_DIRS` | Check for KVM directory "Virtio-Win" | Windows | 55% | | GPL | | | +| `VM::AUDIO` | Check if audio device is present | Windows | 35% | | GPL | | | +| `VM::QEMU_DIR` | Check for QEMU-specific blacklisted directories | Windows | 45% | | GPL | | | +| `VM::MOUSE_DEVICE` | Check for the presence of a mouse device | Windows | 20% | | GPL | | | +| `VM::VM_PROCESSES` | Check for any VM processes that are active | Windows | 30% | | | | | +| `VM::LINUX_USER_HOST` | Check for default VM username and hostname for linux | Linux | 25% | | | | | +| `VM::GAMARUE` | Check for Gamarue ransomware technique which compares VM-specific Window product IDs | Windows | 40% | | | | | +| `VM::VMID_0X4` | Check if the CPU manufacturer ID matches that of a VM brand with leaf 0x40000000 | | 100% | | | | | +| `VM::PARALLELS_VM` | Check for any indication of Parallels VM through BIOS data | Windows | 50% | | | | | +| `VM::RDTSC_VMEXIT` | check through alternative RDTSC technique with VMEXIT | | 25% | | | | Disabled by default | +| `VM::QEMU_BRAND` | Match for QEMU CPU brands with "QEMU Virtual CPU" string | | 100% | | | | | +| `VM::BOCHS_CPU` | Check for various Bochs-related emulation oversights through CPU checks | | 95% | | | | | +| `VM::VPC_BOARD` | Check through the motherboard and match for VirtualPC-specific string | Windows | 20% | | | | | +| `VM::HYPERV_WMI` | Check WMI query for "Hyper-V RAW" string | Windows | 80% | | | | | +| `VM::HYPERV_REG` | Check presence for Hyper-V specific string in registry | Windows | 80% | | | | | +| `VM::BIOS_SERIAL` | Check if the BIOS serial is valid (null = VM) | Windows | 60% | | | | | +| `VM::VBOX_FOLDERS` | Check for VirtualBox-specific string for shared folder ID | Windows | 45% | | | | | +| `VM::MSSMBIOS` | Check MSSMBIOS registry for VM-specific strings | Windows | 75% | | | | | +| `VM::MAC_MEMSIZE` | Check if memory is too low for MacOS system | MacOS | 30% | | | | | +| `VM::MAC_IOKIT` | Check MacOS' IO kit registry for VM-specific strings | MacOS | 80% | | | | | +| `VM::IOREG_GREP` | Check for VM-strings in ioreg commands for MacOS | MacOS | 75% | | | | | +| `VM::MAC_SIP` | Check if System Integrity Protection is disabled (likely a VM if it is) | MacOS | 85% | | | | | +| `VM::HKLM_REGISTRIES` | Check HKLM registries for specific VM strings | Windows | 70% | | | | | +| `VM::QEMU_GA` | Check for "qemu-ga" process | Linux | 20% | | | | | +| `VM::VALID_MSR` | check for valid MSR value 0x40000000 | Windows | 35% | | | | | +| `VM::QEMU_PROC` | Check for QEMU processes | Windows | 30% | | | | | +| `VM::VPC_PROC` | Check for VPC processes | Windows | 30% | | | | | +| `VM::VPC_INVALID` | Check for official VPC method | Windows | 75% | | | 32-bit | | +| `VM::SIDT` | Check for sidt instruction method | Linux, Windows | 30% | | | | | +| `VM::SGDT` | Check for sgdt instruction method | Windows | 30% | | | 32-bit | | +| `VM::SLDT` | Check for sldt instruction method | Windows | 15% | | | 32-bit | | +| `VM::OFFSEC_SIDT` | Check for Offensive Security SIDT method | Windows | 60% | | | 32-bit | | +| `VM::OFFSEC_SGDT` | Check for Offensive Security SGDT method | Windows | 60% | | | 32-bit | | +| `VM::OFFSEC_SLDT` | Check for Offensive Security SLDT method | Windows | 20% | | | 32-bit | | +| `VM::HYPERV_BOARD` | Check for Hyper-V specific string in motherboard | Windows | 45% | | | | | +| `VM::VM_FILES_EXTRA` | Check for VPC and Parallels files | Windows | 70% | | | | | +| `VM::VPC_SIDT` | Check for sidt method with VPC's 0xE8XXXXXX range | Windows | 15% | | | 32-bit | | +| `VM::VMWARE_IOMEM` | Check for VMware string in /proc/iomem | Linux | 65% | | | | | +| `VM::VMWARE_IOPORTS` | Check for VMware string in /proc/ioports | Linux | 70% | | | | | +| `VM::VMWARE_SCSI` | Check for VMware string in /proc/scsi/scsi | Linux | 40% | | | | | +| `VM::VMWARE_DMESG` | Check for VMware-specific device name in dmesg output | Linux | 65% | Admin | | | | +| `VM::VMWARE_STR` | Check str assembly instruction method for VMware | Windows | 35% | | | | | +| `VM::VMWARE_BACKDOOR` | Check for official VMware io port backdoor technique | Windows | 100% | | | 32-bit | | +| `VM::VMWARE_PORT_MEM` | Check for VMware memory using IO port backdoor | Windows | 85% | | | 32-bit | | +| `VM::SMSW` | Check for SMSW assembly instruction technique | Windows | 30% | | | 32-bit | | +| `VM::MUTEX` | Check for mutex strings of VM brands | Windows | 85% | | | | | +| `VM::UPTIME` | Check if uptime is less than or equal to 2 minutes | | 10% | | | | | +| `VM::ODD_CPU_THREADS` | Check for odd CPU threads, usually a sign of modification through VM setting because 99% of CPUs have even numbers of threads | | 80% | | | | | +| `VM::INTEL_THREAD_MISMATCH` | Check for Intel CPU thread count database if it matches the system's thread count | | 85% | | | | | +| `VM::XEON_THREAD_MISMATCH` | Same as above, but for Xeon Intel CPUs | | 85% | | | | | +| `VM::NETTITUDE_VM_MEMORY` | Check for memory regions to detect VM-specific brands | Windows | 75% | | | | | +| `VM::CPUID_BITSET` | Check for CPUID technique by checking whether all the bits equate to more than 4000 | | 20% | | | | | +| `VM::CUCKOO_DIR` | Check for cuckoo directory using crt and WIN API directory functions | Windows | 15% | | | | | +| `VM::CUCKOO_PIPE` | Check for Cuckoo specific piping mechanism | Windows | 20% | | | | | +| `VM::HYPERV_HOSTNAME` | Check for default Azure hostname format regex (Azure uses Hyper-V as their base VM brand) | Windows, Linux | 50% | | | | | +| `VM::GENERAL_HOSTNAME` | Check for commonly set hostnames by certain VM brands | Windows, Linux | 20% | | | | | +| `VM::SCREEN_RESOLUTION` | Check for pre-set screen resolutions commonly found in VMs | Windows | 10% | | | | | +| `VM::DEVICE_STRING` | Check if bogus device string would be accepted | Windows | 25% | | | | | +| `VM::BLUESTACKS_FOLDERS` | Check for the presence of BlueStacks-specific folders | Linux | 15% | | | | | +| `VM::CPUID_SIGNATURE` | Check for signatures in leaf 0x40000001 in CPUID | | 95% | | | | | +| `VM::HYPERV_BITMASK` | Check for Hyper-V CPUID bitmask range for reserved values | | 20% | | | | | +| `VM::KVM_BITMASK` | Check for KVM CPUID bitmask range for reserved values | | 40% | | | | | +| `VM::KGT_SIGNATURE` | Check for Intel KGT (Trusty branch) hypervisor signature in CPUID | | 80% | | | | | +| `VM::VMWARE_DMI` | Check for VMware DMI strings in BIOS serial number | Windows | 30% | | | | |
@@ -434,7 +436,6 @@ VMAware provides a convenient way to not only check for VMs, but also have the f | `VM::ALL` | This will enable all the technique flags, including the cursor check that's disabled by default. | | `VM::NO_MEMO` | This will disable memoization, meaning the result will not be fetched through a previous computation of the `VM::detect()` function. Use this if you're only using a single function from the `VM` struct for a performance boost. | | `VM::DEFAULT` | This represents a range of flags which are enabled if no default argument is provided. | -| `VM::ENABLE_HYPERV_HOST` | Windows 11 (and 10 if enabled manually) may have Hyper-V as a default virtualisation solution for any host program even if the OS is running as host. There isn't a way to detect whether the host program is ran in default virtualisation mode, or manually intended virtualisation. This is a Hyper-V specific problem, and the library will use heuristical methods to discard Hyper-V's host virtualiser as not running in a VM by default. But if this flag is enabled then it will still count it regardless of the risk that it might be Hyper-V's default host virtualisation for every host program. So basically this flag means that "I'm aware this program might be running in a default virtualised environment on host, but I'll still count this as running in a VM anyway whether it's default virtualisation or manually intended virtualisation". | | `VM::MULTIPLE` | This is specific to `VM::brand()`. This will basically return a `std::string` message of what brands could be involved. For example, it could return "`VMware or VirtualBox`" instead of having a single brand string output. This has no effect if applied to any other functions than `VM::brand()`. | | `VM::HIGH_THRESHOLD` | This is specific to `VM::detect()` and `VM::percentage()`, which will set the threshold bar to confidently detect a VM by 3x higher. | | `VM::SPOOFABLE` | This will enable all the "spoofable" techniques (which are 1/3 of the total amount of techniques) | diff --git a/src/cli.cpp b/src/cli.cpp index bfaaed9..1497802 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -137,7 +137,6 @@ R"(Usage: -t | --type returns the VM type (if a VM was found) Extra: - --disable-hyperv-host disable the possibility of Hyper-V default virtualisation result on host OS --disable-notes no notes will be provided --spoofable allow spoofable techniques to be ran (not included by default) @@ -247,6 +246,7 @@ Intel KGT (Trusty) Microsoft Azure Hyper-V Xbox NanoVisor (Hyper-V) SimpleVisor +Hyper-V artifact (not an actual VM) )"; std::exit(0); @@ -258,6 +258,7 @@ std::string type(const std::string &brand_str) { } const std::map type_table { + // type 1 { "Xen HVM", "Hypervisor (type 1)" }, { "VMware ESX", "Hypervisor (type 1)" }, { "ACRN", "Hypervisor (type 1)" }, @@ -274,6 +275,7 @@ std::string type(const std::string &brand_str) { { "Intel KGT (Trusty)", "Hypervisor (type 1)" }, { "SimpleVisor", "Hypervisor (type 1)" }, + // type 2 { "VirtualBox", "Hypervisor (type 2)" }, { "VMware", "Hypervisor (type 2)" }, { "VMware Express", "Hypervisor (type 2)" }, @@ -286,6 +288,7 @@ std::string type(const std::string &brand_str) { { "NetBSD NVMM", "Hypervisor (type 2)" }, { "OpenBSD VMM", "Hypervisor (type 2)" }, + // sandbox { "Cuckoo", "Sandbox" }, { "Sandboxie", "Sandbox" }, { "Hybrid Analysis", "Sandbox" }, @@ -295,6 +298,7 @@ std::string type(const std::string &brand_str) { { "Comodo", "Sandbox" }, { "ThreatExpert", "Sandbox" }, + // misc { "Bochs", "Emulator" }, { "BlueStacks", "Emulator" }, { "Microsoft x86-to-ARM", "Emulator" }, @@ -305,7 +309,8 @@ std::string type(const std::string &brand_str) { { "Microsoft Virtual PC/Hyper-V", "Hypervisor (either type 1 or 2)" }, { "Lockheed Martin LMHS", "Hypervisor (unknown type)" }, { "Wine", "Compatibility layer" }, - { "Apple VZ", "Unknown" } + { "Apple VZ", "Unknown" }, + { "Hyper-V artifact (not an actual VM)", "No VM" } }; auto it = type_table.find(brand_str); @@ -551,6 +556,7 @@ void general() { checker(VM::KVM_BITMASK, "KVM CPUID reserved bitmask"); checker(VM::KGT_SIGNATURE, "Intel KGT signature"); checker(VM::VMWARE_DMI, "VMware DMI"); + checker(VM::EVENT_LOGS, "Hyper-V event logs"); std::printf("\n"); @@ -560,19 +566,24 @@ void general() { std::string brand = VM::brand(VM::MULTIPLE, spoofable_setting); - std::cout << "VM brand: " << (brand == "Unknown" ? red : green) << brand << ansi_exit << "\n"; + std::cout << "VM brand: " << ((brand == "Unknown") || (brand == "Hyper-V artifact (not an actual VM)") ? red : green) << brand << ansi_exit << "\n"; + // meaning "if there's no brand conflicts" if (brand.find(" or ") == std::string::npos) { - const std::string brand = VM::brand(VM::MULTIPLE, spoofable_setting); - const std::string type_value = type(brand); + const std::string tmp_brand = VM::brand(VM::MULTIPLE, spoofable_setting); + const std::string type_value = type(tmp_brand); std::cout << "VM type: "; + + std::string color = ""; - if (type_value == "Unknown") { - std::cout << red << "Unknown" << ansi_exit << "\n"; + if (type_value == "Unknown" || type_value == "No VM") { + color = red; } else { - std::cout << green << type_value << ansi_exit << "\n"; + color = green; } + + std::cout << color << type_value << ansi_exit << "\n"; } const char* percent_color = ""; @@ -634,28 +645,8 @@ void general() { << "\n\n"; - auto is_hyperv_present = []() -> bool { - std::map brand_map = VM::brand_map(); - bool is_hyperv_vpc_present = false; - - for (const auto p_brand : brand_map) { - if (p_brand.second == 0) { - continue; - } - - if ( - (std::strcmp(p_brand.first, "Microsoft Hyper-V") == 0) || - (std::strcmp(p_brand.first, "Virtual PC") == 0) - ) { - is_hyperv_vpc_present = true; - } - } - - return is_hyperv_vpc_present; - }; - - if ((hyperv_setting == VM::ENABLE_HYPERV_HOST) && is_hyperv_present() && notes_enabled) { - std::cout << note << " If you know you are running on host, Hyper-V leaves VM artifacts in CPUIDs which makes the system look like it's running in a Hyper-V VM when it's not. If you want to disable this mechanism, run with \"--disable-hyperv-host\", or disable Hyper-V in your system.\n\n"; + if ((hyperv_setting == VM::ENABLE_HYPERV_HOST) && (brand == "Hyper-V artifact (not an actual VM)") && notes_enabled) { + std::cout << note << " If you know you are running on host, Hyper-V leaves VM artifacts in CPUIDs which makes the system look like it's running in a Hyper-V VM when it's not. If you want to disable this mechanism, uninstall Hyper-V in your system.\n\n"; } else if (notes_enabled) { if (!arg_bitset.test(SPOOFABLE)) { std::cout << tip << "To enable spoofable techniques, run with the \"--spoofable\" argument\n\n"; @@ -768,6 +759,9 @@ int main(int argc, char* argv[]) { if (arg_bitset.test(HYPERV) == false) { setting_bits.set(VM::ENABLE_HYPERV_HOST); + } else { + std::cerr << "--disable-hyperv-host has been deprecated, the determination of whether it's a host Hyper-V or VM Hyper-V is now done automatically"; + return 1; } if (arg_bitset.test(SPOOFABLE)) { diff --git a/src/vmaware.hpp b/src/vmaware.hpp index d5a0b9f..2a57b3d 100644 --- a/src/vmaware.hpp +++ b/src/vmaware.hpp @@ -214,6 +214,7 @@ #include #include #include +#include #pragma comment(lib, "wbemuuid.lib") #pragma comment(lib, "iphlpapi.lib") @@ -225,6 +226,8 @@ #pragma comment(lib, "strmiids.lib") #pragma comment(lib, "uuid.lib") #pragma comment(lib, "ntdll.lib") +#pragma comment(lib, "wevtapi.lib") + #ifdef _UNICODE #define tregex std::wregex @@ -408,6 +411,7 @@ struct VM { KVM_BITMASK, KGT_SIGNATURE, VMWARE_DMI, + EVENT_LOGS, // start of non-technique flags (THE ORDERING IS VERY SPECIFIC HERE AND MIGHT BREAK SOMETHING IF RE-ORDERED) NO_MEMO, @@ -1575,7 +1579,7 @@ struct VM { #else return false; #endif - } + } [[nodiscard]] static std::string get_hostname() { #if (MSVC) @@ -1596,6 +1600,7 @@ struct VM { return std::string(); } + /** * @brief Checks whether Hyper-V host artifacts are present instead of an actual Hyper-V VM * @note idea and credits to Requiem (https://github.com/NotRequiem) @@ -1966,6 +1971,7 @@ struct VM { unsigned long length = 0; ret = RegQueryValueExW(hk, L"SMBiosData", 0, &type, 0, &length); + if (ret != ERROR_SUCCESS) { RegCloseKey(hk); debug("SMBIOS_string(): ret = error 2"); @@ -1986,6 +1992,7 @@ struct VM { } ret = RegQueryValueExW(hk, L"SMBiosData", 0, &type, reinterpret_cast(p), &length); + if (ret != ERROR_SUCCESS) { LocalFree(p); RegCloseKey(hk); @@ -2179,8 +2186,132 @@ struct VM { return is_vm; } + + /** + * @brief Retrieves the last error message from the Windows API. Useful for __VMAWARE_DEBUG__ + * + * @author Requiem (https://github.com/NotRequiem) + * + * @return A std::wstring containing the error message. + */ + [[nodiscard]] static std::wstring GetLastErrorString() { + DWORD error = GetLastError(); + LPWSTR messageBuffer = nullptr; + size_t size = FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, error, 0, (LPWSTR)&messageBuffer, 0, nullptr + ); + + std::wstring message(messageBuffer, size); + LocalFree(messageBuffer); + return message; + } + + + /** + * @brief Searches for specific strings within events in a Windows Event Log. + * + * @param logName The name or path of the event log to search (e.g., "System", "Application", "Security", or a custom path). + * @param searchStrings A vector of strings to search for within the event messages. + * @param flags Query flags that define the direction of the search; default is EvtQueryReverseDirection. + * @param timeout The maximum amount of time (in milliseconds) to wait for events; default is INFINITE. + * @param maxEvents The maximum number of events to process; default is 1000. + * + * @author Requiem (https://github.com/NotRequiem) + * + * @return True if any of the search strings are found in the events; otherwise, false. + */ + [[nodiscard]] static bool query_event_logs(const std::wstring& logName, + const std::vector& searchStrings, + DWORD flags = EvtQueryReverseDirection, + DWORD timeout = INFINITE, + DWORD maxEvents = 1000) { + + EVT_HANDLE hLog = EvtOpenLog(nullptr, logName.c_str(), EvtOpenChannelPath); + if (!hLog) { + std::wcerr << L"Failed to open event log: " << logName << L". Error: " << GetLastErrorString() << std::endl; + return false; + } + + EVT_HANDLE hResults = EvtQuery(nullptr, logName.c_str(), nullptr, flags); + if (!hResults) { + std::wcerr << L"Failed to query event log: " << logName << L". Error: " << GetLastErrorString() << std::endl; + EvtClose(hLog); + return false; + } + + EVT_HANDLE hEvent = nullptr; + DWORD bufferUsed = 0; + DWORD bufferSize = 0; + DWORD count = 0; + WCHAR* pBuffer = nullptr; + + // Iterate over events up to the maximum number specified + for (DWORD eventCount = 0; eventCount < maxEvents; ++eventCount) { + if (!EvtNext(hResults, 1, &hEvent, timeout, 0, &count)) { + if (GetLastError() == ERROR_NO_MORE_ITEMS) { + break; // No more events to process + } + std::wcerr << L"EvtNext failed. Error: " << GetLastErrorString() << std::endl; + EvtClose(hResults); + EvtClose(hLog); + return false; + } + + if (!EvtRender(nullptr, hEvent, EvtRenderEventXml, 0, nullptr, &bufferUsed, &count) && + GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + bufferSize = bufferUsed; + pBuffer = new WCHAR[bufferSize]; + if (!pBuffer) { + std::wcerr << L"Memory allocation failed." << std::endl; + EvtClose(hResults); + EvtClose(hLog); + return false; + } + + if (!EvtRender(nullptr, hEvent, EvtRenderEventXml, bufferSize, pBuffer, &bufferUsed, &count)) { + std::wcerr << L"EvtRender failed. Error: " << GetLastErrorString() << std::endl; + delete[] pBuffer; + EvtClose(hResults); + EvtClose(hLog); + return false; + } + } + else { + std::wcerr << L"EvtRender failed. Error: " << GetLastErrorString() << std::endl; + EvtClose(hResults); + EvtClose(hLog); + return false; + } + + std::wstring eventMessage(pBuffer); + delete[] pBuffer; + + // Check if any of the search strings are found in the event message, not in the event name + bool found = false; + for (const auto& searchString : searchStrings) { + if (eventMessage.find(searchString) != std::wstring::npos) { + found = true; + break; + } + } + + if (found) { + EvtClose(hResults); + EvtClose(hLog); + return true; + } + + EvtClose(hEvent); + } + + EvtClose(hResults); + EvtClose(hLog); + + return false; + } #endif - }; + }; private: // START OF PRIVATE VM DETECTION TECHNIQUE DEFINITIONS @@ -7953,31 +8084,31 @@ struct VM { return false; // returned false because we want the most feature leafs as possible for Hyper-V } - /* this is just a tool to check if all the arrows (^) are aligned correctly, think of it as a ruler and ignore this lol - ||||||||||||||||||||||9876543210 - |||||||||||||||||||||10 - ||||||||||||||||||||11 - |||||||||||||||||||12 - ||||||||||||||||||13 - |||||||||||||||||14 - ||||||||||||||||15 - |||||||||||||||16 - ||||||||||||||17 - |||||||||||||18 - ||||||||||||19 - |||||||||||20 - ||||||||||21 - |||||||||22 - ||||||||23 - |||||||24 - ||||||25 - |||||26 - ||||27 - |||28 - ||29 - |30 - 31 - */ +/* this is just an ascii tool to check if all the arrows (^) are aligned correctly based on bit position, think of it as a ruler. (ignore this btw) +||||||||||||||||||||||9876543210 +|||||||||||||||||||||10 +||||||||||||||||||||11 +|||||||||||||||||||12 +||||||||||||||||||13 +|||||||||||||||||14 +||||||||||||||||15 +|||||||||||||||16 +||||||||||||||17 +|||||||||||||18 +||||||||||||19 +|||||||||||20 +||||||||||21 +|||||||||22 +||||||||23 +|||||||24 +||||||25 +|||||26 +||||27 +|||28 +||29 +|30 +31 +*/ auto leaf_01 = [&]() -> bool { u32 eax, ebx, ecx, edx = 0; @@ -8284,10 +8415,33 @@ struct VM { } + /** + * @brief Check for presence of Hyper-V in the Windows Event Logs + * + * @author Requiem (https://github.com/NotRequiem) + * + * @category Windows + */ + [[nodiscard]] static bool hyperv_event_logs() try { +#if (!MSVC) + return false; +#else + // Define the log name and search strings + std::wstring logName = L"Microsoft-Windows-Kernel-PnP/Configuration"; // Example: "System", "Application", "Security", or a custom path. In this case, we use Microsoft-Windows-Kernel-PnP/Configuration as a Hyper-V VM artifact + std::vector searchStrings = { L"Virtual_Machine", L"VMBUS" }; + bool found = util::query_event_logs(logName, searchStrings); + if (found) { + return core::add(HYPERV); + } - + return false; +#endif + } catch (...) { + debug("EVENT_LOGS: caught error, returned false"); + return false; + } @@ -8557,7 +8711,7 @@ struct VM { if (flag == SPOOFABLE) { for (const auto& tmp : technique_table) { const u8 technique_macro = tmp.first; - const technique& tuple = tmp.second; + const technique &tuple = tmp.second; if (tuple.spoofable) { flag_collector.set(technique_macro); @@ -8903,32 +9057,32 @@ struct VM { brands.emplace(std::make_pair(TMP_HYPERV_VPC, 2)); } - merger(TMP_HYPERV, TMP_HYPERV_ARTIFACT, TMP_HYPERV_ARTIFACT); - merger(TMP_VPC, TMP_HYPERV_ARTIFACT, TMP_HYPERV_ARTIFACT); + merger(TMP_HYPERV, TMP_HYPERV_ARTIFACT, TMP_HYPERV_ARTIFACT); + merger(TMP_VPC, TMP_HYPERV_ARTIFACT, TMP_HYPERV_ARTIFACT); merger(TMP_HYPERV_VPC, TMP_HYPERV_ARTIFACT, TMP_HYPERV_ARTIFACT); - merger(TMP_AZURE, TMP_HYPERV, TMP_AZURE); - merger(TMP_AZURE, TMP_VPC, TMP_AZURE); + merger(TMP_AZURE, TMP_HYPERV, TMP_AZURE); + merger(TMP_AZURE, TMP_VPC, TMP_AZURE); merger(TMP_AZURE, TMP_HYPERV_VPC, TMP_AZURE); - merger(TMP_NANOVISOR, TMP_HYPERV, TMP_NANOVISOR); - merger(TMP_NANOVISOR, TMP_VPC, TMP_NANOVISOR); + merger(TMP_NANOVISOR, TMP_HYPERV, TMP_NANOVISOR); + merger(TMP_NANOVISOR, TMP_VPC, TMP_NANOVISOR); merger(TMP_NANOVISOR, TMP_HYPERV_VPC, TMP_NANOVISOR); - - merger(TMP_QEMU, TMP_KVM, TMP_QEMU_KVM); - merger(TMP_KVM, TMP_HYPERV, TMP_KVM_HYPERV); - merger(TMP_QEMU, TMP_HYPERV, TMP_QEMU_KVM_HYPERV); - merger(TMP_QEMU_KVM, TMP_HYPERV, TMP_QEMU_KVM_HYPERV); - merger(TMP_KVM, TMP_KVM_HYPERV, TMP_KVM_HYPERV); - merger(TMP_QEMU, TMP_KVM_HYPERV, TMP_QEMU_KVM_HYPERV); - merger(TMP_QEMU_KVM, TMP_KVM_HYPERV, TMP_QEMU_KVM_HYPERV); + + merger(TMP_QEMU, TMP_KVM, TMP_QEMU_KVM); + merger(TMP_KVM, TMP_HYPERV, TMP_KVM_HYPERV); + merger(TMP_QEMU, TMP_HYPERV, TMP_QEMU_KVM_HYPERV); + merger(TMP_QEMU_KVM, TMP_HYPERV, TMP_QEMU_KVM_HYPERV); + merger(TMP_KVM, TMP_KVM_HYPERV, TMP_KVM_HYPERV); + merger(TMP_QEMU, TMP_KVM_HYPERV, TMP_QEMU_KVM_HYPERV); + merger(TMP_QEMU_KVM, TMP_KVM_HYPERV, TMP_QEMU_KVM_HYPERV); triple_merger(TMP_QEMU, TMP_KVM, TMP_KVM_HYPERV, TMP_QEMU_KVM_HYPERV); - merger(TMP_VMWARE, TMP_FUSION, TMP_FUSION); - merger(TMP_VMWARE, TMP_EXPRESS, TMP_EXPRESS); - merger(TMP_VMWARE, TMP_ESX, TMP_ESX); - merger(TMP_VMWARE, TMP_GSX, TMP_GSX); + merger(TMP_VMWARE, TMP_FUSION, TMP_FUSION); + merger(TMP_VMWARE, TMP_EXPRESS, TMP_EXPRESS); + merger(TMP_VMWARE, TMP_ESX, TMP_ESX); + merger(TMP_VMWARE, TMP_GSX, TMP_GSX); merger(TMP_VMWARE, TMP_WORKSTATION, TMP_WORKSTATION); using brand_element_t = std::pair; @@ -9164,14 +9318,14 @@ struct VM { using table_t = std::map; - auto modify = [](table_t& table, const enum_flags flag, const u8 percent) -> void { - core::technique& tmp = table.at(flag); + auto modify = [](table_t &table, const enum_flags flag, const u8 percent) -> void { + core::technique &tmp = table.at(flag); table[flag] = { percent, tmp.run, tmp.spoofable }; }; modify(const_cast(core::technique_table), flag, percent); } - }; +}; MSVC_ENABLE_WARNING(ASSIGNMENT_OPERATOR NO_INLINE_FUNC SPECTRE) @@ -9257,6 +9411,8 @@ VM::flagset VM::DEFAULT = []() -> flagset { // disable all the non-default flags tmp.flip(NO_MEMO); tmp.flip(CURSOR); + tmp.flip(RDTSC); + tmp.flip(RDTSC_VMEXIT); tmp.flip(HIGH_THRESHOLD); tmp.flip(ENABLE_HYPERV_HOST); tmp.flip(SPOOFABLE); @@ -9315,104 +9471,105 @@ std::vector VM::core::custom_table = { const std::map VM::core::technique_table = { // FORMAT: VM:: = { certainty%, function pointer, is spoofable? } - { VM::VMID, { 100, VM::vmid, false }}, - { VM::CPU_BRAND, { 50, VM::cpu_brand, false }}, - { VM::HYPERVISOR_BIT, { 100, VM::hypervisor_bit , false}}, - { VM::HYPERVISOR_STR, { 45, VM::hypervisor_str, false }}, - { VM::RDTSC, { 10, VM::rdtsc_check, false }}, - { VM::THREADCOUNT, { 35, VM::thread_count, false }}, - { VM::MAC, { 60, VM::mac_address_check, true }}, - { VM::TEMPERATURE, { 15, VM::temperature, false }}, - { VM::SYSTEMD, { 70, VM::systemd_virt, false }}, - { VM::CVENDOR, { 65, VM::chassis_vendor, false }}, - { VM::CTYPE, { 10, VM::chassis_type, false }}, - { VM::DOCKERENV, { 80, VM::dockerenv, true }}, - { VM::DMIDECODE, { 55, VM::dmidecode, false }}, - { VM::DMESG, { 55, VM::dmesg, false }}, - { VM::HWMON, { 75, VM::hwmon, true }}, - { VM::SIDT5, { 45, VM::sidt5, false }}, - { VM::CURSOR, { 5, VM::cursor_check, true }}, - { VM::VMWARE_REG, { 65, VM::vmware_registry, true }}, - { VM::VBOX_REG, { 65, VM::vbox_registry, true }}, - { VM::USER, { 35, VM::user_check, true }}, - { VM::DLL, { 50, VM::DLL_check, true }}, - { VM::REGISTRY, { 75, VM::registry_key, true }}, - { VM::CWSANDBOX_VM, { 10, VM::cwsandbox_check, true }}, - { VM::VM_FILES, { 60, VM::vm_files, true }}, - { VM::HWMODEL, { 75, VM::hwmodel, true }}, - { VM::DISK_SIZE, { 60, VM::disk_size, false }}, - { VM::VBOX_DEFAULT, { 55, VM::vbox_default_specs, false }}, - { VM::VBOX_NETWORK, { 70, VM::vbox_network_share, false }}, - { VM::WINE_CHECK, { 85, VM::wine, false }}, // GPL - { VM::COMPUTER_NAME, { 15, VM::computer_name_match, true }}, // GPL - { VM::HOSTNAME, { 25, VM::hostname_match, true }}, // GPL - { VM::MEMORY, { 35, VM::low_memory_space, false }}, // GPL - { VM::VBOX_WINDOW_CLASS, { 10, VM::vbox_window_class, false }}, // GPL - { VM::KVM_REG, { 75, VM::kvm_registry, true }}, // GPL - { VM::KVM_DRIVERS, { 55, VM::kvm_drivers, true }}, // GPL - { VM::KVM_DIRS, { 55, VM::kvm_directories, true }}, // GPL - { VM::LOADED_DLLS, { 75, VM::loaded_dlls, true }}, // GPL - { VM::AUDIO, { 35, VM::check_audio, false }}, // GPL - { VM::QEMU_DIR, { 45, VM::qemu_dir, true }}, // GPL - { VM::MOUSE_DEVICE, { 20, VM::mouse_device, true }}, // GPL - { VM::VM_PROCESSES, { 30, VM::vm_processes, true }}, - { VM::LINUX_USER_HOST, { 25, VM::linux_user_host, true }}, - { VM::GAMARUE, { 40, VM::gamarue, false }}, - { VM::VMID_0X4, { 90, VM::vmid_0x4, false }}, - { VM::PARALLELS_VM, { 50, VM::parallels, false }}, - { VM::RDTSC_VMEXIT, { 25, VM::rdtsc_vmexit, false }}, - { VM::QEMU_BRAND, { 100, VM::cpu_brand_qemu, false }}, - { VM::BOCHS_CPU, { 95, VM::bochs_cpu, false }}, - { VM::VPC_BOARD, { 20, VM::vpc_board, false }}, - { VM::HYPERV_WMI, { 80, VM::hyperv_wmi, false }}, - { VM::HYPERV_REG, { 80, VM::hyperv_registry, true }}, - { VM::BIOS_SERIAL, { 60, VM::bios_serial, false }}, - { VM::VBOX_FOLDERS, { 45, VM::vbox_shared_folders, false }}, - { VM::MSSMBIOS, { 75, VM::mssmbios, false }}, - { VM::MAC_MEMSIZE, { 30, VM::hw_memsize, true }}, - { VM::MAC_IOKIT, { 80, VM::io_kit, true }}, - { VM::IOREG_GREP, { 75, VM::ioreg_grep, true }}, - { VM::MAC_SIP, { 85, VM::mac_sip, true }}, - { VM::HKLM_REGISTRIES, { 70, VM::hklm_registries, true }}, - { VM::QEMU_GA, { 20, VM::qemu_ga, true }}, - { VM::VALID_MSR, { 35, VM::valid_msr, false }}, - { VM::QEMU_PROC, { 30, VM::qemu_processes, true }}, - { VM::VPC_PROC, { 30, VM::vpc_proc, true }}, - { VM::VPC_INVALID, { 75, VM::vpc_invalid, false }}, - { VM::SIDT, { 30, VM::sidt, false }}, - { VM::SGDT, { 30, VM::sgdt, false }}, - { VM::SLDT, { 15, VM::sldt, false }}, - { VM::OFFSEC_SIDT, { 60, VM::offsec_sidt, false }}, - { VM::OFFSEC_SGDT, { 60, VM::offsec_sgdt, false }}, - { VM::OFFSEC_SLDT, { 20, VM::offsec_sldt, false }}, - { VM::VPC_SIDT, { 15, VM::vpc_sidt, false }}, - { VM::HYPERV_BOARD, { 45, VM::hyperv_board, false }}, - { VM::VM_FILES_EXTRA, { 70, VM::vm_files_extra, true }}, - { VM::VMWARE_IOMEM, { 65, VM::vmware_iomem, false }}, - { VM::VMWARE_IOPORTS, { 70, VM::vmware_ioports, false }}, - { VM::VMWARE_SCSI, { 40, VM::vmware_scsi, false }}, - { VM::VMWARE_DMESG, { 65, VM::vmware_dmesg, false }}, - { VM::VMWARE_STR, { 35, VM::vmware_str, false }}, - { VM::VMWARE_BACKDOOR, { 100, VM::vmware_backdoor, false }}, - { VM::VMWARE_PORT_MEM, { 85, VM::vmware_port_memory, false }}, - { VM::SMSW, { 30, VM::smsw, false }}, - { VM::MUTEX, { 85, VM::mutex, false }}, - { VM::UPTIME, { 10, VM::uptime, true }}, - { VM::ODD_CPU_THREADS, { 80, VM::odd_cpu_threads, false }}, - { VM::INTEL_THREAD_MISMATCH, { 85, VM::intel_thread_mismatch, false }}, - { VM::XEON_THREAD_MISMATCH, { 85, VM::xeon_thread_mismatch, false }}, - { VM::NETTITUDE_VM_MEMORY, { 75, VM::nettitude_vm_memory, false }}, - { VM::CPUID_BITSET, { 20, VM::cpuid_bitset, false }}, - { VM::CUCKOO_DIR, { 15, VM::cuckoo_dir, true }}, - { VM::CUCKOO_PIPE, { 20, VM::cuckoo_pipe, true }}, - { VM::HYPERV_HOSTNAME, { 50, VM::hyperv_hostname, true }}, - { VM::GENERAL_HOSTNAME, { 20, VM::general_hostname, true }}, - { VM::SCREEN_RESOLUTION, { 30, VM::screen_resolution, false }}, - { VM::DEVICE_STRING, { 25, VM::device_string, false }}, - { VM::BLUESTACKS_FOLDERS, { 15, VM::bluestacks, true }}, - { VM::CPUID_SIGNATURE, { 95, VM::cpuid_signature, false }}, - { VM::HYPERV_BITMASK, { 20, VM::hyperv_bitmask, false }}, - { VM::KVM_BITMASK, { 40, VM::kvm_bitmask, false }}, - { VM::KGT_SIGNATURE, { 80, VM::intel_kgt_signature, false }}, - { VM::VMWARE_DMI, { 30, VM::vmware_dmi, false }} + { VM::VMID, { 100, VM::vmid, false } }, + { VM::CPU_BRAND, { 50, VM::cpu_brand, false } }, + { VM::HYPERVISOR_BIT, { 100, VM::hypervisor_bit , false}} , + { VM::HYPERVISOR_STR, { 45, VM::hypervisor_str, false } }, + { VM::RDTSC, { 10, VM::rdtsc_check, false } }, + { VM::THREADCOUNT, { 35, VM::thread_count, false } }, + { VM::MAC, { 60, VM::mac_address_check, true } }, + { VM::TEMPERATURE, { 15, VM::temperature, false } }, + { VM::SYSTEMD, { 70, VM::systemd_virt, false } }, + { VM::CVENDOR, { 65, VM::chassis_vendor, false } }, + { VM::CTYPE, { 10, VM::chassis_type, false } }, + { VM::DOCKERENV, { 80, VM::dockerenv, true } }, + { VM::DMIDECODE, { 55, VM::dmidecode, false } }, + { VM::DMESG, { 55, VM::dmesg, false } }, + { VM::HWMON, { 75, VM::hwmon, true } }, + { VM::SIDT5, { 45, VM::sidt5, false } }, + { VM::CURSOR, { 5, VM::cursor_check, true } }, + { VM::VMWARE_REG, { 65, VM::vmware_registry, true } }, + { VM::VBOX_REG, { 65, VM::vbox_registry, true } }, + { VM::USER, { 35, VM::user_check, true } }, + { VM::DLL, { 50, VM::DLL_check, true } }, + { VM::REGISTRY, { 75, VM::registry_key, true } }, + { VM::CWSANDBOX_VM, { 10, VM::cwsandbox_check, true } }, + { VM::VM_FILES, { 60, VM::vm_files, true } }, + { VM::HWMODEL, { 75, VM::hwmodel, true } }, + { VM::DISK_SIZE, { 60, VM::disk_size, false } }, + { VM::VBOX_DEFAULT, { 55, VM::vbox_default_specs, false } }, + { VM::VBOX_NETWORK, { 70, VM::vbox_network_share, false } }, + { VM::WINE_CHECK, { 85, VM::wine, false } }, // GPL + { VM::COMPUTER_NAME, { 15, VM::computer_name_match, true } }, // GPL + { VM::HOSTNAME, { 25, VM::hostname_match, true } }, // GPL + { VM::MEMORY, { 35, VM::low_memory_space, false } }, // GPL + { VM::VBOX_WINDOW_CLASS, { 10, VM::vbox_window_class, false } }, // GPL + { VM::KVM_REG, { 75, VM::kvm_registry, true } }, // GPL + { VM::KVM_DRIVERS, { 55, VM::kvm_drivers, true } }, // GPL + { VM::KVM_DIRS, { 55, VM::kvm_directories, true } }, // GPL + { VM::LOADED_DLLS, { 75, VM::loaded_dlls, true } }, // GPL + { VM::AUDIO, { 35, VM::check_audio, false } }, // GPL + { VM::QEMU_DIR, { 45, VM::qemu_dir, true } }, // GPL + { VM::MOUSE_DEVICE, { 20, VM::mouse_device, true } }, // GPL + { VM::VM_PROCESSES, { 30, VM::vm_processes, true } }, + { VM::LINUX_USER_HOST, { 25, VM::linux_user_host, true } }, + { VM::GAMARUE, { 40, VM::gamarue, false } }, + { VM::VMID_0X4, { 90, VM::vmid_0x4, false } }, + { VM::PARALLELS_VM, { 50, VM::parallels, false } }, + { VM::RDTSC_VMEXIT, { 15, VM::rdtsc_vmexit, false } }, + { VM::QEMU_BRAND, { 100, VM::cpu_brand_qemu, false } }, + { VM::BOCHS_CPU, { 95, VM::bochs_cpu, false } }, + { VM::VPC_BOARD, { 20, VM::vpc_board, false } }, + { VM::HYPERV_WMI, { 80, VM::hyperv_wmi, false } }, + { VM::HYPERV_REG, { 80, VM::hyperv_registry, true } }, + { VM::BIOS_SERIAL, { 60, VM::bios_serial, false } }, + { VM::VBOX_FOLDERS, { 45, VM::vbox_shared_folders, false } }, + { VM::MSSMBIOS, { 75, VM::mssmbios, false } }, + { VM::MAC_MEMSIZE, { 30, VM::hw_memsize, true } }, + { VM::MAC_IOKIT, { 80, VM::io_kit, true } }, + { VM::IOREG_GREP, { 75, VM::ioreg_grep, true } }, + { VM::MAC_SIP, { 85, VM::mac_sip, true } }, + { VM::HKLM_REGISTRIES, { 70, VM::hklm_registries, true } }, + { VM::QEMU_GA, { 20, VM::qemu_ga, true } }, + { VM::VALID_MSR, { 35, VM::valid_msr, false } }, + { VM::QEMU_PROC, { 30, VM::qemu_processes, true } }, + { VM::VPC_PROC, { 30, VM::vpc_proc, true } }, + { VM::VPC_INVALID, { 75, VM::vpc_invalid, false } }, + { VM::SIDT, { 30, VM::sidt, false } }, + { VM::SGDT, { 30, VM::sgdt, false } }, + { VM::SLDT, { 15, VM::sldt, false } }, + { VM::OFFSEC_SIDT, { 60, VM::offsec_sidt, false } }, + { VM::OFFSEC_SGDT, { 60, VM::offsec_sgdt, false } }, + { VM::OFFSEC_SLDT, { 20, VM::offsec_sldt, false } }, + { VM::VPC_SIDT, { 15, VM::vpc_sidt, false } }, + { VM::HYPERV_BOARD, { 45, VM::hyperv_board, false } }, + { VM::VM_FILES_EXTRA, { 70, VM::vm_files_extra, true } }, + { VM::VMWARE_IOMEM, { 65, VM::vmware_iomem, false } }, + { VM::VMWARE_IOPORTS, { 70, VM::vmware_ioports, false } }, + { VM::VMWARE_SCSI, { 40, VM::vmware_scsi, false } }, + { VM::VMWARE_DMESG, { 65, VM::vmware_dmesg, false } }, + { VM::VMWARE_STR, { 35, VM::vmware_str, false } }, + { VM::VMWARE_BACKDOOR, { 100, VM::vmware_backdoor, false } }, + { VM::VMWARE_PORT_MEM, { 85, VM::vmware_port_memory, false } }, + { VM::SMSW, { 30, VM::smsw, false } }, + { VM::MUTEX, { 85, VM::mutex, false } }, + { VM::UPTIME, { 10, VM::uptime, true } }, + { VM::ODD_CPU_THREADS, { 80, VM::odd_cpu_threads, false } }, + { VM::INTEL_THREAD_MISMATCH, { 85, VM::intel_thread_mismatch, false } }, + { VM::XEON_THREAD_MISMATCH, { 85, VM::xeon_thread_mismatch, false } }, + { VM::NETTITUDE_VM_MEMORY, { 75, VM::nettitude_vm_memory, false } }, + { VM::CPUID_BITSET, { 20, VM::cpuid_bitset, false } }, + { VM::CUCKOO_DIR, { 15, VM::cuckoo_dir, true } }, + { VM::CUCKOO_PIPE, { 20, VM::cuckoo_pipe, true } }, + { VM::HYPERV_HOSTNAME, { 50, VM::hyperv_hostname, true } }, + { VM::GENERAL_HOSTNAME, { 20, VM::general_hostname, true } }, + { VM::SCREEN_RESOLUTION, { 30, VM::screen_resolution, false } }, + { VM::DEVICE_STRING, { 25, VM::device_string, false } }, + { VM::BLUESTACKS_FOLDERS, { 15, VM::bluestacks, true } }, + { VM::CPUID_SIGNATURE, { 95, VM::cpuid_signature, false } }, + { VM::HYPERV_BITMASK, { 20, VM::hyperv_bitmask, false } }, + { VM::KVM_BITMASK, { 40, VM::kvm_bitmask, false } }, + { VM::KGT_SIGNATURE, { 80, VM::intel_kgt_signature, false } }, + { VM::VMWARE_DMI, { 30, VM::vmware_dmi, false } }, + { VM::EVENT_LOGS, { 30, VM::hyperv_event_logs, true } } }; \ No newline at end of file