@@ -3194,6 +3194,11 @@ struct VM {
31943194 static const char * fetch_manufacturer () noexcept { return manufacturer; }
31953195 static const char * fetch_model () noexcept { return model; }
31963196 };
3197+
3198+ struct hardened {
3199+ static bool result;
3200+ static bool cached;
3201+ };
31973202 };
31983203
31993204 // miscellaneous functionalities
@@ -11922,8 +11927,7 @@ struct VM {
1192211927
1192311928 // this is added as a last ditch attempt to detect a VM,
1192411929 // because if there are indications of hardening then logically
11925- // it should in fact be a VM. It's doubtful if this can actually
11926- // return true, but it's better than nothing
11930+ // it should in fact be a VM.
1192711931 return (is_hardened ());
1192811932 }
1192911933
@@ -12453,55 +12457,63 @@ struct VM {
1245312457 * @return bool
1245412458 */
1245512459 static bool is_hardened () {
12456- // Helper to get the specific brand associated with a technique using the cache
12457- // If not cached, VM::check() will run it and cache the specific brand via core::last_detected_brand
12458- auto detected_brand = [](const enum_flags flag) -> const char * {
12459- // ensure the technique has been run and cached
12460- if (!check (flag)) {
12460+ if (memo::hardened::cached) {
12461+ return memo::hardened::result;
12462+ }
12463+
12464+ auto hardened_logic = []() -> bool {
12465+ // Helper to get the specific brand associated with a technique using the cache.
12466+ auto detected_brand = [](const enum_flags flag) -> const char * {
12467+ if (!check (flag)) {
12468+ return brands::NULL_BRAND;
12469+ }
12470+ if (memo::cache_table[flag].has_value ) {
12471+ const char * b = memo::cache_table[flag].brand_name ;
12472+ return (b != nullptr ) ? b : brands::NULL_BRAND;
12473+ }
1246112474 return brands::NULL_BRAND;
12462- }
12475+ };
1246312476
12464- // access the private cache directly to get the brand string
12465- if (memo::cache_table[flag].has_value ) {
12466- const char * b = memo::cache_table[flag].brand_name ;
12467- return (b != nullptr ) ? b : brands::NULL_BRAND;
12468- }
12477+ const bool hv_present = (check (VM::HYPERVISOR_BIT) || check (VM::HYPERVISOR_STR));
1246912478
12470- return brands::NULL_BRAND;
12471- };
12479+ // rule 1: if VM::FIRMWARE is detected, so should VM::HYPERVISOR_BIT or VM::HYPERVISOR_STR
12480+ const char * firmware_brand = detected_brand (VM::FIRMWARE);
12481+ if (firmware_brand != brands::NULL_BRAND && !hv_present) {
12482+ return true ;
12483+ }
1247212484
12473- const bool hv_present = (check (VM::HYPERVISOR_BIT) || check (VM::HYPERVISOR_STR));
12485+ #if (LINUX)
12486+ // rule 2: if VM::FIRMWARE is detected, so should VM::CVENDOR (QEMU or VBOX)
12487+ if (firmware_brand == brands::QEMU || firmware_brand == brands::VBOX) {
12488+ const char * cvendor_brand = detected_brand (VM::CVENDOR);
12489+ if (firmware_brand != cvendor_brand) {
12490+ return true ;
12491+ }
12492+ }
12493+ #endif
1247412494
12475- // rule 1: if VM::FIRMWARE is detected, so should VM::HYPERVISOR_BIT or VM::HYPERVISOR_STR
12476- const char * firmware_brand = detected_brand (VM::FIRMWARE);
12477- if (firmware_brand != brands::NULL_BRAND && !hv_present) {
12478- return true ;
12479- }
12495+ #if (WINDOWS)
12496+ // rule 3: if VM::ACPI_SIGNATURE (QEMU) is detected, so should VM::FIRMWARE (QEMU)
12497+ const char * acpi_brand = detected_brand (VM::ACPI_SIGNATURE);
12498+ if (acpi_brand == brands::QEMU && firmware_brand != brands::QEMU) {
12499+ return true ;
12500+ }
1248012501
12481- #if (LINUX)
12482- // rule 2: if VM::FIRMWARE is detected, so should VM::CVENDOR (QEMU or VBOX)
12483- if (firmware_brand == brands::QEMU || firmware_brand == brands::VBOX) {
12484- const char * cvendor_brand = detected_brand (VM::CVENDOR);
12485- if (firmware_brand != cvendor_brand) {
12502+ // rule 4: if VM::TRAP or VM::NVRAM is detected, so should VM::HYPERVISOR_BIT or VM::HYPERVISOR_STR
12503+ if ((check (VM::TRAP) || check (VM::NVRAM)) && !hv_present) {
1248612504 return true ;
1248712505 }
12488- }
12489- #endif
12506+ #endif
1249012507
12491- #if (WINDOWS)
12492- // rule 3: if VM::ACPI_SIGNATURE (QEMU) is detected, so should VM::FIRMWARE (QEMU)
12493- const char * acpi_brand = detected_brand (VM::ACPI_SIGNATURE);
12494- if (acpi_brand == brands::QEMU && firmware_brand != brands::QEMU) {
12495- return true ;
12496- }
12508+ return false ;
12509+ };
1249712510
12498- // rule 4: if VM::TRAP or VM::NVRAM is detected, so should VM::HYPERVISOR_BIT or VM::HYPERVISOR_STR
12499- if ((check (VM::TRAP) || check (VM::NVRAM)) && !hv_present) {
12500- return true ;
12501- }
12502- #endif
12511+ const bool result = hardened_logic ();
1250312512
12504- return false ;
12513+ memo::hardened::result = result;
12514+ memo::hardened::cached = true ;
12515+
12516+ return result;
1250512517 }
1250612518
1250712519
@@ -12672,6 +12684,8 @@ bool VM::memo::multi_brand::cached = false;
1267212684bool VM::memo::cpu_brand::cached = false ;
1267312685bool VM::memo::bios_info::cached = false ;
1267412686bool VM::memo::hyperx::cached = false ;
12687+ bool VM::memo::hardened::result = false ;
12688+ bool VM::memo::hardened::cached = false ;
1267512689VM::u32 VM::memo::threadcount::threadcount_cache = 0 ;
1267612690VM::hyperx_state VM::memo::hyperx::state = VM::HYPERV_UNKNOWN;
1267712691std::array<VM::memo::leaf_entry, VM::memo::leaf_cache::CAPACITY> VM::memo::leaf_cache::table{};
0 commit comments