Skip to content

Guest single-stepping (Monitor Trap Flag stepping)

Intel VT-x Monitor Trap Flag (MTF)'i arm ederek bir guest vCPU'yu VM dışından her seferinde bir instruction adımlamak; bu, her instruction boundary'sinde bir VM-exit zorlar — geçici olarak restore edilmiş bir instruction'ın "üzerinden adımlamak (step over)" için kullanılan introspection primitive.

Mechanism

Neden çalışır

Bare-metal bir CPU'da single-stepping RFLAGS.TF (trap flag) ile sürülür: her instruction'dan sonra CPU bir #DB debug exception teslim eder ve bunu CPU'da her ne çalışıyorsa (kernel/debugger) ele almalıdır. Bu mekanizma guest-visible'dır — guest TF'i okuyabilir, #DB'yi hook'layabilir ve adımlandığını fark edebilir.

Intel VT-x out-of-band bir eşdeğer sağlar: Monitor Trap Flag (MTF), VMCS'te yaşayan processor-based bir VM-execution control. monitor-trap-flag VM-execution control set edildiğinde, guest (esasen) her guest instruction'ından sonra bir VM-exit tetikler ve kontrolü in-guest koda değil hypervisor'a (VMX root) teslim eder. Single step bu nedenle guest için görünmezdir: RFLAGS'te hiçbir flag değişmez, #DB inject edilmez ve guest'in kendi debug state'ine dokunulmaz.

Kanonik introspection kullanımı "restore edilmiş bir instruction'ın üzerinden adımlamak"tır. Bir monitor, bir page'in execution'ını EPT üzerinden trap eder (bir EPT violation), sonra trap'i yeniden arm etmeden önce guest'in orijinal permission/byte'lar yerindeyken tam olarak bir instruction çalıştırmasına izin vermelidir. Sıra şudur:

  1. Korunan page'de EPT violation → hypervisor'a VM-exit.
  2. EPT entry'sini geçici olarak gevşet (örn. execute/write'ı restore et) ki o bir gerçek instruction çalışabilsin.
  3. MTF'i set et ki bir sonraki instruction bir VM-exit'e yol açsın.
  4. VM-entry; guest bir instruction çalıştırır; bir MTF VM-exit fire eder.
  5. Kısıtlayıcı EPT permission'ını yeniden uygula ve MTF'i temizle.

Bu "trap → gevşet → MTF-step → yeniden koru" loop'u, EPT tabanlı stealth hook'ların ve hyper-breakpoint'lerin belkemiğidir.

Walkthrough

VMX root / kontrol ettiğiniz bir hypervisor gerektirir

MTF yalnızca bir VMM'in içinden anlamlıdır. Aşağıdaki control bit'i ve exit reason'ı Intel SDM Vol. 3C VMX bölümlerinden gelir; EPT + MTF loop'u ise public VT-x introspection yazılarında dokümante edilen pattern'dir.

1. Control'ü enable et. MTF, VMCS'teki primary processor-based VM-execution controls alanının 27. bit'idir ("monitor trap flag"). Hypervisor, adımlamaya başlamak için bunu VM-entry öncesi set eder ve durdurmak için temizler.

VMCS primary proc-based exec controls |= (1 << 27)   ; arm MTF
... VM-entry ...
; guest runs one instruction
... VM-exit, basic exit reason = 37 (MONITOR TRAP FLAG) ...
VMCS primary proc-based exec controls &= ~(1 << 27)  ; disarm MTF

Ortaya çıkan VM-exit gerçekleştiğinde, VMCS VM-exit reason alanı basic exit reason 37 ("Monitor Trap Flag") bildirir; bu, adımın bir instruction boundary'sinde tamamlandığını işaret eder.

2. EPT step-over loop'u (introspection pattern'inden pseudo-code):

on_ept_violation(gpa) {
    relax_ept_perms(gpa);          // restore X (or W) for one instruction
    set_mtf();                     // arm bit 27 in proc-based ctls
    // VM-entry happens on return
}

on_mtf_vmexit() {                  // basic exit reason 37
    restrict_ept_perms(gpa);       // re-protect the page
    clear_mtf();                   // disarm bit 27
    // VM-entry; guest continues normally
}
Adımlayan bir monitor'dan gözlemlenebilir trace
[vmexit] reason=EPT_VIOLATION gpa=0x1f4a0 acc=exec
[step]   relax X on gpa, arm MTF, VM-entry
[vmexit] reason=37 MONITOR_TRAP_FLAG  rip=0x...   (one insn executed)
[step]   re-protect gpa (--X removed), clear MTF, VM-entry
guest:   no TF set, no #DB observed -> stepping is invisible in-guest

SDM'nin işaret ettiği boundary uyarısına dikkat edin: MTF, event delivery ile etkileşir — VM-entry vectored bir event inject ederse ya da bir fault/exception teslim edilirse, MTF exit'i o teslimden sonraki uygun instruction boundary'sinde alınır; dolayısıyla doğru bir stepper, temiz bir "source-line başına bir exit" modeli varsaymak yerine inject edilen interrupt ve exception'ları hesaba katmalıdır.

Detection

  • In-guest: MTF, RFLAGS.TF'e dokunmadığı ve #DB inject etmediği için klasik pushf/TF self-check'leri onu göremez. Geriye kalan sinyal timing'dir: her adımlanan instruction tam bir VM-exit/entry round trip'e mal olur, dolayısıyla sıkı ve bilinen bir loop'u zamanlayan kod, adımlanırken çok büyük mertebelerde bir yavaşlamayı gözlemleyebilir.
  • From the host: aynı GPA üzerindeki EPT violation'larıyla iç içe geçmiş bir basic-exit-reason-37 event seli, hypervisor telemetry'sinde MTF stepping'in net bir signature'ıdır.

Mitigation

  • Guest-side: trap-flag probe'ları yerine timing tabanlı liveness/attestation'a güvenin; bir MTF stepper, dikkatli kalibre edilmiş bir timer'dan instruction başına exit latency'sini gizleyemez.
  • Host-side: MTF'i privileged bir debug facility olarak ele alın — hangi bileşenlerin/domain'lerin onu arm edebileceğini kısıtlayın ve sürekli MTF exit fırtınalarını rate-limit edin ya da alert üretin, çünkü meşru stepping kısa ve hedefli olur.

References