Execute-only EPT page (hidden breakpoint)¶
Read ve write bit'leri temizlenmiş ama execute bit'i set kalan bir EPT entry'si; böylece page normal execute olur ama her data read ya da write hypervisor'a trap eder — disassembler'ların ve self-check'lerin göremediği bir breakpoint ya da detour'un temeli.
Mechanism¶
Note
Intel SLAT (EPT)'de her guest-physical frame'in access right'ları guest'e değil, host EPT entry'sine aittir. İlgili invariant şudur: EPT permission bit'leri (Read, Write, eXecute) guest'in kendi page table'larından bağımsız olarak kontrol edilir. Bir execute-only page, X=1 yaparken R=0 ve W=0'ı temizler. CPU o zaman frame'den instruction'ları fetch eder ve çalıştırır, ama aynı guest-physical address'e herhangi bir data erişimi (bir read ya da write) EPT permission check'ini fail eder ve bir EPT violation VM-exit'i yükseltir. Bu, "bir page'e erişmek" tek kavramını hypervisor'ın farklı servis edebileceği iki ayrı path'e — execute vs. read/write — böler.
Bu asimetri breakpoint'i gizli yapan şeydir. Host, page'in modifiye edilmiş bir
kopyasını (bir breakpoint byte'ı ya da bir detour jump'ı ile) execution için canlı
tutabilirken, page'i okuyan her şeye şeffaf biçimde orijinal, temiz byte'ları
sunar. Kendi .text'ini checksum'layan bir guest debugger, integrity scanner ya da
anti-cheat, el değmemiş kopyayı okur ve hiçbir şey görmez; instruction'ları fetch
eden CPU ise instrument edilmiş kopyayı çalıştırır. İzolasyon-sınırı açısından:
guest, EPT permission'larını inceleyemez ya da değiştiremez, dolayısıyla "aynı"
adresin read'leri ile execute'larının farklı host frame'lere yönlendirildiğini
gözlemleyecek mimari bir yolu yoktur. Bu, defensive/introspection bir primitive'dir
(analiz için stealth breakpoint'ler) ve aynı şekilde EPT-tabanlı rootkit hook'larının
da zeminidir. Bkz. EPT split ve
EPT-based stealth hooking.
Walkthrough¶
HyperDbg iki çeşit implement eder. İkisi de execute-only state'e dayanır.
Permission state'leri (bir EPT entry, iki faz):
default : R=1 W=1 X=1 -> normal frame
armed (X-only) : R=0 W=0 X=1 -> execution allowed, any read/write => EPT violation
Klasik stealth int3 hook'u (!epthook):
- Hedef page'i (Page A) taze bir host frame'e (Page B) kopyala.
- Page B'de hedef instruction'ın ilk byte'ına
0xCC(int3) yaz. - EPT entry'sini Page B'ye yönelt ve onu execute-only yap (
R=0 W=0 X=1). - Execution'da int3 tetiklenir ve Exception Bitmap bir VM-exit'i zorlar;
hypervisor
#BP'nin kendisine mi ait (debugger'a teslim et) yoksa yabancı mı (guest'e re-inject et) olduğuna karar verir. - O page'in bir read ya da write'ında bir EPT violation oluşur. Handler entry'yi
geri orijinal Page A'ya swap eder,
R=1 W=1 X=0yapar ve Monitor Trap Flag (MTF)'i set eder. Data access o zaman temiz byte'ları görür. - MTF bir single-step VM-exit'e neden olur; handler entry'yi execute-only Page B'ye
(
R=0 W=0 X=1) geri çevirir ve gizli breakpoint'i yeniden arm eder.
Gizli detour (!epthook2):
Handler bunun yerine entry'de R/W'yi temizler ve X'i set eder, Page A'yı Page B'ye
kopyalar ve Page B'yi hook fonksiyonuna absolute bir jump ile patch'ler (length'ler
bir length-disassembler engine ile hesaplanır ki tüm bir instruction overwrite
edilsin). Execution detour'a iner; page'in read'leri trap'lenir ve orijinal byte'lar
sunulur. !epthook2 gizli bir inline hook gibi davranır ve klasik varyanttan daha
hızlıdır, ama tek bir mode kısıtlaması taşır: HyperDbg docs'una göre yalnızca
kernel-mode address'lerde kullanılabilir, user-mode address'ler için
kullanılamaz. !epthook ise tam da bu yüzden tercih edilir; çünkü o mode
kısıtlamasından muaftır ve hem user-mode hem kernel-mode address'lerde
çalışır.
Warning
Breakpoint/detour byte'ı bir instruction boundary'sinde oturmalıdır. İlk olmayan bir byte'ı patch'lemek decoding'i değiştirir ve execution'ı bozar. Ayrıca, bu tasarımda iki detour tarzı hook tek bir fiziksel page'i paylaşamaz — read/execute split'i per-frame'dir.
Detection¶
- Read/execute ayrışması: bir guest kendi kodunu bir buffer'a kopyalayıp okuduğu byte'ları execute ettiği byte'larla karşılaştırabilir (örn. bir checksum hesapla, sonra region'a jump et) — bir uyuşmazlık split bir mapping'i açığa çıkarır.
- EPT-violation timing'i: hook'lanmış bir page'in her data dokunuşundaki
trap-swap-MTF-swap döngüsü normal bir erişimden çok daha yavaştır;
.textüzerindeki sıkı read döngüleri anormal latency gösterir. - Host telemetry'si: VMM'i çalıştıran defender'lar için authoritative sinyal EPT
entry'sinin kendisidir —
R=0 W=0 X=1state'inde bırakılmış frame'ler, eşleşmiş shadow frame'ler ve per-page EPT-violation sayıları.
Mitigation¶
- Execute-only EPT entry'lerini ve eşleşmiş shadow frame'leri host-owned introspection state'i olarak ele al ve onlar üzerinde audit/alert yap; guest, EPT permission'larını asla okuyamamalı ya da modifiye edememeli.
- Stealth hooking'in düşmanca olduğu yerlerde, hypervisor-seviyesi integrity monitoring her guest code frame'inin executable view'ını read view'ıyla karşılaştırabilir.
- Pencereyi minimize et: MTF step'inden hemen sonra yeniden arm et (X-only'ye geri swap) ki temiz page yalnızca tek trap'lenen erişim için açığa çıksın.