Skip to content

Commit d9f65e3

Browse files
authored
Merge pull request #124 from kernelwernel/dev
Dev
2 parents ceaa751 + 57f523f commit d9f65e3

9 files changed

Lines changed: 254 additions & 41 deletions

File tree

README.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@ The library is:
2626
- Contains separate MIT and GPL-3.0 compliant library header files
2727

2828

29-
<br>
30-
31-
> [!CAUTION]
32-
**DO NOT USE THIS LIBRARY FOR CRITICAL SOFTWARE** (i.e. anti-cheats, proprietary software, paid software, etc...)
33-
>
34-
> The full reason can be found [here](deprecation.md)
35-
3629
<br>
3730

3831
## Example 🧪
@@ -165,6 +158,7 @@ If you know a project, or if you're working on a project that uses VMAware, let
165158
- [systemd project](https://github.com/systemd/systemd)
166159
- mrjaxser
167160
- [iMonket](https://github.com/PrimeMonket)
161+
- Eric Parker's discord community
168162

169163
<br>
170164

assets/Hyper-X.drawio

Lines changed: 204 additions & 0 deletions
Large diffs are not rendered by default.

assets/Hyper-X.png

140 KB
Loading

assets/hyperv_fucker.png

-144 KB
Binary file not shown.

docs/documentation.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,6 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
463463
| -p | --percent | Prints the VM likeliness percentage between 0 and 100 |
464464
| -n | --number | Prints the number of VM detection techniques it can performs |
465465
| -t | --type | Returns the VM type (if a VM was found) |
466-
| | --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) |
467466
| | --disable-notes | No notes will be provided |
468467
| | --spoofable | Allow spoofable techniques to be ran (not included by default)
469468

release_notes.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
- completely fixed all false positives due to Hyper-V artifacts with new Hyper-X mechanism
2+
<p align="center">
3+
<img src="assets/Hyper-X.png" align="center" title="VMAware">
4+
<br>
5+
</p>
6+
<br>
7+
<br>
8+
9+
- added new VM brand `Hyper-V artifacts (not an actual VM)`

src/cli.cpp

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,8 @@ constexpr const char* red_orange = "\x1B[38;2;247;127;40m";
5555
constexpr const char* green_orange = "\x1B[38;2;174;197;59m";
5656
constexpr const char* grey = "\x1B[38;2;108;108;108m";
5757

58-
constexpr bool ENABLE_HYPERV = true;
5958
constexpr bool ENABLE_NOTES = true;
6059
constexpr bool ENABLE_SPOOF = false;
61-
constexpr bool DISABLE_HYPERV = false;
6260
constexpr bool DISABLE_NOTES = false;
6361
constexpr bool DISABLE_SPOOF = false;
6462

@@ -73,7 +71,7 @@ enum arg_enum : std::uint8_t {
7371
CONCLUSION,
7472
NUMBER,
7573
TYPE,
76-
HYPERV,
74+
HYPERV, // will be removed in the next release
7775
NOTES,
7876
SPOOFABLE,
7977
NULL_ARG
@@ -429,7 +427,6 @@ void general() {
429427
};
430428

431429
bool notes_enabled = false;
432-
VM::enum_flags hyperv_setting;
433430
VM::enum_flags spoofable_setting;
434431

435432
if (arg_bitset.test(NOTES)) {
@@ -438,12 +435,6 @@ void general() {
438435
notes_enabled = true;
439436
}
440437

441-
if (arg_bitset.test(HYPERV)) {
442-
hyperv_setting = VM::NULL_ARG;
443-
} else {
444-
hyperv_setting = VM::ENABLE_HYPERV_HOST;
445-
}
446-
447438
if (arg_bitset.test(SPOOFABLE)) {
448439
spoofable_setting = VM::SPOOFABLE;
449440
} else {
@@ -587,7 +578,7 @@ void general() {
587578
}
588579

589580
const char* percent_color = "";
590-
const std::uint8_t percent = VM::percentage(hyperv_setting, spoofable_setting);
581+
const std::uint8_t percent = VM::percentage(spoofable_setting);
591582

592583
if (percent == 0) { percent_color = red; }
593584
else if (percent < 25) { percent_color = red_orange; }
@@ -597,7 +588,7 @@ void general() {
597588

598589
std::cout << "VM likeliness: " << percent_color << static_cast<std::uint32_t>(percent) << "%" << ansi_exit << "\n";
599590

600-
const bool is_detected = VM::detect(hyperv_setting, spoofable_setting);
591+
const bool is_detected = VM::detect(spoofable_setting);
601592

602593
std::cout << "VM confirmation: " << (is_detected ? green : red) << std::boolalpha << is_detected << std::noboolalpha << ansi_exit << "\n";
603594

@@ -645,8 +636,8 @@ void general() {
645636
<< "\n\n";
646637

647638

648-
if ((hyperv_setting == VM::ENABLE_HYPERV_HOST) && (brand == "Hyper-V artifact (not an actual VM)") && notes_enabled) {
649-
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";
639+
if ((brand == "Hyper-V artifact (not an actual VM)") && notes_enabled) {
640+
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";
650641
} else if (notes_enabled) {
651642
if (!arg_bitset.test(SPOOFABLE)) {
652643
std::cout << tip << "To enable spoofable techniques, run with the \"--spoofable\" argument\n\n";
@@ -696,7 +687,7 @@ int main(int argc, char* argv[]) {
696687
{ "--spoofable", SPOOFABLE }
697688
}};
698689

699-
[[maybe_unused]] std::string potential_null_arg = "";
690+
std::string potential_null_arg = "";
700691

701692
for (const auto arg_string : args) {
702693
auto it = std::find_if(table.cbegin(), table.cend(), [&](const auto &p) {
@@ -757,9 +748,7 @@ int main(int argc, char* argv[]) {
757748
auto settings = [&]() -> std::bitset<max_bits> {
758749
std::bitset<max_bits> setting_bits;
759750

760-
if (arg_bitset.test(HYPERV) == false) {
761-
setting_bits.set(VM::ENABLE_HYPERV_HOST);
762-
} else {
751+
if (arg_bitset.test(HYPERV)) {
763752
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";
764753
return 1;
765754
}

src/vmaware.hpp

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,8 @@ struct VM {
416416
// start of non-technique flags (THE ORDERING IS VERY SPECIFIC HERE AND MIGHT BREAK SOMETHING IF RE-ORDERED)
417417
NO_MEMO,
418418
HIGH_THRESHOLD,
419-
ENABLE_HYPERV_HOST,
420-
NULL_ARG, // does nothing as a placeholder
419+
ENABLE_HYPERV_HOST [[deprecated("This mechanism is done by default as of 1.8 release")]],
420+
NULL_ARG, // does nothing, just a placeholder flag mainly for the CLI
421421
SPOOFABLE,
422422
MULTIPLE
423423
};
@@ -430,13 +430,15 @@ struct VM {
430430
static constexpr u16 high_threshold_score = 300; // new threshold score from 100 to 350 if VM::HIGH_THRESHOLD flag is enabled
431431
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
432432

433+
433434
// intended for loop indexes
434435
static constexpr u8 enum_begin = 0;
435436
static constexpr u8 enum_end = enum_size + 1;
436437
static constexpr u8 technique_begin = enum_begin;
437438
static constexpr u8 technique_end = NO_MEMO;
438439
static constexpr u8 non_technique_begin = NO_MEMO;
439440
static constexpr u8 non_technique_end = enum_end;
441+
static constexpr u8 ENABLE_HYPERV_HOST_REPLACEMENT = HIGH_THRESHOLD + 1;
440442

441443
public:
442444
static constexpr u8 technique_count = NO_MEMO; // get total number of techniques
@@ -1632,6 +1634,7 @@ struct VM {
16321634
core_debug("HYPER_X: eax = ", eax);
16331635

16341636
if (eax == 12) {
1637+
// SMBIOS check
16351638
const std::string p = SMBIOS_string();
16361639

16371640
core_debug("HYPER_X: SMBIOS string = ", p);
@@ -1640,18 +1643,33 @@ struct VM {
16401643
return add(false);
16411644
}
16421645

1646+
1647+
// motherboard check
16431648
const bool motherboard = motherboard_string(L"Microsoft Corporation");
16441649

16451650
core_debug("HYPER_X: motherboard string = ", motherboard);
16461651

1647-
if (motherboard == true) {
1652+
if (motherboard) {
1653+
return add(false);
1654+
}
1655+
1656+
1657+
// event log check (slow, so in last place)
1658+
std::wstring logName = L"Microsoft-Windows-Kernel-PnP/Configuration";
1659+
std::vector<std::wstring> searchStrings = { L"Virtual_Machine", L"VMBUS" };
1660+
1661+
const bool found = util::query_event_logs(logName, searchStrings);
1662+
1663+
if (found) {
16481664
return add(false);
16491665
}
16501666

1651-
// at this point, it's fair to assume it's a Hyper-V on host
1667+
1668+
// at this point, it's fair to assume it's Hyper-V artifacts on
1669+
// host since none of the "VM-only" techniques returned true
16521670
return add(true);
16531671
} else if (eax == 11) {
1654-
// actual Hyper-V VM
1672+
// actual Hyper-V VM, might do something within this scope in the future idk
16551673
return add(false);
16561674
} else {
16571675
return add(false);
@@ -8606,10 +8624,10 @@ struct VM {
86068624
if (
86078625
flags.test(NO_MEMO) ||
86088626
flags.test(HIGH_THRESHOLD) ||
8609-
flags.test(ENABLE_HYPERV_HOST) ||
86108627
flags.test(SPOOFABLE) ||
8628+
flags.test(ENABLE_HYPERV_HOST_REPLACEMENT) ||
86118629
flags.test(MULTIPLE)
8612-
) {
8630+
) {
86138631
flags |= DEFAULT;
86148632
}
86158633
}
@@ -8893,7 +8911,7 @@ struct VM {
88938911
if (
88948912
(flag_bit == NO_MEMO) ||
88958913
(flag_bit == HIGH_THRESHOLD) ||
8896-
(flag_bit == ENABLE_HYPERV_HOST) ||
8914+
(flag_bit == ENABLE_HYPERV_HOST_REPLACEMENT) ||
88978915
(flag_bit == SPOOFABLE) ||
88988916
(flag_bit == MULTIPLE)
88998917
) {
@@ -9257,7 +9275,7 @@ struct VM {
92579275
flags.set(NO_MEMO, 0);
92589276
flags.set(HIGH_THRESHOLD, 0);
92599277
flags.set(SPOOFABLE, 0);
9260-
flags.set(ENABLE_HYPERV_HOST, 0);
9278+
flags.set(ENABLE_HYPERV_HOST_REPLACEMENT, 0);
92619279
flags.set(MULTIPLE, 0);
92629280

92639281
return flags;
@@ -9416,20 +9434,20 @@ VM::flagset VM::DEFAULT = []() -> flagset {
94169434
tmp.flip(RDTSC);
94179435
tmp.flip(RDTSC_VMEXIT);
94189436
tmp.flip(HIGH_THRESHOLD);
9419-
tmp.flip(ENABLE_HYPERV_HOST);
9437+
tmp.flip(ENABLE_HYPERV_HOST_REPLACEMENT);
94209438
tmp.flip(SPOOFABLE);
94219439
tmp.flip(MULTIPLE);
94229440

94239441
return tmp;
9424-
}();
9442+
}();
94259443

94269444

94279445
// flag to enable every technique, basically VM::DEFAULT but with VM::CURSOR technique
94289446
VM::flagset VM::ALL = []() -> flagset {
94299447
flagset tmp = DEFAULT;
94309448
tmp.set(CURSOR);
94319449
return tmp;
9432-
}();
9450+
}();
94339451

94349452

94359453
std::vector<VM::u8> VM::technique_vector = []() -> std::vector<VM::u8> {
@@ -9441,7 +9459,7 @@ std::vector<VM::u8> VM::technique_vector = []() -> std::vector<VM::u8> {
94419459
}
94429460

94439461
return tmp;
9444-
}();
9462+
}();
94459463

94469464

94479465
// check if cpuid is supported
@@ -9460,7 +9478,7 @@ bool VM::core::cpuid_supported = []() -> bool {
94609478
#else
94619479
return false;
94629480
#endif
9463-
}();
9481+
}();
94649482

94659483

94669484
// this is initialised as empty, because this is where custom techniques can be added at runtime

src/vmaware_MIT.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8018,7 +8018,7 @@ information about the hypervisor Linux is running on
80188018
flag_collector.set(VM::QEMU_GA);
80198019
flag_collector.set(VM::QEMU_PROC);
80208020
flag_collector.set(VM::VPC_PROC);
8021-
flag_collector.set(VM::VM_FILES_EXTRA);
8021+
flag_collector.set(VM::VM_FILES_EXTRA)
80228022
flag_collector.set(VM::UPTIME);
80238023
flag_collector.set(VM::CUCKOO_DIR);
80248024
flag_collector.set(VM::CUCKOO_PIPE);

0 commit comments

Comments
 (0)