VMware Workstation PVSCSI LFH Escape (VMware-vmx on Windows 11)
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Анатомія вразливості: fixed-size realloc + scattered OOB writes
PVSCSI_FillSGIкопіює guest scatter/gather записи в внутрішній масив. Він починається зі статичного буфера на 512 елементів (0x2000). Понад 512 записів відбувається realloc до 0x4000 байт і, через функціональний баг, realloc викликається на кожній ітерації.- Розмір реаллокації ніколи не зростає: 0x4000 / 0x10-байтні записи = 1024 корисні записи. Коли гість надає >1024 записів, кожен новий запис записується на 16 байт за межами щойно алокованого блоку 0x4000, пошкоджуючи заголовок або об’єкт у суміжному чанку.
- Overflow content: VMware stores
{u64 addr; u64 len}; guest provides{u64 addr; u32 len; u32 flags}. The 32-bitlenis zero-extended, so the last dword of every 16-byte OOB element is always 0x00000000.
LFH constraints & deterministic “Ping-Pong” placement
- 0x4000 allocations land in the Windows 11 LFH (16 chunks/bucket, 0x10-byte metadata with keyed checksum). Any chunk whose header checksum is hit later will terminate the process, so corrupted headers must never be reused.
- LFH повертає випадковий вільний чанк, але надає перевагу бакету, що містить найбільш нещодавно звільнений чанк. Змусити доступні лише два слоти:
- Виділіть усі вільні 0x4000 чанки, щоб вирівняти алокатор; spray 32 SVGA shaders щоб заповнити B1 і B2 баки.
- Звільніть B1, залишивши один зафіксований shader (Hole0), щоб B1 залишався активним; алокуйте 15 URBs в B1.
- Звільніть один shader в B2 (PONG), потім негайно звільніть Hole0. LFH чергуватиме алокації між двома доступними слотами PING (B1) і PONG (B2).
- Ітерація 1025 пошкоджує заголовок після PONG (більше не торкається); ітерація 1026 потрапляє в перші 16 байт URB після PING (безпечне обхід метаданих). Відновлюйте PING/PONG плейсхолдер-шейдерами, щоб зберегти стабільний і відтворюваний лей-аут.
Reap Oracle: labeling contiguous holes
- UHCI URBs живуть у FIFO-черзі і звільняються, коли повністю reaped. Обмежений 16-байтний overwrite завжди обнуляє
actual_len, що дає маркер. - Reap URBs в порядку; коли бачите обнулений
actual_len, негайно перезаповніть звільнений слот впізнаваним shader-ом. Ітерація дозволяє вам відмітити Hole0–Hole3 як чотири суміжні чанки в відомому порядку для подальших примітивів, що залежать від сусідства.
Turning constrained writes into arbitrary overwrite (coalescing abuse)
PVSCSI коалесцує суміжні записи за умовою AddrA + LenA == AddrB і компактує пізніші записи вгору.
- Two-pass overflow: Запустіть корупцію починаючи з PING (непарні індекси) і припиніть рано, щоб пропустити coalescing; запустіть знову починаючи з PONG (парні індекси), щоб заповнити прогалини і продовжити запис у запшрейджений shader, що містить фейкові S/G записи.
- Vacuum + payload: Встановіть записи
[1023..2047]в{addr=0,len=0}, щоб coalescing згорнув їх в один, створивши логічний пролом. Пейлоад-елементи, розташовані після цього (в shader), переміщуються вгору, потрапляючи всередину victim URB. - Adjacency-check bypass: Задавши
LenA=0, умова спрощується доAddrA==AddrB. Сформуйте пари
{addr = X, len = 0}
{addr = X, len = Y}
щоб coalescing з’єднав їх в {addr=X,len=Y}. Непарні нуль-розмірні елементи походять з обмеженого overflow; парні значення живуть в shader. Результат: довільні 16-байтні патерни незважаючи на примусове нульове dword.
Hybrid URB infoleak via coalescing side-effects
- Розташуйте суміжні чанки:
[Hole0 (free/PING), URB1 (target), URB2 (valid, actual_len=0), URB3 (leak target)]. - Заповніть URB1 континуальними фейковими записами (розміри
0xFFFFFFFF), мінімально зачіпаючи URB2. Coalescing зливає їх в один запис; сума0xFFFFFFFF * 0x401встановлює верхній dword на зсувіactual_lenURB1 в 0x400. - Компакція копіює наступні дані вгору, підтягаючи заголовок URB2 в URB1. URB1 тепер має валідний заголовок (pipe/list вказівники),
actual_len=0x400і вказівник даних, що вже знаходиться в кінці буфера URB2. - Reaping URB1 копіює 0x400 байт починаючи трохи перед URB3, даючи OOB read заголовка/self-references URB3, що розкриває абсолютні адреси heap і долає ASLR для подальшого форжування структур.
Post-leak primitives (no re-triggering the bug)
- Forge a URB structure inside a shader occupying Hole0, then use the coalescing “move up” to replace URB1 with the forged data.
- Зробіть URB персистентним: встановіть
URB1.next = Hole0і інкрементуйтеrefcount; reaping URB1 поміщає Hole0-backed fake URB на голову FIFO. Майбутні примітиви — просто повторні алокації Hole0 з новими fake URBs. - Arbitrary read: fake URB з обраним
data_ptrіactual_len, потім reap для копіювання host-пам’яті в guest. - Arbitrary write (32-bit): fake URB чиї
pipeвказує на контрольовану пам’ять і зловживання UHCI TDBuffer writeback для запису обраного dword за довільною адресою. - Arbitrary call: перезапишіть callback USB pipe; хост викличе його з контрольованими даними в
RCX+0x90. Динамічно знайдітьWinExec(читання Kernel32 з guest) і сплигніть через CFG-valid gadget inside vmware-vmx, який завантажує аргументи зRCX+0x100перед викликомWinExec("calc.exe").
LFH timing side-channel to learn the initial bucket offset
- Deterministic Ping-Pong requires knowing the LFH free-chunk offset (which of 16 slots will be hit first). Use the VMware backdoor instruction (
inl %%dx, %%eax) with the synchronous VMware Tools commandvmx.capability.unified_loopand a 0x4000-byte string, which forces two 0x4000 allocations per call. - Time 8 calls (16 allocations) via
gettimeofday; one call shows a consistent spike when the LFH creates a new bucket. Repeat with one extra allocation: if the spike stays at the same index the offset is odd, if it shifts it is even; otherwise restart due to noise. - Caveat:
unified_loopstores unique strings in an unfreeable list, causing O(n) lookup overhead and rising noise, so the side-channel must converge quickly.
References
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.


