Skip to content

Red Pill (SIDT/SGDT descriptor-table detection)

Joanna Rutkowska'nın 2004 Red Pill'i: unprivileged SIDT instruction'ı 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

  1. 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.

  1. 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-exiting ve stealth-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.

References