diff --git a/.github/workflows/build_run_win_32.bat b/.github/workflows/build_run_win_32.bat
index 55a3b7c7..34d29c53 100644
--- a/.github/workflows/build_run_win_32.bat
+++ b/.github/workflows/build_run_win_32.bat
@@ -2,7 +2,7 @@ echo on
cd "%~dp0..\.."
mkdir build
cd build
-cmake -G "Visual Studio 17 2022" -A Win32 -S ..
+cmake -DCMAKE_BUILD_TYPE=Debug -G "Visual Studio 17 2022" -A Win32 -S ..
"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\devenv.com" "VMAware.sln" /Build "Release|Win32" /Project "vmaware" /ProjectConfig "Release|Win32"
cd Release
vmaware.exe
diff --git a/.github/workflows/build_run_win_64.bat b/.github/workflows/build_run_win_64.bat
index 546d164d..7e16a057 100644
--- a/.github/workflows/build_run_win_64.bat
+++ b/.github/workflows/build_run_win_64.bat
@@ -2,7 +2,7 @@ echo on
cd "%~dp0..\.."
mkdir build
cd build
-cmake -G "Visual Studio 17 2022" -A x64 -S ..
+cmake -DCMAKE_BUILD_TYPE=Debug -G "Visual Studio 17 2022" -A x64 -S ..
"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\devenv.com" "VMAware.sln" /Build "Release|x64" /Project "vmaware" /ProjectConfig "Release|x64"
cd Release
vmaware.exe
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fe4f6652..a4632255 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -47,7 +47,7 @@ set(TARGET "vmaware")
if (MSVC)
if(CMAKE_BUILD_TYPE MATCHES "Debug")
MESSAGE(STATUS "Build set to debug mode")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Od /RTC1 /debug")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Od /debug")
elseif(CMAKE_BUILD_TYPE MATCHES "Release")
MESSAGE(STATUS "Build set to release mode")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2")
diff --git a/README.md b/README.md
index ec5f0518..c3ce67f7 100644
--- a/README.md
+++ b/README.md
@@ -150,7 +150,7 @@ And if you found this project useful, a star would be appreciated :)
- Tom Liston + Ed Skoudis
- [Tobias Klein](https://www.trapkit.de/index.html)
- [(S21sec) Alfredo Omella](https://www.s21sec.com/)
-- [(eEye Digital Security) Derek Soeder]()
+- [hfiref0x](https://github.com/hfiref0x)
diff --git a/TODO.md b/TODO.md
index 52cd3559..6bfe8891 100644
--- a/TODO.md
+++ b/TODO.md
@@ -18,10 +18,15 @@
- [ ] fix memoization
- [X] add a python script to automatically set the lines of the seperate sections in the header
- [ ] add C++20 concepts for the VM::add_custom() function
-- [ ] check for valid monitor technique
+- [X] check for valid monitor technique
- [ ] fix the is_admin code for windows
-- [ ] test it on compiler explorer with windows 32-bit settings
+- [X] test it on compiler explorer with windows 32-bit settings
+- [ ] upload the lib to dnf
+- [ ] upload the lib to apt
+- [X] add ARM support
+- [ ] look into what `fv-az663-325` is
+- [ ] implement techniques from [here](https://labs.nettitude.com/blog/vm-detection-tricks-part-3-hyper-v-raw-network-protocol/)
+- [ ] add multiple choice for VM::brand()
# Distant plans
-- add ARM support
- add the library to conan.io when released
diff --git a/docs/documentation.md b/docs/documentation.md
index f6497e59..a96e0fbc 100644
--- a/docs/documentation.md
+++ b/docs/documentation.md
@@ -79,11 +79,18 @@ int main() {
This will essentially return the VM brand as a `std::string`. The exact possible brand string return values are:
- `VMware`
- `VirtualBox`
+- `VMware`
+- `VMware Express`
+- `VMware ESX`
+- `VMware GSX`
+- `VMware Workstation`
- `bhyve`
- `KVM`
- `QEMU`
- `QEMU+KVM`
- `Microsoft Hyper-V`
+- `Virtual PC`
+- `Microsoft Virtual PC/Hyper-V`
- `Microsoft x86-to-ARM`
- `Parallels`
- `Xen HVM`
@@ -94,7 +101,6 @@ This will essentially return the VM brand as a `std::string`. The exact possible
- `Docker`
- `Wine`
- `Virtual Apple`
-- `Virtual PC`
- `Anubis`
- `JoeBox`
- `Thread Expert`
@@ -267,9 +273,9 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::PARALLELS_VM` | Check for indications of Parallels VM | Windows | 50% | | |
| `VM::RDTSC_VMEXIT` | Check for RDTSC technique with VMEXIT | Yes | 50% | | |
| `VM::LOADED_DLLS` | Check for DLLs of multiple VM brands | Windows | 75% | | GPL |
-| `VM::QEMU_BRAND` | Check for QEMU CPU brand with cpuid | Yes | 100% | | |
+| `VM::QEMU_BRAND` | Check for QEMU CPU brand with cpuid | Yes | 100% | | |
| `VM::BOCHS_CPU` | Check for Bochs cpuid emulation oversights | Yes | 95% | | |
-| `VM::VPC_BOARD` | Check for VPC specific string in motherboard manufacturer | Windows | 20% | | |
+| `VM::VPC_BOARD` | Check for VPC specific string in motherboard manufacturer | Windows | 20% | | |
| `VM::HYPERV_WMI` | Check for Hyper-V wmi output | Windows | 80% | | |
| `VM::HYPERV_REG` | Check for Hyper-V strings in registry | Windows | 80% | | |
| `VM::BIOS_SERIAL` | Check if BIOS serial number is null | Windows | 60% | | |
diff --git a/src/cli.cpp b/src/cli.cpp
index 57b2f498..d38257a4 100644
--- a/src/cli.cpp
+++ b/src/cli.cpp
@@ -218,7 +218,7 @@ int main(int argc, char* argv[]) {
checker(VM::HYPERV_REG, "Hyper-V registry");
checker(VM::HYPERV_WMI, "Hyper-V WMI output");
checker(VM::VBOX_FOLDERS, "VirtualBox shared folders");
- checker(VM::VBOX_MSSMBIOS, "VirtualBox MSSMBIOS");
+ checker(VM::MSSMBIOS, "MSSMBIOS");
checker(VM::MAC_MEMSIZE, "MacOS hw.memsize");
checker(VM::MAC_IOKIT, "MacOS registry IO-kit");
checker(VM::IOREG_GREP, "IO registry grep");
@@ -247,15 +247,15 @@ int main(int argc, char* argv[]) {
checker(VM::VMWARE_IOPORTS, "/proc/ioports file");
checker(VM::VMWARE_SCSI, "/proc/scsi/scsi file");
checker(VM::VMWARE_DMESG, "VMware dmesg");
- checker(VM::VMWARE_EMULATION, "VMware emulation mode");
checker(VM::VMWARE_STR, "STR instruction");
checker(VM::VMWARE_BACKDOOR, "VMware IO port backdoor");
- checker(VM::SMSW, "SMSW instruction");
checker(VM::VMWARE_PORT_MEM, "VMware port memory");
+ checker(VM::SMSW, "SMSW instruction");
+ checker(VM::MUTEX, "mutex strings");
std::printf("\n");
- const std::string brand = VM::brand();
+ const std::string brand = VM::brand(VM::MULTIPLE);
std::cout << "VM brand: " << (brand == "Unknown" ? red : green) << brand << ansi_exit << "\n";
@@ -309,7 +309,7 @@ int main(int argc, char* argv[]) {
version();
return 0;
} else if (cmp(arg, "-b") || cmp(arg, "--brand")) {
- std::cout << VM::brand() << "\n";
+ std::cout << VM::brand(VM::MULTIPLE) << "\n";
return 0;
} else if (cmp(arg, "-p") || cmp(arg, "--percent")) {
std::cout << static_cast(VM::percentage()) << "\n";
diff --git a/src/vmaware.hpp b/src/vmaware.hpp
index 3d80b614..e035f5ca 100644
--- a/src/vmaware.hpp
+++ b/src/vmaware.hpp
@@ -294,7 +294,7 @@ struct VM {
HYPERV_REG,
BIOS_SERIAL,
VBOX_FOLDERS,
- VBOX_MSSMBIOS,
+ MSSMBIOS,
MAC_MEMSIZE,
MAC_IOKIT,
IOREG_GREP,
@@ -318,14 +318,15 @@ struct VM {
VMWARE_IOPORTS,
VMWARE_SCSI,
VMWARE_DMESG,
- VMWARE_EMULATION,
VMWARE_STR,
VMWARE_BACKDOOR,
VMWARE_PORT_MEM,
SMSW,
+ MUTEX,
EXTREME,
NO_MEMO,
- WIN_HYPERV_DEFAULT
+ WIN_HYPERV_DEFAULT,
+ MULTIPLE
};
private:
static constexpr u8 enum_size = __LINE__ - enum_line_start - 4; // get enum size
@@ -576,18 +577,6 @@ struct VM {
qnx = " QNXQVMBSQG ",
virtapple = "VirtualApple";
-#if (CPP >= 17)
- constexpr std::array IDs{
-#else
- std::array IDs {
-#endif
- bhyve, kvm, qemu,
- hyperv, parallels, parallels,
- parallels2, vmware, vbox,
- xen, acrn, qnx,
- virtapple
- };
-
auto cpuid_thingy = [](const u32 p_leaf, u32* regs, std::size_t start = 0, std::size_t end = 4) -> bool {
u32 x[4]{};
cpu::cpuid(x[0], x[1], x[2], x[3], p_leaf);
@@ -611,36 +600,48 @@ struct VM {
return str;
};
- std::stringstream ss;
- ss << strconvert(sig_reg[0]);
- ss << strconvert(sig_reg[2]);
- ss << strconvert(sig_reg[1]);
+ std::stringstream ss1;
+ std::stringstream ss2;
+
+ ss1 << strconvert(sig_reg[0]);
+ ss1 << strconvert(sig_reg[1]);
+ ss1 << strconvert(sig_reg[2]);
+
+ ss2 << strconvert(sig_reg[0]);
+ ss2 << strconvert(sig_reg[2]);
+ ss2 << strconvert(sig_reg[1]);
- brand = ss.str();
+ std::string brand1 = ss1.str();
+ std::string brand2 = ss2.str();
- debug(technique_name, brand);
+ debug(technique_name, brand1);
+ debug(technique_name, brand2);
#if (CPP < 17)
// bypass compiler warning about unused parameter, ignore this
UNUSED(technique_name);
#endif
- const bool found = (std::find(std::begin(IDs), std::end(IDs), brand) != std::end(IDs));
-
- if (found) {
- if (brand == qemu) { return core::add(QEMU); }
- if (brand == vmware) { return core::add(VMWARE); }
- if (brand == vbox) { return core::add(VBOX); }
- if (brand == bhyve) { return core::add(BHYVE); }
- if (brand == kvm) { return core::add(KVM); }
- if (brand == hyperv) { return core::add(HYPERV); }
- if (brand == xta) { return core::add(MSXTA); }
- if (brand == parallels) { return core::add(PARALLELS); }
- if (brand == parallels2) { return core::add(PARALLELS); }
- if (brand == xen) { return core::add(XEN); }
- if (brand == acrn) { return core::add(ACRN); }
- if (brand == qnx) { return core::add(QNX); }
- if (brand == virtapple) { return core::add(VAPPLE); }
+ const std::vector brand_streams = { brand1, brand2 };
+
+ for (const auto &tmp_brand : brand_streams) {
+ if (tmp_brand == qemu) { return core::add(QEMU); }
+ if (tmp_brand == vmware) { return core::add(VMWARE); }
+ if (tmp_brand == vbox) { return core::add(VBOX); }
+ if (tmp_brand == bhyve) { return core::add(BHYVE); }
+ if (tmp_brand == kvm) { return core::add(KVM); }
+ if (tmp_brand == xta) { return core::add(MSXTA); }
+ if (tmp_brand == parallels) { return core::add(PARALLELS); }
+ if (tmp_brand == parallels2) { return core::add(PARALLELS); }
+ if (tmp_brand == xen) { return core::add(XEN); }
+ if (tmp_brand == acrn) { return core::add(ACRN); }
+ if (tmp_brand == qnx) { return core::add(QNX); }
+ if (tmp_brand == virtapple) { return core::add(VAPPLE); }
+ if (tmp_brand == hyperv) {
+ bool tmp = core::add(VPC);
+ UNUSED(tmp);
+ return core::add(HYPERV);
+ }
}
/**
@@ -650,7 +651,7 @@ struct VM {
* but the Wikipedia article on CPUID says it's
* "KVMKVMKVM\0\0\0", like wtf????
*/
- if (util::find(brand, "KVM")) {
+ if (util::find(brand1, "KVM") || util::find(brand2, "KVM")) {
return core::add(KVM);
}
@@ -1980,19 +1981,19 @@ struct VM {
#else
const char* vendor_file = "/sys/devices/virtual/dmi/id/chassis_vendor";
- if (util::exists(vendor_file)) {
- const std::string vendor = util::read_file(vendor_file);
-
- // TODO: More can be definitely added, I only tried QEMU and VMware so far
- if (vendor == "QEMU") { return core::add(QEMU); }
- if (vendor == "Oracle Corporation") { return core::add(VMWARE); }
-
- debug("CVENDOR: ", "unknown vendor = ", vendor);
- }
- else {
+ if (!util::exists(vendor_file)) {
debug("CVENDOR: ", "file doesn't exist");
+ return false;
}
+ const std::string vendor = util::read_file(vendor_file);
+
+ // TODO: More can definitely be added, I only tried QEMU and VMware so far
+ if (vendor == "QEMU") { return core::add(QEMU); }
+ if (vendor == "Oracle Corporation") { return core::add(VMWARE); }
+
+ debug("CVENDOR: ", "unknown vendor = ", vendor);
+
return false;
#endif
}
@@ -2592,8 +2593,8 @@ struct VM {
}
}
- debug("VM_FILES: vmware score: ", vmware);
- debug("VM_FILES: vbox score: ", vbox);
+ debug("VM_FILES: vmware score: ", static_cast(vmware));
+ debug("VM_FILES: vbox score: ", static_cast(vbox));
if (vbox > vmware) {
return core::add(VBOX);
@@ -4172,14 +4173,14 @@ struct VM {
/**
- * @brief Check VirtualBox MSSMBIOS registry for VM-specific strings
+ * @brief Check MSSMBIOS registry for VM-specific strings
* @category Windows
* @note slightly modified from original code
* @author @waleedassar
* @link https://pastebin.com/fPY4MiYq
*/
- [[nodiscard]] static bool vbox_mssmbios() try {
- if (core::disabled(VBOX_MSSMBIOS)) {
+ [[nodiscard]] static bool mssmbios() try {
+ if (core::disabled(MSSMBIOS)) {
return false;
}
@@ -4223,7 +4224,7 @@ struct VM {
}
MSVC_DISABLE_WARNING(5045)
- auto ScanDataForString = [](unsigned char* data, unsigned long data_length, unsigned char* string2) -> unsigned char* {
+ auto ScanDataForString = [](unsigned char* data, unsigned long data_length, unsigned char* string2) -> unsigned char* {
std::size_t string_length = strlen(reinterpret_cast(string2));
for (std::size_t i = 0; i <= (data_length - string_length); i++) {
@@ -4233,27 +4234,27 @@ struct VM {
}
return 0;
- };
+ };
auto AllToUpper = [](char* str, std::size_t len) {
for (std::size_t i = 0; i < len; ++i) {
str[i] = static_cast(std::toupper(static_cast(str[i])));
}
- };
+ };
MSVC_ENABLE_WARNING(5045)
- AllToUpper(p, length);
+ AllToUpper(p, length);
// cleaner and better shortcut than typing reinterpret_cast a million times
auto cast = [](char* p) -> unsigned char* {
return reinterpret_cast(p);
- };
+ };
unsigned char* x1 = ScanDataForString(cast(p), length, (unsigned char*)("INNOTEK GMBH"));
unsigned char* x2 = ScanDataForString(cast(p), length, (unsigned char*)("VIRTUALBOX"));
unsigned char* x3 = ScanDataForString(cast(p), length, (unsigned char*)("SUN MICROSYSTEMS"));
- unsigned char* x4 = ScanDataForString(cast(p), length, (unsigned char*)("VIRTUAL MACHINE"));
- unsigned char* x5 = ScanDataForString(cast(p), length, (unsigned char*)("VBOXVER"));
+ unsigned char* x4 = ScanDataForString(cast(p), length, (unsigned char*)("VBOXVER"));
+ unsigned char* x5 = ScanDataForString(cast(p), length, (unsigned char*)("VIRTUAL MACHINE"));
if (x1 || x2 || x3 || x4 || x5) {
is_vm = true;
@@ -4270,6 +4271,10 @@ struct VM {
RegCloseKey(hk);
if (is_vm) {
+ if (x5) {
+ return true;
+ }
+
return core::add(VBOX);
}
@@ -5208,7 +5213,7 @@ struct VM {
#if (!MSVC)
return false;
#else
- constexpr std::array, 9> files = { {
+ constexpr std::array, 9> files = { {
{ VPC, "c:\\windows\\system32\\drivers\\vmsrvc.sys" },
{ VPC, "c:\\windows\\system32\\drivers\\vpc-s3.sys" },
{ PARALLELS, "c:\\windows\\system32\\drivers\\prleth.sys" },
@@ -5391,70 +5396,6 @@ struct VM {
}
- /**
- * @brief Check VMware emulation test
- * @category Windows, x86
- * @note Derek Soeder's (eEye Digital Security) VMware emulation test
- * @copyright BSD clause 2
- */
-#if (x86_32 && MSVC)
- #define EndUserModeAddress (*(UINT_PTR*)0x7FFE02B4)
- typedef LONG (NTAPI *NTSETLDTENTRIES)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);
-
- static int handle_exception(LPEXCEPTION_POINTERS lpep, bool &is_vm) {
- if ((UINT_PTR)(lpep->ExceptionRecord->ExceptionAddress) > EndUserModeAddress) {
- is_vm = true;
- }
-
- return (EXCEPTION_EXECUTE_HANDLER);
- }
-
- [[nodiscard]] static bool vmware_emul() {
- if (core::disabled(VMWARE_EMULATION)) {
- return false;
- }
-
- NTSETLDTENTRIES ZwSetLdtEntries;
- LDT_ENTRY csdesc;
- bool is_vm = false;
-
- ZwSetLdtEntries = reinterpret_cast(GetProcAddress(GetModuleHandle ("ntdll.dll"), "ZwSetLdtEntries"));
-
- memset (&csdesc, 0, sizeof (csdesc));
-
- csdesc.LimitLow = (WORD)(EndUserModeAddress >> 12);
- csdesc.HighWord.Bytes.Flags1 = 0xFA;
- csdesc.HighWord.Bytes.Flags2 = 0xC0 | ((EndUserModeAddress >> 28) & 0x0F);
-
- ZwSetLdtEntries (0x000F, ((DWORD*)&csdesc)[0], ((DWORD*)&csdesc)[1], 0, 0, 0);
-
- __try {
- __asm {
- pop eax
- push 0x000F
- push eax
- retf
- }
- __asm {
- or eax, -1
- jmp eax
- }
- }
- __except (handle_exception(GetExceptionInformation(), is_vm)) { }
-
- if (is_vm) {
- return core::add(VMWARE);
- }
-
- return false;
- }
-#else
- [[nodiscard]] static bool vmware_emul() {
- return false;
- }
-#endif
-
-
/**
* @brief Check for official VMware io port backdoor technique
* @category Windows, x86
@@ -5599,6 +5540,62 @@ struct VM {
}
+ /**
+ * @brief Check for mutex strings of VM brands
+ * @category Windows, x86
+ * @note from VMDE project
+ * @author hfiref0x
+ * @copyright MIT
+ */
+ [[nodiscard]] static bool mutex() try {
+ if (core::disabled(MUTEX)) {
+ return false;
+ }
+
+#if (!MSVC)
+ return false;
+#else
+ auto supMutexExist = [](const char* lpMutexName) -> bool {
+ DWORD dwError;
+ HANDLE hObject = NULL;
+ if (lpMutexName == NULL) {
+ return false;
+ }
+
+ SetLastError(0);
+ hObject = CreateMutex(NULL, FALSE, lpMutexName);
+ dwError = GetLastError();
+
+ if (hObject) {
+ CloseHandle(hObject);
+ }
+
+ return (dwError == ERROR_ALREADY_EXISTS);
+ };
+
+ if (
+ supMutexExist("Sandboxie_SingleInstanceMutex_Control") ||
+ supMutexExist("SBIE_BOXED_ServiceInitComplete_Mutex1")
+ ) {
+ return core::add(SANDBOXIE);
+ }
+
+ if (supMutexExist("MicrosoftVirtualPC7UserServiceMakeSureWe'reTheOnlyOneMutex")) {
+ return core::add(VPC);
+ }
+
+ if (supMutexExist("Frz_State")) {
+ return true;
+ }
+
+ return false;
+#endif
+ }
+ catch (...) {
+ debug("MUTEX: catched error, returned false");
+ return false;
+ }
+
struct core {
MSVC_DISABLE_WARNING(4820)
struct technique {
@@ -5619,7 +5616,7 @@ struct VM {
#endif
// directly return when adding a brand to the scoreboard for a more succint expression
-#if (MSVC)
+#if (MSVC)
__declspec(noalias)
#elif (LINUX)
[[gnu::const]]
@@ -5695,7 +5692,7 @@ struct VM {
#endif
ss << ". Consult the documentation's flag handler for VM::check()";
throw std::invalid_argument(std::string(text) + ss.str());
- };
+ };
if (p_flag > enum_size) {
throw_error("Flag argument must be a valid");
@@ -5708,7 +5705,7 @@ struct VM {
if (
(p_flag == NO_MEMO) || \
(p_flag == EXTREME)
- ) {
+ ) {
throw_error("Flag argument must be a technique flag and not a settings flag");
}
@@ -5723,7 +5720,7 @@ struct VM {
auto it = core::table.find(p_flag);
- if (/*VMAWARE_UNLIKELY*/(it == core::table.end())) {
+ if ((it == core::table.end())) {
throw_error("Flag is not known");
}
@@ -5738,72 +5735,55 @@ struct VM {
/**
* @brief Fetch the VM brand
- * @param any combination of flags, can be optional
+ * @param either nothing or VM::MULTIPLE
* @return std::string
* @returns VMware, VirtualBox, KVM, bhyve, QEMU, Microsoft Hyper-V, Microsoft x86-to-ARM, Parallels, Xen HVM, ACRN, QNX hypervisor, Hybrid Analysis, Sandboxie, Docker, Wine, Virtual Apple, Virtual PC, Unknown
* @link https://github.com/kernelwernel/VMAware/blob/main/docs/documentation.md#vmbrand
*/
- [[nodiscard]] static std::string brand(const flagset p_flags = DEFAULT) {
+ [[nodiscard]] static std::string brand(u8 is_multiple = false) {
{
// this is added to set the brand scoreboard table
- u16 tmp = core::run_all(p_flags);
+ u16 tmp = core::run_all(DEFAULT);
UNUSED(tmp);
}
- const char* current_brand = "";
-
- // fetch the brand with the most points in the scoreboard
-#if (CPP >= 20)
- auto it = std::ranges::max_element(core::brand_scoreboard, {},
- [](const auto& pair) {
- return pair.second;
- }
- );
+ #define brands core::brand_scoreboard
- if (it != core::brand_scoreboard.end()) {
- if (
- std::none_of(core::brand_scoreboard.cbegin(), core::brand_scoreboard.cend(),
- [](const auto& pair) {
- return pair.second;
- }
- )
- ) {
- current_brand = "Unknown";
- }
- else {
- current_brand = it->first;
- }
+#ifdef __VMAWARE_DEBUG__
+ for (const auto p : brands) {
+ debug("scoreboard: ", (int)p.second, " : ", p.first);
}
- else {
- current_brand = "Unknown";
+#endif
+
+ if (is_multiple == VM::MULTIPLE) {
+ is_multiple = true;
+ } else if (is_multiple != 0) {
+ throw std::invalid_argument("Flag for VM::brand() must either be empty or VM::MULTIPLE. Consult the documentation's flag handler for VM::check()");
}
-#else
- #if (MSVC)
- int max = 0;
- #else
- u8 max = 0;
- #endif
- #if (CPP >= 17)
- for (const auto& [brand, points] : core::brand_scoreboard) {
+ const char* current_brand = "";
+ i32 max = 0;
+
+ // both do the same thing
+#if (CPP >= 17)
+ for (const auto& [brand, points] : brands) {
if (points > max) {
current_brand = brand;
max = points;
}
}
- #else
- for (auto it = core::brand_scoreboard.cbegin(); it != core::brand_scoreboard.cend(); ++it) {
+#else
+ for (auto it = brands.cbegin(); it != brands.cend(); ++it) {
if (it->second > max) {
current_brand = it->first;
max = it->second;
}
}
- #endif
+#endif
if (max == 0) {
- current_brand = "Unknown";
+ return "Unknown";
}
-#endif
// goofy ass C++11 and C++14 linker error workaround
#if (CPP <= 14)
@@ -5815,6 +5795,9 @@ struct VM {
constexpr const char* TMP_ESX = "VMware ESX";
constexpr const char* TMP_GSX = "VMware GSX";
constexpr const char* TMP_WORKSTATION = "VMware Workstation";
+
+ constexpr const char* TMP_VPC = "Virtual PC";
+ constexpr const char* TMP_HYPERV = "Microsoft Hyper-V";
#else
constexpr const char* TMP_QEMU = VM::QEMU;
constexpr const char* TMP_KVM = VM::KVM;
@@ -5824,17 +5807,22 @@ struct VM {
constexpr const char* TMP_ESX = VM::VMWARE_ESX;
constexpr const char* TMP_GSX = VM::VMWARE_GSX;
constexpr const char* TMP_WORKSTATION = VM::VMWARE_WORKSTATION;
+
+ constexpr const char* TMP_VPC = VM::VPC;
+ constexpr const char* TMP_HYPERV = VM::HYPERV;
#endif
- #define brands core::brand_scoreboard
if (
brands.at(TMP_QEMU) > 0 &&
brands.at(TMP_KVM) > 0
) {
current_brand = "QEMU+KVM";
- }
-
- if (brands.at(TMP_VMWARE) > 0) {
+ } else if (
+ brands.at(TMP_VPC) > 0 &&
+ brands.at(TMP_HYPERV) > 0
+ ) {
+ current_brand = "Microsoft Virtual PC/Hyper-V";
+ } else if (brands.at(TMP_VMWARE) > 0) {
if (brands.at(TMP_EXPRESS) > 0) {
current_brand = TMP_EXPRESS;
} else if (brands.at(TMP_ESX) > 0) {
@@ -5844,13 +5832,30 @@ struct VM {
} else if (brands.at(TMP_WORKSTATION) > 0) {
current_brand = TMP_WORKSTATION;
}
- }
+ } else if (is_multiple) {
+ std::vector potential_brands;
-#ifdef __VMAWARE_DEBUG__
- for (const auto p : brands) {
- debug("scoreboard: ", (int)p.second, " : ", p.first);
+ for (auto it = brands.cbegin(); it != brands.cend(); ++it) {
+ const u8 points = it->second;
+ const std::string brand = it->first;
+
+ if (points > 0) {
+ potential_brands.push_back(brand);
+ }
+ }
+
+ std::stringstream ss;
+ u8 i = 1;
+
+ ss << potential_brands.front();
+
+ for (; i < potential_brands.size(); i++) {
+ ss << " or ";
+ ss << potential_brands.at(i);
+ }
+
+ return ss.str();
}
-#endif
return current_brand;
}
@@ -5989,6 +5994,7 @@ VM::flagset VM::DEFAULT = []() -> flagset {
tmp.flip(NO_MEMO);
tmp.flip(CURSOR);
tmp.flip(WIN_HYPERV_DEFAULT);
+ tmp.flip(MULTIPLE);
return tmp;
}();
@@ -6079,7 +6085,7 @@ const std::map VM::core::table = {
{ VM::HYPERV_REG, { 80, VM::hyperv_registry }},
{ VM::BIOS_SERIAL, { 60, VM::bios_serial }},
{ VM::VBOX_FOLDERS, { 45, VM::vbox_shared_folders }},
- { VM::VBOX_MSSMBIOS, { 75, VM::vbox_mssmbios }},
+ { VM::MSSMBIOS, { 75, VM::mssmbios }},
{ VM::MAC_MEMSIZE, { 30, VM::hw_memsize }},
{ VM::MAC_IOKIT, { 80, VM::io_kit }},
{ VM::IOREG_GREP, { 75, VM::ioreg_grep }},
@@ -6103,11 +6109,11 @@ const std::map VM::core::table = {
{ VM::VMWARE_IOPORTS, { 70, VM::vmware_ioports }},
{ VM::VMWARE_SCSI, { 40, VM::vmware_scsi }},
{ VM::VMWARE_DMESG, { 65, VM::vmware_dmesg }},
- { VM::VMWARE_EMULATION, { 20, VM::vmware_emul }},
{ VM::VMWARE_STR, { 35, VM::vmware_str }},
{ VM::VMWARE_BACKDOOR, { 100, VM::vmware_backdoor }},
{ VM::VMWARE_PORT_MEM, { 85, VM::vmware_port_memory }},
- { VM::SMSW, { 30, VM::smsw }}
+ { VM::SMSW, { 30, VM::smsw }},
+ { VM::MUTEX, { 85, VM::mutex }}
// __TABLE_LABEL, add your technique above
// { VM::FUNCTION, { POINTS, FUNCTION_POINTER }}