EPT-switch single-step (swap to original view, step, swap back)¶
Hook'lanmış bir page'in bir read'ini servis etmek: faulting vCPU'yu orijinal, hook'lanmamış SLAT view'ına geçir, erişim temiz byte'ları görsün diye tam olarak bir instruction single-step et, sonra hooked view'a geri geç — kanonik "hyper-breakpoint" restore döngüsü.
Mechanism¶
Note
Bir SLAT-tabanlı hook (bir EPT split ya da stealth hook) iki memory view tutar: hedef page'i patch'li/breakpoint'li bir frame üzerinde execute-only olan bir hooked view ve page'i temiz frame üzerinde düz okunabilir olan bir original view. Hooked page'in bir read ya da write'ı bir EPT violation ile trap ettiğinde, host ne erişimin hooked frame'e karşı çalışmasına izin verebilir (patch'i açığa çıkarır) ne de permission'ı kalıcı olarak gevşetebilir (hook'u yok eder). EPT switching bunu, faulting vCPU'yu orijinal view'a taşıyarak, o view altında tam olarak bir instruction execute ederek (read temiz byte'ları gözlemler), sonra vCPU'yu hooked view'a geri geçirerek çözer.
Bunun koruduğu invariant host tarafından code-read/code-exec tutarlılığıdır:
read'ler her zaman temiz view'a karşı çözülür, fetch'ler her zaman hooked view'a
karşı çözülür ve temiz byte'ların erişilebilir olduğu pencere tek bir instruction'a
sınırlıdır. View swap per-vCPU'dur (böylece diğer vCPU'lar hooked view'ı çalıştırmaya
devam eder) ve single-step sınırı, guest'in geçici temiz mapping'i fault verdiği tek
erişimden fazlası için kullanamayacağını garanti eden şeydir. Bu, DRAKVUF'un Xen
altp2m view'larıyla kullandığı mekanizmadır ve HyperDbg'nin
!epthook'unun arkasındaki restore path'idir.
Single-step'in kendisi Monitor Trap Flag (MTF) ile gerçekleştirilir: view swap'tan sonra handler MTF'i arm eder ve resume eder; MTF, yeniden execute edilen tek instruction retire olduktan sonra bir VM exit'e neden olur ve host'un hooked view'a geri geçtiği yer o exit'tir. Bir "fast single-stepping" (FSS) optimizasyonu, aynı instruction üzerindeki tekrarlanan step'ler boyunca emulation/step state'ini cache'leyerek per-step maliyetini düşürür.
Walkthrough¶
Breakpoint'li bir page'in bir read'i için DRAKVUF tarzı SLAT view-switch döngüsü:
- Steady state: vCPU hooked altp2m view'ını çalıştırır; hedef GPA, patch'li frame üzerinde execute-only'dir.
- Guest page'i okur → EPT violation (R=0). Handler GPA'yı
GUEST_PHYSICAL_ADDRESSüzerinden tanımlar. - Handler bu vCPU'yu original view'a (temiz, okunabilir frame) geçirir ve MTF'i arm eder.
- Resume: faulting read temiz view'a karşı yeniden execute olur ve orijinal byte'ları döndürür. Instruction retire olur.
- MTF VM exit tetiklenir. Handler vCPU'yu hooked view'a geri geçirir ve MTF'i disarm eder.
- Execution devam eder; page'in bir sonraki fetch'i yine patch'li/
int3frame'i çalıştırır.
view = HOOKED (exec-only, patched) ; steady
read -> EPT violation
switch vCPU -> ORIGINAL (clean, R=1); set MTF; resume
re-exec read sees clean bytes; retires
MTF vmexit: switch vCPU -> HOOKED; clear MTF
Bu, üç klasik hyper-breakpoint restore stratejisinden biridir; public karşılaştırma (Engineering / MDPI 2025) üçünü de 20 test platformunda ölçer:
- EPT switching (bu teknik), fast single-stepping'li ve fast single-stepping'siz.
- Instruction repair — orijinal byte'ı geri yaz, single-step et, breakpoint'i yeniden ekle. Üçü içinde en yavaş ölçülen.
- Instruction emulation — faulting tek instruction'ı CPU'ya temiz byte'ları hiç açığa çıkarmadan VMM'de emüle et. 20 platformun hepsinde en hızlı ölçülen (modern parça'larda, örn. i7-12700H / i9-13900HX, median breakpoint-işleme süreleri ~15 µs'ye kadar düşük). Sıralama (en yavaş repair, sonra EPT switching, sonra emulation) test edilen her platformda tutarlıydı.
Warning
Temiz view, faulting vCPU'da bir instruction boyunca erişilebilir. Single-step sınırı yanlışsa (örn. MTF arm edilmemiş ya da step ortasında bir fault/interrupt teslim edilmiş), guest ya temiz byte'ları amaçlanandan daha uzun gözlemleyebilir ya da hook'lanmamış kodu execute eder hale gelebilir — ikisi de hook'un stealth'ini ya da işlevini bozar. Eşzamanlı vCPU'lar swap'lanan view'ı paylaşmamalıdır.
Detection¶
- Timing: hook'lanmış bir page'in her read'i bir EPT violation, bir view switch, bir MTF single-step ve bir geri switch'e mal olur — bir guest'in monitör edilen page'leri map'lemek için timing'leyebileceği büyük, ölçülebilir bir latency spike'ı.
- Single-step artifact'leri: MTF-driven single-stepping instruction timing'ini
bozar ve performance counter'lar ya da
rdtscdelta'larıyla görünür şekilde etkileşebilir. - Davranışsal ayrışma: herhangi bir EPT split'te olduğu gibi, okuduğu byte'ları execute ettiği davranışla karşılaştıran (checksum) bir guest tutarsızlığı saptar.
Mitigation¶
- altp2m/EPT view konfigürasyonunu ve view-switch kontrolünü kesinlikle host-owned tut; guest'ler bir vCPU'nun hangi view'da olduğunu pin'leyememeli ya da sorgulayamamalı.
- Fidelity izin verdiği yerde instruction emulation'ı tercih et — guest CPU'ya temiz byte'ları asla açığa çıkarmaz ve (public karşılaştırmaya göre) aynı zamanda en hızlısıdır, böylece view-switching'e göre hem bir stealth boşluğunu hem de bir performans boşluğunu kapatır.
- Interrupt'ların/exception'ların single-step penceresi içinde orijinal view'ı sızdıracak şekilde teslim edilemeyeceğinden emin ol; swap'ı tek bir instruction'a sıkıca sınırla.
- Nesting altında, L0 L1'in view-switch + MTF semantiğini sadakatle shadow'lamalı ki bir L2 guest'i restore döngüsünü saptayamasın ya da ondan kaçamasın.