5353 * - struct for internal cpu operations => line 758
5454 * - struct for internal memoization => line 1229
5555 * - struct for internal utility functions => line 1357
56- * - struct for internal core components => line 9941
56+ * - struct for internal core components => line 9961
5757 * - start of VM detection technique list => line 2444
58- * - start of public VM detection functions => line 10609
59- * - start of externally defined variables => line 11545
58+ * - start of public VM detection functions => line 10629
59+ * - start of externally defined variables => line 11565
6060 *
6161 *
6262 * ============================== EXAMPLE ===================================
@@ -2955,8 +2955,13 @@ struct VM {
29552955#endif
29562956
29572957#elif (WINDOWS)
2958+ // Clang/GCC on x64 emits a full 10-byte SIDT (16-bit limit + 64-bit base), on 32-bit it still only writes 6 bytes
2959+ #if defined(_M_X64) || defined(__x86_64__)
2960+ unsigned char m[10 ] = { 0 };
2961+ #else
29582962 unsigned char m[6 ] = { 0 };
2959- u32 idt = 0 ;
2963+ #endif
2964+ u32 idt = 0 ;
29602965
29612966 __try {
29622967#if (CLANG || GCC)
@@ -2982,13 +2987,16 @@ struct VM {
29822987 __except (EXCEPTION_EXECUTE_HANDLER) {
29832988 return false ; // umip
29842989 }
2990+
2991+ // Extract 32-bit base from bytes [2..5]
29852992 idt = *((unsigned long *)&m[2 ]);
29862993
29872994 if ((idt >> 24 ) == 0xE8 ) {
29882995 return core::add (brands::VPC);
29892996 }
29902997
2991- return (m[5 ] > 0xD0 ); // top‐most byte of the 64‑bit base
2998+ // On x64, m[5] is the top byte of the 64-bit base; on x86 it's high byte of 32-bit base
2999+ return (m[5 ] > 0xD0 );
29923000#endif
29933001 }
29943002
@@ -4233,7 +4241,7 @@ struct VM {
42334241 * @implements VM::VPC_INVALID
42344242 */
42354243 [[nodiscard]] static bool vpc_invalid () {
4236- #if (WINDOWS && x86_32)
4244+ #if (WINDOWS && x86_32 && !CLANG )
42374245 bool rc = false ;
42384246
42394247 auto IsInsideVPC_exceptionFilter = [](PEXCEPTION_POINTERS ep) -> DWORD {
@@ -4290,38 +4298,50 @@ struct VM {
42904298 */
42914299 [[nodiscard]] static bool sgdt () {
42924300#if (WINDOWS)
4301+ #if defined(_M_X64) || defined(__x86_64__)
4302+ unsigned char gdtr[10 ] = { 0 };
4303+ #else
42934304 unsigned char gdtr[6 ] = { 0 };
4305+ #endif
42944306 unsigned int gdt = 0 ;
42954307
42964308 __try {
4297- #if (CLANG || GCC)
4309+ #if (CLANG || GCC)
42984310 __asm__ volatile (" sgdt %0" : " =m" (gdtr));
4299- #elif (MSVC && x86_32)
4311+ #elif (MSVC && x86_32)
43004312 __asm {
43014313 sgdt gdtr
43024314 }
4303- #elif (MSVC)
4315+ #elif (MSVC)
43044316 #pragma pack(push, 1)
4305- struct { unsigned short limit; unsigned long long base; } _gdtr = {};
4317+ struct {
4318+ unsigned short limit;
4319+ unsigned long long base;
4320+ } _gdtr = {};
43064321 #pragma pack(pop)
4322+
43074323 _sgdt (&_gdtr);
43084324 std::memcpy (gdtr, &_gdtr, sizeof (gdtr));
4309- #else
4325+ #else
43104326 return false ;
4311- #endif
4327+ #endif
43124328 }
43134329 __except (EXCEPTION_EXECUTE_HANDLER) {
43144330 return false ; // umip
43154331 }
43164332
4333+ // 32-bit base from bytes [2..5]
43174334 std::memcpy (&gdt, &gdtr[2 ], sizeof (gdt));
43184335
4319- if (gdtr[5 ] > 0xD0 ) { // top‐most byte of the 64‑bit base
4336+ // On x64, gdtr[5] is the top byte of the 64-bit base; on x86 it's high byte of 32-bit base
4337+ if (gdtr[5 ] > 0xD0 ) {
43204338 debug (" SGDT: top-most byte signature detected" );
43214339 return true ;
43224340 }
4341+
4342+ // 0xFF signature in the high byte of the 32-bit base
43234343 return ((gdt >> 24 ) == 0xFF );
4324- #else
4344+ #else
43254345 return false ;
43264346#endif
43274347 }
@@ -4500,7 +4520,7 @@ struct VM {
45004520 * @implements VM::VMWARE_BACKDOOR
45014521 */
45024522 [[nodiscard]] static bool vmware_backdoor () {
4503- #if (WINDOWS && x86_32)
4523+ #if (WINDOWS && x86_32 && !CLANG )
45044524 u32 a = 0 ;
45054525 u32 b = 0 ;
45064526
@@ -4509,49 +4529,49 @@ struct VM {
45094529 bool is_vm = false ;
45104530
45114531 for (u8 i = 0 ; i < ioports.size (); ++i) {
4512- ioport = ioports[i];
4513- for (u8 cmd = 0 ; cmd < 0x2c ; ++cmd) {
4514- __try {
4515- __asm {
4516- push eax
4517- push ebx
4518- push ecx
4519- push edx
4520-
4521- mov eax, ' VMXh'
4522- movzx ecx, cmd
4523- mov dx, ioport
4524- in eax, dx // <- key point is here
4525-
4526- mov a, ebx
4527- mov b, ecx
4528-
4529- pop edx
4530- pop ecx
4531- pop ebx
4532- pop eax
4533- }
4532+ ioport = ioports[i];
4533+ for (u8 cmd = 0 ; cmd < 0x2c ; ++cmd) {
4534+ __try {
4535+ __asm {
4536+ push eax
4537+ push ebx
4538+ push ecx
4539+ push edx
4540+
4541+ mov eax, ' VMXh'
4542+ movzx ecx, cmd
4543+ mov dx, ioport
4544+ in eax, dx // <- key point is here
4545+
4546+ mov a, ebx
4547+ mov b, ecx
4548+
4549+ pop edx
4550+ pop ecx
4551+ pop ebx
4552+ pop eax
4553+ }
45344554
4535- is_vm = true ;
4536- break ;
4555+ is_vm = true ;
4556+ break ;
4557+ }
4558+ __except (EXCEPTION_EXECUTE_HANDLER) {}
45374559 }
4538- __except (EXCEPTION_EXECUTE_HANDLER) {}
45394560 }
4540- }
45414561
4542- if (is_vm) {
4543- switch (b) {
4562+ if (is_vm) {
4563+ switch (b) {
45444564 case 1 : return core::add (brands::VMWARE_EXPRESS);
45454565 case 2 : return core::add (brands::VMWARE_ESX);
45464566 case 3 : return core::add (brands::VMWARE_GSX);
45474567 case 4 : return core::add (brands::VMWARE_WORKSTATION);
45484568 default : return core::add (brands::VMWARE);
4569+ }
45494570 }
4550- }
45514571
4552- return false ;
4572+ return false ;
45534573#else
4554- return false ;
4574+ return false ;
45554575#endif
45564576 }
45574577
@@ -7941,7 +7961,7 @@ struct VM {
79417961 overlap = chunk;
79427962 }
79437963
7944- for (size_t i = 0 ; i < std:: size (patterns ); ++i) {
7964+ for (size_t i = 0 ; i < patterns. size (); ++i) {
79457965 if (!seen[i] && chunk.find (patterns[i]) != std::string::npos) {
79467966 debug (" LSHW_QEMU: found " , patterns[i]);
79477967 seen[i] = true ;
0 commit comments