Skip to content

Commit b3b9c60

Browse files
author
Requiem
committed
perf: cache mechanism for is_hardened()
1 parent 43b0999 commit b3b9c60

File tree

1 file changed

+54
-40
lines changed

1 file changed

+54
-40
lines changed

src/vmaware.hpp

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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;
1267212684
bool VM::memo::cpu_brand::cached = false;
1267312685
bool VM::memo::bios_info::cached = false;
1267412686
bool VM::memo::hyperx::cached = false;
12687+
bool VM::memo::hardened::result = false;
12688+
bool VM::memo::hardened::cached = false;
1267512689
VM::u32 VM::memo::threadcount::threadcount_cache = 0;
1267612690
VM::hyperx_state VM::memo::hyperx::state = VM::HYPERV_UNKNOWN;
1267712691
std::array<VM::memo::leaf_entry, VM::memo::leaf_cache::CAPACITY> VM::memo::leaf_cache::table{};

0 commit comments

Comments
 (0)