Skip to content

Instruction repair hyper-breakpoint

Her int3 hit'inde guest memory'deki üzerine yazılmış orijinal byte'ı geri yükleyen ("repair" eden), o tek instruction'ı Monitor Trap Flag ile single-step'leyen ve ardından trap'i yeniden kurmak için 0xCC'yi tekrar enjekte eden bir hyper-breakpoint varyantı.

Mechanism

Note

Bir hyper-breakpoint, hedef instruction'ın ilk byte'ının üzerine bir int3 (0xCC) gizler; execution #BP raise eder ve bu hypervisor tarafından intercept edilir. Doğru şekilde devam edebilmek için instruction-repair varyantı gerçek instruction'ı real silicon üzerinde çalıştırır: kaydedilmiş orijinal byte'ı geri yazar, VMCS içinde Monitor Trap Flag (MTF)'i set eder ki CPU tam olarak bir instruction çalıştırıp ardından bir VM-exit'e zorlansın, ve o MTF exit'inde 0xCC'yi tekrar kurar. DRAKVUF literatürüne göre MTF "processor'ın virtualization extension'larının sağladığı eşdeğer single-stepping işlevselliğidir" ve guest'e şeffaftır — guest'in gözlemleyebileceği kendi TF (RFLAGS trap flag) bayrağını toggle'lamanın aksine.

Tanımlayıcı özellik bir race window'dur: repair (byte geri yüklendi) ile re-injection arasında trap bir an için devre dışıdır. Bu, 0xCC'yi hiçbir zaman kaldırmayan ve dolayısıyla ne MTF single-step'ine ne de re-injection'a ihtiyaç duyan instruction emulation varyantından temel farktır: repair instruction'ı real silicon üzerinde çalıştırıp fidelity'yi garantiler ama açık bir un-patch penceresi ve hit başına ikiye katlanan VM-exit pahasına. DRAKVUF, breakpoint'in "trap'i resetlemek ve system call'ın gelecekteki herhangi bir örneğini kaçırmamak için sadece bir instruction çalıştırıldıktan sonra" tekrar enjekte edilmesi gerektiğini belirtir; o timing'i yakalamanın tek güvenilir yolu MTF single-stepping'tir.

Walkthrough

SmartVMI/DRAKVUF breakpoint handler tanımına göre akış:

  1. Arm. Orijinal byte'ı kaydet; hedefe 0xCC yaz.
  2. #BP exit. Guest breakpoint'e takılır; hypervisor RIP'i eşleştirir ve kayıtlı callback'i çalıştırır.
  3. Repair + single-step. Handler "hypervisor'a orijinal instruction'ı geri yüklemesini ve single-stepping'i etkinleştirmesini söyler":
write_guest_byte(rip, saved_original_byte(rip));  // un-patch ("repair")
set_vmcs_mtf();                                    // Monitor Trap Flag = 1
vm_entry();                                        // run exactly ONE instruction
  1. MTF exit → re-inject. Single step tamamlanır ve bir MTF VM-exit tetikler. Handler artık bir instruction'ın çalıştığını bilir ve yeniden arm etmek güvenlidir:
on_mtf_exit:
    write_guest_byte(target, 0xCC);  // re-inject the breakpoint
    clear_vmcs_mtf();                // MTF = 0
    vm_entry();                      // resume normally

Warning

3–4. adımlar boyunca orijinal byte guest memory'de canlıdır. O window içinde aynı adresi çalıştıran ikinci bir vCPU trap'i atlatıp geçer. Engine'ler bunu altp2m view switching veya per-vCPU page kopyalarıyla korur; SMP guest'lerde naive single-page repair event'leri kaçırabilir.

Beklenen gözlemlenebilir davranış: her hit bir exit çifti üretir — bir #BP exit'ini takiben bir MTF exit — ve page'in 0xCC yerine orijinal byte'ı tuttuğu kısa bir aralık.

Detection

  • Anlık un-patching artı hit başına ikiye katlanan exit bir timing fingerprint'idir: hit edilen instruction'lar native'e kıyasla iki VM-exit ve bir memory round-trip maliyeti getirir.
  • Read tarafında hiçbir stealth katmanlanmamışsa, hit'ler arasında adresi okuyan bir guest 0xCC görür; bir self-checksum bunu tespit eder. DRAKVUF, sadece repair'e güvenmeyerek ve SLAT view switching kullanarak okumaların temiz page'i görmesini sağlayarak bunu mitige eder.

Mitigation

  • Yeniden arm edilen 0xCC'nin guest read'lerine görünmez olması için repair'i altp2m / EPT split ile birleştir.
  • SMP guest'lerde repair window'unu serialize et veya per-vCPU yap, ya da shared byte'ları editlemek yerine tüm vCPU'yu temiz bir view'a takas eden bir EPT-switch single-step tercih et.

References