Skip to content

Instruction emulation hyper-breakpoint

Patch'lenmiş instruction'ı guest'te restore edip yeniden çalıştırmak yerine, original instruction'ı hypervisor içinde decode edip emulate eden bir hyper-breakpoint varyantı — böylece guest'in memory'si hiçbir zaman un-patch edilmez ve breakpoint'in yeniden re-arm edilmesi gerekmez.

Mechanism

Note

Bir hyper-breakpoint, hedef instruction'ın ilk byte'ının üzerine bir int3 (0xCC) byte'ı yerleştirir; bunu çalıştırmak hypervisor'ın intercept ettiği bir #BP exception'ı doğurur (bir exception-bitmap VM-exit). Asıl problem continuation: original instruction'ın ilk byte'ı kaybolduğu için CPU öylece devam edemez. instruction-emulation varyantı bunu guest memory'sine dokunmadan çözer: hypervisor saklanmış original byte'(lar)ı okur, original instruction'ın tamamını decode eder ve etkisini guest state'e (register'lar, flag'ler, memory) karşı software içinde çalıştırır, ardından guest RIP'i onun ötesine ilerletir. 0xCC hiçbir zaman kaldırılmadığından, trap'in disarm olduğu bir pencere yoktur ve onu re-inject etmeye gerek kalmaz — byte'ı restore edip Monitor Trap Flag üzerinden single-step yapan instruction repair ile karşılaştır.

Bu, bir memory-write + single-step gidiş-dönüşünü (bir ekstra VM-exit) host içindeki bir software instruction decoder/emulator maliyetiyle takas eder.

Walkthrough

Kavramsal akış (hyper-breakpoint varyant karşılaştırma literatüründen):

  1. Arm. Hedef adresteki original byte'ı sakla ve üzerine 0xCC yaz.
  2. Trap. Guest byte'ı çalıştırır; #BP bir VM-exit'e yol açar. Handler, fault'lanan RIP'i kayıtlı bir hyper-breakpoint ile eşleştirir ve callback'i çalıştırır.
  3. Repair yerine emulate. Original byte'ı geri yazmak yerine handler:
orig = saved_original_bytes(rip)      // bytes hidden by the 0xCC
insn = decode(orig)                   // length + semantics
emulate(insn, &guest_state)           // apply effect to regs/flags/mem
guest_rip += insn.length              // step over the original instruction

0xCC tüm bu süre boyunca guest memory'sinde kalır. 4. Resume. VM-entry doğrudan bir sonraki instruction'a döner. Trap bir sonraki isabet için hâlâ arm'lıdır — re-injection adımı yok.

Warning

Correctness, eksiksiz ve sadık bir emulator'a bağlıdır. Decoder'ın modellemediği herhangi bir instruction ya da yanlış uyguladığı herhangi bir side effect (segmentation, fault'lar, locked op'ların atomicity'si, FPU/SSE state), guest'i bozar. Bu, gerçek instruction'ı her zaman gerçek silicon üzerinde çalıştıran repair/EPT-switch varyantlarına karşı merkezî takastır. Correctness'i tercih eden engine'ler (örn. DRAKVUF) emulation'dan bilinçli olarak kaçınır ve bunun yerine SLAT view switching kullanır.

Beklenen gözlem: her breakpoint isabeti, ardından bir Monitor-Trap-Flag exit'i olmadan ve page'in geçici bir un-patch'i olmadan tek bir #BP VM-exit üretir.

Detection

  • 0xCC executable byte'larda kalıcı olarak bulunur, dolayısıyla patch'lenmiş adresi okuyabilen bir guest (EPT split gibi read-side stealth katmanlanmadığında) breakpoint'i doğrudan görür — bir self-checksum bunu tespit eder.
  • Davranışsal timing native'den farklıdır çünkü her isabet bir emulation pass'i getirir.

Mitigation

  • SLAT/altp2m read-side stealth katmanla, böylece patch'lenmiş page'in okumaları temiz byte'ları görürken 0xCC yalnızca çalıştırılır.
  • Emulator sadakatinin şüpheli olduğu yerlerde, gerçek instruction'ı çalıştıran instruction repair veya bir EPT-switch single-step tercih et.

References