diff --git a/README.md b/README.md
index e125b77..2c6c912 100644
--- a/README.md
+++ b/README.md
@@ -157,7 +157,7 @@ You can view the full docs [here](docs/documentation.md). All the details such a
Who is this library for and what are the use cases?
-> It's designed for security researchers, VM engineers, gamer developers, and pretty much anybody who needs a practical and rock-solid VM detection mechanism in their project. For example, the library is suitable if you're making a VM and you're testing the effectiveness of concealing itself. If you're a proprietary software developer, the library is useful to thwart against reverse engineers. If you're a malware analyst and you want to check the concealment capability of your VM, this would be the perfect tool to benchmark how well-concealed your VM is against malware.
+> It's designed for security researchers, VM engineers, anticheat developers, and pretty much anybody who needs a practical and rock-solid VM detection mechanism in their project. For example, the library is suitable if you're making a VM and you're testing the effectiveness of concealing itself. If you're a proprietary software developer, the library is useful to thwart against reverse engineers. If you're a malware analyst and you want to check the concealment capability of your VM, this would be the perfect tool to benchmark how well-concealed your VM is against malware.
>
> Additionally, software could adjust the behaviour of their program base on the detected environment. It could be useful for debugging and testing purposes, system administrators could manage configurations differently, and some applications might want to restrict usage in VMs to prevent unauthorized distribution or testing.
@@ -169,7 +169,7 @@ You can view the full docs [here](docs/documentation.md). All the details such a
> There's already loads of projects that have the same goal such as
InviZzzible, pafish and Al-Khaser. But the difference between the aforementioned projects is that they don't provide a programmable interface to interact with the detection mechanisms, on top of having little to no support for non-Windows systems.
-> Pafish and InviZzzible have been abandoned for years, while Al-Khaser does receive updates and has a wide scope of detection that includes anti-debuggers, anti-injection, and so on, but the VM detections are not sophisticated enough to be practically applied to real-world scenarios, while most of the technique they implement are bypassable.
+> Pafish and InviZzzible have been abandoned for years, while Al-Khaser does receive updates and has a wide scope of detection that includes anti-debuggers, anti-injection, and so on, but the VM detections are not sophisticated enough to be practically applied to real-world scenarios.
>
> I wanted the core detection techniques to be accessible programmatically in a cross-platform way for everybody to get something useful out of it rather than providing just a CLI tool. It also contains a larger quantity of techniques, so it's basically just a VM detection library and tool on steroids with maximum flexibility.
@@ -187,20 +187,6 @@ You can view the full docs [here](docs/documentation.md). All the details such a
-
-How can the library distinguish between Hyper-V artifacts and an actual Hyper-V VM in the system?
-
-
-> Hyper-V has an obscure feature where if it's enabled in the host system, the CPU hardware values makes it look like the whole system is running inside Hyper-V, which isn't true. This makes it a challenge to determine whether the hardware values the library is collecting is either a real Hyper-V VM, or just the artifacts of what Hyper-V has left as a consequence of having it enabled in the host system.
->
-> The reason why this is a problem is because the library might falsely conclude that your the host system is running in Hyper-V, which is a false positive. This is where the **Hyper-X** mechanism comes into play to distinguish between these two. This was designed by Requiem
-
-
-
-
-
-
-
How effective are VM hardeners against the lib?
@@ -222,7 +208,7 @@ You can view the full docs [here](docs/documentation.md). All the details such a
What about using this for malware?
-> This project is not soliciting the development of malware for obvious reasons. Even if you intend to use it for concealment purposes, it'll most likely be flagged by antiviruses anyway and nothing is obfuscated to begin with. Good fucking luck obfuscating 10k+ lines of C++ code lmao.
+> This project is not soliciting the development of malware for obvious reasons. Even if you intend to use it for concealment purposes, it'll most likely be flagged by antiviruses anyway and nothing is obfuscated to begin with. Good fucking luck obfuscating 12k+ lines of C++ code lmao.
@@ -232,7 +218,7 @@ You can view the full docs [here](docs/documentation.md). All the details such a
> I would've made it strictly MIT so proprietary software can make use of the library, but some of the techniques employed are from GPL 3.0 projects, and I have no choice but to use the same license for legal reasons.
>
-> This gave me an idea to make an MIT version without all of the GPL code so it can also be used without forcing your code to be open-source. It should be noted that the MIT version removes 9 techniques out of 120 (as of 2.0 version), and the lesser the number of techniques, the less accurate the overall result might be.
+> This gave me an idea to make an MIT version without all of the GPL code so it can also be used without forcing your code to be open-source. It should be noted that the MIT version removes 9 techniques out of 128 (as of 2.0 version), and the lesser the number of techniques, the less accurate the overall result might be.
diff --git a/docs/documentation.md b/docs/documentation.md
index b84b4c1..1600a75 100644
--- a/docs/documentation.md
+++ b/docs/documentation.md
@@ -457,7 +457,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::HYPERV_QUERY` | Checks if a call to NtQuerySystemInformation with the 0x9f leaf fills a _SYSTEM_HYPERVISOR_DETAIL_INFORMATION structure | Windows | 50% | | | | |
| `VM::BAD_POOLS` | Checks for system pools allocated by hypervisors | Windows | 80% | | | | |
| `VM::AMD_SEV` | Check for AMD-SEV MSR running on the system | Linux and MacOS | 50% | Admin | | | |
-| `VM::AMD_RESERVED` | Check for bits that should be reserved in leaf 8000000Ah | 50% | | | | |
+| `VM::AMD_RESERVED` | Check for bits that should be reserved in leaf 8000000Ah | | 50% | | | |
| `VM::AMD_THREAD_MISMATCH` | Check for AMD CPU thread count database if it matches the system's thread count | | 100% | | | | |
| `VM::NATIVE_VHD` | Checks if the OS was booted from a VHD container | | 100% | | | | |
| `VM::VIRTUAL_REGISTRY` | Checks for particular object directory which is present in Sandboxie virtual environment but not in usual host systems | | 65% | | | | |
@@ -520,7 +520,6 @@ This is the table of all the brands the lib supports.
| Hyper-V artifact (not an actual VM) | `VM::brands::HYPERV_ARTIFACT` | Unknown | |
| User-mode Linux | `VM::brands::UML` | Paravirtualised/Hypervisor (type 2) | |
| IBM PowerVM | `VM::brands::POWERVM` | Hypervisor (type 1) | |
-| Google Compute Engine (KVM) | `VM::brands::GCE` | Hypervisor (type 1) | |
| OpenStack (KVM) | `VM::brands::OPENSTACK` | Hypervisor (type 1) | |
| KubeVirt (KVM) | `VM::brands::KUBEVIRT` | Hypervisor (type 1) | |
| AWS Nitro System EC2 (KVM-based) | `VM::brands::AWS_NITRO` | Hypervisor (type 1) | |
@@ -537,6 +536,7 @@ This is the table of all the brands the lib supports.
| AMD SEV-ES | `VM::brands::AMD_SEV_ES` | VM encryptor | |
| AMD SEV-SNP | `VM::brands::AMD_SEV_SNP` | VM encryptor | |
| Neko Project II | `VM::brands::NEKO_PROJECT` | Emulator | |
+| Google Compute Engine (KVM) | `VM::brands::GCE` | Cloud VM service | |
diff --git a/src/vmaware.hpp b/src/vmaware.hpp
index b476817..463411d 100644
--- a/src/vmaware.hpp
+++ b/src/vmaware.hpp
@@ -24,14 +24,14 @@
*
*
* ================================ SECTIONS ==================================
- * - enums for publicly accessible techniques => line 328
- * - struct for internal cpu operations => line 603
- * - struct for internal memoization => line 1059
- * - struct for internal utility functions => line 1449
- * - struct for internal core components => line 9714
- * - start of internal VM detection techniques => line 2861
- * - start of public VM detection functions => line 10116
- * - start of externally defined variables => line 10987
+ * - enums for publicly accessible techniques => line 338
+ * - struct for internal cpu operations => line 620
+ * - struct for internal memoization => line 1078
+ * - struct for internal utility functions => line 1472
+ * - struct for internal core components => line 10709
+ * - start of internal VM detection techniques => line 2831
+ * - start of public VM detection functions => line 11113
+ * - start of externally defined variables => line 12018
*
*
* ================================ EXAMPLE ==================================
@@ -9021,6 +9021,19 @@ struct VM {
}
}
}
+
+ query = L"SELECT Model FROM Win32_ComputerSystem";
+ properties = { L"Model" };
+ results = wmi::execute(query, properties);
+
+ for (const auto& result : results) {
+ if (result.type == wmi::result_type::String) {
+ if (result.strValue == "Google Compute Engine") {
+ return core::add(brands::GCE);
+ }
+ }
+ }
+
return false;
#endif
}
@@ -11824,7 +11837,6 @@ static bool rdtsc() {
{ brands::INTEL_HAXM, "Hypervisor (type 1)" },
{ brands::INTEL_KGT, "Hypervisor (type 1)" },
{ brands::SIMPLEVISOR, "Hypervisor (type 1)" },
- { brands::GCE, "Hypervisor (type 1)" },
{ brands::OPENSTACK, "Hypervisor (type 1)" },
{ brands::KUBEVIRT, "Hypervisor (type 1)" },
{ brands::POWERVM, "Hypervisor (type 1)" },
@@ -11868,9 +11880,6 @@ static bool rdtsc() {
{ brands::LMHS, "Hypervisor (unknown type)" },
{ brands::WINE, "Compatibility layer" },
{ brands::INTEL_TDX, "Trusted Domain" },
- { brands::AMD_SEV, "" },
- { brands::AMD_SEV_ES, "" },
- { brands::AMD_SEV_SNP, "" },
{ brands::APPLE_VZ, "Unknown" },
{ brands::HYPERV_ARTIFACT, "Unknown" },
{ brands::UML, "Paravirtualised/Hypervisor (type 2)" },
@@ -11878,6 +11887,7 @@ static bool rdtsc() {
{ brands::AMD_SEV, "VM encryptor" },
{ brands::AMD_SEV_ES, "VM encryptor" },
{ brands::AMD_SEV_SNP, "VM encryptor" },
+ { brands::GCE, "Cloud VM service" },
};
auto it = type_table.find(brand_str.c_str());
diff --git a/src/vmaware_MIT.hpp b/src/vmaware_MIT.hpp
index 2b6ccce..6e354c8 100644
--- a/src/vmaware_MIT.hpp
+++ b/src/vmaware_MIT.hpp
@@ -20,53 +20,31 @@
* - Repository: https://github.com/kernelwernel/VMAware
* - Docs: https://github.com/kernelwernel/VMAware/docs/documentation.md
* - Full credits: https://github.com/kernelwernel/VMAware#credits-and-contributors-%EF%B8%8F
- * - License: MIT
- *
- * MIT License
- *
- * Copyright (c) 2024 kernelwernel
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * - License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
*
*
* ================================ SECTIONS ==================================
- * - enums for publicly accessible techniques => line 357
- * - struct for internal cpu operations => line 624
- * - struct for internal memoization => line 1079
- * - struct for internal utility functions => line 1467
- * - struct for internal core components => line 9421
- * - start of internal VM detection techniques => line 2829
- * - start of public VM detection functions => line 9825
- * - start of externally defined variables => line 10717
+ * - enums for publicly accessible techniques => line 338
+ * - struct for internal cpu operations => line 611
+ * - struct for internal memoization => line 1070
+ * - struct for internal utility functions => line 1465
+ * - struct for internal core components => line 10368
+ * - start of internal VM detection techniques => line 2825
+ * - start of public VM detection functions => line 10777
+ * - start of externally defined variables => line 11682
*
*
* ================================ EXAMPLE ==================================
* #include "vmaware.hpp"
* #include
- *
+ *
* int main() {
* if (VM::detect()) {
* std::cout << "Virtual machine detected!" << "\n";
* } else {
* std::cout << "Running on baremetal" << "\n";
* }
- *
+ *
* std::cout << "VM name: " << VM::brand() << "\n";
* std::cout << "VM type: " << VM::type() << "\n";
* std::cout << "VM certainty: " << (int)VM::percentage() << "%" << "\n";
@@ -209,6 +187,7 @@
#endif
#if (CPP >= 17)
#include
+#include
#endif
#ifdef __VMAWARE_DEBUG__
#include
@@ -260,6 +239,7 @@
#include
#include
+#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "shlwapi.lib")
@@ -275,7 +255,7 @@
#pragma comment(lib, "powrprof.lib")
#elif (LINUX)
-#if (x86_64)
+#if (x86)
#include
#include
#include
@@ -345,11 +325,11 @@ MSVC_DISABLE_WARNING(ASSIGNMENT_OPERATOR NO_INLINE_FUNC SPECTRE)
struct VM {
private:
- using u8 = std::uint8_t;
+ using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
- using i8 = std::int8_t;
+ using i8 = std::int8_t;
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
@@ -451,7 +431,7 @@ struct VM {
ACPI_DETECT,
GPU_NAME,
VM_DEVICES,
- VMWARE_MEMORY,
+ VM_MEMORY,
IDT_GDT_MISMATCH,
PROCESSOR_NUMBER,
NUMBER_OF_CORES,
@@ -468,6 +448,11 @@ struct VM {
HYPERV_QUERY,
BAD_POOLS,
AMD_SEV,
+ AMD_RESERVED,
+ AMD_THREAD_MISMATCH,
+ NATIVE_VHD,
+ VIRTUAL_REGISTRY,
+ FIRMWARE_SCAN,
// ADD NEW TECHNIQUE ENUM NAME HERE
// start of settings technique flags (THE ORDERING IS VERY SPECIFIC HERE AND MIGHT BREAK SOMETHING IF RE-ORDERED)
@@ -499,7 +484,7 @@ struct VM {
// this is specifically meant for VM::detected_count() to
// get the total number of techniques that detected a VM
- static u8 detected_count_num;
+ static u8 detected_count_num;
private:
@@ -598,12 +583,13 @@ struct VM {
static constexpr const char* AMD_SEV = "AMD SEV";
static constexpr const char* AMD_SEV_ES = "AMD SEV-ES";
static constexpr const char* AMD_SEV_SNP = "AMD SEV-SNP";
+ static constexpr const char* NEKO_PROJECT = "Neko Project II";
static constexpr const char* NULL_BRAND = "Unknown";
};
// macro for bypassing unused parameter/variable warnings
- #define UNUSED(x) ((void)(x))
+#define UNUSED(x) ((void)(x))
// likely and unlikely macros
#if (LINUX)
@@ -778,11 +764,11 @@ struct VM {
constexpr std::size_t buffer_size = sizeof(int32_t) * buffer.size();
std::array charbuffer{};
- constexpr std::array ids = {{
+ constexpr std::array ids = { {
cpu::leaf::brand1,
cpu::leaf::brand2,
cpu::leaf::brand3
- }};
+ } };
std::string brand = "";
@@ -814,7 +800,7 @@ struct VM {
}
return true;
- };
+ };
u32 sig_reg[3] = { 0 };
@@ -829,7 +815,7 @@ struct VM {
auto strconvert = [](u64 n) -> std::string {
const std::string& str(reinterpret_cast(&n));
return str;
- };
+ };
// the reason why there's 2 is because depending on the leaf,
// the last 4 characters might be switched with the middle
@@ -889,7 +875,7 @@ struct VM {
steps.model == celeron_model &&
steps.family == celeron_family &&
steps.extmodel == celeron_extmodel
- );
+ );
}
@@ -906,7 +892,7 @@ struct VM {
constexpr const char* intel_i_series_regex = "i[0-9]-[A-Z0-9]{1,7}";
constexpr const char* intel_xeon_series_regex = "[DEW]-[A-Z0-9]{1,7}";
- constexpr const char* amd_ryzen_regex = "^(PRO)?[A-Z0-9]{1,7}";
+ constexpr const char* amd_ryzen_regex = "AMD Ryzen ^(PRO)?[A-Z0-9]{1,7}";
std::string match_str = "";
@@ -926,7 +912,7 @@ struct VM {
}
return false;
- };
+ };
bool found = false;
bool is_xeon = false;
@@ -937,12 +923,14 @@ struct VM {
if (match(intel_i_series_regex)) {
found = true;
is_i_series = true;
- } else if (match(intel_xeon_series_regex)) {
+ }
+ else if (match(intel_xeon_series_regex)) {
found = true;
is_xeon = true;
}
}
+ // example: AMD Ryzen 9 3950X 16-Core Processor
if (cpu::is_amd()) {
if (match(amd_ryzen_regex)) {
found = true;
@@ -989,7 +977,8 @@ struct VM {
hyperplatform = "PpyH",
minivisor = "MiniVisor\0\0\0",
intel_tdx = "IntelTDX ", // source: virt-what
- lkvm = "LKVMLKVMLKVM";
+ lkvm = "LKVMLKVMLKVM",
+ neko = "Neko Project";
const std::array brand_strings = cpu_manufacturer(p_leaf);
debug(technique_name, brand_strings.at(0));
@@ -1000,7 +989,7 @@ struct VM {
UNUSED(technique_name);
#endif
- for (const std::string &brand_str : brand_strings) {
+ for (const std::string& brand_str : brand_strings) {
if (brand_str == qemu) { return core::add(brands::QEMU); }
if (brand_str == vmware) { return core::add(brands::VMWARE); }
if (brand_str == vbox) { return core::add(brands::VBOX); }
@@ -1024,6 +1013,7 @@ struct VM {
if (brand_str == minivisor) { return core::add(brands::MINIVISOR); }
if (brand_str == intel_tdx) { return core::add(brands::INTEL_TDX); }
if (brand_str == lkvm) { return core::add(brands::LKVM); }
+ if (brand_str == neko) { return core::add(brands::NEKO_PROJECT); }
// both Hyper-V and VirtualPC have the same string value
if (brand_str == hyperv) {
@@ -1074,7 +1064,7 @@ struct VM {
return false;
}
- };
+ };
// memoization
struct memo {
@@ -1125,10 +1115,11 @@ struct VM {
static bool all_present() {
if (cache_table.size() == technique_count) {
return true;
- } else if (cache_table.size() == static_cast(technique_count) - 3) {
+ }
+ else if (cache_table.size() == static_cast(technique_count) - 3) {
return (
!cache_keys.test(VMWARE_DMESG)
- );
+ );
}
return false;
@@ -1235,13 +1226,17 @@ struct VM {
struct result {
result_type type;
+#pragma warning(disable: 4582) // MSVC: constructor/destructor not called
+#pragma warning(disable: 4583) // MSVC: destructor not called
union {
std::string strValue;
int intValue;
double doubleValue;
};
- result(const std::string& str) : type(result_type::String), strValue(str) {}
+ result(const std::string& str) : type(result_type::String) {
+ new (&strValue) std::string(str);
+ }
result(int integer) : type(result_type::Integer), intValue(integer) {}
@@ -1297,6 +1292,8 @@ struct VM {
strValue.~basic_string();
}
}
+#pragma warning(default: 4582)
+#pragma warning(default: 4583)
};
static bool initialize() {
@@ -1522,7 +1519,7 @@ struct VM {
#endif
}
-#if (WINDOWS) && (_UNICODE)
+#if defined(WINDOWS) && (defined(UNICODE) || defined(_UNICODE))
// handle TCHAR conversion
[[nodiscard]] static bool exists(const TCHAR* path) {
char c_szText[_MAX_PATH]{};
@@ -1551,7 +1548,7 @@ struct VM {
return (
(uid != euid) ||
(euid == 0)
- );
+ );
#elif (WINDOWS)
BOOL is_admin = FALSE;
HANDLE hToken = NULL;
@@ -1575,7 +1572,7 @@ struct VM {
}
}
- CloseHandle(hToken);
+ CloseHandle(hToken);
return is_admin;
#endif
@@ -1781,7 +1778,7 @@ struct VM {
if (size == 0)
return 81;
-
+
debug("private util::get_disk_size( function: ", "disk size = ", size, "GB");
return size; // Return disk size in GB
@@ -1817,7 +1814,8 @@ struct VM {
if (std::isdigit(c)) {
number_str += c;
in_number = true;
- } else if (in_number) {
+ }
+ else if (in_number) {
break;
}
}
@@ -1875,11 +1873,11 @@ struct VM {
}
// Checks if a process is running
- [[nodiscard]] static bool is_proc_running(const TCHAR* executable) {
+ [[nodiscard]] static bool is_proc_running(const char* executable) {
#if (WINDOWS)
DWORD processes[1024], bytesReturned;
- if (!EnumProcesses(processes, sizeof(processes), &bytesReturned))
+ if (!K32EnumProcesses(processes, sizeof(processes), &bytesReturned))
return false;
DWORD numProcesses = bytesReturned / sizeof(DWORD);
@@ -1887,9 +1885,9 @@ struct VM {
for (DWORD i = 0; i < numProcesses; ++i) {
const HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processes[i]);
if (process != nullptr) {
- TCHAR processName[MAX_PATH];
- if (GetModuleBaseName(process, nullptr, processName, sizeof(processName) / sizeof(TCHAR))) {
- if (!_tcsicmp(processName, executable)) {
+ char processName[MAX_PATH];
+ if (K32GetModuleBaseNameA(process, nullptr, processName, sizeof(processName))) {
+ if (_stricmp(processName, executable) == 0) {
CloseHandle(process);
return true;
}
@@ -1976,7 +1974,7 @@ struct VM {
#else
return false;
#endif
- }
+ }
// Retrieves the computer name
[[nodiscard]] static std::string get_hostname() {
@@ -2046,15 +2044,15 @@ struct VM {
};
/**
- * On Hyper-V virtual machines, the cpuid function reports an EAX value of 11.
+ * On Hyper-V virtual machines, the cpuid function reports an EAX value of 11.
* This value is tied to the Hyper-V partition model, where each virtual machine runs as a child partition.
- * These child partitions have limited privileges and access to hypervisor resources,
- * which is reflected in the maximum input value for hypervisor CPUID information as 11.
+ * These child partitions have limited privileges and access to hypervisor resources,
+ * which is reflected in the maximum input value for hypervisor CPUID information as 11.
* Essentially, it indicates that the hypervisor is managing the VM and that the VM is not running directly on hardware but rather in a virtualized environment.
- *
- * On the other hand, in bare-metal systems running Hyper-V, the EAX value is 12.
- * This higher value corresponds to the root partition, which has more privileges and control over virtualization resources compared to child partitions.
- * The root partition is responsible for managing other child partitions and interacts more closely with the hardware.
+ *
+ * On the other hand, in bare-metal systems running Hyper-V, the EAX value is 12.
+ * This higher value corresponds to the root partition, which has more privileges and control over virtualization resources compared to child partitions.
+ * The root partition is responsible for managing other child partitions and interacts more closely with the hardware.
* The EAX value of 12 indicates that additional CPUID leaves (up to 12) are available to the root partition, which exposes more functionality than in a guest VM.
*/
@@ -2073,7 +2071,7 @@ struct VM {
const bool has_hyperv_indications = (
eax() == 11 ||
is_event_log_hyperv()
- );
+ );
if (has_hyperv_indications) {
core_debug("HYPER_X: added Hyper-V real VM");
@@ -2414,11 +2412,11 @@ struct VM {
* @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,
+ [[nodiscard]] static bool query_event_logs(const std::wstring & logName,
+ const std::vector&searchStrings,
DWORD flags = EvtQueryReverseDirection,
DWORD timeout = INFINITE,
const DWORD maxEvents = 1000) {
@@ -2506,21 +2504,19 @@ struct VM {
*
* This function adjusts the token privileges to enable debugging rights,
* which are required for the lib to access the memory of certain processes.
- *
- * @return `true` if the privilege was successfully enabled, otherwise `false`.
*/
- static bool EnableDebugPrivilege() {
+ [[nodiscard]] static void EnableDebugPrivilege() {
HANDLE hToken;
TOKEN_PRIVILEGES tp{};
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
- return false;
+ return;
}
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
CloseHandle(hToken);
- return false;
+ return;
}
tp.PrivilegeCount = 1;
@@ -2529,16 +2525,15 @@ struct VM {
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
CloseHandle(hToken);
- return false;
+ return;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
CloseHandle(hToken);
- return false;
+ return;
}
CloseHandle(hToken);
- return true;
}
@@ -2560,7 +2555,7 @@ struct VM {
*
* @return bool `true` if `searchString` is found in `buffer`, `false` otherwise.
*/
- [[nodiscard]] static bool findSubstring(const wchar_t* buffer, const size_t bufferSize, const std::wstring& searchString) {
+ [[nodiscard]] static bool findSubstring(const wchar_t* buffer, const size_t bufferSize, const std::wstring & searchString) {
size_t searchLength = searchString.length();
if (searchLength > bufferSize) return false;
@@ -2603,13 +2598,13 @@ struct VM {
/**
* @brief Finds the process ID (PID) of a service by its name.
*
- * This function queries WMI to retrieve the process ID of a service running on the system.
+ * This function queries WMI to retrieve the process ID of a service running on the system.
* This is needed when trying to access processes with the "svchost" name.
*
* @param serviceName The name of the service to search for.
* @return The process ID (PID) if found, otherwise returns `0`.
*/
- [[nodiscard]] static DWORD FindProcessIdByServiceName(const std::wstring& serviceName) {
+ [[nodiscard]] static DWORD FindProcessIdByServiceName(const std::wstring & serviceName) {
const std::wstring query = L"SELECT ProcessId, Name FROM Win32_Service WHERE Name='" +
serviceName + L"'";
@@ -2712,7 +2707,7 @@ struct VM {
}
return threadCount;
- };
+ };
auto GetThreadsUsingWMI = []() -> int {
if (!wmi::initialize()) {
@@ -2727,13 +2722,13 @@ struct VM {
}
return 0;
- };
+ };
auto GetThreadsUsingGetSystemInfo = []() -> int {
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return static_cast(sysinfo.dwNumberOfProcessors); // This is safe as long as the value of dwNumberOfProcessors is within the range of the int type (which it usually will be)
- };
+ };
auto GetThreadsUsingGetProcessAffinityMask = []() -> int {
DWORD_PTR processAffinityMask, systemAffinityMask;
@@ -2741,7 +2736,7 @@ struct VM {
return static_cast(std::bitset(processAffinityMask).count());
}
return 0;
- };
+ };
auto GetThreadsUsingNtQuerySystemInformation = []() -> int {
HMODULE hModule = GetModuleHandleA("ntdll.dll");
@@ -2761,7 +2756,7 @@ struct VM {
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
- );
+ );
NtQuerySystemInformationFunc NtQuerySystemInformation = reinterpret_cast(functions[0]);
@@ -2776,7 +2771,7 @@ struct VM {
}
return 0;
- };
+ };
int wmiThreads = GetThreadsUsingWMI();
int sysinfoThreads = GetThreadsUsingGetSystemInfo();
@@ -2808,12 +2803,12 @@ struct VM {
}
/**
- * @brief Checks if the Hyper-V CPUID leaf is present.
+ * @brief Checks if hypervisor CPUID specific leaves are present.
*
* This function uses the CPUID instruction to determine if the system supports
- * the Hyper-V-specific CPUID leaf (0x40000000).
+ * the hypervisor-specific CPUID leaf (0x40000000).
*
- * @return `true` if the Hyper-V CPUID leaf is present, otherwise `false`.
+ * @return `true` if hypervisor CPUID information is present, otherwise `false`.
*/
[[nodiscard]] static bool is_hyperv_leaf_present() {
char out[sizeof(int32_t) * 4 + 1] = { 0 }; // e*x size + number of e*x registers + null terminator
@@ -2824,7 +2819,7 @@ struct VM {
return eax != 0;
}
#endif
- };
+ };
private: // START OF PRIVATE VM DETECTION TECHNIQUE DEFINITIONS
@@ -2860,12 +2855,12 @@ struct VM {
std::string brand = cpu::get_brand();
// TODO: might add more potential keywords, be aware that it could (theoretically) cause false positives
- constexpr std::array vmkeywords {{
+ constexpr std::array vmkeywords{ {
"qemu", "kvm", "virtual",
"vbox", "virtualbox", "monitor",
- "bhyve", "hyperv", "hypervisor",
+ "bhyve", "hyperv", "hypervisor",
"hvisor", "parallels", "vmware"
- }};
+ } };
u8 match_count = 0;
@@ -3013,7 +3008,8 @@ struct VM {
if (success) {
std::memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
- } else {
+ }
+ else {
debug("MAC: ", "not successful");
}
#elif (WINDOWS)
@@ -3053,7 +3049,7 @@ struct VM {
<< static_cast(mac[1]) << ":"
<< static_cast(mac[2]) << ":XX:XX:XX";
/* removed for privacy reasons, cuz only the first 3 bytes are needed
- << static_cast(mac[3]) << ":"
+ << static_cast(mac[3]) << ":"
<< static_cast(mac[4]) << ":"
<< static_cast(mac[5]);
*/
@@ -3063,7 +3059,7 @@ struct VM {
// better expression to fix code duplication
auto compare = [=](const u8 mac1, const u8 mac2, const u8 mac3) noexcept -> bool {
return (mac[0] == mac1 && mac[1] == mac2 && mac[2] == mac3);
- };
+ };
if (compare(0x08, 0x00, 0x27)) {
return core::add(brands::VBOX);
@@ -3074,7 +3070,7 @@ struct VM {
(compare(0x00, 0x1C, 0x14)) ||
(compare(0x00, 0x50, 0x56)) ||
(compare(0x00, 0x05, 0x69))
- ) {
+ ) {
return core::add(brands::VMWARE);
}
@@ -3178,7 +3174,8 @@ struct VM {
if (util::exists(chassis)) {
return (stoi(util::read_file(chassis)) == 1);
- } else {
+ }
+ else {
debug("CTYPE: ", "file doesn't exist");
}
@@ -3227,15 +3224,20 @@ struct VM {
if (*result == "" || result == nullptr) {
debug("DMIDECODE: ", "invalid output");
return false;
- } else if (*result == "QEMU") {
+ }
+ else if (*result == "QEMU") {
return core::add(brands::QEMU);
- } else if (*result == "VirtualBox") {
+ }
+ else if (*result == "VirtualBox") {
return core::add(brands::VBOX);
- } else if (*result == "KVM") {
+ }
+ else if (*result == "KVM") {
return core::add(brands::KVM);
- } else if (std::atoi(result->c_str()) >= 1) {
+ }
+ else if (std::atoi(result->c_str()) >= 1) {
return true;
- } else {
+ }
+ else {
debug("DMIDECODE: ", "output = ", *result);
}
@@ -3265,13 +3267,17 @@ struct VM {
if (*result == "" || result == nullptr) {
return false;
- } else if (*result == "KVM") {
+ }
+ else if (*result == "KVM") {
return core::add(brands::KVM);
- } else if (*result == "QEMU") {
+ }
+ else if (*result == "QEMU") {
return core::add(brands::QEMU);
- } else if (std::atoi(result->c_str())) {
+ }
+ else if (std::atoi(result->c_str())) {
return true;
- } else {
+ }
+ else {
debug("DMESG: ", "output = ", *result);
}
@@ -3310,12 +3316,11 @@ struct VM {
__asm__ __volatile__("sidt %0" : "=m"(values));
#ifdef __VMAWARE_DEBUG__
- u64 result = 0;
- for (u8 i = 0; i < 10; i++) {
- result <<= 8;
- result |= values[i];
+ debug("SIDT5: values = ");
+ for (u8 i = 0; i < 10; ++i) {
+ debug(std::hex, std::setw(2), std::setfill('0'), static_cast(values[i]));
+ if (i < 9) debug(" ");
}
- debug("SIDT5: ", "values = 0x", std::hex, std::setw(16), std::setfill('0'), result);
#endif
return (values[9] == 0x00); // 10th byte in x64 mode
@@ -3325,12 +3330,11 @@ struct VM {
__asm__ __volatile__("sidt %0" : "=m"(values));
#ifdef __VMAWARE_DEBUG__
- u32 result = 0;
- for (u8 i = 0; i < 6; i++) {
- result <<= 8;
- result |= values[i];
+ debug("SIDT5: values = ");
+ for (u8 i = 0; i < 6; ++i) {
+ debug(std::hex, std::setw(2), std::setfill('0'), static_cast(values[i]));
+ if (i < 5) debug(" ");
}
- debug("SIDT5: ", "values = 0x", std::hex, std::setw(16), std::setfill('0'), result);
#endif
return (values[5] == 0x00); // 6th byte in x86 mode
@@ -3340,7 +3344,7 @@ struct VM {
#endif
#else
- return false;
+ return false;
#endif
}
@@ -3390,7 +3394,8 @@ struct VM {
MultiByteToWideChar(CP_ACP, 0, regkey_s, -1, wRegKey, MAX_PATH);
ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wRegKey, 0, KEY_READ | KEY_WOW64_64KEY, ®key);
- } else {
+ }
+ else {
wchar_t wRegKey[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, regkey_s, -1, wRegKey, MAX_PATH);
@@ -3516,137 +3521,122 @@ struct VM {
char szWinDir[MAX_PATH] = { 0 };
if (GetWindowsDirectoryA(szWinDir, MAX_PATH) == 0) {
+ if (wow64RedirectDisabled) {
+ Wow64RevertWow64FsRedirection(&oldValue);
+ }
return false;
}
constexpr std::array vbox_and_vmware = { {
- "System32\\Drivers\\Vmmouse.sys", // VMware
- "System32\\Drivers\\Vmusbmouse.sys", // VMware
- "System32\\Drivers\\vm3dgl.dll", // VMware
- "System32\\Drivers\\vmdum.dll", // VMware
- "System32\\Drivers\\VmGuestLibJava.dll",// VMware
- "System32\\Drivers\\vm3dver.dll", // VMware
- "System32\\Drivers\\vmtray.dll", // VMware
- "System32\\Drivers\\VMToolsHook.dll", // VMware
- "System32\\Drivers\\vmGuestLib.dll", // VMware
- "System32\\Drivers\\vmhgfs.dll", // VMware
- "System32\\Drivers\\VBoxMouse.sys", // VBox
- "System32\\Drivers\\VBoxGuest.sys", // VBox
- "System32\\Drivers\\VBoxSF.sys", // VBox
- "System32\\Drivers\\VBoxVideo.sys", // VBox
- "System32\\vboxoglpackspu.dll", // VBox
- "System32\\vboxoglpassthroughspu.dll", // VBox
- "System32\\vboxservice.exe", // VBox
- "System32\\vboxoglcrutil.dll", // VBox
- "System32\\vboxdisp.dll", // VBox
- "System32\\vboxhook.dll", // VBox
- "System32\\vboxmrxnp.dll", // VBox
- "System32\\vboxogl.dll", // VBox
- "System32\\vboxtray.exe", // VBox
- "System32\\VBoxControl.exe", // VBox
- "System32\\vboxoglerrorspu.dll", // VBox
- "System32\\vboxoglfeedbackspu.dll", // VBox
- "System32\\vboxoglarrayspu.dll" // VBox
- } };
+ "Drivers\\Vmmouse.sys",
+ "Drivers\\Vmusbmouse.sys",
+ "Drivers\\vm3dgl.dll",
+ "Drivers\\vmdum.dll",
+ "Drivers\\VmGuestLibJava.dll",
+ "Drivers\\vm3dver.dll",
+ "Drivers\\vmtray.dll",
+ "Drivers\\VMToolsHook.dll",
+ "Drivers\\vmGuestLib.dll",
+ "Drivers\\vmhgfs.dll",
+ "Drivers\\VBoxMouse.sys",
+ "Drivers\\VBoxGuest.sys",
+ "Drivers\\VBoxSF.sys",
+ "Drivers\\VBoxVideo.sys",
+ "vboxoglpackspu.dll",
+ "vboxoglpassthroughspu.dll",
+ "vboxservice.exe",
+ "vboxoglcrutil.dll",
+ "vboxdisp.dll",
+ "vboxhook.dll",
+ "vboxmrxnp.dll",
+ "vboxogl.dll",
+ "vboxtray.exe",
+ "VBoxControl.exe",
+ "vboxoglerrorspu.dll",
+ "vboxoglfeedbackspu.dll",
+ "vboxoglarrayspu.dll"
+ } };
constexpr std::array kvmFiles = { {
- "System32\\drivers\\balloon.sys", // KVM
- "System32\\drivers\\netkvm.sys", // KVM
- "System32\\drivers\\pvpanic.sys", // KVM
- "System32\\drivers\\viofs.sys", // KVM
- "System32\\drivers\\viogpudo.sys", // KVM
- "System32\\drivers\\vioinput.sys", // KVM
- "System32\\drivers\\viorng.sys", // KVM
- "System32\\drivers\\vioscsi.sys", // KVM
- "System32\\drivers\\vioser.sys", // KVM
- "System32\\drivers\\viostor.sys" // KVM
+ "Drivers\\balloon.sys",
+ "Drivers\\netkvm.sys",
+ "Drivers\\pvpanic.sys",
+ "Drivers\\viofs.sys",
+ "Drivers\\viogpudo.sys",
+ "Drivers\\vioinput.sys",
+ "Drivers\\viorng.sys",
+ "Drivers\\vioscsi.sys",
+ "Drivers\\vioser.sys",
+ "Drivers\\viostor.sys"
} };
constexpr std::array parallelsFiles = { {
- "System32\\drivers\\prleth.sys", // Parallels
- "System32\\drivers\\prlfs.sys", // Parallels
- "System32\\drivers\\prlmouse.sys", // Parallels
- "System32\\drivers\\prlvideo.sys", // Parallels
- "System32\\drivers\\prltime.sys", // Parallels
- "System32\\drivers\\prl_pv32.sys", // Parallels
- "System32\\drivers\\prl_paravirt_32.sys"// Parallels
+ "Drivers\\prleth.sys",
+ "Drivers\\prlfs.sys",
+ "Drivers\\prlmouse.sys",
+ "Drivers\\prlvideo.sys",
+ "Drivers\\prltime.sys",
+ "Drivers\\prl_pv32.sys",
+ "Drivers\\prl_paravirt_32.sys"
} };
constexpr std::array vpcFiles = { {
- "System32\\drivers\\vmsrvc.sys", // VPC
- "System32\\drivers\\vpc-s3.sys" // VPC
+ "Drivers\\vmsrvc.sys",
+ "Drivers\\vpc-s3.sys"
} };
u8 vbox = 0, vmware = 0, kvm = 0, vpc = 0, parallels = 0;
- for (const auto& relativePath : vbox_and_vmware) {
- char szPath[MAX_PATH] = { 0 };
- PathCombineA(szPath, szWinDir, relativePath);
- if (util::exists(szPath)) {
- if (std::string(relativePath).find("VBox") != std::string::npos) {
- vbox++;
- }
- else {
- vmware++;
+
+ auto file_exists = [](const char* path) -> bool {
+ DWORD attrs = GetFileAttributesA(path);
+ return (attrs != INVALID_FILE_ATTRIBUTES) && !(attrs & FILE_ATTRIBUTE_DIRECTORY);
+ };
+
+ auto checkFiles = [&](const auto& files, u8& count, const char* brand) {
+ for (const auto& relativePath : files) {
+ char szPath[MAX_PATH] = { 0 };
+ PathCombineA(szPath, szWinDir, relativePath);
+ if (file_exists(szPath)) {
+ count++;
}
}
- }
- for (const auto& relativePath : kvmFiles) {
- char szPath[MAX_PATH] = { 0 };
- PathCombineA(szPath, szWinDir, relativePath);
- if (util::exists(szPath)) {
- kvm++;
- }
- }
- for (const auto& relativePath : parallelsFiles) {
- char szPath[MAX_PATH] = { 0 };
- PathCombineA(szPath, szWinDir, relativePath);
- if (util::exists(szPath)) {
- parallels++;
- }
- }
- for (const auto& relativePath : vpcFiles) {
- char szPath[MAX_PATH] = { 0 };
- PathCombineA(szPath, szWinDir, relativePath);
- if (util::exists(szPath)) {
- vpc++;
- }
+ debug("%s score: %u", (std::string(brand) + " score: ").c_str(), static_cast(count));
+ (void)brand;
+ };
+
+ checkFiles(vbox_and_vmware, vbox, "VBOX/VMWARE");
+ checkFiles(kvmFiles, kvm, "KVM");
+ checkFiles(parallelsFiles, parallels, "PARALLELS");
+ checkFiles(vpcFiles, vpc, "VPC");
+
+ if (wow64RedirectDisabled) {
+ Wow64RevertWow64FsRedirection(&oldValue);
}
- debug("VM_FILES: vmware score: ", static_cast(vmware));
- debug("VM_FILES: vbox score: ", static_cast(vbox));
- debug("KVM_FILES: kvm score: ", static_cast(kvm));
- debug("VPC_FILES: vpc score: ", static_cast(vpc));
- debug("PARALLELS_FILES: parallels score: ", static_cast(parallels));
+ if (file_exists("C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\agent.pyw")) {
+ return core::add(brands::CUCKOO);
+ }
if (vbox > vmware && vbox > kvm && vbox > vpc && vbox > parallels) {
return core::add(brands::VBOX);
}
- else if (vmware > vbox && vmware > kvm && vmware > vpc && vmware > parallels) {
+ if (vmware > vbox && vmware > kvm && vmware > vpc && vmware > parallels) {
return core::add(brands::VMWARE);
}
- else if (kvm > vbox && kvm > vmware && kvm > vpc && kvm > parallels) {
+ if (kvm > vbox && kvm > vmware && kvm > vpc && kvm > parallels) {
return core::add(brands::KVM);
}
- else if (vpc > vbox && vpc > vmware && vpc > kvm && vpc > parallels) {
+ if (vpc > vbox && vpc > vmware && vpc > kvm && vpc > parallels) {
return core::add(brands::VPC);
}
- else if (parallels > vbox && parallels > vmware && parallels > kvm && parallels > vpc) {
+ if (parallels > vbox && parallels > vmware && parallels > kvm && parallels > vpc) {
return core::add(brands::PARALLELS);
}
- // if we reach here: vbox == vmware == cuckoo == kvm == vpc == parallels
- else if (vbox > 0 && vmware > 0 && kvm > 0 && vpc > 0 && parallels > 0) {
+ if (vbox > 0 && vmware > 0 && kvm > 0 && vpc > 0 && parallels > 0) {
return true;
}
- if (wow64RedirectDisabled) {
- Wow64RevertWow64FsRedirection(&oldValue);
- }
-
- if (util::exists("C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\agent.pyw")) {
- return core::add(brands::CUCKOO);
- }
-
return false;
#endif
}
@@ -3724,7 +3714,6 @@ struct VM {
const u32 disk = util::get_disk_size();
const u64 ram = util::get_physical_ram_size();
- debug("VBOX_DEFAULT: disk = ", disk);
debug("VBOX_DEFAULT: ram = ", ram);
if ((disk > 80) || (ram > 4)) {
@@ -3748,7 +3737,7 @@ struct VM {
}
return "unknown";
- };
+ };
const std::string distro = get_distro();
@@ -3766,7 +3755,7 @@ struct VM {
"gentoo" == distro ||
"fedora" == distro ||
"debian" == distro
- ) {
+ ) {
return ((8 == disk) && (1 == ram));
}
@@ -3777,33 +3766,26 @@ struct VM {
if ("ol" == distro) { // ol = oracle
return ((12 == disk) && (1 == ram));
}
+
+ return false;
#elif (WINDOWS)
const u8 version = util::get_windows_version();
- if (version == 0) {
- return false;
- }
-
- // less than windows 10
if (version < 10) {
- debug("VBOX_DEFAULT: less than windows 10 detected");
return false;
}
- // windows 10
- if (10 == version) {
- debug("VBOX_DEFAULT: windows 10 detected");
+ // For Windows 10/11 and newer versions
+ if (version == 10) {
+ debug("VBOX_DEFAULT: Windows 10 detected");
return ((50 == disk) && (2 == ram));
}
- // windows 11
- if (11 == version) {
- debug("VBOX_DEFAULT: windows 11 detected");
- return ((80 == disk) && (4 == ram));
- }
+ // Windows 11 check (version 11+)
+ debug("VBOX_DEFAULT: Windows 11 detected");
+ return ((80 == disk) && (4 == ram));
#endif
#endif
- return false;
}
@@ -3815,25 +3797,21 @@ struct VM {
#if (!WINDOWS)
return false;
#else
- u32 pnsize = 0x1000;
- TCHAR* provider = new TCHAR[pnsize];
+ DWORD pnsize = 0x1000;
+ char provider[0x1000];
- u32 retv = WNetGetProviderName(WNNC_NET_RDR2SAMPLE, provider, reinterpret_cast(&pnsize));
+ DWORD retv = WNetGetProviderNameA(WNNC_NET_RDR2SAMPLE, provider, &pnsize);
bool result = false;
if (retv == NO_ERROR) {
- result = (lstrcmpi(provider, _T("VirtualBox Shared Folders")) == 0);
+ result = (_stricmp(provider, "VirtualBox Shared Folders") == 0);
}
- delete[] provider;
-
return result;
#endif
}
-
-
/**
* @brief Check for any VM processes that are active
* @category Windows
@@ -3842,31 +3820,31 @@ struct VM {
#if (!WINDOWS)
return false;
#else
- if (util::is_proc_running(_T("joeboxserver.exe")) || util::is_proc_running(_T("joeboxcontrol.exe"))) {
+ if (util::is_proc_running(("joeboxserver.exe")) || util::is_proc_running(("joeboxcontrol.exe"))) {
return core::add(brands::JOEBOX);
}
- if (util::is_proc_running(_T("prl_cc.exe")) || util::is_proc_running(_T("prl_tools.exe"))) {
+ if (util::is_proc_running(("prl_cc.exe")) || util::is_proc_running(("prl_tools.exe"))) {
return core::add(brands::PARALLELS);
}
- if (util::is_proc_running(_T("vboxservice.exe")) || util::is_proc_running(_T("vboxtray.exe"))) {
+ if (util::is_proc_running(("vboxservice.exe")) || util::is_proc_running(("vboxtray.exe"))) {
return core::add(brands::VBOX);
}
- if (util::is_proc_running(_T("vmsrvc.exe")) || util::is_proc_running(_T("vmusrvc.exe"))) {
+ if (util::is_proc_running(("vmsrvc.exe")) || util::is_proc_running(("vmusrvc.exe"))) {
return core::add(brands::VPC);
}
- if (util::is_proc_running(_T("xenservice.exe")) || util::is_proc_running(_T("xsvc_depriv.exe"))) {
+ if (util::is_proc_running(("xenservice.exe")) || util::is_proc_running(("xsvc_depriv.exe"))) {
return core::add(brands::XEN);
}
- if (util::is_proc_running(_T("vm3dservice.exe"))) {
+ if (util::is_proc_running(("vm3dservice.exe")) || util::is_proc_running(("VGAuthService.exe")) || util::is_proc_running(("vmtoolsd.exe"))) {
return core::add(brands::VMWARE);
}
- if (util::is_proc_running(_T("qemu-ga.exe")) || util::is_proc_running(_T("vdagent.exe")) || util::is_proc_running(_T("vdservice.exe"))) {
+ if (util::is_proc_running(("qemu-ga.exe")) || util::is_proc_running(("vdagent.exe")) || util::is_proc_running(("vdservice.exe"))) {
return core::add(brands::QEMU);
}
@@ -3896,7 +3874,7 @@ struct VM {
return (
(strcmp(username, "liveuser") == 0) &&
(strcmp(hostname, "localhost-live") == 0)
- );
+ );
#endif
}
@@ -3916,26 +3894,11 @@ struct VM {
szBuff = (char*)calloc(512, sizeof(char));
- const HANDLE hMod = GetModuleHandleA("SbieDll.dll"); // Sandboxie
- if (hMod != 0) {
- free(szBuff);
- return core::add(brands::SANDBOXIE);
- }
-
- /* this gave a false positive
- hMod = GetModuleHandleA("dbghelp.dll"); // ThreatExpert
- if (hMod != 0) {
- free(szBuff);
- return core::add(brands::THREATEXPERT);
- }
- */
-
nRes = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", 0L, KEY_QUERY_VALUE, &hOpen);
if (nRes == ERROR_SUCCESS) {
iBuffSize = sizeof(szBuff);
nRes = RegQueryValueExA(hOpen, "ProductId", NULL, NULL, (unsigned char*)szBuff, reinterpret_cast(&iBuffSize));
if (nRes == ERROR_SUCCESS) {
- // Check if szBuff is not NULL before using strcmp
if (szBuff == NULL) {
RegCloseKey(hOpen);
return false;
@@ -3944,20 +3907,22 @@ struct VM {
if (strcmp(szBuff, "55274-640-2673064-23950") == 0) { // joebox
free(szBuff);
return core::add(brands::JOEBOX);
- } else if (strcmp(szBuff, "76487-644-3177037-23510") == 0) { // CW Sandbox
+ }
+ else if (strcmp(szBuff, "76487-644-3177037-23510") == 0) { // CW Sandbox
free(szBuff);
return core::add(brands::CWSANDBOX);
- } else if (strcmp(szBuff, "76487-337-8429955-22614") == 0) { // anubis
+ }
+ else if (strcmp(szBuff, "76487-337-8429955-22614") == 0) { // anubis
free(szBuff);
return core::add(brands::ANUBIS);
- } else {
+ }
+ else {
free(szBuff);
return false;
}
}
RegCloseKey(hOpen);
}
- // Set szBuff to NULL after freeing to avoid double free issues
free(szBuff);
return false;
#endif
@@ -3979,7 +3944,7 @@ struct VM {
return (
cpu::vmid_template(cpu::leaf::hypervisor, "VMID_0x4: ") ||
cpu::vmid_template(cpu::leaf::hypervisor + 1, "VMID_0x4 + 1: ")
- );
+ );
#endif
}
@@ -4014,7 +3979,7 @@ struct VM {
auto compare = [](const std::string& str) -> bool {
std::regex pattern("Parallels", std::regex_constants::icase);
return std::regex_match(str, pattern);
- };
+ };
if (
compare(info->get_manufacturer()) ||
@@ -4084,7 +4049,8 @@ struct VM {
debug("BOCHS_CPU: technique 1 found");
return core::add(brands::BOCHS);
}
- } else if (amd) {
+ }
+ else if (amd) {
// technique 2: "processor" should have a capital P
if (brand == "AMD Athlon(tm) processor") {
debug("BOCHS_CPU: technique 2 found");
@@ -4113,7 +4079,7 @@ struct VM {
}
return false;
- };
+ };
auto is_k8 = [](const u32 eax) -> bool {
const u32 family = (eax >> 8) & 0xF;
@@ -4126,7 +4092,7 @@ struct VM {
}
return false;
- };
+ };
if (!(is_k7(eax) || is_k8(eax))) {
return false;
@@ -4168,7 +4134,7 @@ struct VM {
const bool all_digits = std::all_of(extract.cbegin(), extract.cend(), [](const char c) {
return std::isdigit(c);
- });
+ });
if (all_digits) {
if (extract == "0") {
@@ -4296,35 +4262,29 @@ struct VM {
return reinterpret_cast(p);
};
- const unsigned char* x1 = ScanDataForString(cast(p), length, reinterpret_cast("INNOTEK GMBH"));
- const unsigned char* x2 = ScanDataForString(cast(p), length, reinterpret_cast("VIRTUALBOX"));
- const unsigned char* x3 = ScanDataForString(cast(p), length, reinterpret_cast("SUN MICROSYSTEMS"));
- const unsigned char* x4 = ScanDataForString(cast(p), length, reinterpret_cast("VBOXVER"));
- const unsigned char* x5 = ScanDataForString(cast(p), length, reinterpret_cast("VIRTUAL MACHINE"));
- const unsigned char* x6 = ScanDataForString(cast(p), length, reinterpret_cast("VMWARE"));
-
- std::string result = "";
- bool is_vm = false;
+ constexpr std::array strings_to_scan = { {
+ "INNOTEK GMBH",
+ "VIRTUALBOX",
+ "SUN MICROSYSTEMS",
+ "VBOXVER",
+ "VIRTUAL MACHINE",
+ "VMWARE"
+ } };
- if (x1 || x2 || x3 || x4 || x5 || x6) {
- is_vm = true;
+ for (const char* search_str : strings_to_scan) {
+ const unsigned char* found = ScanDataForString(cast(p), length, reinterpret_cast(search_str));
+ if (found) {
#ifdef __VMAWARE_DEBUG__
- if (x1) { debug("SMBIOS: x1 = ", x1); result = std::string(reinterpret_cast(x1)); }
- if (x2) { debug("SMBIOS: x2 = ", x2); result = std::string(reinterpret_cast(x2)); }
- if (x3) { debug("SMBIOS: x3 = ", x3); result = std::string(reinterpret_cast(x3)); }
- if (x4) { debug("SMBIOS: x4 = ", x4); result = std::string(reinterpret_cast(x4)); }
- if (x5) { debug("SMBIOS: x5 = ", x5); result = std::string(reinterpret_cast(x5)); }
- if (x6) { debug("SMBIOS: x6 = ", x6); result = std::string(reinterpret_cast(x6)); }
+ debug("SMBIOS: found = ", found);
#endif
+ LocalFree(p);
+ RegCloseKey(hk);
+ return true;
+ }
}
LocalFree(p);
RegCloseKey(hk);
-
- if (is_vm) {
- return true;
- }
-
return false;
#endif
}
@@ -4500,13 +4460,13 @@ struct VM {
}
return false;
- };
+ };
return (
check_usb() ||
check_general() ||
check_rom()
- );
+ );
#endif
}
@@ -4621,8 +4581,8 @@ struct VM {
check_key(brands::VMWARE, "SYSTEM\\ControlSet002\\Services\\Disk\\Enum", "FriendlyName", "VMware");
check_key(brands::VMWARE, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "DeviceDesc", "VMware");
check_key(brands::VMWARE, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "FriendlyName", "VMware");
- // check_key(HKCR\Installer\Products ProductName vmware tools
- // check_key(HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall DisplayName vmware tools
+ // check_key(HKCR\Installer\Products ProductName vmware tools
+ // check_key(HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall DisplayName vmware tools
check_key(brands::VMWARE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", "DisplayName", "vmware tools");
check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "CoInstallers32", "*vmx*");
check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "DriverDesc", "VMware*");
@@ -4699,10 +4659,10 @@ struct VM {
test ebx, ebx
setz[rc]
- pop edx
- pop ecx
- pop ebx
- pop eax
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
}
}
__except (IsInsideVPC_exceptionFilter(GetExceptionInformation())) {
@@ -5020,7 +4980,7 @@ struct VM {
* @note paper describing this technique is located at /papers/www.s21sec.com_vmware-eng.pdf (2006)
* @category Windows
*/
- [[nodiscard]] static bool vmware_str() {
+ [[nodiscard]] static bool vmware_str() {
#if (WINDOWS && x86_32)
unsigned short tr = 0;
__asm {
@@ -5086,11 +5046,11 @@ struct VM {
if (is_vm) {
switch (b) {
- case 1: return core::add(brands::VMWARE_EXPRESS);
- case 2: return core::add(brands::VMWARE_ESX);
- case 3: return core::add(brands::VMWARE_GSX);
- case 4: return core::add(brands::VMWARE_WORKSTATION);
- default: return core::add(brands::VMWARE);
+ case 1: return core::add(brands::VMWARE_EXPRESS);
+ case 2: return core::add(brands::VMWARE_ESX);
+ case 3: return core::add(brands::VMWARE_GSX);
+ case 4: return core::add(brands::VMWARE_WORKSTATION);
+ default: return core::add(brands::VMWARE);
}
}
#endif
@@ -5163,7 +5123,7 @@ struct VM {
return (
(((reax >> 24) & 0xFF) == 0xCC) &&
(((reax >> 16) & 0xFF) == 0xCC)
- );
+ );
#else
return false;
#endif
@@ -5197,12 +5157,12 @@ struct VM {
}
return (dwError == ERROR_ALREADY_EXISTS);
- };
+ };
if (
supMutexExist("Sandboxie_SingleInstanceMutex_Control") ||
supMutexExist("SBIE_BOXED_ServiceInitComplete_Mutex1")
- ) {
+ ) {
return core::add(brands::SANDBOXIE);
}
@@ -5210,7 +5170,7 @@ struct VM {
return core::add(brands::VPC);
}
- if (supMutexExist("Frz_State")) {
+ if (supMutexExist("Frz_State")) { // DeepFreeze
return true;
}
@@ -5237,48 +5197,48 @@ struct VM {
// check if the microarchitecture was made before 2006, which was around the time multi-core processors were implemented
auto old_microarchitecture = [&steps]() -> bool {
- constexpr std::array, 32> old_archs = {{
- // 80486
- {{ 0x4, 0x0, 0x1 }},
- {{ 0x4, 0x0, 0x2 }},
- {{ 0x4, 0x0, 0x3 }},
- {{ 0x4, 0x0, 0x4 }},
- {{ 0x4, 0x0, 0x5 }},
- {{ 0x4, 0x0, 0x7 }},
- {{ 0x4, 0x0, 0x8 }},
- {{ 0x4, 0x0, 0x9 }},
-
- // P5
- {{ 0x5, 0x0, 0x1 }},
- {{ 0x5, 0x0, 0x2 }},
- {{ 0x5, 0x0, 0x4 }},
- {{ 0x5, 0x0, 0x7 }},
- {{ 0x5, 0x0, 0x8 }},
-
- // P6
- {{ 0x6, 0x0, 0x1 }},
- {{ 0x6, 0x0, 0x3 }},
- {{ 0x6, 0x0, 0x5 }},
- {{ 0x6, 0x0, 0x6 }},
- {{ 0x6, 0x0, 0x7 }},
- {{ 0x6, 0x0, 0x8 }},
- {{ 0x6, 0x0, 0xA }},
- {{ 0x6, 0x0, 0xB }},
-
- // Netburst
- {{ 0xF, 0x0, 0x6 }},
- {{ 0xF, 0x0, 0x4 }},
- {{ 0xF, 0x0, 0x3 }},
- {{ 0xF, 0x0, 0x2 }},
- {{ 0xF, 0x0, 0x10 }},
-
- {{ 0x6, 0x1, 0x5 }}, // Pentium M (Talopai)
- {{ 0x6, 0x1, 0x6 }}, // Core (Client)
- {{ 0x6, 0x0, 0x9 }}, // Pentium M
- {{ 0x6, 0x0, 0xD }}, // Pentium M
- {{ 0x6, 0x0, 0xE }}, // Modified Pentium M
- {{ 0x6, 0x0, 0xF }} // Core (Client)
- }};
+ constexpr std::array, 32> old_archs = { {
+ // 80486
+ {{ 0x4, 0x0, 0x1 }},
+ {{ 0x4, 0x0, 0x2 }},
+ {{ 0x4, 0x0, 0x3 }},
+ {{ 0x4, 0x0, 0x4 }},
+ {{ 0x4, 0x0, 0x5 }},
+ {{ 0x4, 0x0, 0x7 }},
+ {{ 0x4, 0x0, 0x8 }},
+ {{ 0x4, 0x0, 0x9 }},
+
+ // P5
+ {{ 0x5, 0x0, 0x1 }},
+ {{ 0x5, 0x0, 0x2 }},
+ {{ 0x5, 0x0, 0x4 }},
+ {{ 0x5, 0x0, 0x7 }},
+ {{ 0x5, 0x0, 0x8 }},
+
+ // P6
+ {{ 0x6, 0x0, 0x1 }},
+ {{ 0x6, 0x0, 0x3 }},
+ {{ 0x6, 0x0, 0x5 }},
+ {{ 0x6, 0x0, 0x6 }},
+ {{ 0x6, 0x0, 0x7 }},
+ {{ 0x6, 0x0, 0x8 }},
+ {{ 0x6, 0x0, 0xA }},
+ {{ 0x6, 0x0, 0xB }},
+
+ // Netburst
+ {{ 0xF, 0x0, 0x6 }},
+ {{ 0xF, 0x0, 0x4 }},
+ {{ 0xF, 0x0, 0x3 }},
+ {{ 0xF, 0x0, 0x2 }},
+ {{ 0xF, 0x0, 0x10 }},
+
+ {{ 0x6, 0x1, 0x5 }}, // Pentium M (Talopai)
+ {{ 0x6, 0x1, 0x6 }}, // Core (Client)
+ {{ 0x6, 0x0, 0x9 }}, // Pentium M
+ {{ 0x6, 0x0, 0xD }}, // Pentium M
+ {{ 0x6, 0x0, 0xE }}, // Modified Pentium M
+ {{ 0x6, 0x0, 0xF }} // Core (Client)
+ } };
constexpr u8 FAMILY = 0;
constexpr u8 EXTMODEL = 1;
@@ -5295,7 +5255,7 @@ struct VM {
}
return false;
- };
+ };
// self-explanatory
if (!(cpu::is_intel() || cpu::is_amd())) {
@@ -6349,12 +6309,12 @@ struct VM {
debug("XEON_THREAD_MISMATCH: CPU model = ", model.string);
- #if (WINDOWS)
- if (util::does_threadcount_mismatch()) {
- debug("INTEL_THREAD_MISMATCH: Thread tampering detected");
- return false;
- }
- #endif
+#if (WINDOWS)
+ if (util::does_threadcount_mismatch()) {
+ debug("INTEL_THREAD_MISMATCH: Thread tampering detected");
+ return false;
+ }
+#endif
std::map thread_database = {
// Xeon D
@@ -6627,8 +6587,8 @@ struct VM {
CM_FULL_RESOURCE_DESCRIPTOR List[1];
} *PCM_RESOURCE_LIST, CM_RESOURCE_LIST;
struct map_key {
- LPCTSTR KeyPath;
- LPCTSTR ValueName;
+ LPCTSTR KeyPath;
+ LPCTSTR ValueName;
};
#define VBOX_PHYS_LO 0x0000000000001000ULL
@@ -6848,7 +6808,7 @@ struct VM {
}
return false;
- };
+ };
// win api
auto IsDirectory1 = [](std::string& strDirName) -> bool {
@@ -6869,7 +6829,7 @@ struct VM {
CloseHandle(hFile);
return true;
- };
+ };
// crt
auto IsDirectory = [](std::string& strDirName) -> bool {
@@ -6878,7 +6838,7 @@ struct VM {
}
return false;
- };
+ };
std::string strDirName = "C:\\Cuckoo";
@@ -6886,7 +6846,7 @@ struct VM {
IsDirectory(strDirName) ||
IsDirectory1(strDirName) ||
IsDirectory2(strDirName)
- ) {
+ ) {
return core::add(brands::CUCKOO);
}
@@ -6961,7 +6921,7 @@ struct VM {
auto cmp = [&](const char* str2) -> bool {
return (hostname == str2);
- };
+ };
if (
cmp("Sandbox") ||
@@ -6969,7 +6929,7 @@ struct VM {
cmp("Malware") ||
cmp("malsand") ||
cmp("ClonePC")
- ) {
+ ) {
return true;
}
@@ -7005,7 +6965,7 @@ struct VM {
(horiz == 1024 && verti == 768) ||
(horiz == 800 && verti == 600) ||
(horiz == 640 && verti == 480)
- ) {
+ ) {
return true;
}
@@ -7030,7 +6990,8 @@ struct VM {
if (BuildCommDCBAndTimeoutsA("jhl46745fghb", &dcb, &timeouts)) {
return true;
- } else {
+ }
+ else {
return false;
}
#endif
@@ -7048,7 +7009,7 @@ struct VM {
if (
util::exists("/mnt/windows/BstSharedFolder") ||
util::exists("/sdcard/windows/BstSharedFolder")
- ) {
+ ) {
return core::add(brands::BLUESTACKS);
}
@@ -7081,8 +7042,8 @@ struct VM {
debug("CPUID_SIGNATURE: eax = ", eax);
switch (eax) {
- case nanovisor: return core::add(brands::NANOVISOR);
- case simplevisor: return core::add(brands::SIMPLEVISOR);
+ case nanovisor: return core::add(brands::NANOVISOR);
+ case simplevisor: return core::add(brands::SIMPLEVISOR);
}
return false;
@@ -7115,14 +7076,14 @@ struct VM {
cpu::cpuid(eax, ebx, ecx, edx, leaf);
switch (register_id) {
- case EAX: return eax;
- case EBX: return ebx;
- case ECX: return ecx;
- case EDX: return edx;
+ case EAX: return eax;
+ case EBX: return ebx;
+ case ECX: return ecx;
+ case EDX: return edx;
}
return 0;
- };
+ };
const u32 max_leaf = fetch_register(EAX, 0x40000000);
@@ -7132,31 +7093,31 @@ struct VM {
return false; // returned false because we want the most feature leafs as possible for Hyper-V
}
-/* 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
-*/
+ /* 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;
@@ -7175,8 +7136,8 @@ struct VM {
(ebx == 0) &&
(ecx == 0) &&
(edx == 0)
- );
- };
+ );
+ };
auto leaf_03 = [&]() -> bool {
const u32 ecx = fetch_register(ECX, 0x40000003);
@@ -7189,7 +7150,8 @@ struct VM {
if (ecx == 0 || edx == 0) {
return false;
- } else {
+ }
+ else {
return (
((ecx & 0b11111) == 0) &&
((ecx >> 9) == 0) &&
@@ -7197,9 +7159,9 @@ struct VM {
((edx & (1 << 22)) == 0) &&
(((edx >> 24) & 0b11) == 0) &&
((edx >> 27) == 0)
- );
+ );
}
- };
+ };
auto leaf_04 = [&]() -> bool {
const u32 eax = fetch_register(EAX, 0x40000004);
@@ -7217,25 +7179,26 @@ struct VM {
eax == 0 ||
ecx == 0 ||
edx != 0 // edx is supposed to be null
- ) {
+ ) {
return false;
- } else {
+ }
+ else {
return (
((eax & (1 << 8)) == 0) &&
((eax & (1 << 16)) == 0) &&
((eax >> 19) == 0) &&
((ecx >> 7) == 0) &&
(edx == 0)
- );
+ );
}
- };
+ };
auto leaf_05 = [&]() -> bool {
const u32 edx = fetch_register(EDX, 0x40000005);
debug("05 edx = ", std::bitset<32>(edx));
debug(" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
return (edx == 0);
- };
+ };
auto leaf_06 = [&]() -> bool {
u32 eax, ebx, ecx, edx = 0;
@@ -7255,18 +7218,19 @@ struct VM {
ebx != 0 ||
ecx != 0 ||
edx != 0 // edx is supposed to be null
- ) {
+ ) {
return false;
- } else {
+ }
+ else {
return (
((eax & (1 << 15)) == 0) &&
((eax >> 25) == 0) &&
(ebx == 0) &&
(ecx == 0) &&
(edx == 0)
- );
+ );
}
- };
+ };
auto leaf_09 = [&]() -> bool {
u32 eax, ebx, ecx, edx = 0;
@@ -7286,9 +7250,10 @@ struct VM {
ebx != 0 ||
ecx != 0 ||
edx == 0
- ) {
+ ) {
return false;
- } else {
+ }
+ else {
return (
((eax & 0b11) == 0) &&
((eax & (1 << 3)) == 0) &&
@@ -7300,9 +7265,9 @@ struct VM {
(((edx >> 5) & 0b1111111111) == 0) &&
((edx & (1 << 16)) == 0) &&
((edx >> 18) == 0)
- );
+ );
}
- };
+ };
auto leaf_0A = [&]() -> bool {
u32 eax, ebx, ecx, edx = 0;
@@ -7322,18 +7287,19 @@ struct VM {
eax == 0 ||
ecx != 0 ||
edx != 0
- ) {
+ ) {
return false;
- } else {
+ }
+ else {
return (
((eax & (1 << 16)) == 0) &&
((eax >> 21) == 0) &&
((ebx >> 30) == 0) &&
(ecx == 0) &&
(edx == 0)
- );
+ );
}
- };
+ };
debug("01: ", leaf_01());
debug("03: ", leaf_03());
@@ -7351,7 +7317,7 @@ struct VM {
leaf_06() &&
leaf_09() &&
leaf_0A()
- ) {
+ ) {
return core::add(brands::HYPERV);
}
@@ -7377,7 +7343,7 @@ struct VM {
(ebx == 0x4b4d564b) &&
(ecx == 0x564b4d56) &&
(edx == 0x4d)
- )) {
+ )) {
return false;
}
@@ -7387,7 +7353,7 @@ struct VM {
(eax & (1 << 8)) &&
(((eax >> 13) & 0b1111111111) == 0) &&
((eax >> 24) == 0)
- ) {
+ ) {
return core::add(brands::KVM);
}
@@ -7413,7 +7379,7 @@ struct VM {
// Not sure if it's little endian or big endian, so i'm comparing both
((ecx == 0x4D4D5645) && (edx == 0x43544E49)) ||
((ecx == 0x45564D4D) && (edx == 0x494E5443))
- ) {
+ ) {
return core::add(brands::INTEL_KGT);
}
@@ -7445,7 +7411,7 @@ struct VM {
return false;
#endif
- }
+ }
/**
@@ -7491,19 +7457,19 @@ struct VM {
if (
util::exists(sys_vendor) &&
util::exists(modalias)
- ) {
+ ) {
const std::string sys_vendor_str = util::read_file(sys_vendor);
const std::string modalias_str = util::read_file(modalias);
return (
util::find(sys_vendor_str, "QEMU") &&
util::find(modalias_str, "QEMU")
- );
+ );
}
return false;
#endif
- }
+ }
/**
@@ -7518,16 +7484,23 @@ struct VM {
return false;
}
- const char* usb_path = "/sys/kernel/debug/usb/devices";
+ constexpr const char* usb_path = "/sys/kernel/debug/usb/devices";
+
+ std::ifstream file(usb_path);
+ if (!file) {
+ return false;
+ }
- if (util::exists(usb_path)) {
- const std::string usb_path_str = util::read_file(usb_path);
- return (util::find(usb_path_str, "QEMU"));
+ std::string line;
+ while (std::getline(file, line)) {
+ if (line.find("QEMU") != std::string::npos) {
+ return true;
+ }
}
return false;
#endif
- }
+ }
/**
@@ -7549,9 +7522,9 @@ struct VM {
while ((entry = readdir(dir)) != nullptr) {
if (
- (entry->d_name[0] == '.' && entry->d_name[1] == '\0') ||
+ (entry->d_name[0] == '.' && entry->d_name[1] == '\0') ||
(entry->d_name[1] == '.' && entry->d_name[2] == '\0')
- ) {
+ ) {
continue;
}
@@ -7577,7 +7550,7 @@ struct VM {
// check if there's a few files in that directory
return ((count != 0) && type);
#endif
- }
+ }
/**
@@ -7609,7 +7582,7 @@ struct VM {
return false;
#endif
- }
+ }
/**
@@ -7640,12 +7613,15 @@ struct VM {
if (bytes_read > 0) {
buffer[bytes_read] = '\0';
ss << buffer;
- } else if (bytes_read == 0) {
+ }
+ else if (bytes_read == 0) {
usleep(100000); // Sleep for 100 milliseconds
- } else {
+ }
+ else {
if (errno == EAGAIN) {
usleep(100000); // Sleep for 100 milliseconds
- } else {
+ }
+ else {
debug("KMSG: Error reading /dev/kmsg");
break;
}
@@ -7666,7 +7642,7 @@ struct VM {
return (util::find(content, "Hypervisor detected"));
#endif
- }
+ }
/**
@@ -7688,7 +7664,7 @@ struct VM {
return false;
#endif
- }
+ }
/**
@@ -7740,7 +7716,7 @@ struct VM {
return false;
#endif
- }
+ }
/**
@@ -7758,7 +7734,7 @@ struct VM {
return (util::exists("/proc/device-tree/hypervisor/compatible"));
#endif
- }
+ }
/**
@@ -7776,7 +7752,7 @@ struct VM {
cat: /sys/class/dmi/id/product_uuid: Permission denied
*/
- constexpr std::array dmi_array {
+ constexpr std::array dmi_array{
"/sys/class/dmi/id/bios_vendor",
"/sys/class/dmi/id/board_name",
"/sys/class/dmi/id/board_vendor",
@@ -7786,7 +7762,7 @@ struct VM {
"/sys/class/dmi/id/sys_vendor"
};
- constexpr std::array, 15> vm_table {{
+ constexpr std::array, 15> vm_table{ {
{ "kvm", brands::KVM },
{ "openstack", brands::OPENSTACK },
{ "kubevirt", brands::KUBEVIRT },
@@ -7803,9 +7779,9 @@ struct VM {
{ "hyper-v", brands::HYPERV },
{ "apple virtualization", brands::APPLE_VZ },
{ "google compute engine", brands::GCE }
- }};
+ } };
- auto to_lower = [](std::string &str) {
+ auto to_lower = [](std::string& str) {
for (auto& c : str) {
if (c == ' ') {
continue;
@@ -7813,9 +7789,9 @@ struct VM {
c = static_cast(tolower(c));
}
- };
+ };
- for (const auto &vm_string : vm_table) {
+ for (const auto& vm_string : vm_table) {
for (const auto file : dmi_array) {
if (!util::exists(file)) {
continue;
@@ -7831,7 +7807,8 @@ struct VM {
if (smbios_vm_bit()) {
return core::add(brands::AWS_NITRO);
}
- } else {
+ }
+ else {
return core::add(vm_string.second);
}
}
@@ -7840,7 +7817,7 @@ struct VM {
return false;
#endif
- }
+ }
/**
@@ -7873,7 +7850,7 @@ struct VM {
return (content.at(19) & (1 << 4));
#endif
- }
+ }
/**
@@ -7909,21 +7886,21 @@ struct VM {
if (
util::exists(osrelease) &&
util::exists(version)
- ) {
+ ) {
const std::string osrelease_content = util::read_file(osrelease);
const std::string version_content = util::read_file(version);
if (
(util::find(osrelease_content, "WSL") || util::find(osrelease_content, "Microsoft")) &&
(util::find(version, "WSL") || util::find(version, "Microsoft"))
- ) {
+ ) {
return core::add(brands::WSL);
}
}
return false;
#endif
- }
+ }
/**
@@ -7944,8 +7921,8 @@ struct VM {
}
}
- std::transform(result.begin(), result.end(), result.begin(),
- [](unsigned char c) {
+ std::transform(result.begin(), result.end(), result.begin(),
+ [](unsigned char c) {
return static_cast(::tolower(c));
}
);
@@ -7970,7 +7947,7 @@ struct VM {
/**
* @brief Check for VM-specific names for drivers
* @category Windows
- * @author Requiem
+ * @author Requiem (https://github.com/NotRequiem)
*/
[[nodiscard]] static bool driver_names() {
#if (!WINDOWS)
@@ -8034,7 +8011,7 @@ struct VM {
if (ntQuerySystemInformation == nullptr || ntAllocateVirtualMemory == nullptr || ntFreeVirtualMemory == nullptr) // just to avoid compiler warnings
return false;
-
+
ULONG ulSize = 0;
NTSTATUS status = ntQuerySystemInformation(SystemModuleInformation, nullptr, 0, &ulSize);
if (status != STATUS_INFO_LENGTH_MISMATCH) return false;
@@ -8114,16 +8091,17 @@ struct VM {
* @author Requiem (https://github.com/NotRequiem)
*/
[[nodiscard]] static bool hdd_serial_number() {
-#if (!WINDOWS)
+#if (!WINDOWS)
return false;
#else
- const char* vboxSerial = "VBbd5bbffd-59166c24";
+ static const std::regex vboxRegex(R"(^VB[0-9a-f]{8}-[0-9a-f]{8}$)", std::regex_constants::icase);
const char* vmwareSerial = "39D8_B594_A8C5_AEF2_000C_296C_C5CE_FE12";
+
wmi_result results = wmi::execute(L"SELECT SerialNumber FROM Win32_DiskDrive", { L"SerialNumber" });
for (const auto& res : results) {
if (res.type == wmi::result_type::String) {
- if (_stricmp(res.strValue.c_str(), vboxSerial) == 0) {
+ if (std::regex_match(res.strValue, vboxRegex)) {
return core::add(brands::VBOX);
}
if (_stricmp(res.strValue.c_str(), vmwareSerial) == 0) {
@@ -8163,7 +8141,7 @@ struct VM {
}
wmi_result portResults = wmi::execute(L"SELECT * FROM Win32_PortConnector", { L"Caption" });
-
+
return results.empty();
#endif
};
@@ -8193,6 +8171,10 @@ struct VM {
if (util::find(res.strValue, "VMware Virtual NVMe Disk")) {
return core::add(brands::VMWARE);
}
+
+ if (util::find(res.strValue, "VBOX HARDDISK")) {
+ return core::add(brands::VBOX);
+ }
}
}
@@ -8272,35 +8254,29 @@ struct VM {
return reinterpret_cast(p);
};
- const unsigned char* x1 = ScanDataForString(cast(p), length, reinterpret_cast("INNOTEK GMBH"));
- const unsigned char* x2 = ScanDataForString(cast(p), length, reinterpret_cast("VIRTUALBOX"));
- const unsigned char* x3 = ScanDataForString(cast(p), length, reinterpret_cast("SUN MICROSYSTEMS"));
- const unsigned char* x4 = ScanDataForString(cast(p), length, reinterpret_cast("VBOXVER"));
- const unsigned char* x5 = ScanDataForString(cast(p), length, reinterpret_cast("VIRTUAL MACHINE"));
- const unsigned char* x6 = ScanDataForString(cast(p), length, reinterpret_cast("VMWARE"));
-
- std::string result = "";
- bool is_vm = false;
+ constexpr std::array strings_to_scan = { {
+ "INNOTEK GMBH",
+ "VBOXAPIC",
+ "SUN MICROSYSTEMS",
+ "VBOXVER",
+ "VIRTUAL MACHINE",
+ "VMWARE"
+ } };
- if (x1 || x2 || x3 || x4 || x5 || x6) {
- is_vm = true;
+ for (const char* search_str : strings_to_scan) {
+ const unsigned char* found = ScanDataForString(cast(p), length, reinterpret_cast(search_str));
+ if (found) {
#ifdef __VMAWARE_DEBUG__
- if (x1) { debug("SMBIOS: x1 = ", x1); result = std::string(reinterpret_cast(x1)); }
- if (x2) { debug("SMBIOS: x2 = ", x2); result = std::string(reinterpret_cast(x2)); }
- if (x3) { debug("SMBIOS: x3 = ", x3); result = std::string(reinterpret_cast(x3)); }
- if (x4) { debug("SMBIOS: x4 = ", x4); result = std::string(reinterpret_cast(x4)); }
- if (x5) { debug("SMBIOS: x5 = ", x5); result = std::string(reinterpret_cast(x5)); }
- if (x6) { debug("SMBIOS: x6 = ", x6); result = std::string(reinterpret_cast(x6)); }
+ debug("SMBIOS: found = ", found);
#endif
+ LocalFree(p);
+ RegCloseKey(hk);
+ return true;
+ }
}
LocalFree(p);
RegCloseKey(hk);
-
- if (is_vm) {
- return true;
- }
-
return false;
#endif
};
@@ -8343,8 +8319,8 @@ struct VM {
#else
for (const auto& pair : vm_gpu_names) {
const TCHAR* vm_gpu = pair.first;
- const char* brand = pair.second;
- if (deviceString == vm_gpu) {
+ if (deviceString.find(vm_gpu) != std::basic_string::npos) {
+ const char* brand = pair.second;
core::add(brand);
return true;
}
@@ -8377,9 +8353,8 @@ struct VM {
(handle1 != INVALID_HANDLE_VALUE) ||
(handle2 != INVALID_HANDLE_VALUE) ||
(handle3 != INVALID_HANDLE_VALUE) ||
- (handle4 != INVALID_HANDLE_VALUE) ||
- (handle5 != INVALID_HANDLE_VALUE)
- ) {
+ (handle4 != INVALID_HANDLE_VALUE)
+ ) {
result = true;
}
@@ -8387,88 +8362,146 @@ struct VM {
CloseHandle(handle2);
CloseHandle(handle3);
CloseHandle(handle4);
- CloseHandle(handle5);
if (result) {
return core::add(brands::VBOX);
}
+ if (handle5 != INVALID_HANDLE_VALUE) {
+ CloseHandle(handle5);
+ return core::add(brands::VMWARE);
+ }
+ CloseHandle(handle5);
+
return false;
#endif
- }
+ }
/**
- * @brief Check for VMware-specific memory traces in a specific process.
+ * @brief Check for specific VM memory traces in certain processes
* @category Windows
* @author Requiem (https://github.com/NotRequiem)
*/
- [[nodiscard]] static bool vmware_memory() {
+ [[nodiscard]] static bool vm_memory() {
#if (!WINDOWS)
return false;
#else
- const std::wstring searchString1 = L"_VMWARE_";
- const std::wstring searchString2 = L"VMware, Inc.";
-
- auto scan_service_memory = [](const std::wstring& searchString, const std::wstring& serviceName) -> bool {
+#if CPP >= 17
+ auto scan_service_for_brands = [](const std::wstring& serviceName, const std::vector>& checks) -> std::optional {
+#else
+ auto scan_service_for_brands = [](const std::wstring& serviceName, const std::vector>& checks, const char*& result) -> bool {
+#endif
const DWORD pid = util::FindProcessIdByServiceName(serviceName);
- if (pid == 0) return false; // Process missing; potentially tampered
+ if (pid == 0) {
+ return false;
+ }
util::EnableDebugPrivilege();
const HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
- if (!hProcess) return false; // Not running as admin or insufficient permissions
+ if (!hProcess) {
+ return false;
+ }
MEMORY_BASIC_INFORMATION mbi{};
uintptr_t address = 0x1000;
+ bool found = false;
+ const char* foundBrand = nullptr;
- while (VirtualQueryEx(hProcess, reinterpret_cast(address), &mbi, sizeof(mbi)) == sizeof(mbi)) {
- uintptr_t regionBase = reinterpret_cast(mbi.BaseAddress);
- if (regionBase == 0 || address == 0) {
+ while (!found && VirtualQueryEx(hProcess, reinterpret_cast(address), &mbi, sizeof(mbi)) == sizeof(mbi)) {
+ const uintptr_t regionBase = reinterpret_cast(mbi.BaseAddress);
+ if (regionBase == 0) {
address += mbi.RegionSize;
continue;
}
- if (
- (mbi.State == MEM_COMMIT) &&
- (mbi.Protect & (PAGE_READWRITE)) &&
- !(mbi.Protect & PAGE_GUARD) &&
- !(mbi.Protect & PAGE_NOACCESS)
- ) {
- size_t regionSize = static_cast(mbi.RegionSize);
+ if ((mbi.State == MEM_COMMIT) &&
+ (mbi.Protect & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)) &&
+ !(mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)))
+ {
+ const size_t regionSize = static_cast(mbi.RegionSize);
std::vector buffer(regionSize / sizeof(wchar_t));
SIZE_T bytesRead = 0;
if (ReadProcessMemory(hProcess, reinterpret_cast(regionBase), buffer.data(), buffer.size() * sizeof(wchar_t), &bytesRead) && bytesRead > 0) {
- if (util::findSubstring(buffer.data(), bytesRead / sizeof(wchar_t), searchString)) {
- CloseHandle(hProcess);
- return true;
+ const size_t charCount = bytesRead / sizeof(wchar_t);
+#if CPP >= 17
+ for (const auto& [searchString, brand] : checks) {
+#else
+ for (const auto& check_pair : checks) {
+ const std::wstring& searchString = check_pair.first;
+ const char* brand = check_pair.second;
+#endif
+ if (util::findSubstring(buffer.data(), charCount, searchString)) {
+ found = true;
+ foundBrand = brand;
+ break;
+ }
+ }
}
}
- }
address = regionBase + mbi.RegionSize;
- }
+ }
CloseHandle(hProcess);
- return false;
- };
- if (scan_service_memory(searchString1, L"PlugPlay")) {
- return core::add(brands::VMWARE);
- }
+#if CPP >= 17
+ return found ? std::optional(foundBrand) : std::nullopt;
+#else
+ if (found) result = foundBrand;
+ return found;
+#endif
+ };
- if (scan_service_memory(searchString2, L"Winmgmt")) {
- return core::add(brands::VMWARE);
- }
+ // CDPSvc check for manufacturer
+#if CPP >= 17
+ if (const auto brand = scan_service_for_brands(L"CDPSvc", { { L"VMware, Inc.", VM::brands::VMWARE } })) {
+ return core::add(*brand);
+ }
+#else
+ const char* cdpsvcBrand;
+ if (scan_service_for_brands(L"CDPSvc", { { L"VMware, Inc.", VM::brands::VMWARE } }, cdpsvcBrand)) {
+ return core::add(cdpsvcBrand);
+ }
+#endif
+
+ // Diagnostic Policy Service checks based on file execution detection in the System Resource Usage Monitor database
+ const std::vector> dps_checks = {
+ { L"VBoxTray", VM::brands::VBOX },
+ { L"joeboxserver.exe", VM::brands::JOEBOX },
+ { L"joeboxcontrol.exe", VM::brands::JOEBOX },
+ { L"prl_cc.exe", VM::brands::PARALLELS },
+ { L"prl_tools.exe", VM::brands::PARALLELS },
+ { L"vboxservice.exe", VM::brands::VBOX },
+ { L"vboxtray.exe", VM::brands::VBOX },
+ { L"vmsrvc.exe", VM::brands::VPC },
+ { L"vmusrvc.exe", VM::brands::VPC },
+ { L"xenservice.exe", VM::brands::XEN },
+ { L"xsvc_depriv.exe", VM::brands::XEN },
+ { L"vm3dservice.exe", VM::brands::VMWARE },
+ { L"VGAuthService.exe", VM::brands::VMWARE },
+ { L"vmtoolsd.exe", VM::brands::VMWARE },
+ { L"qemu-ga.exe", VM::brands::QEMU },
+ { L"vdagent.exe", VM::brands::QEMU },
+ { L"vdservice.exe", VM::brands::QEMU }
+ };
- if (scan_service_memory(searchString2, L"CDPSvc")) {
- return core::add(brands::VMWARE);
+#if CPP >= 17
+ if (const auto brand = scan_service_for_brands(L"DPS", dps_checks)) {
+ return core::add(*brand);
+ }
+#else
+ const char* dpsBrand;
+ if (scan_service_for_brands(L"DPS", dps_checks, dpsBrand)) {
+ return core::add(dpsBrand);
}
+#endif
return false;
#endif
- }
+ }
/**
@@ -8501,7 +8534,7 @@ struct VM {
#pragma pack(push, 1)
struct DescriptorTablePointer {
uint16_t limit;
- uint64_t base;
+ uint64_t base;
};
#pragma pack(pop)
@@ -8509,11 +8542,11 @@ struct VM {
DescriptorTablePointer gdtr = {};
__sidt(&idtr);
- _sgdt(&gdtr);
+ _sgdt(&gdtr);
gdtResults[i] = std::to_string(gdtr.base);
idtResults[i] = std::to_string(idtr.base);
- });
+ });
}
for (auto& thread : threads) {
@@ -8576,9 +8609,8 @@ struct VM {
for (const auto& result : results) {
if (result.type == wmi::result_type::Integer) {
- std::wcout << result.intValue << std::endl;
if (result.intValue < 2) {
- return true;
+ return true;
}
}
}
@@ -8639,7 +8671,7 @@ struct VM {
}
if (result.strValue == "innotek GmbH") {
return core::add(brands::VBOX);
- }
+ }
if (result.strValue == "Xen") {
return core::add(brands::XEN);
}
@@ -8648,6 +8680,19 @@ struct VM {
}
}
}
+
+ query = L"SELECT Model FROM Win32_ComputerSystem";
+ properties = { L"Model" };
+ results = wmi::execute(query, properties);
+
+ for (const auto& result : results) {
+ if (result.type == wmi::result_type::String) {
+ if (result.strValue == "Google Compute Engine") {
+ return core::add(brands::GCE);
+ }
+ }
+ }
+
return false;
#endif
}
@@ -8727,13 +8772,13 @@ struct VM {
* @category Windows
* @note This has been revised multiple times with previously removed techniques
*/
- [[nodiscard]]
+ [[nodiscard]]
#if (LINUX)
// this is added so that no sanitizers can potentially cause unwanted delays while measuring rdtsc in a debug compilation
__attribute__((no_sanitize("address", "leak", "thread", "undefined")))
#endif
-static bool rdtsc() {
+ static bool rdtsc() {
#if (ARM && !x86)
return false;
#else
@@ -8746,11 +8791,11 @@ static bool rdtsc() {
for (int i = 0; i < iterations; i++) {
start = __rdtsc();
- #if (WINDOWS)
+#if (WINDOWS)
__cpuid(cpu_info, 0);
- #elif (LINUX || APPLE)
+#elif (LINUX || APPLE)
__cpuid(0, eax, ebx, ecx, edx);
- #endif
+#endif
end = __rdtsc();
total_cycles += (end - start);
@@ -8840,28 +8885,28 @@ static bool rdtsc() {
}
- /**
- * @brief Check for existence of qemu_fw_cfg directories within sys/module and /sys/firmware
- * @category Linux
- */
- [[nodiscard]] static bool sys_qemu_dir() {
+ /**
+ * @brief Check for existence of qemu_fw_cfg directories within sys/module and /sys/firmware
+ * @category Linux
+ */
+ [[nodiscard]] static bool sys_qemu_dir() {
#if (!LINUX)
- return false;
+ return false;
#else
- const std::string module_path = "/sys/module/qemu_fw_cfg/";
- const std::string firmware_path = "/sys/firmware/qemu_fw_cfg/";
-
- #if (CPP >= 17)
+ const std::string module_path = "/sys/module/qemu_fw_cfg/";
+ const std::string firmware_path = "/sys/firmware/qemu_fw_cfg/";
+
+#if (CPP >= 17)
namespace fs = std::filesystem;
- return (
- fs::is_directory(module_path) &&
- fs::is_directory(firmware_path) &&
- fs::exists(module_path) &&
- fs::exists(firmware_path)
- );
- #else
- auto is_directory(const std::string& path) -> bool {
+ return (
+ fs::is_directory(module_path) &&
+ fs::is_directory(firmware_path) &&
+ fs::exists(module_path) &&
+ fs::exists(firmware_path)
+ );
+#else
+ auto is_directory(const std::string & path) -> bool {
struct stat info;
if (stat(path.c_str(), &info) != 0) {
return false;
@@ -8869,66 +8914,66 @@ static bool rdtsc() {
return (info.st_mode & S_IFDIR); // check if directory
};
- return (
- is_directory(module_path) &&
- is_directory(firmware_path) &&
- util::exists(module_path) &&
- util::exists(firmware_path)
- );
- #endif
+ return (
+ is_directory(module_path) &&
+ is_directory(firmware_path) &&
+ util::exists(module_path) &&
+ util::exists(firmware_path)
+ );
#endif
- }
+#endif
+ }
- /**
- * @brief Check for QEMU string instances with lshw command
- * @category Linux
- */
- [[nodiscard]] static bool lshw_qemu() {
+ /**
+ * @brief Check for QEMU string instances with lshw command
+ * @category Linux
+ */
+ [[nodiscard]] static bool lshw_qemu() {
#if (!LINUX)
- return false;
+ return false;
#else
- if (!(
- (util::exists("/usr/bin/lshw")) ||
+ if (!(
+ (util::exists("/usr/bin/lshw")) ||
(util::exists("/bin/lshw")) ||
(util::exists("/usr/sbin/lshw"))
- )) {
- debug("LSHW_QEMU: ", "binary doesn't exist");
- return false;
- }
-
- const std::unique_ptr result = util::sys_result("lshw 2>&1");
-
- if (result == nullptr) {
- debug("LSHW_QEMU: ", "invalid stdout output from lshw");
- return false;
- }
-
- const std::string full_command = *result;
-
- u8 score = 0;
+ )) {
+ debug("LSHW_QEMU: ", "binary doesn't exist");
+ return false;
+ }
+
+ const std::unique_ptr result = util::sys_result("lshw 2>&1");
+
+ if (result == nullptr) {
+ debug("LSHW_QEMU: ", "invalid stdout output from lshw");
+ return false;
+ }
+
+ const std::string full_command = *result;
+
+ u8 score = 0;
auto qemu_finder = [&](const char* str) -> void {
- if (util::find(full_command, str)) {
+ if (util::find(full_command, str)) {
debug("LSHW_QEMU: found ", str);
- score++;
+ score++;
}
- };
-
- qemu_finder("QEMU PCIe Root port");
- qemu_finder("QEMU XHCI Host Controller");
- qemu_finder("QEMU DVD-ROM");
- qemu_finder("QEMU QEMU USB Tablet");
-
- return (score >= 3); // if one of the strings above were detected 3 times, flag as VM
+ };
+
+ qemu_finder("QEMU PCIe Root port");
+ qemu_finder("QEMU XHCI Host Controller");
+ qemu_finder("QEMU DVD-ROM");
+ qemu_finder("QEMU QEMU USB Tablet");
+
+ return (score >= 3); // if one of the strings above were detected 3 times, flag as VM
#endif
- }
+ }
/**
* @brief Check if the maximum number of virtual processors matches the maximum number of logical processors
* @category Windows
- * @author Requiem
+ * @author Requiem (https://github.com/NotRequiem)
*/
[[nodiscard]] static bool virtual_processors() {
#if (!WINDOWS)
@@ -8959,7 +9004,10 @@ static bool rdtsc() {
implementationLimits.MaxVirtualProcessors = static_cast(registers.eax);
implementationLimits.MaxLogicalProcessors = static_cast(registers.ebx);
- if (implementationLimits.MaxLogicalProcessors != implementationLimits.MaxVirtualProcessors) {
+ if (implementationLimits.MaxVirtualProcessors != implementationLimits.MaxLogicalProcessors) {
+ return true;
+ }
+ if (implementationLimits.MaxVirtualProcessors == 0 || implementationLimits.MaxLogicalProcessors == 0) {
return true;
}
@@ -8971,7 +9019,7 @@ static bool rdtsc() {
/*
* @brief Detects if the motherboard product matches the signature of a virtual machine
* @category Windows
- * @author Requiem
+ * @author Requiem (https://github.com/NotRequiem)
*/
[[nodiscard]] static bool motherboard_product() {
#if (!WINDOWS)
@@ -9338,42 +9386,40 @@ static bool rdtsc() {
}
- /**
- * @brief Check for AMD-SEV MSR running on the system
- * @category x86, Linux, MacOS
- * @note idea from virt-what
- */
- [[nodiscard]] static bool amd_sev() {
+ /**
+ * @brief Check for AMD-SEV MSR running on the system
+ * @category x86, Linux, MacOS
+ * @note idea from virt-what
+ */
+ [[nodiscard]] static bool amd_sev() {
#if (!x86 && !LINUX && !APPLE)
- return false;
-#else
-
- if (!cpu::is_amd()) {
- return false;
- }
-
- if (!util::is_admin()) {
- return false;
- }
-
- constexpr u32 encrypted_memory_capability = 0x8000001f;
- constexpr u32 msr_index = 0xc0010131;
-
-
- if (!cpu::is_leaf_supported(encrypted_memory_capability)) {
- return false;
- }
-
- u32 eax, unused = 0;
- cpu::cpuid(eax, unused, unused, unused, encrypted_memory_capability);
-
-
- if (!(eax & (1 << 1))) {
- return false;
- }
-
- u64 result = 0;
-
+ return false;
+#else
+ if (!cpu::is_amd()) {
+ return false;
+ }
+
+ if (!util::is_admin()) {
+ return false;
+ }
+
+ constexpr u32 encrypted_memory_capability = 0x8000001f;
+ constexpr u32 msr_index = 0xc0010131;
+
+ if (!cpu::is_leaf_supported(encrypted_memory_capability)) {
+ return false;
+ }
+
+ u32 eax, unused = 0;
+ cpu::cpuid(eax, unused, unused, unused, encrypted_memory_capability);
+
+
+ if (!(eax & (1 << 1))) {
+ return false;
+ }
+
+ u64 result = 0;
+
const std::string msr_device = "/dev/cpu/0/msr";
std::ifstream msr_file(msr_device, std::ios::binary);
@@ -9392,12 +9438,912 @@ static bool rdtsc() {
if (result & (static_cast(1) << 2)) { return core::add(brands::AMD_SEV_SNP); }
else if (result & (static_cast(1) << 1)) { return core::add(brands::AMD_SEV_ES); }
- else if (result & 1) { return core::add(brands::AMD_SEV); }
-
- return false;
+ else if (result & 1) { return core::add(brands::AMD_SEV); }
+
+ return false;
#endif
- }
+ }
+
+ /**
+ * @brief Check for bits that should be reserved in leaf 8000000Ah
+ * @category x86
+ * @note https://en.wikipedia.org/wiki/CPUID#EAX=8000'000Ah:_SVM_features
+ */
+ [[nodiscard]] static bool amd_reserved() {
+#if (!x86)
+ return false;
+#else
+ if (!cpu::is_amd()) {
+ return false;
+ }
+
+ if (!cpu::is_leaf_supported(0x8000000A)) {
+ return false;
+ }
+
+ u32 eax = 0, ebx = 0, ecx = 0, edx = 0;
+ cpu::cpuid(eax, ebx, ecx, edx, 0x8000000A, 0);
+
+ // EAX: Check bits 31:8
+ if (eax & 0xFFFFFF00) {
+ return true;
+ }
+
+ // EBX: Check bits 31:8
+ if (ebx & 0xFFFFFF00) {
+ return true;
+ }
+
+ // ECX must be zero
+ if (ecx != 0) {
+ return true;
+ }
+
+ // EDX: Check reserved bits 9,11,14,22
+ if (edx & ((1 << 9) | (1 << 11) | (1 << 14) | (1 << 22))) {
+ return true;
+ }
+
+ return false;
+#endif
+ }
+
+
+ /**
+ * @brief Check for AMD CPU thread count database if it matches the system's thread count
+ * @link https://www.amd.com/en/products/specifications/processors.html
+ * @category x86
+ * @note
+ */
+ [[nodiscard]] static bool amd_thread_mismatch() {
+#if (!x86)
+ return false;
+#else
+ if (!cpu::is_amd()) {
+ return false;
+ }
+
+ if (cpu::has_hyperthreading()) {
+ return false;
+ }
+
+ std::string model = cpu::get_brand();
+
+ for (char& c : model) {
+ c = static_cast(std::tolower(c));
+ }
+
+#if (WINDOWS)
+ if (util::does_threadcount_mismatch()) {
+ debug("AMD_THREAD_MISMATCH: Thread tampering detected");
+ return true;
+ }
+#endif
+
+ debug("AMD_THREAD_MISMATCH: CPU model = ", model);
+
+ constexpr std::array, 559> thread_database = { {
+ { "3015ce ", 4 },
+ { "3015e ", 4 },
+ { "3020e ", 2 },
+ { "860k ", 4 },
+ { "870k ", 4 },
+ { "a10 pro-7350b ", 4 },
+ { "a10 pro-7800b ", 4 },
+ { "a10 pro-7850b ", 4 },
+ { "a10-6700 ", 4 },
+ { "a10-6700t ", 4 },
+ { "a10-6790b ", 4 },
+ { "a10-6790k ", 4 },
+ { "a10-6800b ", 4 },
+ { "a10-6800k ", 4 },
+ { "a10-7300 ", 4 },
+ { "a10-7400p ", 4 },
+ { "a10-7700k ", 4 },
+ { "a10-7800 ", 4 },
+ { "a10-7850k ", 4 },
+ { "a10-7860k ", 4 },
+ { "a10-7870k ", 4 },
+ { "a10-8700b ", 4 },
+ { "a10-8700p ", 4 },
+ { "a10-8750b ", 4 },
+ { "a10-8850b ", 4 },
+ { "a12-8800b ", 4 },
+ { "a4 micro-6400t ", 4 },
+ { "a4 pro-3340b ", 4 },
+ { "a4 pro-3350b ", 4 },
+ { "a4 pro-7300b ", 2 },
+ { "a4 pro-7350b ", 2 },
+ { "a4-5000 ", 4 },
+ { "a4-5100 ", 4 },
+ { "a4-6210 ", 4 },
+ { "a4-6300 ", 2 },
+ { "a4-6320 ", 2 },
+ { "a4-7210 ", 4 },
+ { "a4-7300 ", 2 },
+ { "a4-8350b ", 2 },
+ { "a4-9120c ", 2 },
+ { "a6 pro-7050b ", 2 },
+ { "a6 pro-7400b ", 2 },
+ { "a6-5200 ", 4 },
+ { "a6-5200m ", 4 },
+ { "a6-5350m ", 2 },
+ { "a6-6310 ", 4 },
+ { "a6-6400b ", 2 },
+ { "a6-6400k ", 2 },
+ { "a6-6420b ", 2 },
+ { "a6-6420k ", 2 },
+ { "a6-7000 ", 2 },
+ { "a6-7310 ", 4 },
+ { "a6-7400k ", 2 },
+ { "a6-8500b ", 4 },
+ { "a6-8500p ", 2 },
+ { "a6-8550b ", 2 },
+ { "a6-9220c ", 2 },
+ { "a8 pro-7150b ", 4 },
+ { "a8 pro-7600b ", 4 },
+ { "a8-6410 ", 4 },
+ { "a8-6500 ", 4 },
+ { "a8-6500b ", 4 },
+ { "a8-6500t ", 4 },
+ { "a8-6600k ", 4 },
+ { "a8-7100 ", 4 },
+ { "a8-7200p ", 4 },
+ { "a8-7410 ", 4 },
+ { "a8-7600 ", 4 },
+ { "a8-7650k ", 4 },
+ { "a8-7670k ", 4 },
+ { "a8-8600b ", 4 },
+ { "a8-8600p ", 4 },
+ { "a8-8650b ", 4 },
+ { "ai 5 340 ", 12 },
+ { "ai 5 pro 340 ", 12 },
+ { "ai 7 350 ", 16 },
+ { "ai 7 pro 350 ", 16 },
+ { "ai 7 pro 360 ", 16 },
+ { "ai 9 365 ", 20 },
+ { "ai 9 hx 370 ", 24 },
+ { "ai 9 hx 375 ", 24 },
+ { "ai 9 hx pro 370 ", 24 },
+ { "ai 9 hx pro 375 ", 24 },
+ { "ai max 385 ", 16 },
+ { "ai max 390 ", 24 },
+ { "ai max pro 380 ", 12 },
+ { "ai max pro 385 ", 16 },
+ { "ai max pro 390 ", 24 },
+ { "ai max+ 395 ", 32 },
+ { "ai max+ pro 395 ", 32 },
+ { "athlon silver 3050c ", 2 }, // there's an extra space in the AMD specifications for some reason, which I assume it's a typo. I added the fixed and typo'd version just in case.
+ { "athlon silver 3050c ", 2 },
+ { "athlon 200ge ", 4 },
+ { "athlon 220ge ", 4 },
+ { "athlon 240ge ", 4 },
+ { "athlon 255e ", 2 },
+ { "athlon 3000g ", 4 },
+ { "athlon 300ge ", 4 },
+ { "athlon 300u ", 4 },
+ { "athlon 320ge ", 4 },
+ { "athlon 425e ", 3 },
+ { "athlon 460 ", 3 },
+ { "athlon 5150 ", 4 },
+ { "athlon 5350 ", 4 },
+ { "athlon 5370 ", 4 },
+ { "athlon 620e ", 4 },
+ { "athlon 631 ", 4 },
+ { "athlon 638 ", 4 },
+ { "athlon 641 ", 4 },
+ { "athlon 740 ", 4 },
+ { "athlon 750k ", 4 },
+ { "athlon 760k ", 4 },
+ { "athlon 860k ", 4 },
+ { "athlon gold 3150c ", 4 },
+ { "athlon gold 3150g ", 4 },
+ { "athlon gold 3150ge ", 4 },
+ { "athlon gold 3150u ", 4 },
+ { "athlon gold 7220c ", 4 },
+ { "athlon gold 7220u ", 4 },
+ { "athlon gold pro 3150g ", 4 },
+ { "athlon gold pro 3150ge ", 4 },
+ { "athlon pro 200ge ", 4 },
+ { "athlon pro 200u ", 4 },
+ { "athlon pro 300ge ", 4 },
+ { "athlon pro 300u ", 4 },
+ { "athlon pro 3045b ", 2 },
+ { "athlon pro 3145b ", 4 },
+ { "athlon silver 3050e ", 4 },
+ { "athlon silver 3050ge ", 4 },
+ { "athlon silver 3050u ", 2 },
+ { "athlon silver 7120c ", 2 },
+ { "athlon silver 7120u ", 2 },
+ { "athlon silver pro 3125ge ", 4 },
+ { "athlon x4 940 ", 4 },
+ { "athlon x4 950 ", 4 },
+ { "athlon x4 970 ", 4 },
+ { "b57 ", 2 },
+ { "b59 ", 2 },
+ { "b60 ", 2 },
+ { "b75 ", 3 },
+ { "b77 ", 3 },
+ { "b97 ", 4 },
+ { "b99 ", 4 },
+ { "e1 micro-6200t ", 2 },
+ { "e1-2100 ", 2 },
+ { "e1-2200 ", 2 },
+ { "e1-2500 ", 2 },
+ { "e1-6010 ", 2 },
+ { "e1-7010 ", 2 },
+ { "e2-3000 ", 2 },
+ { "e2-3800 ", 4 },
+ { "e2-6110 ", 4 },
+ { "e2-7110 ", 4 },
+ { "fx 6100 ", 6 },
+ { "fx-4100 ", 4 },
+ { "fx-4130 ", 4 },
+ { "fx-4170 ", 4 },
+ { "fx-4300 ", 4 },
+ { "fx-4320 ", 4 },
+ { "fx-4350 ", 4 },
+ { "fx-6200 ", 6 },
+ { "fx-6300 ", 6 },
+ { "fx-6350 ", 6 },
+ { "fx-7500 ", 4 },
+ { "fx-7600p ", 4 },
+ { "fx-8120 ", 8 },
+ { "fx-8150 ", 8 },
+ { "fx-8300 ", 8 },
+ { "fx-8310 ", 8 },
+ { "fx-8320 ", 8 },
+ { "fx-8320e ", 8 },
+ { "fx-8350 ", 8 },
+ { "fx-8370 ", 8 },
+ { "fx-8370e ", 8 },
+ { "fx-8800p ", 4 },
+ { "fx-9370 ", 8 },
+ { "fx-9590 ", 8 },
+ { "micro-6700t ", 4 },
+ { "n640 ", 2 },
+ { "n660 ", 2 },
+ { "n870 ", 3 },
+ { "n960 ", 4 },
+ { "n970 ", 4 },
+ { "p650 ", 2 },
+ { "p860 ", 3 },
+ { "phenom ii 1075t ", 6 },
+ { "phenom ii 555 ", 2 },
+ { "phenom ii 565 ", 2 },
+ { "phenom ii 570 ", 2 },
+ { "phenom ii 840 ", 4 },
+ { "phenom ii 850 ", 4 },
+ { "phenom ii 960t ", 4 },
+ { "phenom ii 965 ", 4 },
+ { "phenom ii 975 ", 4 },
+ { "phenom ii 980 ", 4 },
+ { "ryzen 3 1200 ", 4 },
+ { "ryzen 3 1300x ", 4 },
+ { "ryzen 3 210 ", 8 },
+ { "ryzen 3 2200g ", 4 },
+ { "ryzen 3 2200ge ", 4 },
+ { "ryzen 3 2200u ", 4 },
+ { "ryzen 3 2300u ", 4 },
+ { "ryzen 3 2300x ", 4 },
+ { "ryzen 3 3100 ", 8 },
+ { "ryzen 3 3200g ", 4 },
+ { "ryzen 3 3200ge ", 4 },
+ { "ryzen 3 3200u ", 4 },
+ { "ryzen 3 3250c ", 4 },
+ { "ryzen 3 3250u ", 4 },
+ { "ryzen 3 3300u ", 4 },
+ { "ryzen 3 3300x ", 8 },
+ { "ryzen 3 3350u ", 4 },
+ { "ryzen 3 4100 ", 8 },
+ { "ryzen 3 4300g ", 8 },
+ { "ryzen 3 4300ge ", 8 },
+ { "ryzen 3 4300u ", 4 },
+ { "ryzen 3 5125c ", 4 },
+ { "ryzen 3 5300g ", 8 },
+ { "ryzen 3 5300ge ", 8 },
+ { "ryzen 3 5300u ", 8 },
+ { "ryzen 3 5305g ", 8 },
+ { "ryzen 3 5305ge ", 8 },
+ { "ryzen 3 5400u ", 8 },
+ { "ryzen 3 5425c ", 8 },
+ { "ryzen 3 5425u ", 8 },
+ { "ryzen 3 7320c ", 8 },
+ { "ryzen 3 7320u ", 8 },
+ { "ryzen 3 7330u ", 8 },
+ { "ryzen 3 7335u ", 8 },
+ { "ryzen 3 7440u ", 8 },
+ { "ryzen 3 8300g ", 8 },
+ { "ryzen 3 8300ge ", 8 },
+ { "ryzen 3 8440u ", 8 },
+ { "ryzen 3 pro 1200 ", 4 },
+ { "ryzen 3 pro 1300 ", 4 },
+ { "ryzen 3 pro 210 ", 8 },
+ { "ryzen 3 pro 2200g ", 4 },
+ { "ryzen 3 pro 2200ge ", 4 },
+ { "ryzen 3 pro 2300u ", 4 },
+ { "ryzen 3 pro 3200g ", 4 },
+ { "ryzen 3 pro 3200ge ", 4 },
+ { "ryzen 3 pro 3300u ", 4 },
+ { "ryzen 3 pro 4350g ", 8 },
+ { "ryzen 3 pro 4350ge ", 8 },
+ { "ryzen 3 pro 4355g ", 8 },
+ { "ryzen 3 pro 4355ge ", 8 },
+ { "ryzen 3 pro 4450u ", 8 },
+ { "ryzen 3 pro 5350g ", 8 },
+ { "ryzen 3 pro 5350ge ", 8 },
+ { "ryzen 3 pro 5355g ", 8 },
+ { "ryzen 3 pro 5355ge ", 8 },
+ { "ryzen 3 pro 5450u ", 8 },
+ { "ryzen 3 pro 5475u ", 8 },
+ { "ryzen 3 pro 7330u ", 8 },
+ { "ryzen 3 pro 7335u ", 8 },
+ { "ryzen 3 pro 8300g ", 8 },
+ { "ryzen 3 pro 8300ge ", 8 },
+ { "ryzen 5 1400 ", 8 },
+ { "ryzen 5 1500x ", 8 },
+ { "ryzen 5 1600 ", 12 },
+ { "ryzen 5 1600 (af )", 12 },
+ { "ryzen 5 1600x ", 12 },
+ { "ryzen 5 220 ", 12 },
+ { "ryzen 5 230 ", 12 },
+ { "ryzen 5 240 ", 12 },
+ { "ryzen 5 2400g ", 8 },
+ { "ryzen 5 2400ge ", 8 },
+ { "ryzen 5 2500u ", 8 },
+ { "ryzen 5 2500x ", 8 },
+ { "ryzen 5 2600 ", 12 },
+ { "ryzen 5 2600e ", 12 },
+ { "ryzen 5 2600h ", 8 },
+ { "ryzen 5 2600x ", 12 },
+ { "ryzen 5 3400g ", 8 },
+ { "ryzen 5 3400ge ", 8 },
+ { "ryzen 5 3450u ", 8 },
+ { "ryzen 5 3500 ", 6 },
+ { "ryzen 5 3500c ", 8 },
+ { "ryzen 5 3500u ", 8 },
+ { "ryzen 5 3550h ", 8 },
+ { "ryzen 5 3580u ", 8 },
+ { "ryzen 5 3600 ", 12 },
+ { "ryzen 5 3600x ", 12 },
+ { "ryzen 5 3600xt ", 12 },
+ { "ryzen 5 4500 ", 12 },
+ { "ryzen 5 4500u ", 6 },
+ { "ryzen 5 4600g ", 12 },
+ { "ryzen 5 4600ge ", 12 },
+ { "ryzen 5 4600h ", 12 },
+ { "ryzen 5 4600u ", 12 },
+ { "ryzen 5 4680u ", 12 },
+ { "ryzen 5 5500 ", 12 },
+ { "ryzen 5 5500gt ", 12 },
+ { "ryzen 5 5500h ", 8 },
+ { "ryzen 5 5500u ", 12 },
+ { "ryzen 5 5560u ", 12 },
+ { "ryzen 5 5600 ", 12 },
+ { "ryzen 5 5600g ", 12 },
+ { "ryzen 5 5600ge ", 12 },
+ { "ryzen 5 5600gt ", 12 },
+ { "ryzen 5 5600h ", 12 },
+ { "ryzen 5 5600hs ", 12 },
+ { "ryzen 5 5600t ", 12 },
+ { "ryzen 5 5600u ", 12 },
+ { "ryzen 5 5600x ", 12 },
+ { "ryzen 5 5600x3d ", 12 },
+ { "ryzen 5 5600xt ", 12 },
+ { "ryzen 5 5605g ", 12 },
+ { "ryzen 5 5605ge ", 12 },
+ { "ryzen 5 5625c ", 12 },
+ { "ryzen 5 5625u ", 12 },
+ { "ryzen 5 6600h ", 12 },
+ { "ryzen 5 6600hs ", 12 },
+ { "ryzen 5 6600u ", 12 },
+ { "ryzen 5 7235hs ", 8 },
+ { "ryzen 5 7400f ", 12 },
+ { "ryzen 5 7430u ", 12 },
+ { "ryzen 5 7500f ", 12 },
+ { "ryzen 5 7520c ", 8 },
+ { "ryzen 5 7520u ", 8 },
+ { "ryzen 5 7530u ", 12 },
+ { "ryzen 5 7535hs ", 12 },
+ { "ryzen 5 7535u ", 12 },
+ { "ryzen 5 7540u ", 12 },
+ { "ryzen 5 7545u ", 12 },
+ { "ryzen 5 7600 ", 12 },
+ { "ryzen 5 7600x ", 12 },
+ { "ryzen 5 7600x3d ", 12 },
+ { "ryzen 5 7640hs ", 12 },
+ { "ryzen 5 7640u ", 12 },
+ { "ryzen 5 7645hx ", 12 },
+ { "ryzen 5 8400f ", 12 },
+ { "ryzen 5 8500g ", 12 },
+ { "ryzen 5 8500ge ", 12 },
+ { "ryzen 5 8540u ", 12 },
+ { "ryzen 5 8600g ", 12 },
+ { "ryzen 5 8640hs ", 12 },
+ { "ryzen 5 8640u ", 12 },
+ { "ryzen 5 8645hs ", 12 },
+ { "ryzen 5 9600 ", 12 },
+ { "ryzen 5 9600x ", 12 },
+ { "ryzen 5 pro 1500 ", 8 },
+ { "ryzen 5 pro 1600 ", 12 },
+ { "ryzen 5 pro 220 ", 12 },
+ { "ryzen 5 pro 230 ", 12 },
+ { "ryzen 5 pro 2400g ", 8 },
+ { "ryzen 5 pro 2400ge ", 8 },
+ { "ryzen 5 pro 2500u ", 8 },
+ { "ryzen 5 pro 2600 ", 12 },
+ { "ryzen 5 pro 3350g ", 8 },
+ { "ryzen 5 pro 3350ge ", 4 },
+ { "ryzen 5 pro 3400g ", 8 },
+ { "ryzen 5 pro 3400ge ", 8 },
+ { "ryzen 5 pro 3500u ", 8 },
+ { "ryzen 5 pro 3600 ", 12 },
+ { "ryzen 5 pro 4650g ", 12 },
+ { "ryzen 5 pro 4650ge ", 12 },
+ { "ryzen 5 pro 4650u ", 12 },
+ { "ryzen 5 pro 4655g ", 12 },
+ { "ryzen 5 pro 4655ge ", 12 },
+ { "ryzen 5 pro 5645 ", 12 },
+ { "ryzen 5 pro 5650g ", 12 },
+ { "ryzen 5 pro 5650ge ", 12 },
+ { "ryzen 5 pro 5650u ", 12 },
+ { "ryzen 5 pro 5655g ", 12 },
+ { "ryzen 5 pro 5655ge ", 12 },
+ { "ryzen 5 pro 5675u ", 12 },
+ { "ryzen 5 pro 6650h ", 12 },
+ { "ryzen 5 pro 6650hs ", 12 },
+ { "ryzen 5 pro 6650u ", 12 },
+ { "ryzen 5 pro 7530u ", 12 },
+ { "ryzen 5 pro 7535u ", 12 },
+ { "ryzen 5 pro 7540u ", 12 },
+ { "ryzen 5 pro 7545u ", 12 },
+ { "ryzen 5 pro 7640hs ", 12 },
+ { "ryzen 5 pro 7640u ", 12 },
+ { "ryzen 5 pro 7645 ", 12 },
+ { "ryzen 5 pro 8500g ", 12 },
+ { "ryzen 5 pro 8500ge ", 12 },
+ { "ryzen 5 pro 8540u ", 12 },
+ { "ryzen 5 pro 8600g ", 12 },
+ { "ryzen 5 pro 8600ge ", 12 },
+ { "ryzen 5 pro 8640hs ", 12 },
+ { "ryzen 5 pro 8640u ", 12 },
+ { "ryzen 5 pro 8645hs ", 12 },
+ { "ryzen 7 1700 ", 16 },
+ { "ryzen 7 1700x ", 16 },
+ { "ryzen 7 1800x ", 16 },
+ { "ryzen 7 250 ", 16 },
+ { "ryzen 7 260 ", 16 },
+ { "ryzen 7 2700 ", 16 },
+ { "ryzen 7 2700e ", 16 },
+ { "ryzen 7 2700u ", 8 },
+ { "ryzen 7 2700x ", 16 },
+ { "ryzen 7 2800h ", 8 },
+ { "ryzen 7 3700c ", 8 },
+ { "ryzen 7 3700u ", 8 },
+ { "ryzen 7 3700x ", 16 },
+ { "ryzen 7 3750h ", 8 },
+ { "ryzen 7 3780u ", 8 },
+ { "ryzen 7 3800x ", 16 },
+ { "ryzen 7 3800xt ", 16 },
+ { "ryzen 7 4700g ", 16 },
+ { "ryzen 7 4700ge ", 16 },
+ { "ryzen 7 4700u ", 8 },
+ { "ryzen 7 4800h ", 16 },
+ { "ryzen 7 4800hs ", 16 },
+ { "ryzen 7 4800u ", 16 },
+ { "ryzen 7 4980u ", 16 },
+ { "ryzen 7 5700 ", 16 },
+ { "ryzen 7 5700g ", 16 },
+ { "ryzen 7 5700ge ", 16 },
+ { "ryzen 7 5700u ", 16 },
+ { "ryzen 7 5700x ", 16 },
+ { "ryzen 7 5700x3d ", 16 },
+ { "ryzen 7 5705g ", 16 },
+ { "ryzen 7 5705ge ", 16 },
+ { "ryzen 7 5800 ", 16 },
+ { "ryzen 7 5800h ", 16 },
+ { "ryzen 7 5800hs ", 16 },
+ { "ryzen 7 5800u ", 16 },
+ { "ryzen 7 5800x ", 16 },
+ { "ryzen 7 5800x3d ", 16 },
+ { "ryzen 7 5800xt ", 16 },
+ { "ryzen 7 5825c ", 16 },
+ { "ryzen 7 5825u ", 16 },
+ { "ryzen 7 6800h ", 16 },
+ { "ryzen 7 6800hs ", 16 },
+ { "ryzen 7 6800u ", 16 },
+ { "ryzen 7 7435hs ", 16 },
+ { "ryzen 7 7700 ", 16 },
+ { "ryzen 7 7700x ", 16 },
+ { "ryzen 7 7730u ", 16 },
+ { "ryzen 7 7735hs ", 16 },
+ { "ryzen 7 7735u ", 16 },
+ { "ryzen 7 7736u ", 16 },
+ { "ryzen 7 7745hx ", 16 },
+ { "ryzen 7 7800x3d ", 16 },
+ { "ryzen 7 7840hs ", 16 },
+ { "ryzen 7 7840hx ", 24 },
+ { "ryzen 7 7840u ", 16 },
+ { "ryzen 7 8700f ", 16 },
+ { "ryzen 7 8700g ", 16 },
+ { "ryzen 7 8840hs ", 16 },
+ { "ryzen 7 8840u ", 16 },
+ { "ryzen 7 8845hs ", 16 },
+ { "ryzen 7 9700x ", 16 },
+ { "ryzen 7 9800x3d ", 16 },
+ { "ryzen 7 pro 1700 ", 16 },
+ { "ryzen 7 pro 1700x ", 16 },
+ { "ryzen 7 pro 250 ", 16 },
+ { "ryzen 7 pro 2700 ", 16 },
+ { "ryzen 7 pro 2700u ", 8 },
+ { "ryzen 7 pro 2700x ", 16 },
+ { "ryzen 7 pro 3700 ", 16 },
+ { "ryzen 7 pro 3700u ", 8 },
+ { "ryzen 7 pro 4750g ", 16 },
+ { "ryzen 7 pro 4750ge ", 16 },
+ { "ryzen 7 pro 4750u ", 16 },
+ { "ryzen 7 pro 5750g ", 16 },
+ { "ryzen 7 pro 5750ge ", 16 },
+ { "ryzen 7 pro 5755g ", 16 },
+ { "ryzen 7 pro 5755ge ", 16 },
+ { "ryzen 7 pro 5845 ", 16 },
+ { "ryzen 7 pro 5850u ", 16 },
+ { "ryzen 7 pro 5875u ", 16 },
+ { "ryzen 7 pro 6850h ", 16 },
+ { "ryzen 7 pro 6850hs ", 16 },
+ { "ryzen 7 pro 6850u ", 16 },
+ { "ryzen 7 pro 6860z ", 16 },
+ { "ryzen 7 pro 7730u ", 16 },
+ { "ryzen 7 pro 7735u ", 16 },
+ { "ryzen 7 pro 7745 ", 16 },
+ { "ryzen 7 pro 7840hs ", 16 },
+ { "ryzen 7 pro 7840u ", 16 },
+ { "ryzen 7 pro 8700g ", 16 },
+ { "ryzen 7 pro 8700ge ", 16 },
+ { "ryzen 7 pro 8840hs ", 16 },
+ { "ryzen 7 pro 8840u ", 16 },
+ { "ryzen 7 pro 8845hs ", 16 },
+ { "ryzen 9 270 ", 16 },
+ { "ryzen 9 3900 processor ", 24 },
+ { "ryzen 9 3900x ", 24 },
+ { "ryzen 9 3900xt ", 24 },
+ { "ryzen 9 3950x ", 32 },
+ { "ryzen 9 4900h ", 16 },
+ { "ryzen 9 4900hs ", 16 },
+ { "ryzen 9 5900 ", 24 },
+ { "ryzen 9 5900hs ", 16 },
+ { "ryzen 9 5900hx ", 16 },
+ { "ryzen 9 5900x ", 24 },
+ { "ryzen 9 5900xt ", 32 },
+ { "ryzen 9 5950x ", 32 },
+ { "ryzen 9 5980hs ", 16 },
+ { "ryzen 9 5980hx ", 16 },
+ { "ryzen 9 6900hs ", 16 },
+ { "ryzen 9 6900hx ", 16 },
+ { "ryzen 9 6980hs ", 16 },
+ { "ryzen 9 6980hx ", 16 },
+ { "ryzen 9 7845hx ", 24 },
+ { "ryzen 9 7900 ", 24 },
+ { "ryzen 9 7900x ", 24 },
+ { "ryzen 9 7900x3d ", 24 },
+ { "ryzen 9 7940hs ", 16 },
+ { "ryzen 9 7940hx ", 32 },
+ { "ryzen 9 7945hx ", 32 },
+ { "ryzen 9 7945hx3d ", 32 },
+ { "ryzen 9 7950x ", 32 },
+ { "ryzen 9 7950x3d ", 32 },
+ { "ryzen 9 8945hs ", 16 },
+ { "ryzen 9 9850hx ", 24 },
+ { "ryzen 9 9900x ", 24 },
+ { "ryzen 9 9900x3d ", 24 },
+ { "ryzen 9 9950x ", 32 },
+ { "ryzen 9 9950x3d ", 32 },
+ { "ryzen 9 9955hx ", 32 },
+ { "ryzen 9 9955hx3d ", 32 },
+ { "ryzen 9 pro 3900 ", 24 },
+ { "ryzen 9 pro 5945 ", 24 },
+ { "ryzen 9 pro 6950h ", 16 },
+ { "ryzen 9 pro 6950hs ", 16 },
+ { "ryzen 9 pro 7940hs ", 16 },
+ { "ryzen 9 pro 7945 ", 24 },
+ { "ryzen 9 pro 8945hs ", 16 },
+ { "ryzen threadripper 1900x ", 16 },
+ { "ryzen threadripper 1920x ", 24 },
+ { "ryzen threadripper 1950x ", 32 },
+ { "ryzen threadripper 2920x ", 24 },
+ { "ryzen threadripper 2950x ", 32 },
+ { "ryzen threadripper 2970wx ", 48 },
+ { "ryzen threadripper 2990wx ", 64 },
+ { "ryzen threadripper 3960x ", 48 },
+ { "ryzen threadripper 3970x ", 64 },
+ { "ryzen threadripper 3990x ", 128 },
+ { "ryzen threadripper 7960x ", 48 },
+ { "ryzen threadripper 7970x ", 64 },
+ { "ryzen threadripper 7980x ", 128 },
+ { "ryzen threadripper pro 3945wx ", 24 },
+ { "ryzen threadripper pro 3955wx ", 32 },
+ { "ryzen threadripper pro 3975wx ", 64 },
+ { "ryzen threadripper pro 3995wx ", 128 },
+ { "ryzen threadripper pro 5945wx ", 24 },
+ { "ryzen threadripper pro 5955wx ", 32 },
+ { "ryzen threadripper pro 5965wx ", 48 },
+ { "ryzen threadripper pro 5975wx ", 64 },
+ { "ryzen threadripper pro 5995wx ", 128 },
+ { "ryzen threadripper pro 7945wx ", 24 },
+ { "ryzen threadripper pro 7955wx ", 32 },
+ { "ryzen threadripper pro 7965wx ", 48 },
+ { "ryzen threadripper pro 7975wx ", 64 },
+ { "ryzen threadripper pro 7985wx ", 128 },
+ { "ryzen threadripper pro 7995wx ", 192 },
+ { "ryzen z1 ", 12 },
+ { "ryzen z1 extreme ", 16 },
+ { "sempron 2650 ", 2 },
+ { "sempron 3850 ", 4 },
+ { "x940 ", 4 },
+ { "z2 extreme ", 16 },
+ { "z2 go ", 8 }
+ } };
+
+ bool found = false;
+
+ for (const auto& pair : thread_database) {
+ if (model.find(pair.first) != std::string::npos) {
+ found = (std::thread::hardware_concurrency() == static_cast(pair.second));
+ break;
+ }
+ }
+
+ return found;
+#endif
+ }
+
+
+ /**
+ * @brief Checks if the OS was booted from a VHD container
+ * @category Windows
+ */
+ [[nodiscard]] static bool native_vhd() {
+#if (!WINDOWS)
+ return false;
+#else
+ BOOL isNativeVhdBoot = FALSE;
+
+ if (IsNativeVhdBoot(&isNativeVhdBoot)) {
+ return isNativeVhdBoot == TRUE;
+ }
+
+ return false;
+#endif
+ }
+
+
+ /**
+ * @brief Checks for particular object directory which is present in Sandboxie virtual environment but not in usual host systems
+ * @category Windows
+ * @note https://evasions.checkpoint.com/src/Evasions/techniques/global-os-objects.html
+ */
+ [[nodiscard]] static bool virtual_registry() {
+#if (!WINDOWS)
+ return false;
+#else
+#pragma warning (disable: 4459)
+ typedef struct _UNICODE_STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+ PWSTR Buffer;
+ } UNICODE_STRING;
+ typedef UNICODE_STRING* PUNICODE_STRING;
+ typedef const UNICODE_STRING* PCUNICODE_STRING;
+
+ typedef struct _OBJECT_ATTRIBUTES {
+ ULONG Length;
+ HANDLE RootDirectory;
+ PUNICODE_STRING ObjectName;
+ ULONG Attributes;
+ PVOID SecurityDescriptor;
+ PVOID SecurityQualityOfService;
+ } OBJECT_ATTRIBUTES;
+ typedef OBJECT_ATTRIBUTES* POBJECT_ATTRIBUTES;
+
+ typedef enum _OBJECT_INFORMATION_CLASS {
+ ObjectBasicInformation = 0,
+ ObjectNameInformation = 1,
+ ObjectTypeInformation = 2
+ } OBJECT_INFORMATION_CLASS;
+
+ typedef struct _OBJECT_NAME_INFORMATION {
+ UNICODE_STRING Name;
+ } OBJECT_NAME_INFORMATION, * POBJECT_NAME_INFORMATION;
+#pragma warning (default : 4459)
+ HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
+ if (!hNtdll) return false;
+
+ typedef NTSTATUS(NTAPI* PNtOpenKey)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
+ typedef NTSTATUS(NTAPI* PNtQueryObject)(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+ typedef BOOLEAN(NTAPI* PRtlEqualUnicodeString)(PCUNICODE_STRING, PCUNICODE_STRING, BOOLEAN);
+#pragma warning (disable : 4191)
+ auto NtOpenKey = reinterpret_cast(GetProcAddress(hNtdll, "NtOpenKey"));
+ auto NtQueryObject = reinterpret_cast(GetProcAddress(hNtdll, "NtQueryObject"));
+ auto RtlEqualUnicodeString = reinterpret_cast(GetProcAddress(hNtdll, "RtlEqualUnicodeString"));
+#pragma warning (default : 4191)
+ if (!NtOpenKey || !NtQueryObject || !RtlEqualUnicodeString) return false;
+
+ UNICODE_STRING keyPath{};
+ keyPath.Buffer = const_cast(L"\\REGISTRY\\USER");
+ keyPath.Length = static_cast(wcslen(keyPath.Buffer) * sizeof(WCHAR));
+ keyPath.MaximumLength = keyPath.Length + sizeof(WCHAR);
+
+ OBJECT_ATTRIBUTES objAttr{};
+ {
+ (&objAttr)->Length = sizeof(OBJECT_ATTRIBUTES);
+ (&objAttr)->RootDirectory = nullptr;
+ (&objAttr)->Attributes = 0x00000040L;
+ (&objAttr)->ObjectName = &keyPath;
+ (&objAttr)->SecurityDescriptor = nullptr;
+ (&objAttr)->SecurityQualityOfService = 0;
+ };
+
+ HANDLE hKey = nullptr;
+ NTSTATUS status = NtOpenKey(&hKey, KEY_READ, &objAttr);
+ if (!(((NTSTATUS)(status)) >= 0)) return false;
+
+ BYTE buffer[1024]{};
+ ULONG returnedLength = 0;
+ status = NtQueryObject(hKey, ObjectNameInformation, buffer, sizeof(buffer), &returnedLength);
+ CloseHandle(hKey);
+
+ if (!(((NTSTATUS)(status)) >= 0)) return false;
+
+ auto pObjectName = reinterpret_cast(buffer);
+ UNICODE_STRING expectedName{};
+ expectedName.Buffer = const_cast(L"\\REGISTRY\\USER");
+ expectedName.Length = static_cast(wcslen(expectedName.Buffer) * sizeof(WCHAR));
+ expectedName.MaximumLength = expectedName.Length + sizeof(WCHAR);
+
+ if (!RtlEqualUnicodeString(&pObjectName->Name, &expectedName, TRUE)) {
+ return core::add(brands::SANDBOXIE);
+ }
+
+ return false;
+#endif
+ }
+
+
+ /**
+ * @brief Checks for VM signatures in firmware
+ * @category Windows
+ * @note https://github.com/hfiref0x/VMDE/blob/master/src/vmde/detect.c
+ */
+ [[nodiscard]] static bool firmware_scan() {
+#if (!WINDOWS)
+ return false;
+#else
+#pragma warning (disable: 4459)
+ typedef enum _SYSTEM_INFORMATION_CLASS {
+ SystemFirmwareTableInformation = 76
+ } SYSTEM_INFORMATION_CLASS;
+
+ typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION {
+ ULONG ProviderSignature;
+ ULONG Action;
+ ULONG TableID;
+ ULONG TableBufferLength;
+ UCHAR TableBuffer[1];
+ } SYSTEM_FIRMWARE_TABLE_INFORMATION, * PSYSTEM_FIRMWARE_TABLE_INFORMATION;
+#pragma warning (default : 4459)
+
+ typedef NTSTATUS(NTAPI* PNtQuerySystemInformation)(ULONG, PVOID, ULONG, PULONG);
+ constexpr ULONG STATUS_BUFFER_TOO_SMALL = 0xC0000023;
+ constexpr DWORD ACPI_SIG = 'ACPI';
+ constexpr DWORD RSMB_SIG = 'RSMB';
+ constexpr DWORD FIRM_SIG = 'FIRM';
+
+ const HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
+ if (!hNtdll) return false;
+
+ const auto NtQuery = reinterpret_cast(
+ GetProcAddress(hNtdll, "NtQuerySystemInformation"));
+ if (!NtQuery) return false;
+
+ const char* targets[] = {
+ "Parallels Software International", "Parallels(R)", "innotek",
+ "Oracle", "VirtualBox", "VS2005R2", "VMware, Inc.",
+ "VMware", "S3 Corp.", "Virtual Machine", "Qemu"
+ };
+
+ auto check_firmware_table = [&](DWORD signature, ULONG tableID) -> bool {
+ PSYSTEM_FIRMWARE_TABLE_INFORMATION info = nullptr;
+ ULONG retLen = 0;
+ NTSTATUS status;
+
+ info = static_cast(malloc(sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION)));
+ if (!info) return false;
+
+ info->ProviderSignature = signature;
+ info->Action = 1;
+ info->TableID = tableID;
+ info->TableBufferLength = 0;
+
+ status = NtQuery(76, info, sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION), &retLen);
+ if (status == STATUS_BUFFER_TOO_SMALL) {
+ free(info);
+ info = static_cast(malloc(retLen));
+ if (!info) return false;
+
+ info->ProviderSignature = signature;
+ info->Action = 1;
+ info->TableID = tableID;
+ info->TableBufferLength = retLen - sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION);
+
+ status = NtQuery(76, info, retLen, &retLen);
+ if (status >= 0) {
+ void* buffer = malloc(info->TableBufferLength);
+ if (buffer) {
+ memcpy(buffer, info->TableBuffer, info->TableBufferLength);
+ for (const char* target : targets) {
+ size_t len = strlen(target);
+ for (size_t j = 0; j <= info->TableBufferLength - len; ++j) {
+ if (memcmp((char*)buffer + j, target, len) == 0) {
+ free(buffer);
+ free(info);
+ return true;
+ }
+ }
+ }
+ free(buffer);
+ }
+ }
+ }
+ free(info);
+ return false;
+ };
+
+ if (check_firmware_table(RSMB_SIG, 0)) return true;
+ for (ULONG addr : { 0xC0000, 0xE0000 }) {
+ if (check_firmware_table(FIRM_SIG, addr)) return true;
+ }
+
+ PSYSTEM_FIRMWARE_TABLE_INFORMATION acpiEnum = nullptr;
+ ULONG retLen = 0;
+ NTSTATUS status;
+
+ acpiEnum = static_cast(malloc(sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION)));
+ if (!acpiEnum) return false;
+
+ acpiEnum->ProviderSignature = ACPI_SIG;
+ acpiEnum->Action = 0;
+ acpiEnum->TableID = 0;
+ acpiEnum->TableBufferLength = 0;
+
+ status = NtQuery(76, acpiEnum, sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION), &retLen);
+ if (status == STATUS_BUFFER_TOO_SMALL) {
+ free(acpiEnum);
+ acpiEnum = static_cast(malloc(retLen));
+ if (!acpiEnum) return false;
+
+ acpiEnum->ProviderSignature = ACPI_SIG;
+ acpiEnum->Action = 0;
+ acpiEnum->TableID = 0;
+ acpiEnum->TableBufferLength = retLen - sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION);
+
+ status = NtQuery(76, acpiEnum, retLen, &retLen);
+ if (status >= 0) {
+ const DWORD* tables = reinterpret_cast(acpiEnum->TableBuffer);
+ ULONG tableCount = acpiEnum->TableBufferLength / sizeof(DWORD);
+
+ for (ULONG t = 0; t < tableCount; ++t) {
+ if (check_firmware_table(ACPI_SIG, tables[t])) {
+ free(acpiEnum);
+ return true;
+ }
+ }
+ }
+ }
+ free(acpiEnum);
+ return false;
+#endif
+ }
// ADD NEW TECHNIQUE FUNCTION HERE
@@ -9421,7 +10367,7 @@ static bool rdtsc() {
struct core {
MSVC_DISABLE_WARNING(PADDING)
- struct technique {
+ struct technique {
u8 points = 0; // this is the certainty score between 0 and 100
std::function run; // this is the technique function itself
bool is_spoofable = false; // this is to indicate that the technique can be very easily spoofed (not guaranteed)
@@ -9434,16 +10380,16 @@ static bool rdtsc() {
};
MSVC_ENABLE_WARNING(PADDING)
- // initial technique list, this is where all the techniques are stored
- static std::pair technique_list[];
-
+ // initial technique list, this is where all the techniques are stored
+ static std::pair technique_list[];
+
// the actual table, which is derived from the list above and will be
// used for most functionalities related to technique interactions
static std::map technique_table;
// specific to VM::add_custom(), where custom techniques will be stored here
static std::vector custom_table;
-
+
// self-explanatory
static bool cpuid_supported;
@@ -9527,9 +10473,10 @@ static bool rdtsc() {
flags.test(DYNAMIC) ||
flags.test(NULL_ARG) ||
flags.test(MULTIPLE)
- ) {
+ ) {
flags |= DEFAULT;
- } else {
+ }
+ else {
throw std::invalid_argument("Invalid flag option found, aborting");
}
}
@@ -9541,7 +10488,7 @@ static bool rdtsc() {
const bool memo_enabled = core::is_disabled(flags, NO_MEMO);
u16 threshold_points = 150;
-
+
// set it to 300 if high threshold is enabled
if (core::is_enabled(flags, HIGH_THRESHOLD)) {
threshold_points = high_threshold_score;
@@ -9587,7 +10534,7 @@ static bool rdtsc() {
// the number of techniques that returned a positive
detected_count_num++;
}
-
+
// for things like VM::detect() and VM::percentage(),
// a score of 150+ is guaranteed to be a VM, so
// there's no point in running the rest of the techniques
@@ -9629,7 +10576,7 @@ static bool rdtsc() {
if (memo_enabled) {
memo::cache_store(
technique.id,
- result,
+ result,
technique.points
);
}
@@ -9646,17 +10593,17 @@ static bool rdtsc() {
* which could either be a std::bitset, a uint8_t, or a combination
* of both of them. This will handle both argument types and implement
* them depending on what their types are. If it's a std::bitset,
- * do the |= operation on flag_collector. If it's a uint8_t, simply
+ * do the |= operation on flag_collector. If it's a uint8_t, simply
* .set() that into the flag_collector. That's the gist of it.
*
* Also I won't even deny, the majority of this section was 90% generated
* by chatgpt. Can't be arsed with this C++ templatisation shit.
- * Like is it really my fault that I have a hard time understanging C++'s
- * god awful metaprogramming designs? And don't even get me started on SNIFAE.
- *
+ * Like is it really my fault that I have a hard time understanging C++'s
+ * god awful metaprogramming designs? And don't even get me started on SNIFAE.
+ *
* You don't need an IQ of 3 digits to realise how dogshit this language
* is, when you end up in situations where there's a few correct solutions
- * to a problem, but with a billion ways you can do the same thing but in
+ * to a problem, but with a billion ways you can do the same thing but in
* the "wrong" way. I genuinely can't wait for Carbon to come out.
*/
private:
@@ -9670,7 +10617,7 @@ static bool rdtsc() {
if (
(flag == INVALID) ||
(flag > enum_size)
- ) {
+ ) {
throw std::invalid_argument("Non-flag or invalid flag provided for VM::detect(), aborting");
}
@@ -9692,7 +10639,7 @@ static bool rdtsc() {
// Define derived classes for specific type implementations
struct TestBitsetHandler : public TestHandler {
- using TestHandler::handle;
+ using TestHandler::handle;
void handle(const flagset& flags) override {
flagset_manager(flags);
@@ -9700,7 +10647,7 @@ static bool rdtsc() {
};
struct TestUint8Handler : public TestHandler {
- using TestHandler::handle;
+ using TestHandler::handle;
void handle(const enum_flags flag) override {
flag_manager(flag);
@@ -9737,9 +10684,11 @@ static bool rdtsc() {
if (isType(first)) {
dispatch(first, bitsetHandler);
- } else if (isType(first)) {
+ }
+ else if (isType(first)) {
dispatch(first, uint8Handler);
- } else {
+ }
+ else {
const std::string msg =
"Arguments must either be a std::bitset<" +
std::to_string(static_cast(enum_size + 1)) +
@@ -9759,9 +10708,11 @@ static bool rdtsc() {
if (isType(first)) {
throw std::invalid_argument("Arguments must not contain VM::DEFAULT or VM::ALL, only technique flags are accepted (view the documentation for a full list)");
- } else if (isType(first)) {
+ }
+ else if (isType(first)) {
dispatch(first, uint8Handler);
- } else {
+ }
+ else {
throw std::invalid_argument("Arguments must be a technique flag, aborting");
}
@@ -9786,7 +10737,7 @@ static bool rdtsc() {
// return value by enabling the bits based on the argument.
template
static flagset arg_handler(Args&&... args) {
- if VMAWARE_CONSTEXPR (is_empty()) {
+ if VMAWARE_CONSTEXPR(is_empty()) {
return DEFAULT;
}
@@ -9807,7 +10758,7 @@ static bool rdtsc() {
static flagset disabled_arg_handler(Args&&... args) {
flag_collector.reset();
- if VMAWARE_CONSTEXPR (is_empty()) {
+ if VMAWARE_CONSTEXPR(is_empty()) {
throw std::invalid_argument("VM::DISABLE() must contain a flag");
}
@@ -9832,11 +10783,11 @@ static bool rdtsc() {
* @link https://github.com/kernelwernel/VMAware/blob/main/docs/documentation.md#vmcheck
*/
static bool check(
- const enum_flags flag_bit,
+ const enum_flags flag_bit,
const enum_flags memo_arg = NULL_ARG
// clang doesn't support std::source_location for some reason
#if (CPP >= 20 && !CLANG)
- , const std::source_location& loc = std::source_location::current()
+ , const std::source_location & loc = std::source_location::current()
#endif
) {
// lambda to manage exceptions
@@ -9847,7 +10798,7 @@ static bool rdtsc() {
#endif
ss << ". Consult the documentation's flag handler for VM::check()";
throw std::invalid_argument(std::string(text) + ss.str());
- };
+ };
// check if flag is out of range
if (flag_bit > enum_size) {
@@ -9860,14 +10811,14 @@ static bool rdtsc() {
(flag_bit == HIGH_THRESHOLD) ||
(flag_bit == DYNAMIC) ||
(flag_bit == MULTIPLE)
- ) {
+ ) {
throw_error("Flag argument must be a technique flag and not a settings flag");
}
if (
- (memo_arg != NO_MEMO) &&
+ (memo_arg != NO_MEMO) &&
(memo_arg != NULL_ARG)
- ) {
+ ) {
throw_error("Flag argument for memoization must be either VM::NO_MEMO or left empty");
}
@@ -9937,7 +10888,8 @@ static bool rdtsc() {
core_debug("VM::brand(): returned multi brand from cache");
return memo::multi_brand::fetch();
}
- } else {
+ }
+ else {
if (memo::brand::is_cached()) {
core_debug("VM::brand(): returned brand from cache");
return memo::brand::fetch();
@@ -9996,7 +10948,7 @@ static bool rdtsc() {
std::map brands;
// add the relevant brands with at least 1 point
- for (const auto &element : core::brand_scoreboard) {
+ for (const auto& element : core::brand_scoreboard) {
if (element.second > 0) {
brands.insert(std::make_pair(element.first, element.second));
}
@@ -10015,7 +10967,7 @@ static bool rdtsc() {
if (brands.size() == 1) {
return brands.begin()->first;
}
-
+
// remove Hyper-V artifacts if found with other
// brands, because that's not a VM. It's added
// only for the sake of information cuz of the
@@ -10031,12 +10983,12 @@ static bool rdtsc() {
if (
(brands.count(a) > 0) &&
(brands.count(b) > 0)
- ) {
+ ) {
brands.erase(a);
brands.erase(b);
brands.emplace(std::make_pair(result, 2));
}
- };
+ };
// same as above, but for 3
auto triple_merger = [&](const char* a, const char* b, const char* c, const char* result) -> void {
@@ -10044,13 +10996,13 @@ static bool rdtsc() {
(brands.count(a) > 0) &&
(brands.count(b) > 0) &&
(brands.count(c) > 0)
- ) {
+ ) {
brands.erase(a);
brands.erase(b);
brands.erase(c);
brands.emplace(std::make_pair(result, 2));
}
- };
+ };
// some edgecase handling for Hyper-V and VirtualPC since
@@ -10058,11 +11010,12 @@ static bool rdtsc() {
if ((brands.count(TMP_HYPERV) > 0) && (brands.count(TMP_VPC) > 0)) {
if (brands.count(TMP_HYPERV) == brands.count(TMP_VPC)) {
merger(TMP_VPC, TMP_HYPERV, TMP_HYPERV_VPC);
- } else {
+ }
+ else {
brands.erase(TMP_VPC);
}
}
-
+
// this is the section where brand post-processing will be done.
// The reason why this part is necessary is because it will
@@ -10077,35 +11030,35 @@ static bool rdtsc() {
// a more accurate idea of the brand(s) involved.
- 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, 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);
- merger(TMP_VMWARE_HARD, TMP_VMWARE, TMP_VMWARE_HARD);
- merger(TMP_VMWARE_HARD, TMP_FUSION, TMP_VMWARE_HARD);
- merger(TMP_VMWARE_HARD, TMP_EXPRESS, TMP_VMWARE_HARD);
- merger(TMP_VMWARE_HARD, TMP_ESX, TMP_VMWARE_HARD);
- merger(TMP_VMWARE_HARD, TMP_GSX, TMP_VMWARE_HARD);
+ merger(TMP_VMWARE_HARD, TMP_VMWARE, TMP_VMWARE_HARD);
+ merger(TMP_VMWARE_HARD, TMP_FUSION, TMP_VMWARE_HARD);
+ merger(TMP_VMWARE_HARD, TMP_EXPRESS, TMP_VMWARE_HARD);
+ merger(TMP_VMWARE_HARD, TMP_ESX, TMP_VMWARE_HARD);
+ merger(TMP_VMWARE_HARD, TMP_GSX, TMP_VMWARE_HARD);
merger(TMP_VMWARE_HARD, TMP_WORKSTATION, TMP_VMWARE_HARD);
// the brand element, which stores the NAME (const char*) and the SCORE (u8)
@@ -10117,14 +11070,14 @@ static bool rdtsc() {
std::vector vec(brands.begin(), brands.end());
std::sort(vec.begin(), vec.end(), [](
- const brand_element_t &a,
- const brand_element_t &b
- ) {
- return a.second < b.second;
- });
+ const brand_element_t& a,
+ const brand_element_t& b
+ ) {
+ return a.second < b.second;
+ });
return vec;
- };
+ };
std::vector vec = sorter();
std::string ret_str = "Unknown";
@@ -10135,7 +11088,8 @@ static bool rdtsc() {
// See VM::MULTIPLE flag in docs for more information.
if (!is_multiple) {
ret_str = vec.front().first;
- } else {
+ }
+ else {
std::stringstream ss;
std::size_t i = 1;
@@ -10152,7 +11106,8 @@ static bool rdtsc() {
if (is_multiple) {
core_debug("VM::brand(): cached multiple brand string");
memo::multi_brand::store(ret_str);
- } else {
+ }
+ else {
core_debug("VM::brand(): cached brand string");
memo::brand::store(ret_str);
}
@@ -10233,9 +11188,11 @@ static bool rdtsc() {
// above 150 to get to 100%
if (points >= threshold) {
percent = 100;
- } else if (points >= 100) {
+ }
+ else if (points >= 100) {
percent = 99;
- } else {
+ }
+ else {
percent = static_cast(points);
}
@@ -10254,7 +11211,7 @@ static bool rdtsc() {
std::function detection_func
// clang doesn't support std::source_location for some reason
#if (CPP >= 20 && !CLANG)
- , const std::source_location& loc = std::source_location::current()
+ , const std::source_location & loc = std::source_location::current()
#endif
) {
// lambda to throw the error
@@ -10265,7 +11222,7 @@ static bool rdtsc() {
#endif
ss << ". Consult the documentation's parameters for VM::add_custom()";
throw std::invalid_argument(std::string(text) + ss.str());
- };
+ };
if (percent > 100) {
throw_error("Percentage parameter must be between 0 and 100");
@@ -10322,122 +11279,125 @@ static bool rdtsc() {
*/
[[nodiscard]] static std::string flag_to_string(const enum_flags flag) {
switch (flag) {
- case VMID: return "VMID";
- case CPU_BRAND: return "CPU_BRAND";
- case HYPERVISOR_BIT: return "HYPERVISOR_BIT";
- case HYPERVISOR_STR: return "HYPERVISOR_STR";
- case RDTSC: return "RDTSC";
- case THREADCOUNT: return "THREADCOUNT";
- case MAC: return "MAC";
- case TEMPERATURE: return "TEMPERATURE";
- case SYSTEMD: return "SYSTEMD";
- case CVENDOR: return "CVENDOR";
- case CTYPE: return "CTYPE";
- case DOCKERENV: return "DOCKERENV";
- case DMIDECODE: return "DMIDECODE";
- case DMESG: return "DMESG";
- case HWMON: return "HWMON";
- case SIDT5: return "SIDT5";
- case DLL: return "DLL";
- case REGISTRY: return "REGISTRY";
- case VM_FILES: return "VM_FILES";
- case HWMODEL: return "HWMODEL";
- case DISK_SIZE: return "DISK_SIZE";
- case VBOX_DEFAULT: return "VBOX_DEFAULT";
- case VBOX_NETWORK: return "VBOX_NETWORK";
- case VM_PROCESSES: return "VM_PROCESSES";
- case LINUX_USER_HOST: return "LINUX_USER_HOST";
- case GAMARUE: return "GAMARUE";
- case VMID_0X4: return "VMID_0X4";
- case PARALLELS_VM: return "PARALLELS_VM";
- case QEMU_BRAND: return "QEMU_BRAND";
- case BOCHS_CPU: return "BOCHS_CPU";
- case BIOS_SERIAL: return "BIOS_SERIAL";
- case MSSMBIOS: return "MSSMBIOS";
- case MAC_MEMSIZE: return "MAC_MEMSIZE";
- case MAC_IOKIT: return "MAC_IOKIT";
- case IOREG_GREP: return "IOREG_GREP";
- case MAC_SIP: return "MAC_SIP";
- case HKLM_REGISTRIES: return "HKLM_REGISTRIES";
- case QEMU_GA: return "QEMU_GA";
- case VPC_INVALID: return "VPC_INVALID";
- case SIDT: return "SIDT";
- case SGDT: return "SGDT";
- case SLDT: return "SLDT";
- case OFFSEC_SIDT: return "OFFSEC_SIDT";
- case OFFSEC_SGDT: return "OFFSEC_SGDT";
- case OFFSEC_SLDT: return "OFFSEC_SLDT";
- case VPC_SIDT: return "VPC_SIDT";
- case VMWARE_IOMEM: return "VMWARE_IOMEM";
- case VMWARE_IOPORTS: return "VMWARE_IOPORTS";
- case VMWARE_SCSI: return "VMWARE_SCSI";
- case VMWARE_DMESG: return "VMWARE_DMESG";
- case VMWARE_STR: return "VMWARE_STR";
- case VMWARE_BACKDOOR: return "VMWARE_BACKDOOR";
- case VMWARE_PORT_MEM: return "VMWARE_PORT_MEM";
- case SMSW: return "SMSW";
- case MUTEX: return "MUTEX";
- case ODD_CPU_THREADS: return "ODD_CPU_THREADS";
- case INTEL_THREAD_MISMATCH: return "INTEL_THREAD_MISMATCH";
- case XEON_THREAD_MISMATCH: return "XEON_THREAD_MISMATCH";
- case NETTITUDE_VM_MEMORY: return "NETTITUDE_VM_MEMORY";
- case CPUID_BITSET: return "CPUID_BITSET";
- case CUCKOO_DIR: return "CUCKOO_DIR";
- case CUCKOO_PIPE: return "CUCKOO_PIPE";
- case HYPERV_HOSTNAME: return "HYPERV_HOSTNAME";
- case GENERAL_HOSTNAME: return "GENERAL_HOSTNAME";
- case SCREEN_RESOLUTION: return "SCREEN_RESOLUTION";
- case DEVICE_STRING: return "DEVICE_STRING";
- case BLUESTACKS_FOLDERS: return "BLUESTACKS_FOLDERS";
- case CPUID_SIGNATURE: return "CPUID_SIGNATURE";
- case HYPERV_BITMASK: return "HYPERV_BITMASK";
- case KVM_BITMASK: return "KVM_BITMASK";
- case KGT_SIGNATURE: return "KGT_SIGNATURE";
- case VMWARE_DMI: return "VMWARE_DMI";
- case VMWARE_EVENT_LOGS: return "VMWARE_EVENT_LOGS";
- case QEMU_VIRTUAL_DMI: return "QEMU_VIRTUAL_DMI";
- case QEMU_USB: return "QEMU_USB";
- case HYPERVISOR_DIR: return "HYPERVISOR_DIR";
- case UML_CPU: return "UML_CPU";
- case KMSG: return "KMSG";
- case VM_PROCS: return "VM_PROCS";
- case VBOX_MODULE: return "VBOX_MODULE";
- case SYSINFO_PROC: return "SYSINFO_PROC";
- case DEVICE_TREE: return "DEVICE_TREE";
- case DMI_SCAN: return "DMI_SCAN";
- case SMBIOS_VM_BIT: return "SMBIOS_VM_BIT";
- case PODMAN_FILE: return "PODMAN_FILE";
- case WSL_PROC: return "WSL_PROC";
- case GPU_CHIPTYPE: return "GPU_CHIPTYPE";
- case DRIVER_NAMES: return "DRIVER_NAMES";
- case VM_SIDT: return "VM_SIDT";
- case HDD_SERIAL: return "HDD_SERIAL";
- case PORT_CONNECTORS: return "PORT_CONNECTORS";
- case VM_HDD: return "VM_HDD";
- case ACPI_DETECT: return "ACPI_DETECT";
- case GPU_NAME: return "GPU_NAME";
- case VM_DEVICES: return "VM_DEVICES";
- case VMWARE_MEMORY: return "VMWARE_MEMORY";
- case IDT_GDT_MISMATCH: return "IDT_GDT_MISMATCH";
- case PROCESSOR_NUMBER: return "PROCESSOR_NUMBER";
- case NUMBER_OF_CORES: return "NUMBER_OF_CORES";
- case WMI_MODEL: return "WMI_MODEL";
- case WMI_MANUFACTURER: return "WMI_MANUFACTURER";
- case WMI_TEMPERATURE: return "WMI_TEMPERATURE";
- case PROCESSOR_ID: return "PROCESSOR_ID";
- case CPU_FANS: return "CPU_FANS";
- case POWER_CAPABILITIES: return "POWER_CAPABILITIES";
- case SETUPAPI_DISK: return "SETUPAPI_DISK";
- case VMWARE_HARDENER: return "VMWARE_HARDENER";
- case SYS_QEMU: return "SYS_QEMU";
- case LSHW_QEMU: return "LSHW_QEMU";
- case VIRTUAL_PROCESSORS: return "VIRTUAL_PROCESSORS";
- case MOTHERBOARD_PRODUCT: return "MOTHERBOARD_PRODUCT";
- case HYPERV_QUERY: return "HYPERV_QUERY";
- case BAD_POOLS: return "BAD_POOLS";
- case AMD_SEV: return "AMD_SEV";
- // ADD NEW CASE HERE FOR NEW TECHNIQUE
- default: return "Unknown flag";
+ case VMID: return "VMID";
+ case CPU_BRAND: return "CPU_BRAND";
+ case HYPERVISOR_BIT: return "HYPERVISOR_BIT";
+ case HYPERVISOR_STR: return "HYPERVISOR_STR";
+ case RDTSC: return "RDTSC";
+ case THREADCOUNT: return "THREADCOUNT";
+ case MAC: return "MAC";
+ case TEMPERATURE: return "TEMPERATURE";
+ case SYSTEMD: return "SYSTEMD";
+ case CVENDOR: return "CVENDOR";
+ case CTYPE: return "CTYPE";
+ case DOCKERENV: return "DOCKERENV";
+ case DMIDECODE: return "DMIDECODE";
+ case DMESG: return "DMESG";
+ case HWMON: return "HWMON";
+ case SIDT5: return "SIDT5";
+ case DLL: return "DLL";
+ case REGISTRY: return "REGISTRY";
+ case VM_FILES: return "VM_FILES";
+ case HWMODEL: return "HWMODEL";
+ case DISK_SIZE: return "DISK_SIZE";
+ case VBOX_DEFAULT: return "VBOX_DEFAULT";
+ case VBOX_NETWORK: return "VBOX_NETWORK";
+ case VM_PROCESSES: return "VM_PROCESSES";
+ case LINUX_USER_HOST: return "LINUX_USER_HOST";
+ case GAMARUE: return "GAMARUE";
+ case VMID_0X4: return "VMID_0X4";
+ case PARALLELS_VM: return "PARALLELS_VM";
+ case QEMU_BRAND: return "QEMU_BRAND";
+ case BOCHS_CPU: return "BOCHS_CPU";
+ case BIOS_SERIAL: return "BIOS_SERIAL";
+ case MSSMBIOS: return "MSSMBIOS";
+ case MAC_MEMSIZE: return "MAC_MEMSIZE";
+ case MAC_IOKIT: return "MAC_IOKIT";
+ case IOREG_GREP: return "IOREG_GREP";
+ case MAC_SIP: return "MAC_SIP";
+ case HKLM_REGISTRIES: return "HKLM_REGISTRIES";
+ case QEMU_GA: return "QEMU_GA";
+ case VPC_INVALID: return "VPC_INVALID";
+ case SIDT: return "SIDT";
+ case SGDT: return "SGDT";
+ case SLDT: return "SLDT";
+ case OFFSEC_SIDT: return "OFFSEC_SIDT";
+ case OFFSEC_SGDT: return "OFFSEC_SGDT";
+ case OFFSEC_SLDT: return "OFFSEC_SLDT";
+ case VPC_SIDT: return "VPC_SIDT";
+ case VMWARE_IOMEM: return "VMWARE_IOMEM";
+ case VMWARE_IOPORTS: return "VMWARE_IOPORTS";
+ case VMWARE_SCSI: return "VMWARE_SCSI";
+ case VMWARE_DMESG: return "VMWARE_DMESG";
+ case VMWARE_STR: return "VMWARE_STR";
+ case VMWARE_BACKDOOR: return "VMWARE_BACKDOOR";
+ case VMWARE_PORT_MEM: return "VMWARE_PORT_MEM";
+ case SMSW: return "SMSW";
+ case MUTEX: return "MUTEX";
+ case ODD_CPU_THREADS: return "ODD_CPU_THREADS";
+ case INTEL_THREAD_MISMATCH: return "INTEL_THREAD_MISMATCH";
+ case XEON_THREAD_MISMATCH: return "XEON_THREAD_MISMATCH";
+ case NETTITUDE_VM_MEMORY: return "NETTITUDE_VM_MEMORY";
+ case CPUID_BITSET: return "CPUID_BITSET";
+ case CUCKOO_DIR: return "CUCKOO_DIR";
+ case CUCKOO_PIPE: return "CUCKOO_PIPE";
+ case HYPERV_HOSTNAME: return "HYPERV_HOSTNAME";
+ case GENERAL_HOSTNAME: return "GENERAL_HOSTNAME";
+ case SCREEN_RESOLUTION: return "SCREEN_RESOLUTION";
+ case DEVICE_STRING: return "DEVICE_STRING";
+ case BLUESTACKS_FOLDERS: return "BLUESTACKS_FOLDERS";
+ case CPUID_SIGNATURE: return "CPUID_SIGNATURE";
+ case HYPERV_BITMASK: return "HYPERV_BITMASK";
+ case KVM_BITMASK: return "KVM_BITMASK";
+ case KGT_SIGNATURE: return "KGT_SIGNATURE";
+ case VMWARE_DMI: return "VMWARE_DMI";
+ case VMWARE_EVENT_LOGS: return "VMWARE_EVENT_LOGS";
+ case QEMU_VIRTUAL_DMI: return "QEMU_VIRTUAL_DMI";
+ case QEMU_USB: return "QEMU_USB";
+ case HYPERVISOR_DIR: return "HYPERVISOR_DIR";
+ case UML_CPU: return "UML_CPU";
+ case KMSG: return "KMSG";
+ case VM_PROCS: return "VM_PROCS";
+ case VBOX_MODULE: return "VBOX_MODULE";
+ case SYSINFO_PROC: return "SYSINFO_PROC";
+ case DEVICE_TREE: return "DEVICE_TREE";
+ case DMI_SCAN: return "DMI_SCAN";
+ case SMBIOS_VM_BIT: return "SMBIOS_VM_BIT";
+ case PODMAN_FILE: return "PODMAN_FILE";
+ case WSL_PROC: return "WSL_PROC";
+ case GPU_CHIPTYPE: return "GPU_CHIPTYPE";
+ case DRIVER_NAMES: return "DRIVER_NAMES";
+ case VM_SIDT: return "VM_SIDT";
+ case HDD_SERIAL: return "HDD_SERIAL";
+ case PORT_CONNECTORS: return "PORT_CONNECTORS";
+ case VM_HDD: return "VM_HDD";
+ case ACPI_DETECT: return "ACPI_DETECT";
+ case GPU_NAME: return "GPU_NAME";
+ case VM_DEVICES: return "VM_DEVICES";
+ case VM_MEMORY: return "VM_MEMORY";
+ case IDT_GDT_MISMATCH: return "IDT_GDT_MISMATCH";
+ case PROCESSOR_NUMBER: return "PROCESSOR_NUMBER";
+ case NUMBER_OF_CORES: return "NUMBER_OF_CORES";
+ case WMI_MODEL: return "WMI_MODEL";
+ case WMI_MANUFACTURER: return "WMI_MANUFACTURER";
+ case WMI_TEMPERATURE: return "WMI_TEMPERATURE";
+ case PROCESSOR_ID: return "PROCESSOR_ID";
+ case CPU_FANS: return "CPU_FANS";
+ case VMWARE_HARDENER: return "VMWARE_HARDENER";
+ case SYS_QEMU: return "SYS_QEMU";
+ case LSHW_QEMU: return "LSHW_QEMU";
+ case VIRTUAL_PROCESSORS: return "VIRTUAL_PROCESSORS";
+ case MOTHERBOARD_PRODUCT: return "MOTHERBOARD_PRODUCT";
+ case HYPERV_QUERY: return "HYPERV_QUERY";
+ case BAD_POOLS: return "BAD_POOLS";
+ case AMD_SEV: return "AMD_SEV";
+ case AMD_RESERVED: return "AMD_RESERVED";
+ case AMD_THREAD_MISMATCH: return "AMD_THREAD_MISMATCH";
+ case NATIVE_VHD: return "NATIVE_VHD";
+ case VIRTUAL_REGISTRY: return "VIRTUAL_REGISTRY";
+ case FIRMWARE_SCAN: return "FIRMWARE_SCAN";
+ // ADD NEW CASE HERE FOR NEW TECHNIQUE
+ default: return "Unknown flag";
}
}
@@ -10453,7 +11413,7 @@ static bool rdtsc() {
const u8 percent
// clang doesn't support std::source_location for some reason
#if (CPP >= 20 && !CLANG)
- , const std::source_location& loc = std::source_location::current()
+ , const std::source_location & loc = std::source_location::current()
#endif
) {
// lambda to throw the error
@@ -10464,7 +11424,7 @@ static bool rdtsc() {
#endif
ss << ". Consult the documentation's parameters for VM::modify_score()";
throw std::invalid_argument(std::string(text) + ss.str());
- };
+ };
if (percent > 100) {
throw_error("Percentage parameter must be between 0 and 100");
@@ -10479,12 +11439,12 @@ static bool rdtsc() {
throw_error("The flag is not a technique flag");
}
- using table_t = std::map;
+ 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.is_spoofable };
- };
+ };
modify(core::technique_table, flag, percent);
}
@@ -10522,7 +11482,7 @@ static bool rdtsc() {
return "Unknown";
}
- const std::map type_table {
+ const std::map type_table{
// type 1
{ brands::XEN, "Hypervisor (type 1)" },
{ brands::VMWARE_ESX, "Hypervisor (type 1)" },
@@ -10538,7 +11498,6 @@ static bool rdtsc() {
{ brands::INTEL_HAXM, "Hypervisor (type 1)" },
{ brands::INTEL_KGT, "Hypervisor (type 1)" },
{ brands::SIMPLEVISOR, "Hypervisor (type 1)" },
- { brands::GCE, "Hypervisor (type 1)" },
{ brands::OPENSTACK, "Hypervisor (type 1)" },
{ brands::KUBEVIRT, "Hypervisor (type 1)" },
{ brands::POWERVM, "Hypervisor (type 1)" },
@@ -10571,6 +11530,7 @@ static bool rdtsc() {
// misc
{ brands::BOCHS, "Emulator" },
{ brands::BLUESTACKS, "Emulator" },
+ { brands::NEKO_PROJECT, "Emulator" },
{ brands::QEMU, "Emulator/Hypervisor (type 2)" },
{ brands::JAILHOUSE, "Partitioning Hypervisor" },
{ brands::UNISYS, "Partitioning Hypervisor" },
@@ -10581,13 +11541,14 @@ static bool rdtsc() {
{ brands::LMHS, "Hypervisor (unknown type)" },
{ brands::WINE, "Compatibility layer" },
{ brands::INTEL_TDX, "Trusted Domain" },
- { brands::AMD_SEV, "" },
- { brands::AMD_SEV_ES, "" },
- { brands::AMD_SEV_SNP, "" },
{ brands::APPLE_VZ, "Unknown" },
{ brands::HYPERV_ARTIFACT, "Unknown" },
{ brands::UML, "Paravirtualised/Hypervisor (type 2)" },
{ brands::WSL, "Hybrid Hyper-V (type 1 and 2)" }, // debatable tbh
+ { brands::AMD_SEV, "VM encryptor" },
+ { brands::AMD_SEV_ES, "VM encryptor" },
+ { brands::AMD_SEV_SNP, "VM encryptor" },
+ { brands::GCE, "Cloud VM service" },
};
auto it = type_table.find(brand_str.c_str());
@@ -10625,8 +11586,8 @@ static bool rdtsc() {
const std::string very_likely = "Very likely";
const std::string inside_vm = "Running inside";
- auto make_conclusion = [&](const std::string &category) -> std::string {
- std::string article = "";
+ auto make_conclusion = [&](const std::string& category) -> std::string {
+ std::string article = "";
if (brand_tmp == brands::NULL_BRAND) {
brand_tmp = "unknown"; // this is basically just to remove the capital "U", since it would look weird to see "an Unknown"
@@ -10648,38 +11609,41 @@ static bool rdtsc() {
(brand_tmp == brands::AMD_SEV_ES) ||
(brand_tmp == brands::AMD_SEV_SNP) ||
(brand_tmp == brands::NULL_BRAND)
- ) {
+ ) {
article = " an ";
- } else {
+ }
+ else {
article = " a ";
}
if (brand_tmp == brands::HYPERV_ARTIFACT) {
- return (category + article + brand_tmp);
- } else {
+ return (category + article + brand_tmp);
+ }
+ else {
return (category + article + brand_tmp + " VM");
}
- };
+ };
if (core::is_enabled(flags, DYNAMIC)) {
- if (percent_tmp == 0) { return baremetal; }
- else if (percent_tmp <= 20) { return very_unlikely; }
- else if (percent_tmp <= 35) { return unlikely; }
- else if (percent_tmp < 50) { return make_conclusion(potentially); }
- else if (percent_tmp <= 62) { return make_conclusion(might); }
- else if (percent_tmp <= 75) { return make_conclusion(likely); }
- else if (percent_tmp < 100) { return make_conclusion(very_likely); }
- else { return make_conclusion(inside_vm); }
+ if (percent_tmp == 0) { return baremetal; }
+ else if (percent_tmp <= 20) { return very_unlikely; }
+ else if (percent_tmp <= 35) { return unlikely; }
+ else if (percent_tmp < 50) { return make_conclusion(potentially); }
+ else if (percent_tmp <= 62) { return make_conclusion(might); }
+ else if (percent_tmp <= 75) { return make_conclusion(likely); }
+ else if (percent_tmp < 100) { return make_conclusion(very_likely); }
+ else { return make_conclusion(inside_vm); }
}
if (percent_tmp == 100) {
return make_conclusion(inside_vm);
- } else {
+ }
+ else {
return baremetal;
}
}
- #pragma pack(push, 1)
+#pragma pack(push, 1)
struct vmaware {
std::string brand;
std::string type;
@@ -10702,7 +11666,7 @@ static bool rdtsc() {
technique_count = VM::technique_count;
}
};
- #pragma pack(pop)
+#pragma pack(pop)
static u16 technique_count; // get total number of techniques
@@ -10710,7 +11674,7 @@ static bool rdtsc() {
#ifdef __VMAWARE_DEBUG__
static u16 total_points;
#endif
-};
+ };
MSVC_ENABLE_WARNING(ASSIGNMENT_OPERATOR NO_INLINE_FUNC SPECTRE)
@@ -10784,6 +11748,7 @@ std::map VM::core::brand_scoreboard{
{ VM::brands::AMD_SEV, 0 },
{ VM::brands::AMD_SEV_ES, 0 },
{ VM::brands::AMD_SEV_SNP, 0 },
+ { VM::brands::NEKO_PROJECT, 0 },
{ VM::brands::NULL_BRAND, 0 }
};
@@ -10836,7 +11801,7 @@ VM::flagset VM::DEFAULT = []() noexcept -> flagset {
tmp.flip(MULTIPLE);
return tmp;
-}();
+ }();
// flag to enable every technique
@@ -10853,7 +11818,7 @@ VM::flagset VM::ALL = []() noexcept -> flagset {
tmp.flip(MULTIPLE);
return tmp;
-}();
+ }();
std::vector VM::technique_vector = []() -> std::vector {
@@ -10865,7 +11830,7 @@ std::vector VM::technique_vector = []() -> std::vector {
}
return tmp;
-}();
+ }();
// this value is incremented each time VM::add_custom is called
@@ -10888,7 +11853,7 @@ bool VM::core::cpuid_supported = []() -> bool {
#else
return false;
#endif
-}();
+ }();
// the 0~100 points are debatable, but I think it's fine how it is. Feel free to disagree.
@@ -10896,7 +11861,7 @@ std::pair VM::core::technique_list[] = {
// 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_BIT, { 100, VM::hypervisor_bit , false}} ,
{ VM::HYPERVISOR_STR, { 75, VM::hypervisor_str, false } },
{ VM::RDTSC, { 40, VM::rdtsc, false } },
{ VM::THREADCOUNT, { 25, VM::thread_count, false } },
@@ -10914,10 +11879,10 @@ std::pair VM::core::technique_list[] = {
{ VM::REGISTRY, { 50, VM::registry_key, true } },
{ VM::VM_FILES, { 25, VM::vm_files, true } },
{ VM::HWMODEL, { 35, VM::hwmodel, true } },
- { VM::DISK_SIZE, { 60, VM::disk_size, false } },
+ { VM::DISK_SIZE, { 60, VM::disk_size, false } },
{ VM::VBOX_DEFAULT, { 25, VM::vbox_default_specs, false } },
- { VM::VBOX_NETWORK, { 100, VM::vbox_network_share, false } },
- { VM::VM_PROCESSES, { 15, VM::vm_processes, true } },
+ { VM::VBOX_NETWORK, { 100, VM::vbox_network_share, false } },,
+ { VM::VM_PROCESSES, { 15, VM::vm_processes, true } },
{ VM::LINUX_USER_HOST, { 10, VM::linux_user_host, true } },
{ VM::GAMARUE, { 10, VM::gamarue, true } },
{ VM::VMID_0X4, { 100, VM::vmid_0x4, false } },
@@ -10928,58 +11893,58 @@ std::pair VM::core::technique_list[] = {
{ VM::MSSMBIOS, { 85, VM::mssmbios, false } },
{ VM::MAC_MEMSIZE, { 15, VM::hw_memsize, true } },
{ VM::MAC_IOKIT, { 40, VM::io_kit, true } },
- { VM::IOREG_GREP, { 30, VM::ioreg_grep, true } },
- { VM::MAC_SIP, { 40, VM::mac_sip, true } },
+ { VM::IOREG_GREP, { 30, VM::ioreg_grep, true } },
+ { VM::MAC_SIP, { 40, VM::mac_sip, true } },
{ VM::HKLM_REGISTRIES, { 25, VM::hklm_registries, true } },
- { VM::QEMU_GA, { 10, VM::qemu_ga, true } },
- { VM::VPC_INVALID, { 75, VM::vpc_invalid, false } },
+ { VM::QEMU_GA, { 10, VM::qemu_ga, true } },
+ { VM::VPC_INVALID, { 75, VM::vpc_invalid, false } },
{ VM::SIDT, { 25, 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::VMWARE_IOMEM, { 65, VM::vmware_iomem, 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::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_SCSI, { 40, VM::vmware_scsi, false } },
{ VM::VMWARE_DMESG, { 65, VM::vmware_dmesg, false } },
- { VM::VMWARE_STR, { 35, VM::vmware_str, 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::VMWARE_PORT_MEM, { 85, VM::vmware_port_memory, false } },
+ { VM::SMSW, { 30, VM::smsw, false } },
+ { VM::MUTEX, { 85, VM::mutex, false } },
{ VM::ODD_CPU_THREADS, { 80, VM::odd_cpu_threads, false } },
{ VM::INTEL_THREAD_MISMATCH, { 100, VM::intel_thread_mismatch, false } },
- { VM::XEON_THREAD_MISMATCH, { 85, VM::xeon_thread_mismatch, false } },
+ { VM::XEON_THREAD_MISMATCH, { 85, VM::xeon_thread_mismatch, false } },
{ VM::NETTITUDE_VM_MEMORY, { 100, VM::nettitude_vm_memory, false } },
{ VM::CPUID_BITSET, { 25, VM::cpuid_bitset, false } },
{ VM::CUCKOO_DIR, { 30, VM::cuckoo_dir, true } },
- { VM::CUCKOO_PIPE, { 30, VM::cuckoo_pipe, true } },
+ { VM::CUCKOO_PIPE, { 30, VM::cuckoo_pipe, true } },
{ VM::HYPERV_HOSTNAME, { 30, VM::hyperv_hostname, true } },
{ VM::GENERAL_HOSTNAME, { 10, VM::general_hostname, true } },
{ VM::SCREEN_RESOLUTION, { 20, VM::screen_resolution, false } },
{ VM::DEVICE_STRING, { 25, VM::device_string, false } },
- { VM::BLUESTACKS_FOLDERS, { 5, 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::BLUESTACKS_FOLDERS, { 5, 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, { 40, VM::vmware_dmi, false } },
{ VM::VMWARE_EVENT_LOGS, { 25, VM::vmware_event_logs, false } },
{ VM::QEMU_VIRTUAL_DMI, { 40, VM::qemu_virtual_dmi, false } },
{ VM::QEMU_USB, { 20, VM::qemu_USB, false } },
- { VM::HYPERVISOR_DIR, { 20, VM::hypervisor_dir, false } },
+ { VM::HYPERVISOR_DIR, { 20, VM::hypervisor_dir, false } },
{ VM::UML_CPU, { 80, VM::uml_cpu, false } },
- { VM::KMSG, { 5, VM::kmsg, true } },
- { VM::VM_PROCS, { 10, VM::vm_procs, true } },
- { VM::VBOX_MODULE, { 15, VM::vbox_module, false } },
- { VM::SYSINFO_PROC, { 15, VM::sysinfo_proc, false } },
- { VM::DEVICE_TREE, { 20, VM::device_tree, false } },
- { VM::DMI_SCAN, { 50, VM::dmi_scan, false } },
- { VM::SMBIOS_VM_BIT, { 50, VM::smbios_vm_bit, false } },
- { VM::PODMAN_FILE, { 5, VM::podman_file, true } },
- { VM::WSL_PROC, { 30, VM::wsl_proc_subdir, false } },
+ { VM::KMSG, { 5, VM::kmsg, true } },
+ { VM::VM_PROCS, { 10, VM::vm_procs, true } },
+ { VM::VBOX_MODULE, { 15, VM::vbox_module, false } },
+ { VM::SYSINFO_PROC, { 15, VM::sysinfo_proc, false } },
+ { VM::DEVICE_TREE, { 20, VM::device_tree, false } },
+ { VM::DMI_SCAN, { 50, VM::dmi_scan, false } },
+ { VM::SMBIOS_VM_BIT, { 50, VM::smbios_vm_bit, false } },
+ { VM::PODMAN_FILE, { 5, VM::podman_file, true } },
+ { VM::WSL_PROC, { 30, VM::wsl_proc_subdir, false } },
{ VM::GPU_CHIPTYPE, { 100, VM::gpu_chiptype, false } },
{ VM::DRIVER_NAMES, { 80, VM::driver_names, false } },
{ VM::VM_SIDT, { 100, VM::vm_sidt, false } },
@@ -10989,7 +11954,7 @@ std::pair VM::core::technique_list[] = {
{ VM::ACPI_DETECT, { 85, VM::acpi, false } },
{ VM::GPU_NAME, { 100, VM::vm_gpu, false } },
{ VM::VM_DEVICES, { 45, VM::vm_devices, true } },
- { VM::VMWARE_MEMORY, { 50, VM::vmware_memory, false } },
+ { VM::VM_MEMORY, { 80, VM::vm_memory, false } },
{ VM::IDT_GDT_MISMATCH, { 50, VM::idt_gdt_mismatch, false } },
{ VM::PROCESSOR_NUMBER, { 50, VM::processor_number, false } },
{ VM::NUMBER_OF_CORES, { 50, VM::number_of_cores, false } },
@@ -11005,7 +11970,12 @@ std::pair VM::core::technique_list[] = {
{ VM::MOTHERBOARD_PRODUCT, { 50, VM::motherboard_product, false } },
{ VM::HYPERV_QUERY, { 50, VM::hyperv_query, false } },
{ VM::BAD_POOLS, { 80, VM::bad_pools, false } },
- { VM::AMD_SEV, { 50, VM::amd_sev, false } },
+ { VM::AMD_SEV, { 50, VM::amd_sev, false } },
+ { VM::AMD_RESERVED, { 50, VM::amd_reserved, false } },
+ { VM::AMD_THREAD_MISMATCH, { 100, VM::amd_thread_mismatch, false } },
+ { VM::NATIVE_VHD, { 100, VM::native_vhd, false } },
+ { VM::VIRTUAL_REGISTRY, { 65, VM::virtual_registry, false } },
+ { VM::FIRMWARE_SCAN, { 90, VM::firmware_scan, false } },
// ADD NEW TECHNIQUE STRUCTURE HERE
};
@@ -11024,4 +11994,4 @@ table_t VM::core::technique_table = []() -> table_t {
table.insert(technique);
}
return table;
-}();
\ No newline at end of file
+ }();
\ No newline at end of file