Skip to content

Data-only kernel exploit technique ported to 24H2

Windows 11 24H2 PreviousMode read/write primitive'ini kaldırdıktan sonra, bir data-only escalation, SeDebugPrivilege'i flip etmek için SepDuplicateToken()'daki _TOKEN reference-counter increment'ini yeniden kullanır.

Mechanism

Bir data-only attack, bir kernel read/write primitive'ini control flow'u hijack etmeden privilege escalation'a çevirir ve CFG/HVCI/kCET'i yener. Uzun süredir kullanılan Windows data-only primitive'i _KTHREAD.PreviousMode'du: onu UserMode (0)'a set etmek, Nt* memory API'lerinin (NtReadVirtualMemory / NtWriteVirtualMemory) kernel address'leri user mode'dan istenmiş gibi ele almasını sağlar ve tam arbitrary read/write verir. Windows 11 24H2 PreviousMode tekniğini öldürdü ve eski yöntemin side-effect'leri de cleanup için aynı API'lere bağlıydı, ki bu imkânsız hale geldi.

Note

24H2 yerine geçen şey, token duplication'dan kurulmuş saf bir arbitrary-increment primitive'i. _TOKEN.BnoIsolationHandlesEntry, bir _SEP_CACHED_HANDLES_ENTRY'ye işaret eder:

struct _SEP_CACHED_HANDLES_ENTRY {
    struct _RTL_DYNAMIC_HASH_TABLE_ENTRY HashEntry;                  // 0x00
    LONGLONG                              ReferenceCount;            // 0x18
    struct _SEP_CACHED_HANDLES_ENTRY_DESCRIPTOR EntryDescriptor;    // 0x20
    ULONG                                 HandleCount;               // 0x38
    VOID**                                Handles;                   // 0x40
};

SepDuplicateToken() çalıştığında ve entry'nin ReferenceCount'u (offset 0x18) sıfır olmadığında, başka hiçbir side effect olmadan basitçe o 64-bit field'ı increment eder. Kernel write kontrolüne sahip bir attacker BnoIsolationHandlesEntry'yi target - 0x18'e işaret ettirirse, her token duplication target'taki 8 byte'ı increment eder. Bu, herhangi bir kernel address üzerinde nişanlanmış bir ++'tır.

Warning

Primitive yalnızca increment edilen değer 0x1 - 0x7fffffffffffffff aralığında kaldığı sürece güvenli. Duplication sırasında sıfır veya aralık-dışı bir değer bir bugcheck'e (BSOD) yol açar, yani hedef byte zaten sıfır olmamalı ve increment sayısı sınırlı olmalı.

Walkthrough

Amaç, mevcut process token'ının privilege bitmap'lerinde SeDebugPrivilege'i enable etmek. _TOKEN.Privileges (_SEP_TOKEN_PRIVILEGES) üç 8-byte bitmap tutar: Present, Enabled ve EnabledByDefault; bu escalation yalnızca Present ve Enabled'ı hedefler. SeDebugPrivilege bit 0x14'tür (bit 20).

Primitive yalnızca increment ettiği için, bitmap'in tek bir byte'ını hedefler ve o byte içinde istenen biti set etmek için gereken miktarda increment edersin:

// pseudocode for one bitmap (Present, then Enabled)
//   priv = SeDebugPrivilege bit index = 0x14
//   byte_off = priv >> 3        // which byte of the 8-byte bitmap
//   amount   = 1 << (priv & 7)  // increment to set the bit in that byte

// 1. Aim BnoIsolationHandlesEntry so the counter sits on the chosen byte:
//    BnoIsolationHandlesEntry = process_token + Privileges.Present
//                               + byte_off - 0x18;
write_kernel_ptr(token + offsetof_BnoIsolationHandlesEntry, target - 0x18);

// 2. Duplicate the token 'amount' times; each call increments the byte.
for (i = 0; i < amount; i++)
    DuplicateTokenEx(hToken, ..., &hDup[i]);

// 3. Repeat for Privileges.Enabled so the privilege is both present
//    and enabled.

SeDebugPrivilege, mevcut _EPROCESS'in token'ında present ve enabled olunca, process tam escalation için bir SYSTEM process'i açabilir ve içine inject edebilir.

Cleanup ve self-correction

Çoğaltılmış token handle'larını kapatmak, SepDuplicateToken'ın karşılığının reference counter'ı decrement etmesini sürer, böylece işin bitince hDup[] handle'larını kapatmak bitmap byte'ını geri aşağı yürütür, inject edilmiş privilege'ı otomatik olarak düşürür ve yırtık (torn) bir token state'inden kaçınır.

Detection

  • Kendi _TOKEN'ına önceki bir kernel write ile ilişkili bir DuplicateTokenEx çağrısı patlaması yapan bir user-mode process anormaldir; EDR, Privileges.Present/Enabled'ı meşru bir atama olmadan SeDebugPrivilege kazanan token'ları işaretleyebilir.
  • HVCI / Kernel CFG data-only flip'leri durdurmaz; ilk kernel write primitive'ini reddetmek için attack-surface reduction'a (driver blocklist) güven.

Mitigation

  • Alttaki kernel read/write primitive'ini (exploit edilen zafiyetli driver'ı) ele; teknik, birinin zaten var olduğunu varsayar.
  • Microsoft'un 24H2 PreviousMode hardening'i, bu port'u zorlayan mitigation'ın ta kendisidir; token reference-count path'lerinin sürekli hardening'i ve BnoIsolationHandlesEntry'nin doğrulanması bu varyantı kapatırdı.
  • Primitive'i en baştan elde etmenin maliyetini artırmak için HVCI'yi, vulnerable-driver blocklist'i ve Credential Guard'ı enable et.

References