diff --git a/README.md b/README.md index cf3fc667..b6941226 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,6 @@ The library is: - Contains separate MIT and GPL-3.0 compliant library header files -
- -> [!CAUTION] -**DO NOT USE THIS LIBRARY FOR CRITICAL SOFTWARE** (i.e. anti-cheats, proprietary software, paid software, etc...) -> -> The full reason can be found [here](deprecation.md) -
## Example 🧪 @@ -165,6 +158,7 @@ If you know a project, or if you're working on a project that uses VMAware, let - [systemd project](https://github.com/systemd/systemd) - mrjaxser - [iMonket](https://github.com/PrimeMonket) +- Eric Parker's discord community
diff --git a/assets/Hyper-X.drawio b/assets/Hyper-X.drawio new file mode 100644 index 00000000..4929d912 --- /dev/null +++ b/assets/Hyper-X.drawio @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Hyper-X.png b/assets/Hyper-X.png new file mode 100644 index 00000000..23f7e44e Binary files /dev/null and b/assets/Hyper-X.png differ diff --git a/assets/hyperv_fucker.png b/assets/hyperv_fucker.png deleted file mode 100644 index d7f61781..00000000 Binary files a/assets/hyperv_fucker.png and /dev/null differ diff --git a/docs/documentation.md b/docs/documentation.md index c16d2366..08ecf554 100644 --- a/docs/documentation.md +++ b/docs/documentation.md @@ -463,7 +463,6 @@ VMAware provides a convenient way to not only check for VMs, but also have the f | -p | --percent | Prints the VM likeliness percentage between 0 and 100 | | -n | --number | Prints the number of VM detection techniques it can performs | | -t | --type | Returns the VM type (if a VM was found) | -| | --disable-hyperv-host | Disable the possibility of Hyper-V default virtualisation result on host OS (this can be used as a combination with the above commands) | | | --disable-notes | No notes will be provided | | | --spoofable | Allow spoofable techniques to be ran (not included by default) diff --git a/release_notes.md b/release_notes.md new file mode 100644 index 00000000..4b98bfae --- /dev/null +++ b/release_notes.md @@ -0,0 +1,9 @@ +- completely fixed all false positives due to Hyper-V artifacts with new Hyper-X mechanism +

+ +
+

+
+
+ +- added new VM brand `Hyper-V artifacts (not an actual VM)` diff --git a/src/cli.cpp b/src/cli.cpp index 14978023..e19ff562 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -55,10 +55,8 @@ constexpr const char* red_orange = "\x1B[38;2;247;127;40m"; constexpr const char* green_orange = "\x1B[38;2;174;197;59m"; constexpr const char* grey = "\x1B[38;2;108;108;108m"; -constexpr bool ENABLE_HYPERV = true; constexpr bool ENABLE_NOTES = true; constexpr bool ENABLE_SPOOF = false; -constexpr bool DISABLE_HYPERV = false; constexpr bool DISABLE_NOTES = false; constexpr bool DISABLE_SPOOF = false; @@ -73,7 +71,7 @@ enum arg_enum : std::uint8_t { CONCLUSION, NUMBER, TYPE, - HYPERV, + HYPERV, // will be removed in the next release NOTES, SPOOFABLE, NULL_ARG @@ -429,7 +427,6 @@ void general() { }; bool notes_enabled = false; - VM::enum_flags hyperv_setting; VM::enum_flags spoofable_setting; if (arg_bitset.test(NOTES)) { @@ -438,12 +435,6 @@ void general() { notes_enabled = true; } - if (arg_bitset.test(HYPERV)) { - hyperv_setting = VM::NULL_ARG; - } else { - hyperv_setting = VM::ENABLE_HYPERV_HOST; - } - if (arg_bitset.test(SPOOFABLE)) { spoofable_setting = VM::SPOOFABLE; } else { @@ -587,7 +578,7 @@ void general() { } const char* percent_color = ""; - const std::uint8_t percent = VM::percentage(hyperv_setting, spoofable_setting); + const std::uint8_t percent = VM::percentage(spoofable_setting); if (percent == 0) { percent_color = red; } else if (percent < 25) { percent_color = red_orange; } @@ -597,7 +588,7 @@ void general() { std::cout << "VM likeliness: " << percent_color << static_cast(percent) << "%" << ansi_exit << "\n"; - const bool is_detected = VM::detect(hyperv_setting, spoofable_setting); + const bool is_detected = VM::detect(spoofable_setting); std::cout << "VM confirmation: " << (is_detected ? green : red) << std::boolalpha << is_detected << std::noboolalpha << ansi_exit << "\n"; @@ -645,8 +636,8 @@ void general() { << "\n\n"; - if ((hyperv_setting == VM::ENABLE_HYPERV_HOST) && (brand == "Hyper-V artifact (not an actual VM)") && notes_enabled) { - std::cout << note << " If you know you are running on host, Hyper-V leaves VM artifacts in CPUIDs which makes the system look like it's running in a Hyper-V VM when it's not. If you want to disable this mechanism, uninstall Hyper-V in your system.\n\n"; + if ((brand == "Hyper-V artifact (not an actual VM)") && notes_enabled) { + std::cout << note << "The result means that the CLI has found Hyper-V, but as an artifact instead of an actual VM. This means that although the hardware values in fact match with Hyper-V due to how it's designed by Microsoft, the CLI has determined you are NOT in a Hyper-V VM.\n\n"; } else if (notes_enabled) { if (!arg_bitset.test(SPOOFABLE)) { std::cout << tip << "To enable spoofable techniques, run with the \"--spoofable\" argument\n\n"; @@ -696,7 +687,7 @@ int main(int argc, char* argv[]) { { "--spoofable", SPOOFABLE } }}; - [[maybe_unused]] std::string potential_null_arg = ""; + std::string potential_null_arg = ""; for (const auto arg_string : args) { auto it = std::find_if(table.cbegin(), table.cend(), [&](const auto &p) { @@ -757,9 +748,7 @@ int main(int argc, char* argv[]) { auto settings = [&]() -> std::bitset { std::bitset setting_bits; - if (arg_bitset.test(HYPERV) == false) { - setting_bits.set(VM::ENABLE_HYPERV_HOST); - } else { + if (arg_bitset.test(HYPERV)) { std::cerr << "--disable-hyperv-host has been deprecated, the determination of whether it's a host Hyper-V or VM Hyper-V is now done automatically"; return 1; } diff --git a/src/vmaware.hpp b/src/vmaware.hpp index 2a57b3d0..232466a1 100644 --- a/src/vmaware.hpp +++ b/src/vmaware.hpp @@ -416,8 +416,8 @@ struct VM { // start of non-technique flags (THE ORDERING IS VERY SPECIFIC HERE AND MIGHT BREAK SOMETHING IF RE-ORDERED) NO_MEMO, HIGH_THRESHOLD, - ENABLE_HYPERV_HOST, - NULL_ARG, // does nothing as a placeholder + ENABLE_HYPERV_HOST [[deprecated("This mechanism is done by default as of 1.8 release")]], + NULL_ARG, // does nothing, just a placeholder flag mainly for the CLI SPOOFABLE, MULTIPLE }; @@ -430,6 +430,7 @@ struct VM { static constexpr u16 high_threshold_score = 300; // new threshold score from 100 to 350 if VM::HIGH_THRESHOLD flag is enabled static constexpr bool SHORTCUT = true; // macro for whether VM::core::run_all() should take a shortcut by skipping the rest of the techniques if the threshold score is already met + // intended for loop indexes static constexpr u8 enum_begin = 0; static constexpr u8 enum_end = enum_size + 1; @@ -437,6 +438,7 @@ struct VM { static constexpr u8 technique_end = NO_MEMO; static constexpr u8 non_technique_begin = NO_MEMO; static constexpr u8 non_technique_end = enum_end; + static constexpr u8 ENABLE_HYPERV_HOST_REPLACEMENT = HIGH_THRESHOLD + 1; public: static constexpr u8 technique_count = NO_MEMO; // get total number of techniques @@ -1632,6 +1634,7 @@ struct VM { core_debug("HYPERV_FUCKER: eax = ", eax); if (eax == 12) { + // SMBIOS check const std::string p = SMBIOS_string(); core_debug("HYPERV_FUCKER: SMBIOS string = ", p); @@ -1640,18 +1643,33 @@ struct VM { return add(false); } + + // motherboard check const bool motherboard = motherboard_string(L"Microsoft Corporation"); core_debug("HYPERV_FUCKER: motherboard string = ", motherboard); - if (motherboard == true) { + if (motherboard) { + return add(false); + } + + + // event log check (slow, so in last place) + std::wstring logName = L"Microsoft-Windows-Kernel-PnP/Configuration"; + std::vector searchStrings = { L"Virtual_Machine", L"VMBUS" }; + + const bool found = util::query_event_logs(logName, searchStrings); + + if (found) { return add(false); } - // at this point, it's fair to assume it's a Hyper-V on host + + // at this point, it's fair to assume it's Hyper-V artifacts on + // host since none of the "VM-only" techniques returned true return add(true); } else if (eax == 11) { - // actual Hyper-V VM + // actual Hyper-V VM, might do something within this scope in the future idk return add(false); } else { return add(false); @@ -8604,10 +8622,10 @@ struct VM { if ( flags.test(NO_MEMO) || flags.test(HIGH_THRESHOLD) || - flags.test(ENABLE_HYPERV_HOST) || flags.test(SPOOFABLE) || + flags.test(ENABLE_HYPERV_HOST_REPLACEMENT) || flags.test(MULTIPLE) - ) { + ) { flags |= DEFAULT; } } @@ -8891,7 +8909,7 @@ struct VM { if ( (flag_bit == NO_MEMO) || (flag_bit == HIGH_THRESHOLD) || - (flag_bit == ENABLE_HYPERV_HOST) || + (flag_bit == ENABLE_HYPERV_HOST_REPLACEMENT) || (flag_bit == SPOOFABLE) || (flag_bit == MULTIPLE) ) { @@ -9255,7 +9273,7 @@ struct VM { flags.set(NO_MEMO, 0); flags.set(HIGH_THRESHOLD, 0); flags.set(SPOOFABLE, 0); - flags.set(ENABLE_HYPERV_HOST, 0); + flags.set(ENABLE_HYPERV_HOST_REPLACEMENT, 0); flags.set(MULTIPLE, 0); return flags; @@ -9414,12 +9432,12 @@ VM::flagset VM::DEFAULT = []() -> flagset { tmp.flip(RDTSC); tmp.flip(RDTSC_VMEXIT); tmp.flip(HIGH_THRESHOLD); - tmp.flip(ENABLE_HYPERV_HOST); + tmp.flip(ENABLE_HYPERV_HOST_REPLACEMENT); tmp.flip(SPOOFABLE); tmp.flip(MULTIPLE); return tmp; - }(); +}(); // flag to enable every technique, basically VM::DEFAULT but with VM::CURSOR technique @@ -9427,7 +9445,7 @@ VM::flagset VM::ALL = []() -> flagset { flagset tmp = DEFAULT; tmp.set(CURSOR); return tmp; - }(); +}(); std::vector VM::technique_vector = []() -> std::vector { @@ -9439,7 +9457,7 @@ std::vector VM::technique_vector = []() -> std::vector { } return tmp; - }(); +}(); // check if cpuid is supported @@ -9458,7 +9476,7 @@ bool VM::core::cpuid_supported = []() -> bool { #else return false; #endif - }(); +}(); // this is initialised as empty, because this is where custom techniques can be added at runtime diff --git a/src/vmaware_MIT.hpp b/src/vmaware_MIT.hpp index 56d0dad0..18776654 100644 --- a/src/vmaware_MIT.hpp +++ b/src/vmaware_MIT.hpp @@ -8018,7 +8018,7 @@ information about the hypervisor Linux is running on flag_collector.set(VM::QEMU_GA); flag_collector.set(VM::QEMU_PROC); flag_collector.set(VM::VPC_PROC); - flag_collector.set(VM::VM_FILES_EXTRA); + flag_collector.set(VM::VM_FILES_EXTRA) flag_collector.set(VM::UPTIME); flag_collector.set(VM::CUCKOO_DIR); flag_collector.set(VM::CUCKOO_PIPE);