@@ -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