Skip to content

Commit d516ba9

Browse files
authored
Merge branch 'dev' into dev
2 parents affe870 + aea7219 commit d516ba9

File tree

1 file changed

+97
-51
lines changed

1 file changed

+97
-51
lines changed

src/vmaware.hpp

Lines changed: 97 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,7 +1940,8 @@ struct VM {
19401940
// yes, vmaware runs on dinosaur cpus without sse4.2 pretty often
19411941
i32 regs[4];
19421942
cpu::cpuid(regs, 1);
1943-
const bool has_sse42 = (regs[2] & (1 << 20)) != 0;
1943+
constexpr u32 SSE42_FEATURE = (1 << 20);
1944+
const bool has_sse42 = (regs[2] & SSE42_FEATURE) != 0;
19441945

19451946
return has_sse42 ? crc32_hw : crc32_sw;
19461947
}
@@ -2382,15 +2383,15 @@ struct VM {
23822383
#else
23832384
const std::string& brand = cpu::get_brand();
23842385

2385-
struct CStrView {
2386+
struct string_view {
23862387
const char* data;
23872388
std::size_t size;
2388-
constexpr CStrView(const char* d, std::size_t s) noexcept
2389+
constexpr string_view(const char* d, std::size_t s) noexcept
23892390
: data(d), size(s) {
23902391
}
23912392
};
23922393

2393-
static constexpr std::array<CStrView, 10> checks{ {
2394+
static constexpr std::array<string_view, 10> checks{ {
23942395
{ "qemu", 4 },
23952396
{ "kvm", 3 },
23962397
{ "vbox", 4 },
@@ -2414,7 +2415,7 @@ struct VM {
24142415
if (v.size == 7 // "monitor"
24152416
|| ((v.size == 6) && (v.data[0] == 'h')) // "hvisor"
24162417
|| ((v.size == 10) && (v.data[0] == 'h')) // "hypervisor"
2417-
) {
2418+
) {
24182419
return true;
24192420
}
24202421

@@ -10678,7 +10679,7 @@ struct VM {
1067810679
if (
1067910680
(shortcut) &&
1068010681
(points >= threshold_points)
10681-
) {
10682+
) {
1068210683
return points;
1068310684
}
1068410685
}
@@ -11032,7 +11033,7 @@ struct VM {
1103211033
(flag_bit == HIGH_THRESHOLD) ||
1103311034
(flag_bit == DYNAMIC) ||
1103411035
(flag_bit == MULTIPLE)
11035-
) {
11036+
) {
1103611037
throw_error("Flag argument must be a technique flag and not a settings flag");
1103711038
}
1103811039

@@ -11079,10 +11080,7 @@ struct VM {
1107911080

1108011081
// is the multiple setting flag enabled?
1108111082
const bool is_multiple = core::is_enabled(flags, MULTIPLE);
11082-
11083-
// run all the techniques
11084-
const u16 score = core::run_all(flags);
11085-
11083+
1108611084
// check if the result is already cached and return that instead
1108711085
if (is_multiple) {
1108811086
if (memo::multi_brand::is_cached()) {
@@ -11097,6 +11095,11 @@ struct VM {
1109711095
}
1109811096
}
1109911097

11098+
// run all the techniques
11099+
core::run_all(flags);
11100+
11101+
// goofy ass C++11 and C++14 linker error workaround.
11102+
// And yes, this does look stupid.
1110011103
#if (VMA_CPP <= 14)
1110111104
constexpr const char* TMP_QEMU = "QEMU";
1110211105
constexpr const char* TMP_KVM = "KVM";
@@ -11305,9 +11308,79 @@ struct VM {
1130511308
debug("VM::brand(): cached multiple brand string");
1130611309
return memo::multi_brand::fetch();
1130711310
}
11311+
11312+
// this is added in case the lib detects a non-Hyper-X technique.
11313+
// A Hyper-X affiliated technique should make the overall score
11314+
// as 0, but this isn't the case if non-Hyper-X techniques were
11315+
// found. There may be a conflict between an Unknown and Hyper-V
11316+
// brand, which is exactly what this section is meant to handle.
11317+
// It will remove the Hyper-V artifact brand string from the
11318+
// std::map to pave the way for other brands to take precedence.
11319+
// One of the main reasons to do this is because it would look
11320+
// incredibly awkward if the brand was "Hyper-V artifacts (not an
11321+
// actual VM)", clearly stating that it's NOT a VM while the VM
11322+
// confirmation is true and percentage is 100%, as if that makes
11323+
// any sense whatsoever. That's what this part fixes.
11324+
if (brands.count(TMP_HYPERV_ARTIFACT) > 0) {
11325+
brands.erase(TMP_HYPERV_ARTIFACT);
11326+
}
11327+
11328+
11329+
// the brand element, which stores the NAME (const char*) and the SCORE (u8)
11330+
using brand_element_t = std::pair<const char*, brand_score_t>;
11331+
11332+
// convert the std::map into a std::vector, easier to handle this way
11333+
std::vector<brand_element_t> vec(brands.begin(), brands.end());
11334+
11335+
// sort the relevant brands vector so that the brands with
11336+
// the highest score appears first in descending order
11337+
std::sort(vec.begin(), vec.end(), [](
11338+
const brand_element_t &a,
11339+
const brand_element_t &b
11340+
) {
11341+
return a.second > b.second;
11342+
});
11343+
11344+
std::string ret_str = brands::NULL_BRAND;
11345+
11346+
11347+
// if the multiple setting flag is NOT set, return the
11348+
// brand with the highest score. Else, return a std::string
11349+
// of the brand message (i.e. "VirtualBox or VMware").
11350+
// See VM::MULTIPLE flag in docs for more information.
11351+
if (!is_multiple) {
11352+
ret_str = vec.front().first;
11353+
} else {
11354+
std::stringstream ss;
11355+
std::size_t i = 1;
11356+
11357+
ss << vec.front().first;
11358+
for (; i < vec.size(); i++) {
11359+
ss << " or ";
11360+
ss << vec.at(i).first;
11361+
}
11362+
ret_str = ss.str();
11363+
}
11364+
11365+
11366+
// cache the result
11367+
if (is_multiple) {
11368+
debug("VM::brand(): cached multiple brand string");
11369+
memo::multi_brand::store(ret_str);
11370+
} else {
11371+
debug("VM::brand(): cached brand string");
11372+
memo::brand::store(ret_str);
11373+
}
11374+
11375+
11376+
// debug stuff to see the brand scoreboard, ignore this
11377+
#ifdef __VMAWARE_DEBUG__
11378+
for (const auto& p : brands) {
11379+
debug("scoreboard: ", (int)p.second, " : ", p.first);
1130811380
}
11381+
#endif
1130911382

11310-
return brands::NULL_BRAND;
11383+
return ret_str;
1131111384
}
1131211385

1131311386

@@ -11322,6 +11395,11 @@ struct VM {
1132211395
// fetch all the flags in a std::bitset
1132311396
flagset flags = core::arg_handler(args...);
1132411397

11398+
// early return, since this is NOT a VM
11399+
if (brand(flags) == brands::HYPERV_ARTIFACT) {
11400+
return false;
11401+
}
11402+
1132511403
// run all the techniques based on the
1132611404
// flags above, and get a total score
1132711405
const u16 points = core::run_all(flags, SHORTCUT);
@@ -11353,6 +11431,11 @@ struct VM {
1135311431
// fetch all the flags in a std::bitset
1135411432
const flagset flags = core::arg_handler(args...);
1135511433

11434+
// early return, since this is NOT a VM
11435+
if (brand(flags) == brands::HYPERV_ARTIFACT) {
11436+
return 0;
11437+
}
11438+
1135611439
// run all the techniques based on the
1135711440
// flags above, and get a total score
1135811441
const u16 points = core::run_all(flags, SHORTCUT);
@@ -11579,44 +11662,6 @@ struct VM {
1157911662
return tmp;
1158011663
}
1158111664

11582-
/**
11583-
* @brief Change the certainty score of a technique
11584-
* @param technique flag, then the new percentage score to overwite
11585-
* @return void
11586-
* @warning ⚠️ FOR DEVELOPMENT USAGE ONLY, NOT MEANT FOR PUBLIC USE FOR NOW ⚠️
11587-
*/
11588-
static void modify_score(
11589-
const enum_flags flag,
11590-
const u8 percent
11591-
#if (VMA_CPP >= 20) && (!CLANG || __clang_major__ >= 16)
11592-
, const std::source_location& loc = std::source_location::current()
11593-
#endif
11594-
) {
11595-
// lambda to throw the error
11596-
auto throw_error = [&](const char* text) -> void {
11597-
std::stringstream ss;
11598-
#if (VMA_CPP >= 20 && !CLANG)
11599-
ss << ", error in " << loc.function_name() << " at " << loc.file_name() << ":" << loc.line() << ")";
11600-
#endif
11601-
ss << ". Consult the documentation's parameters for VM::modify_score()";
11602-
throw std::invalid_argument(std::string(text) + ss.str());
11603-
};
11604-
11605-
if (percent > 100) {
11606-
throw_error("Percentage parameter must be between 0 and 100");
11607-
}
11608-
11609-
#if (VMA_CPP >= 23)
11610-
[[assume(percent <= 100)]];
11611-
#endif
11612-
11613-
// check if the flag provided is a setting flag, which isn't valid
11614-
if (static_cast<u8>(flag) >= technique_end) {
11615-
throw_error("The flag is not a technique flag");
11616-
}
11617-
11618-
core::technique_table[flag].points = percent;
11619-
}
1162011665

1162111666
/**
1162211667
* @brief Fetch the total number of detected techniques
@@ -11795,7 +11840,7 @@ struct VM {
1179511840
(brand_tmp == brands::AMD_SEV_SNP) ||
1179611841
(brand_tmp == brands::NSJAIL) ||
1179711842
(brand_tmp == brands::NULL_BRAND)
11798-
) {
11843+
) {
1179911844
addition = " an ";
1180011845
}
1180111846

@@ -11805,6 +11850,7 @@ struct VM {
1180511850

1180611851
const char* suffix = " VM";
1180711852
if (str_eq(brand_tmp, brands::HYPERV_ARTIFACT) && percent_tmp != 100) {
11853+
if (brand_tmp == brands::HYPERV_ARTIFACT) {
1180811854
suffix = "";
1180911855
}
1181011856

0 commit comments

Comments
 (0)