Skip to content

SSDT / Shadow SSDT tampering surface and detection

nt!KeServiceDescriptorTable ve Shadow SSDT'yi bir ring0 attack surface olarak kavramsal kataloglama: syscall dispatch table'ların ne olduğu, x86'da neden klasik rootkit hedefi olduğu ve x64'te read-only + PatchGuard-protected olduğu için tampering'in artık stable bir technique değil, birincil olarak bir detection signal olması.

Mechanism

Korunan dispatch-table invariant'ı

KeServiceDescriptorTable, syscall dispatch'in kalbindeki bir descriptor yapısıdır. nt member'ı KiServiceTable'ı (SSDT) gösterir; ikinci member win32k ise GUI/window manager syscall'ları için Shadow SSDT'dir. Bir user-mode syscall geldiğinde nt!KiSystemCall64, service number'ı bu table'a index olarak kullanır ve karşılık gelen kernel routine'e control transfer eder.

x86'da bu table entry'leri doğrudan absolute pointer'lardı: bir slot'u overwrite eden ring0 kodu, o syscall'ı kendi hook'una yönlendirebilirdi. Klasik rootkit'ler tam da bunu yapıp file, registry key ve process gizlemek için NtQuerySystemInformation / NtQueryDirectoryFile gibi çağrıları intercept ederdi. Boundary burada aşılır çünkü trusted bir dispatch pointer, attacker'ın kontrol ettiği bir hedefe repoint edilir.

x64'te iki temel şey değişti ve bu yüzden altitude "technique"ten "detection signal"a kayar:

  • Relative offset encoding. Entry artık pointer değil, KiServiceTable base'ine göre bir signed 32-bit relative offset'tir. Yani hook hedefi ntoskrnl image aralığından çok uzağa konamaz — data-only bir tampering'in hareket alanı daralır.
  • PatchGuard / KPP. SSDT ve Shadow SSDT, Kernel Patch Protection'ın periyodik integrity check'lerle izlediği critical structure listesindedir. Table'a yazılan herhangi bir modification, randomized bir check tarafından yakalanınca KeBugCheckEx ile CRITICAL_STRUCTURE_CORRUPTION (0x109) BSOD'u tetiklenir.

Walkthrough

Aşağıdaki adımlar public internals writeup'larından (ired.team, Windows-Internals notları) derlenen üst-seviye, kavramsal bir reproduction'dır — silahlandırılmış kod değil, table'ı incelemek için mantıksal akış.

  1. Table'ı locate et. x64'te KeServiceDescriptorTable artık export edilmediği için, debugger tarafında bilinen sembolden okunur. Kavramsal WinDbg fragment'i:

    dps nt!KeServiceDescriptorTable L4     ; nt / win32k member'ları
    dd /c1 nt!KiServiceTable L2            ; ilk birkaç relative offset
    
  2. Bir entry'yi resolve et. Absolute routine adresi offset'ten türetilir; dokümante edilen ilişki Routine = KiServiceTableBase + (offset >>> 4) şeklindedir. Beklenen sonuç: her slot ntoskrnl image içindeki bir nt!Nt* fonksiyonuna resolve olmalı.

  3. Baseline al. Temiz bir sistemde tüm slot'ların resolve olduğu hedef aralık ve table'ın checksum'ı kaydedilir. Bu, tampering karşılaştırması için ground truth'tur.

  4. Anomaly ara (tampering hipotezi). Bir slot artık ntoskrnl (veya Shadow SSDT için win32k) aralığına değil, unbacked/pool memory'ye ya da farklı bir module'e resolve oluyorsa, bu bir pointer-replacement hook adayıdır. x64'te böyle bir yazma kalıcı olamaz: PatchGuard er ya da geç 0x109 ile crash eder.

Neden artık stable bir technique değil

x64'te SSDT slot'unu overwrite etmek race'e girmiş bir tampering'dir: bir sonraki randomized KPP scan'ine kadar "çalışır", sonra sistemi BSOD'a sürükler. Bu yüzden modern offensive research SSDT'yi doğrudan hedef almaktan çok, alt-syscall / callback yollarına kayar; SSDT tarafında kalan değer defender için yüksek-fidelity bir detection signal olmasıdır.

Detection

  • PatchGuard bugcheck telemetri. CRITICAL_STRUCTURE_CORRUPTION (0x109) crash dump'ları, korunan bir structure'ın (SSDT dahil) modify edildiğinin güçlü bir post-hoc kanıtıdır; !analyze -v çıktısı ihlal eden region'u işaret eder.
  • Table checksum / integrity monitoring. EDR veya bir integrity driver, boot-time'da alınan SSDT + Shadow SSDT checksum'ını periyodik olarak yeniden hesaplayıp karşılaştırabilir; mismatch bir tampering indicator'ıdır.
  • Slot-target sanity check. Her SSDT entry ntoskrnl, her Shadow SSDT entry win32k image aralığına resolve olmalı. Non-image / pool memory'ye ya da imzasız bir module'e resolve olan bir slot anomalidir.
  • BYOVD context. Böyle bir yazmayı gerçekleştirebilmek zaten ring0 gerektirir; bu yüzden yeni yüklenen unsigned/known-vulnerable driver load event'leri (Microsoft vulnerable driver blocklist ile) korele edilmelidir.

Mitigation

  • PatchGuard / KPP x64'te SSDT ve Shadow SSDT'yi default olarak korur; bunu disable etmeye çalışan tampering'in kendisi ek bir detection surface'idir.
  • HVCI / VBS. Hypervisor-enforced code integrity, kernel memory'nin writable+executable olmasını ve imzasız kod çalıştırmayı engelleyerek pointer hook'un hem yazılmasını hem de hedefe execute etmesini zorlaştırır (bkz. hvci-vbs-code-integrity-bypass).
  • Driver Signature Enforcement + vulnerable driver blocklist. Tampering'in ön koşulu olan ring0 erişimini kısar; BYOVD giriş yolunu daraltır.
  • KASLR table'ı locate etme maliyetini yükseltir.

References