@@ -707,7 +707,7 @@ struct VM {
707707
708708 // specifically for util::hyper_x() and memo::hyperv
709709 enum hyperx_state : u8 {
710- HYPERV_UNKNOWN_VM = 0 ,
710+ HYPERV_UNKNOWN = 0 ,
711711 HYPERV_REAL_VM,
712712 HYPERV_ARTIFACT_VM,
713713 HYPERV_ENLIGHTENMENT
@@ -1802,7 +1802,7 @@ struct VM {
18021802 * - HYPERV_ARTIFACT_VM for host with Hyper-V enabled
18031803 * - HYPERV_REAL_VM for real Hyper-V VM
18041804 * - HYPERV_ENLIGHTENMENT for QEMU with Hyper-V enlightenments
1805- * - HYPERV_UNKNOWN_VM for unknown/undetected state
1805+ * - HYPERV_UNKNOWN for unknown/undetected state
18061806 */
18071807 [[nodiscard]] static hyperx_state hyper_x () {
18081808 #if (!WINDOWS)
@@ -1863,7 +1863,7 @@ struct VM {
18631863 }
18641864 else {
18651865 core_debug (" HYPER_X: Hyper-V is not active" );
1866- state = HYPERV_UNKNOWN_VM ;
1866+ state = HYPERV_UNKNOWN ;
18671867 }
18681868 }
18691869 else {
@@ -2287,14 +2287,24 @@ struct VM {
22872287 #if (!x86)
22882288 return false ;
22892289 #else
2290- if (util::hyper_x () == HYPERV_ARTIFACT_VM) {
2291- return false ;
2290+ u32 eax = 0 , ebx = 0 , ecx = 0 , edx = 0 ;
2291+ cpu::cpuid (eax, ebx, ecx, edx, 1 );
2292+ constexpr u32 HYPERVISOR_MASK = (1u << 31 );
2293+
2294+ if (ecx & HYPERVISOR_MASK) {
2295+ if (util::hyper_x () == HYPERV_ARTIFACT_VM) {
2296+ return false ;
2297+ }
2298+ return true ;
2299+ }
2300+
2301+ const auto hx = util::hyper_x ();
2302+ if (hx != HYPERV_UNKNOWN) {
2303+ debug (" HYPERVISOR_BIT: Running under nested virtualization" );
2304+ return true ; // hypervisor bit is not set but Hyper-V was detected through root partition checks
22922305 }
22932306
2294- u32 unused, ecx = 0 ;
2295- cpu::cpuid (unused, unused, ecx, unused, 1 );
2296- const u32 mask = (1u << 31 );
2297- return (ecx & mask);
2307+ return false ;
22982308 #endif
22992309 }
23002310
@@ -5696,7 +5706,7 @@ struct VM {
56965706
56975707 /* *
56985708 * @brief Check for uncommon IDT virtual addresses
5699- * @author Matteo Malvica (Linux)
5709+ * @author Matteo Malvica
57005710 * @author Idea to check VPC's range from Tom Liston and Ed Skoudis' paper "On the Cutting Edge: Thwarting Virtual Machine Detection" (Windows)
57015711 * @link https://www.matteomalvica.com/blog/2018/12/05/detecting-vmware-on-64-bit-systems/ (Linux)
57025712 * @category Windows, Linux, x86
@@ -5711,31 +5721,25 @@ struct VM {
57115721 #if (x86_64)
57125722 // 64-bit Linux: IDT descriptor is 10 bytes (2-byte limit + 8-byte base)
57135723 __asm__ __volatile__ (" sidt %0" : " =m" (values));
5714-
57155724 #ifdef __VMAWARE_DEBUG__
5716- debug (" SIDT5 : values = " );
5725+ debug (" SIDT : values = " );
57175726 for (u8 i = 0 ; i < 10 ; ++i) {
57185727 debug (std::hex, std::setw (2 ), std::setfill (' 0' ), static_cast <unsigned >(values[i]));
57195728 if (i < 9 ) debug (" " );
57205729 }
57215730 #endif
5722-
57235731 return (values[9 ] == 0x00 ); // 10th byte in x64 mode
5724-
57255732 #elif (x86_32)
57265733 // 32-bit Linux: IDT descriptor is 6 bytes (2-byte limit + 4-byte base)
57275734 __asm__ __volatile__ (" sidt %0" : " =m" (values));
5728-
57295735 #ifdef __VMAWARE_DEBUG__
5730- debug (" SIDT5 : values = " );
5736+ debug (" SIDT : values = " );
57315737 for (u8 i = 0 ; i < 6 ; ++i) {
57325738 debug (std::hex, std::setw (2 ), std::setfill (' 0' ), static_cast <unsigned >(values[i]));
57335739 if (i < 5 ) debug (" " );
57345740 }
57355741 #endif
5736-
57375742 return (values[5 ] == 0x00 ); // 6th byte in x86 mode
5738-
57395743 #else
57405744 return false ;
57415745 #endif
@@ -11827,7 +11831,7 @@ std::string VM::memo::brand::brand_cache = "";
1182711831std::string VM::memo::multi_brand::brand_cache = " " ;
1182811832std::string VM::memo::cpu_brand::brand_cache = " " ;
1182911833VM::u32 VM::memo::threadcount::threadcount_cache = 0 ;
11830- VM::hyperx_state VM::memo::hyperx::state = VM::HYPERV_UNKNOWN_VM ;
11834+ VM::hyperx_state VM::memo::hyperx::state = VM::HYPERV_UNKNOWN ;
1183111835bool VM::memo::hyperx::cached = false ;
1183211836
1183311837#ifdef __VMAWARE_DEBUG__
0 commit comments