Skip to content

Commit e633579

Browse files
author
Requiem
committed
fix: CFG indirect call trigger in hypervisor hook detection
1 parent a33ba94 commit e633579

2 files changed

Lines changed: 31 additions & 6 deletions

File tree

src/cli/output.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ const char* get_vm_description(const std::string& vm_brand) {
191191
{ VM::brands::INTEL_KGT, "Intel Kernel Guard Technology (KGT) is a policy specification and enforcement framework for ensuring runtime integrity of kernel and platform assets. Demonstrated secure enclaves for critical OS components using VT-x/EPT before being superseded by CET (Control-flow Enforcement Technology) and HyperGuard in Windows 10." },
192192
{ VM::brands::AZURE_HYPERV, "Azure Hyper-V is Microsoft's cloud-optimized hypervisor variant powering Azure VMs. Implements Azure-specific virtual devices like NVMe Accelerated Networking and vTPMs. Supports nested virtualization for running Hyper-V/containers within Azure VMs, enabling cloud-based CI/CD pipelines and dev/test environments." },
193193
{ VM::brands::SIMPLEVISOR, "SimpleVisor is a minimalist Intel VT-x hypervisor by Alex Ionescu for Windows/Linux research. Demonstrates EPT-based memory isolation and hypercall handling. Used to study VM escapes and hypervisor rootkits, with hooks for intercepting CR3 changes and MSR accesses." },
194-
{ VM::brands::HYPERV_ROOT, "VMAware detected Hyper-V operating as a type 1 hypervisor, not as a guest virtual machine. Although your hardware/firmware signatures match Microsoft's Hyper-V architecture, we determined that you're running on baremetal. This prevents false positives, as Windows sometimes runs under Hyper-V (type 1) hypervisor." },
194+
{ VM::brands::HYPERV_ROOT, "VMAware detected Hyper-V operating as a type 1 hypervisor, not as a guest virtual machine. This prevents false positives, as Windows sometimes runs under Hyper-V." },
195195
{ VM::brands::UML, "User-Mode Linux (UML) allows running Linux kernels as user-space processes using ptrace-based virtualization. Primarily used for kernel debugging and network namespace testing. Offers lightweight isolation without hardware acceleration, but requires host/guest kernel version matching for stable operation." },
196196
{ VM::brands::POWERVM, "IBM PowerVM is a type 1 hypervisor for POWER9/10 systems, supporting Live Partition Mobility and Shared Processor Pools. Implements VIOS (Virtual I/O Server) for storage/networking virtualization, enabling concurrent AIX, IBM i, and Linux workloads with RAS features like predictive failure analysis." },
197197
{ VM::brands::GCE, "Google Compute Engine (GCE) utilizes KVM-based virtualization with custom Titanium security chips for hardware root of trust. Features live migration during host maintenance and shielded VMs with UEFI secure boot. Underpins Google Cloud's Confidential Computing offering using AMD SEV-SNP memory encryption." },

src/vmaware.hpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ namespace brands { // TODO, remove this in the 2.8.0 or any release after the 2.
505505
LEGACY(AZURE_HYPERV, "Microsoft Azure Hyper-V");
506506
LEGACY(SIMPLEVISOR, "SimpleVisor");
507507
// not in macro due to mismatch with VM::brands and brands:: renaming this to HYPERV_ROOT
508-
[[deprecated("Use VM::brands::HYPERV_ROOT instead")]] static constexpr const char* HYPERV_ARTIFACT = "Hyper-V root partition (host system, not an actual VM)";
508+
[[deprecated("Use VM::brands::HYPERV_ROOT instead")]] static constexpr const char* HYPERV_ARTIFACT = "Hyper-V root partition (host system)";
509509
LEGACY(UML, "User-mode Linux");
510510
LEGACY(POWERVM, "IBM PowerVM");
511511
LEGACY(GCE, "Google Compute Engine (KVM)");
@@ -4900,6 +4900,33 @@ struct VM {
49004900

49014901
return got_any;
49024902
}
4903+
4904+
// indirect call without CFG checks
4905+
#if (MSVC)
4906+
#define NO_CF_GUARD __declspec(guard(nocf)) __declspec(noinline)
4907+
#elif (CLANG)
4908+
#if __has_declspec_attribute(guard)
4909+
#define NO_CF_GUARD __declspec(guard(nocf)) __attribute__((noinline))
4910+
#elif __has_attribute(nocf_check)
4911+
#define NO_CF_GUARD __attribute__((nocf_check)) __attribute__((noinline))
4912+
#else
4913+
#define NO_CF_GUARD __attribute__((noinline))
4914+
#endif
4915+
#elif (GCC)
4916+
#if defined(__has_attribute) && __has_attribute(nocf_check)
4917+
#define NO_CF_GUARD __attribute__((nocf_check)) __attribute__((noinline))
4918+
#else
4919+
#define NO_CF_GUARD __attribute__((noinline))
4920+
#endif
4921+
#else
4922+
#define NO_CF_GUARD
4923+
#endif
4924+
4925+
// helper function to invoke pointers without instrumentation
4926+
NO_CF_GUARD static void execute_unchecked(void* pointer) {
4927+
using func_t = void(*)();
4928+
reinterpret_cast<func_t>(pointer)();
4929+
}
49034930
#endif
49044931
};
49054932

@@ -12411,8 +12438,7 @@ struct VM {
1241112438
using execute_throws_t = bool(*)(void*);
1241212439
execute_throws_t execute_throws = [](void* pointer) -> bool {
1241312440
__try {
12414-
using func_t = void(*)();
12415-
reinterpret_cast<func_t>(pointer)(); // breakpoint hit
12441+
util::execute_unchecked(pointer); // breakpoint hit
1241612442
}
1241712443
__except (EXCEPTION_EXECUTE_HANDLER) {
1241812444
return true;
@@ -12542,8 +12568,7 @@ struct VM {
1254212568
}
1254312569

1254412570
__try {
12545-
using func_t = void(*)();
12546-
reinterpret_cast<func_t>(pointer)();
12571+
util::execute_unchecked(pointer);
1254712572
}
1254812573
__except (EXCEPTION_EXECUTE_HANDLER) {
1254912574
did_anyone_throw = 1;

0 commit comments

Comments
 (0)