Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 6 additions & 106 deletions src/vmaware.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5132,7 +5132,7 @@

std::string line;
int processors = 0;
bool in_section = false;

Check warning on line 5135 in src/vmaware.hpp

View workflow job for this annotation

GitHub Actions / Analyze (cpp, gcc-14, Ninja Multi-Config, Debug, ON)

variable 'in_section' set but not used [-Wunused-but-set-variable]
int cur_phys = -1, cur_core = -1;
std::vector<std::pair<int, int>> cores;

Expand Down Expand Up @@ -5678,8 +5678,10 @@
debug("TIMER: VMM -> ", cpuid_l, " | nVMM -> ", ref_l, " | Ratio -> ", latency_ratio);
if (latency_ratio >= threshold) hypervisor_detected = true;

// Now detect bypassers letting the VM boot with cpuid interception, and then disabling interception with SVM by flipping bit 18 in the VMCB
// if hypervisor lies about the CPU vendor, it will create 100000 more detectable signals (querying intel-specific behavior)
// Now detect bypassers disabling cpuid interception with SVM
// Even when a bypasser disables INTERCEPT_CPUID in the VMCB, they often fail to realize that certain CPUID leaves do not return static values from the hardware
// Instead, they return values based on the LAPIC state or internal CPU registers that the hypervisor must initialize for the vCPU to function
// if hypervisor lies about the CPU vendor, it will create 100000 more detectable signals (querying Intel-specific behavior)
if (cpu::is_amd() && !hypervisor_detected) {
i32 res_d0[4], res_d1[4], res_d12[4], res_ext[4];
trigger_vmexit(res_d0, 0xD, 0); // XCR0 features
Expand Down Expand Up @@ -5707,7 +5709,6 @@

std::thread t1(counter_thread);
trigger_thread();

t1.join();

if (hypervisor_detected) {
Expand All @@ -5718,7 +5719,7 @@
}

return hypervisor_detected;
#endif
#endif
return false;
}

Expand Down Expand Up @@ -11903,108 +11904,7 @@
return true;
}
}

// we will run amd only stuff
if (!cpu::is_amd()) {
return false;
}

struct state {
volatile int in_asm;
volatile int exception_seen;
};

static thread_local state* tls_state = nullptr;

state state{};
tls_state = &state;

// lambda to capture exceptions
const PVOID vh = AddVectoredExceptionHandler(
1,
[](PEXCEPTION_POINTERS ep) -> LONG {
if (!tls_state || !tls_state->in_asm)
return EXCEPTION_CONTINUE_SEARCH;

const DWORD code = ep->ExceptionRecord->ExceptionCode;
if (code == EXCEPTION_ILLEGAL_INSTRUCTION) {
tls_state->exception_seen = 1;
#if (x86_64)
ep->ContextRecord->Rip += 3;
#else
ep->ContextRecord->Eip += 3;
#endif
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
);
if (!vh) return false;

// xor rdpru ret
constexpr unsigned char code[] = {
0x31, 0xC9,
0x0F, 0x01, 0xFD,
0xC3
};

PVOID mem = nullptr;
SIZE_T size = sizeof(code);

if (nt_allocate_virtual_memory(
current_process,
&mem,
0,
&size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE) != 0 || !mem)
{
RemoveVectoredExceptionHandler(vh);
return false;
}

memcpy(mem, code, sizeof(code));

nt_flush_instruction_cache(current_process, mem, sizeof(code));

using fn_t = void(*)();
fn_t fn = reinterpret_cast<fn_t>(mem);

state.exception_seen = 0;
state.in_asm = 1;

__try {
fn();
}
__except (EXCEPTION_EXECUTE_HANDLER) {
state.exception_seen = 1;
}

state.in_asm = 0;

if (state.exception_seen) {
debug("KVM_INTERCEPTION: Detected a hypervisor intercepting performance counter reads");
generic_hypervisor = true;
}

SIZE_T free_size = 0;
nt_free_virtual_memory(
current_process,
&mem,
&free_size,
MEM_RELEASE
);

nt_close(current_process);

RemoveVectoredExceptionHandler(vh);

// KVM does this, but other hypervisors might do the same, reason why is generic
// kernel might configure CR4 to inject exception if CPL > 0, so if this case is detected, trigger a lower probability score
if (generic_hypervisor) {
return core::add(brand_enum::NULL_BRAND, 50);
}


return false;
}

Expand Down
Loading