Red Pill (SIDT/SGDT descriptor-table detection)¶
Joanna Rutkowska'nın 2004 Red Pill'i: unprivileged
SIDTinstruction'ı IDTR base'ini guest memory'ye yazar; bir VMM altında guest'in IDTR'ı relocate edilir, dolayısıyla anormal derecede yüksek bir base address virtualization'ı ele verir.
Mechanism¶
Note
SIDT (Store Interrupt Descriptor Table Register), IDTR'ı (2-byte limit +
linear base) bir memory operand'a yazar; operand boyutu mode'a bağlıdır —
32-bit mode'da 6 byte (2-byte limit + 4-byte base), 64-bit mode'da 10 byte
(2-byte limit + 8-byte base). Aşağıdaki klasik örnek 32-bit layout'u (6 byte,
m[2+4]) varsayar. SGDT ve SLDT
gibi privileged değildir — ring 3'te çalışır ve hiçbir exception
doğurmaz, dolayısıyla klasik (non-VT-x) virtualization'da VMM onu intercept
edemez. CPU başına yalnızca bir fiziksel IDTR vardır ama bir host ve bir ya da
daha fazla guest eşzamanlı çalışır; VMM, her guest'in IDT'sini çakışmayan bir
linear address'e relocate etmelidir ki guest host'unkiyle çarpışmasın. Guest,
relocate edilmiş base'i doğrudan SIDT ile okuyabildiği için, VMM
relocation'ının kullandığı alışılmadık yüksek aralıkta (tipik OS aralığı
yerine) oturan bir IDTR base'i güvenilir bir "ben virtualize'ım" sinyalidir.
Teknik, isolation boundary'sini gözlemler: VMM'in gizleyemeyeceği bir
register, descriptor table'ın taşındığı gerçeğini sızdırır.
Walkthrough¶
- Rutkowska'nın orijinal Red Pill'i SIDT'yi inline encode eder ve saklanan base'in high byte'ını inceler:
int swallow_redpill () {
unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
*((unsigned*)&rpill[3]) = (unsigned)m; /* patch SIDT operand -> m */
((void(*)())&rpill)(); /* SIDT m ; RET */
return (m[5] > 0xd0) ? 1 : 0; /* high byte of IDT base */
}
Opcode byte'ları 0F 01 0D <addr>, SIDT [addr]'dir; m[2..5], 32-bit IDT
base'ini tutar. Gözlemlenen relocation'lar: VMware Workstation IDT'yi
0xffXXXXXX yakınına, Virtual PC 0xe8XXXXXX yakınına relocate etti — her
ikisi de bare-metal bir Windows IDT'sinin ulaşmadığı 0xd0 high-byte
threshold'unun üstünde.
- Assembly'deki eşdeğer idiom:
sidt [m] ; store IDTR (limit+base) to m
mov al, [m+5] ; high byte of 32-bit IDT base
cmp al, 0d0h
ja under_vmm
Warning
Sabit 0xd0 threshold'u, spesifik ürünlere ve 32-bit address layout'larına
bağlı 2004 bir heuristic'tir; 64-bit host'lara, SMP'ye (her CPU'nun kendi
IDTR'ı vardır, dolayısıyla sonuçlar core'a göre değişir) ya da IDT'yi artık
ayırt edici bir aralığa relocate etmeyen modern hypervisor'lara taşınabilir
değildir. Red Pill'i robust bir modern detector değil, klasik bir illustration
olarak ele al.
Detection¶
Bir defender / sandbox guest'in probe yaptığını nasıl fark eder:
- Descriptor-table exiting: VT-x/AMD-V,
SIDT/SGDT/SLDT/STR'yi trap'leyebilir (descriptor-table exiting). Bunları ring 3'te çalıştıran, özellikle ardından high address byte üzerinde bir compare gelen bir guest, VMM'in loglayabileceği güçlü bir Red-Pill probe imzasıdır. Bkz.descriptor-table-exiting. - Sandbox-aware sample'ları flag'lemek için diğer anti-VM heuristic'leriyle (timing, CPUID leaf'leri) eşleştir.
Mitigation¶
Bir hypervisor detection'ı nasıl yener:
- Descriptor-table exiting + spoofing: "descriptor-table exiting" VM-exit
control'ünü etkinleştir ve SIDT/SGDT'de relocate edilmiş olan yerine makul bir
bare-metal aralığında bir IDTR base döndür. Bkz.
descriptor-table-exitingvestealth-vt-x-hypervisor-anti-detection. - Hardware virtualization layout: modern VT-x/AMD-V, guest descriptor state'ini VMCS/VMCB'de tutar ki guest kendi IDTR base'ini görsün — sızdıracak çakışan bir relocation yoktur, klasik Red Pill'i hiçbir trap olmadan etkisizleştirir.
Warning
Her SIDT/SGDT'yi trap'lemenin bir performance maliyeti vardır ve trap'in kendisi timing artifact'leri getirebilir; stealth, SIDT, SGDT, CPUID ve timing genelinde tutarlılık gerektirir ki spoof'lanan değerler uyuşsun.