VMware Workstation PVSCSI LFH Escape (VMware-vmx on Windows 11)
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Hata anatomisi: fixed-size realloc + scattered OOB writes
PVSCSI_FillSGIguest scatter/gather girdilerini dahili bir diziye kopyalar. 512-entry statik bir buffer ile (0x2000) başlar. 512 girişin üstünde 0x4000 byte’a realloc eder ve fonksiyonel bir hata nedeniyle her iterasyonda yeniden realloc eder.- Reallocation boyutu hiç büyümez: 0x4000 / 0x10-byte entry = 1024 kullanılabilir entry. Guest >1024 entry sağladığında, her yeni entry taze allocate edilmiş 0x4000 chunk’ının 16 byte sonrasına yazılır ve bitişik chunk header veya objeyi bozar.
- Overflow içeriği: VMware
{u64 addr; u64 len}saklar; guest{u64 addr; u32 len; u32 flags}sağlar. 32-bitlenzero-extended olduğu için her 16-byte OOB elementinin son dword’u her zaman 0x00000000 olur.
LFH constraints & deterministic “Ping-Pong” placement
- 0x4000 allocasyonları Windows 11 LFH içine düşer (16 chunks/bucket, 0x10-byte metadata ile keyed checksum). Header checksum’u bozulan herhangi bir chunk daha sonra kullanılırsa process sonlanır; bu yüzden bozulmuş header’lar asla yeniden kullanılmamalıdır.
- LFH rastgele bir free chunk döndürür, ama en son free edilmiş chunk’ı içeren bucket’ı tercih eder. Sadece iki boş slot zorlayın:
- Allocator’ı hizalamak için tüm boş 0x4000 chunk’ları ayırın; B1 ve B2 bucket’larını doldurmak için 32 SVGA shader spreyleyin.
- B1’i, bir tane sabitlenmiş shader (Hole0) dışında free edin ki B1 aktif kalsın; B1’e 15 URB allocate edin.
- B2’de bir shader’ı free edin (PONG), sonra hemen Hole0’ı free edin. LFH iki mevcut slot arasında tahsisleri PING (B1) ve PONG (B2) olarak dönüşümlü yapacaktır.
-
- iterasyon PONG’un hemen sonrasındaki header’ı bozar (bir daha dokunulmaz); 1026. iterasyon PING’den sonraki ilk 16 byte’ı URB içinde hedefler (metadata bypass için güvenli). Yerleşimi stabil ve tekrarlanabilir tutmak için PING/PONG’u placeholder shader’larla geri alın.
Reap Oracle: labeling contiguous holes
- UHCI URB’leri FIFO kuyruğunda yaşar ve tamamen reaped edildiğinde free edilir. Kısıtlı 16-byte overwrite her zaman
actual_len’i sıfırlar, bu da bir işaretleyici verir. - URB’leri sırayla reap edin; sıfırlanmış bir
actual_lengörüldüğünde hemen freed slot’u tanınabilir bir shader ile doldurun. İterasyonlar sayesinde daha sonra adjacency’e dayalı primitifler için Hole0–Hole3’ü bilinen sırada dört bitişik chunk olarak eşleyebilirsiniz.
Turning constrained writes into arbitrary overwrite (coalescing abuse)
PVSCSI bitişik entry’leri AddrA + LenA == AddrB kontrolü ile coalesce eder ve sonraki entry’leri yukarı doğru compact eder.
- İki geçişli overflow: PING’den (tek indeksler) başlayarak tetikleyin ve coalescing’i atlamak için erken çıkın; PONG’dan (çift indeksler) başlayarak tekrar tetikleyin ki boşluklar doldurulsun ve fake S/G entry’leri içeren spreylənmiş bir shader’a yazma devam etsin.
- Vacuum + payload:
[1023..2047]entry’lerini{addr=0,len=0}olarak ayarlayın, böylece coalescing bunları tek bir entry içinde çökerterek mantıksal bir delik oluşturur. Daha sonra (shader içindeki) payload entry’leri yukarı doğru taşınır, kurban URB içine yerleşir. - Adjacency-check bypass:
LenA=0koyarak koşulAddrA==AddrBolur. Çiftleri şöyle hazırlayın:
{addr = X, len = 0}
{addr = X, len = Y}
böylece coalescing bunları {addr=X,len=Y} olarak birleştirir. Çift indeksli sıfır-boyutlu elemanlar kısıtlı overflow’dan gelir; tek indeksliler shader’da yaşar. Sonuç: zorunlu sıfır dword’a rağmen arbitrary 16-byte pattern’ler elde edilir.
Hybrid URB infoleak via coalescing side-effects
- Bitişik chunk’ları şöyle düzenleyin:
[Hole0 (free/PING), URB1 (target), URB2 (valid, actual_len=0), URB3 (leak target)]. - URB1’i bitişik fake entry’lerle doldurun (boyutlar
0xFFFFFFFF), URB2’ye minimal dokunun. Coalescing bunları tek entry’e birleştirir;0xFFFFFFFF * 0x401toplamı URB1’inactual_lenoffset’indeki üst dword’u 0x400 yapar. - Compact işlemi aşağıdaki veriyi yukarı doğru kopyalarak URB2’nin header’ını URB1 içine çeker. URB1 şimdi geçerli bir header’a (pipe/list pointer’ları),
actual_len=0x400’e ve URB2 buffer’ının sonuna işaret eden bir data pointer’a sahip olur. - URB1’i reap etmek URB3’ten hemen önce başlayan 0x400 byte kopyalanmasına yol açar ve URB3’ün header/self-referanslarının OOB okunmasını sağlar; bu da mutlak heap adreslerini açığa çıkarır ve sonraki sahte yapıların ASLR’ını bozar.
Post-leak primitives (no re-triggering the bug)
- Hole0 içinde yer alan bir shader’a sahte bir URB yapısı forge edin, sonra coalescing “move up” ile URB1’i bu forge edilmiş veriyle değiştirin.
- URB’yi persistent yapın:
URB1.next = Hole0koyun ve refcount’u artırın; URB1’i reap etmek Hole0 destekli sahte URB’yi FIFO başına getirir. Gelecek primitifler sadece Hole0’ın yeni sahte URB’lerle yeniden allocate edilmesidir. - Arbitrary read: seçilen
data_ptrveactual_lenile sahte URB; sonra reap ile host belleğini guest’e kopyalayın. - Arbitrary write (32-bit):
pipe’ı kontrollü belleğe işaret eden sahte URB ve UHCI TDBuffer writeback’i suistimal ederek seçilmiş bir dword’u rastgele bir adrese yazdırın. - Arbitrary call: bir USB pipe callback’i overwrite edin; host bunu
RCX+0x90’da kontrollü veri ile çağırır.WinExec’i dinamik olarak çözün (guest tarafında Kernel32 okuması) ve argümanlarıRCX+0x100’den yükleyen ve ardındanWinExec("calc.exe")’ye yönlendiren vmware-vmx içindeki CFG-valid gadget üzerinden pivot yapın.
LFH timing side-channel to learn the initial bucket offset
- Deterministik Ping-Pong için LFH free-chunk offset’ini (16 slottan hangisinin önce vurulacağı) bilmek gerekir. Senkron VMware Tools komutu
vmx.capability.unified_loopile VMware backdoor instruction (inl %%dx, %%eax) kullanın ve 0x4000-byte string gönderin; bu çağrı başına iki 0x4000 allocasyon zorlar. gettimeofdayile 8 çağrıyı (16 allocasyon) zamanlayın; LFH yeni bir bucket oluşturduğunda tek bir çağrı tutarlı bir spike gösterir. Bir ekstra allocation ile tekrar edin: spike aynı indekste kalıyorsa offset tek (odd), kayıyorsa çift (even); aksi takdirde gürültü nedeniyle yeniden başlayın.- Uyarı:
unified_loopbenzersiz string’leri free edilemeyen bir listede saklar, bu da O(n) lookup overhead ve artan gürültüye sebep olur; bu yüzden side-channel hızlıca yakınsamalıdır.
References
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.


