Skip to content

Commit e3b163b

Browse files
author
Requiem
committed
removed VM::IDT_GDT_SCAN
1 parent 95673f0 commit e3b163b

6 files changed

Lines changed: 31 additions & 212 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ You can view the full docs [here](docs/documentation.md). All the details such a
239239

240240
> I would've made it strictly MIT so proprietary software can make use of the library, but some of the techniques employed are from GPL projects, and I have no choice but to use the same license for legal reasons.
241241
>
242-
> This gave me an idea to make an MIT version without all of the GPL code so it can also be used without forcing your code to be open source. It should be noted that the MIT version removes <b>7</b> techniques out of 118 (as of 2.0 version), and the lesser the number of techniques, the less accurate the overall result might be.
242+
> This gave me an idea to make an MIT version without all of the GPL code so it can also be used without forcing your code to be open source. It should be noted that the MIT version removes <b>7</b> techniques out of 117 (as of 2.0 version), and the lesser the number of techniques, the less accurate the overall result might be.
243243
244244
</details>
245245

docs/documentation.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,6 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
512512
| `VM::GPU_CAPABILITIES` | Check for GPU capabilities related to VMs | Windows | 100% | Admin | | | Admin only needed for some heuristics |
513513
| `VM::GPU_VM_STRINGS` | Check for specific GPU string signatures related to VMs | Windows | 100% | | | | If GPU_CAPABILITIES also flags, the overall score will be 50 instead of 100 |
514514
| `VM::VM_DEVICES` | Check for VM-specific devices | Windows | 50% | | | | |
515-
| `VM::IDT_GDT_SCAN` | Check if the IDT and GDT virtual base addresses are equal across different CPU cores when not running under Hyper-V | Windows | 50% | | | | |
516515
| `VM::PROCESSOR_NUMBER` | Check for number of processors | Windows | 50% | | | | |
517516
| `VM::NUMBER_OF_CORES` | Check for number of cores | Windows | 50% | | | | |
518517
| `VM::ACPI_TEMPERATURE` | Check for device's temperature | Windows | 25% | | | | |

src/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
|------|---------|
33
| `cli.cpp` | Entire CLI tool code |
44
| `vmaware.hpp` | Official and original library header in GPL-3.0, most likely what you're looking for. |
5-
| `vmaware_MIT.hpp` | Same as above but in MIT. But this removes 7 techniques out of 118 |
5+
| `vmaware_MIT.hpp` | Same as above but in MIT. But this removes 7 techniques out of 117 |
66

77
<br>
88

src/cli.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,6 @@ bool is_unsupported(VM::enum_flags flag) {
455455
case VM::PORT_CONNECTORS:
456456
case VM::GPU_VM_STRINGS:
457457
case VM::GPU_CAPABILITIES:
458-
case VM::IDT_GDT_SCAN:
459458
case VM::PROCESSOR_NUMBER:
460459
case VM::NUMBER_OF_CORES:
461460
case VM::ACPI_TEMPERATURE:
@@ -972,7 +971,6 @@ void general() {
972971
checker(VM::PORT_CONNECTORS, "physical connection ports");
973972
checker(VM::GPU_CAPABILITIES, "GPU capabilities");
974973
checker(VM::GPU_VM_STRINGS, "GPU strings");
975-
checker(VM::IDT_GDT_SCAN, "IDT GDT consistency");
976974
checker(VM::PROCESSOR_NUMBER, "processor count");
977975
checker(VM::NUMBER_OF_CORES, "CPU core count");
978976
checker(VM::ACPI_TEMPERATURE, "thermal devices");

src/vmaware.hpp

Lines changed: 15 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,6 @@ struct VM {
646646
GPU_VM_STRINGS,
647647
GPU_CAPABILITIES,
648648
VM_DEVICES,
649-
IDT_GDT_SCAN,
650649
PROCESSOR_NUMBER,
651650
NUMBER_OF_CORES,
652651
ACPI_TEMPERATURE,
@@ -7706,23 +7705,23 @@ struct VM {
77067705
const HANDLE handle5 = CreateFileA(("\\\\.\\HGFS"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
77077706
const HANDLE handle6 = CreateFileA(("\\\\.\\pipe\\cuckoo"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
77087707

7709-
bool result = false;
7708+
bool vbox = false;
77107709

77117710
if (
77127711
(handle1 != INVALID_HANDLE_VALUE) ||
77137712
(handle2 != INVALID_HANDLE_VALUE) ||
77147713
(handle3 != INVALID_HANDLE_VALUE) ||
77157714
(handle4 != INVALID_HANDLE_VALUE)
77167715
) {
7717-
result = true;
7716+
vbox = true;
77187717
}
77197718

77207719
CloseHandle(handle1);
77217720
CloseHandle(handle2);
77227721
CloseHandle(handle3);
77237722
CloseHandle(handle4);
77247723

7725-
if (result) {
7724+
if (vbox) {
77267725
debug("VM_DEVICES: Detected VBox related device handles");
77277726
return core::add(brands::VBOX);
77287727
}
@@ -7746,98 +7745,6 @@ struct VM {
77467745
}
77477746

77487747

7749-
/**
7750-
* @brief Check if the IDT and GDT virtual base addresses are equal across different CPU cores when not running under Hyper-V
7751-
* @note The Windows kernel has different interrupt handlers registered for each CPU core, resulting in different virtual addresses when calling SIDT and SGDT in kernel-mode.
7752-
* However, when Windows is running under Hyper-V (in a root partition), the IDT and GDT base address will always be the same across all CPU cores if called from user-mode.
7753-
* This kernel address leak prevention measure is done by Hyper-V on purpose and can be abused to detect VMs.
7754-
* @category Windows, x64
7755-
* @author Requiem (https://github.com/NotRequiem)
7756-
* @implements VM::IDT_GDT_SCAN
7757-
*/
7758-
[[nodiscard]] static bool idt_gdt_scan() {
7759-
#if (!WINDOWS)
7760-
return false;
7761-
#else
7762-
// If the system is running under any Hyper-V hypervisor (type 1 or type 2), the IDT and GDT will be equal, as this function is called from user-mode.
7763-
if (util::hyper_x() != HYPERV_UNKNOWN_VM) {
7764-
return false;
7765-
}
7766-
7767-
unsigned int num_threads = std::thread::hardware_concurrency();
7768-
7769-
uint64_t* gdtResults = new uint64_t[num_threads];
7770-
uint64_t* idtResults = new uint64_t[num_threads];
7771-
7772-
std::vector<std::thread> threads;
7773-
threads.reserve(num_threads);
7774-
7775-
for (unsigned int i = 0; i < num_threads; ++i) {
7776-
try {
7777-
threads.emplace_back([i, gdtResults, idtResults]() {
7778-
const HANDLE thread = GetCurrentThread();
7779-
DWORD_PTR affinity_mask = 1ULL << i;
7780-
SetThreadAffinityMask(thread, affinity_mask);
7781-
7782-
#pragma pack(push, 1)
7783-
struct DescriptorTablePointer {
7784-
uint16_t limit;
7785-
uint64_t base;
7786-
};
7787-
#pragma pack(pop)
7788-
7789-
DescriptorTablePointer idtr = {};
7790-
DescriptorTablePointer gdtr = {};
7791-
7792-
#if (CLANG || GCC)
7793-
__asm__ volatile("sidt %0" : "=m"(idtr));
7794-
__asm__ volatile("sgdt %0" : "=m"(gdtr));
7795-
#else
7796-
__sidt(&idtr);
7797-
_sgdt(&gdtr);
7798-
#endif
7799-
7800-
gdtResults[i] = gdtr.base;
7801-
idtResults[i] = idtr.base;
7802-
});
7803-
}
7804-
catch (...) {
7805-
delete[] gdtResults;
7806-
delete[] idtResults;
7807-
return false; // umip
7808-
}
7809-
}
7810-
7811-
for (auto& thread : threads) {
7812-
thread.join();
7813-
}
7814-
7815-
bool equal = true;
7816-
7817-
for (unsigned int i = 1; i < num_threads; ++i) {
7818-
if (gdtResults[i] != gdtResults[0]) {
7819-
equal = false;
7820-
break;
7821-
}
7822-
}
7823-
7824-
if (equal) {
7825-
for (unsigned int i = 1; i < num_threads; ++i) {
7826-
if (idtResults[i] != idtResults[0]) {
7827-
equal = false;
7828-
break;
7829-
}
7830-
}
7831-
}
7832-
7833-
delete[] gdtResults;
7834-
delete[] idtResults;
7835-
7836-
return equal;
7837-
#endif
7838-
}
7839-
7840-
78417748
/**
78427749
* @brief Check for number of logical processors
78437750
* @category Windows
@@ -7886,12 +7793,14 @@ struct VM {
78867793
while (size > 0) {
78877794
if (ptr->Relationship == RelationProcessorCore) {
78887795
++physicalCoreCount;
7796+
if (physicalCoreCount > 1)
7797+
return false;
78897798
}
78907799
size -= ptr->Size;
78917800
ptr = reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(reinterpret_cast<BYTE*>(ptr) + ptr->Size);
78927801
}
78937802

7894-
return (physicalCoreCount < 2);
7803+
return true;
78957804
#endif
78967805
}
78977806

@@ -8030,7 +7939,7 @@ struct VM {
80307939
// Disable specific sanitizers for more accurate timing measurements.
80317940
__attribute__((no_sanitize("address", "leak", "thread", "undefined")))
80327941
#endif
8033-
static bool timer() {
7942+
static bool timer() {
80347943
#if (ARM || !x86)
80357944
return false;
80367945
#else
@@ -8217,8 +8126,10 @@ struct VM {
82178126
const bool qpcCheck = (dummyTime != 0) && ((cpuIdTime / dummyTime) > qpcRatioThreshold);
82188127
#ifdef __VMAWARE_DEBUG__
82198128
debug("TIMER: QPC check - CPUID: ", cpuIdTime,
8220-
" ns, Dummy: ", dummyTime,
8221-
" ns, Ratio: ", (cpuIdTime / dummyTime));
8129+
" ns, RWB: ", dummyTime,
8130+
" ns, Ratio: ", (cpuIdTime / dummyTime),
8131+
" (Threshold: ", qpcRatioThreshold,
8132+
')');
82228133
#endif
82238134

82248135
if (qpcCheck) {
@@ -8243,7 +8154,7 @@ struct VM {
82438154
__except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION
82448155
? EXCEPTION_EXECUTE_HANDLER
82458156
: EXCEPTION_CONTINUE_SEARCH) {
8246-
// // RDTSCP is widely supported on real hardware, most likely VM
8157+
// RDTSCP is widely supported on real hardware, most likely VM
82478158
tscIssueCount++;
82488159
continue;
82498160
}
@@ -8255,7 +8166,9 @@ struct VM {
82558166
debug("TIMER: TSC sync check",
82568167
" - Core1: ", tscCore1,
82578168
" Core2: ", tscCore2,
8258-
" Diff: ", tscCore2 - tscCore1);
8169+
" Diff: ", tscCore2 - tscCore1,
8170+
" (Threshold: ", tscSyncDiffThreshold,
8171+
')');
82598172
#endif
82608173
return (tscIssueCount >= tscIterations / 2);
82618174
}();
@@ -11423,7 +11336,6 @@ struct VM {
1142311336
case GPU_VM_STRINGS: return "GPU_STRINGS";
1142411337
case GPU_CAPABILITIES: return "GPU_CAPABILITIES";
1142511338
case VM_DEVICES: return "VM_DEVICES";
11426-
case IDT_GDT_SCAN: return "IDT_GDT_SCAN";
1142711339
case PROCESSOR_NUMBER: return "PROCESSOR_NUMBER";
1142811340
case NUMBER_OF_CORES: return "NUMBER_OF_CORES";
1142911341
case ACPI_TEMPERATURE: return "ACPI_TEMPERATURE";
@@ -11986,7 +11898,6 @@ std::pair<VM::enum_flags, VM::core::technique> VM::core::technique_list[] = {
1198611898
std::make_pair(VM::GPU_VM_STRINGS, VM::core::technique(100, VM::gpu_vm_strings)),
1198711899
std::make_pair(VM::GPU_CAPABILITIES, VM::core::technique(100, VM::gpu_capabilities)),
1198811900
std::make_pair(VM::VM_DEVICES, VM::core::technique(50, VM::vm_devices)),
11989-
std::make_pair(VM::IDT_GDT_SCAN, VM::core::technique(50, VM::idt_gdt_scan)),
1199011901
std::make_pair(VM::PROCESSOR_NUMBER, VM::core::technique(50, VM::processor_number)),
1199111902
std::make_pair(VM::NUMBER_OF_CORES, VM::core::technique(50, VM::number_of_cores)),
1199211903
std::make_pair(VM::ACPI_TEMPERATURE, VM::core::technique(25, VM::acpi_temperature)),

0 commit comments

Comments
 (0)