Skip to content

VirtualAlloc heap spraying

Büyük, page-aligned VirtualAlloc MEM_COMMIT region'ları kullanarak attacker-controlled veriyi bilinen/tahmin edilebilir bir adrese yerleştirmek (precise-allocation spray, örneğin tarihî 0x0c0c0c0c pattern'i).

Mechanism

VirtualAlloc, belleği bir process heap üzerinden değil, doğrudan virtual-memory katmanında reserve ve commit eder. Büyük, bitişik, page-aligned region'lar döndürdüğü ve (Windows 8 öncesinde) onları tahmin edilebilir adreslere yerleştirdiği için precise heap spraying'in beygiri oldu: "flooding a process's heap with large, predictable patterns of data."

Note

Bir defender'ın kavraması gereken özellik: sıradan malloc/HeapAlloc yerleşimi allocator internals tarafından yönetilir ve nişan almak zordur, ama VirtualAlloc virtual-memory seviyesinde ince taneli kontrol ve büyük bitişik block'lar aracılığıyla tahmin edilebilir yerleşim verir. Yeterince bu tür region spray'le, ve seçilen bir adres — klasik olarak 32-bit'te tekrar eden 0x0c0c0c0c değeri — ezici olasılıkla attacker-controlled byte'ların içine düşer. Tekrarlanan word çifte görev görür: hem geçerli bir pointer'dır hem de bir instruction-stream NOP-equivalent'idir, böylece "spray'in herhangi bir yerine" düşen corrupted bir control-flow hedefi payload'a kayar. VirtualAlloc ayrıca executable bellek de (PAGE_EXECUTE_READWRITE) isteyebilir; bu tarihsel olarak spray'lenmiş byte'ların doğrudan çalıştırılmasına imkân vererek heap'in non-executable varsayılanlarını atlatıyordu.

Bu, vad-spraying'in user-mode address-prediction kardeşidir: spray'in güvenilirliği, herhangi bir allocator'ın free list'lerini groom'lamaktan değil, commit edilmiş aynı region'ların salt hacminin bir adresi istatistiksel olarak kesinlikle attacker-owned hale getirmesinden gelir.

Walkthrough

Üst düzey ve kavramsal, public heap-spray yazılarından:

  1. Payload birimini inşa et. Bir NOP sled (örneğin 0x90 byte'ları ya da NOP-equivalent gibi davranan 0x0c0c0c0c word'leri) ve ardından payload'dan oluşan bir region oluştur.
  2. Çok sayıda büyük region commit et. Tekrar tekrar büyük MEM_COMMIT block'ları VirtualAlloc'la ve her birini payload birimiyle doldur:

    for i in 0..N:
        p = VirtualAlloc(NULL, BIG, MEM_COMMIT|MEM_RESERVE, prot)
        fill(p, nop_sled + payload)
    
  3. Hedef adresi geçerli kıl. Tahmin edilen bir adres (tarihsel olarak 0x0c0c0c0c) region'lardan birinin içine düşene kadar yeterince spray'le.

  4. Bug'ı tetikle. Bir memory-corruption primitive'i, control flow'u ya da dereference edilen bir pointer'ı, artık attacker byte'larına çözülen tahmin edilen adrese yönlendirir.
Neden 0x0c0c0c0c

x86'da 0x0c byte'ı zararsız OR AL, imm8 olarak decode olur, böylece bir dizi 0x0c0c0c0c bir NOP sled gibi davranırken aynı anda 0x0c0c0c0c dword değeri kullanılabilir bir jump/read adresidir — klasik spray'in hem "nereyi gösteriyorum" hem de "oraya vardığımda ne çalışır" gereksinimlerini birlikte karşılayan tek bir sabit.

Detection

  • API telemetry: olağandışı sayıda büyük VirtualAlloc/NtAllocateVirtualMemory commit'i yapan bir process, özellikle PAGE_EXECUTE_READWRITE ile, güçlü bir spray göstergesidir; ETW ya da EDR üzerinden topla.
  • Content heuristics: tek bir tekrar eden pattern'i (NOP sled + payload) paylaşan çok sayıda committed region, committed private belleği tarayarak tespit edilebilir.
  • Crash context: committed private bellekte yuvarlak, tekrar eden bir adreste (örneğin 0x0c0c0c0c) bir control-flow transferi ya da fault, oturmuş bir spray'in işaretidir.

Mitigation

  • DEP/NX data page'lerden çalıştırmayı durdurur; attacker ayrıca executable bellek de elde etmedikçe execute-from-spray modelini bozar.
  • Bottom-up/top-down ASLR (Windows 8+) VirtualAlloc/MapViewOfFile base'lerini randomize eder; 64-bit'te high-entropy ASLR bottom-up için "1 TB of variance … 24 bits of entropy" verir, böylece "systems today do not have enough memory available to spray the amount that would be needed."
  • CFG/XFG indirect call hedeflerini doğrular, böylece spray'de bir isabet bile geçersiz bir call hedefi olarak reddedilir.
  • Uygulama seviyesinde nullpage/bilinen-adres reservation'ı ve RWX allocation'ları devre dışı bırakma (W^X policy), tekniğin dayandığı tahmin edilebilir, executable iniş bölgelerini ortadan kaldırır.

References