Skip to content

Hyper-V enlightenments (synthetic MSRs / hypercalls)

Hyper-V Top-Level Functional Specification (TLFS) tarafından tanımlanan paravirtualized interface: bir guest, hypervisor'ı 0x400000000x4000000A CPUID leaf'leri üzerinden keşfeder, sonra VM-exit'leri azaltan "exit-less" feature'ları kullanmak için synthetic MSR'lara ve bir hypercall page'e opt-in olur. Bunları tespit edip enumerate etmek, aynı zamanda hassas bir hypervisor-fingerprinting surface'idir.

Mechanism

Neden çalışır

Saf hardware virtualization, guest'i gerçek hardware'e sahip olduğuna inandırır, ama o zaman birçok operasyon (EOI'ler, IPI'ler üzerinden TLB shootdown'ları, timer read'leri) her biri bir VM-exit'e mal olur. Enlightenment'lar açık, cooperative bir sözleşmedir: Hyper-V üzerinde olduğunu bilen bir guest, hypervisor'ı tanımlı bir ABI üzerinden doğrudan çağırabilir ve exit-ağırlıklı hardware emulation'ını ucuz shared-memory veya hypercall path'leriyle değiştirebilir.

Keşif, hypervisor CPUID leaf'leri üzerinden olur (TLFS feature discovery):

  • 0x40000000 — maximum hypervisor leaf (EAX) ve EBX/ECX/EDX'teki vendor ID signature ("Microsoft Hv").
  • 0x40000001interface signature; Microsoft'un hypervisor'ı "Hv#1" (0x31237648) döndürür ki bu HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL ve HV_X64_MSR_VP_INDEX'in var olduğunu garanti eder.
  • 0x40000002 — hypervisor version/build.
  • 0x40000003feature identification (hangi synthetic MSR'ların/privilege'lerin mevcut olduğu, örn. bit 4'te XMM fast hypercall input, bit 15'te output).
  • 0x40000004 — implementation recommendation'ları (örn. TLB flush / APIC için hypercall'ları tercih et).
  • 0x40000005 — implementation limit'leri (max VP/LP).
  • 0x40000006 — tespit edilen hardware feature'ları.
  • 0x40000009/0x4000000Anested hypervisor ve enlightened-VMX feature'ları (örn. enlightened MSR bitmap 0x4000000A'da raporlanır).

Guest ardından interface'i synthetic MSR'lar üzerinden aktive eder: kimliğini HV_X64_MSR_GUEST_OS_ID'ye (0x40000000) yazar, sonra HV_X64_MSR_HYPERCALL'a (0x40000001) bir guest physical page number ve enable bit'i yazarak hypercall page'i map'ler — byte'ları hypervisor tarafından sağlanan bir overlay page'dir, böylece guest, alttaki VMCALL/VMMCALL opcode'undan bağımsız olarak onun içine CALL edebilir. Diğer MSR'lar belirli enlightenment'ları açığa çıkarır (her biri CPUID ile gate'li): HV_X64_MSR_VP_INDEX (0x40000002), SynIC control/SINT MSR'ları (0x400000800x4000009F), synthetic-timer MSR'ları (0x400000B00x400000B7) ve time MSR'ları HV_X64_MSR_TIME_REF_COUNT (0x40000020) / HV_X64_MSR_REFERENCE_TSC (0x40000021).

Paravirtualization'ı enable eden aynı leaf'ler/MSR'lar, hypervisor'ı da ilan eder — bu yüzden onları enumerate etmek güvenilir bir VM/hypervisor fingerprint'idir.

Walkthrough

MSR numaraları ve kurulum sırası TLFS'ten gelir

Aşağıdaki CPUID leaf'leri, MSR numaraları ve hypercall-page adımları Microsoft Hypervisor TLFS'inden (hypercall interface + feature discovery) ve QEMU Hyper-V enlightenments referansından alınmıştır; yalnızca belirtilen spesifikasyonlar kullanılmıştır.

1. Bir hypervisor olduğunu ve onun Hv#1 olduğunu doğrula.

CPUID.1:ECX[31]            -> hypervisor-present bit set
CPUID.0x40000000:EAX       -> max leaf (>= 0x40000005 expected)
CPUID.0x40000000:EBX/ECX/EDX -> "Microsoft Hv"
CPUID.0x40000001:EAX       -> "Hv#1" (0x31237648)

2. Hypercall interface'ini kur (TLFS sırası):

wrmsr(HV_X64_MSR_GUEST_OS_ID /*0x40000000*/, encode_os_identity());   // must be non-zero first
val = rdmsr(HV_X64_MSR_HYPERCALL /*0x40000001*/);
if (!(val & 1)) {                      // bit 0 = Enable hypercall page
    gpa_pfn = pick_guest_page();
    wrmsr(HV_X64_MSR_HYPERCALL, (gpa_pfn << 12) | 1);   // bits 63:12 = GPFN, bit 0 = enable
}
// now CALL the start of the hypercall page with inputs in RCX/RDX/R8

RCX'teki hypercall input value, call code'u (bit 15:0), bir Fast bit'i (16, register vs. memory parametreleri) ve rep count/start field'larını paketler; RDX/R8 input/output parameter GPA'larını taşır; sonuç RAX'te geri gelir. Hypercall'lar yalnızca CPL 0'dan legaldir (aksi hâlde #UD).

VM-exit'leri kaldıran enlightenment'lar (QEMU hv-* görünümü)
hv-vapic      VP Assist page  -> exit-less (paravirt) APIC EOI
hv-vpindex    HV_X64_MSR_VP_INDEX (0x40000002)  -> VP identity for hypercalls
hv-time       REFERENCE_TSC (0x40000021)/TIME_REF_COUNT (0x40000020) -> exit-less time reads
hv-synic      SynIC MSRs 0x40000080..0x4000009F -> synthetic interrupts
hv-stimer     STIMERx MSRs 0x400000B0..0x400000B7 -> per-vCPU synthetic timers
hv-tlbflush   HvCallFlush* hypercalls           -> remote TLB flush without IPIs
hv-ipi        HvCallSendSyntheticClusterIpi     -> cluster IPI in one hypercall
hv-evmcs      enlightened VMCS (nested, Intel)  -> faster L0<->L1 nested exits
hv-emsr-bitmap CPUID 0x4000000A                 -> fewer MSR-bitmap updates (nested)

Her feature, bir guest onu kullanmadan önce ilan edilmiş (CPUID) olmalıdır; ilan edilmemiş bir facility'yi kullanmak tipik olarak fault eder (#UD).

Detection

  • Bir guest'in hypervisor'ını fingerprint'lemek: CPUID.1:ECX[31]'i, sonra 0x40000000/0x40000001 leaf'lerini okuyun — "Microsoft Hv" vendor string'i ve "Hv#1" interface signature'ı Hyper-V'yi (ve Windows guest'leri için Hyper-V taklit ettiğinde KVM/QEMU'yu) kesin olarak teşhis eder. Bkz. cpuid-hypervisor-vendor-id-leaf-probing.md ve cpuid-hypervisor-present-bit-detection.md.
  • Host-side: bir guest'in HV_X64_MSR_GUEST_OS_ID / HV_X64_MSR_HYPERCALL yazması ve bir hypercall page map'lemesi normal enlightenment handshake'idir; anormal kullanım (örn. beklenmeyen bir bileşenden veya kilitli bir page'i taşımak) ilgi çeken sinyaldir.

Mitigation

  • Anti-fingerprinting (araştırma/red-team): bir hypervisor, "Hv#1" ipucunu reddetmek için non-Hyper-V (veya boş) bir 0x4000000x interface'i sunabilir; bunun bedeli Windows guest'inin enlightenment performance'ını kaybetmesidir.
  • Hardening (defender/operator): hypercall ABI'sini bir attack surface olarak ele alın — hypercall input'larını/GPA'larını validate edin (TLFS, input page'in map'li ve readable, output'un writable, 8-byte aligned ve page-spanning olmaması gerektiğini şart koşar), CPL-0 ve privilege kısıtlamalarını enforce edin ve uygun olduğu yerde hypercall-page MSR'ını kilitleyin ki page yeniden konumlanamasın.

References