Skip to content

ret2dir (Return-to-direct-mapped memory)

SMEP/SMAP/PXN tarzı "no kernel→user" savunmalarını, attacker-controlled user page'lere physmap (direct map) içindeki kernel alias'ları üzerinden erişerek aş.

Mechanism

Neden çalışır

Fiziksel RAM'in büyük kısmını kolayca erişilebilir kılmak için Linux kernel bir direct map (diğer adıyla physmap) tutar — tüm fiziksel belleği lineer şekilde map'leyen, geniş ve contiguous bir kernel virtual bölgesi (x86-64'te page_offset_base). Bu da şu demek: her user page'in ikinci bir kernel tarafı virtual alias'ı vardır; aynı physical frame hem userland'den hem de physmap'ten adreslenebilir.

Klasik ret2usr exploit'leri bir kernel pointer'ı bir user adresine işaret edecek şekilde hijack eder; SMEP (kernel'in user page'leri exec etmesini engeller), SMAP (kernel'in user page'lere data erişimini engeller), ARM PXN ve PaX KERNEXEC/UDEREF gibi savunmaların hepsi user adresine göre çalışır. ret2dir bunları atlatır: user alias'a sıçramak yerine, tam da aynı page'in physmap alias'ına sıçra. O alias bir kernel adresidir, dolayısıyla CPU'nun bakış açısından user/kernel sınırını geçen bir şey yoktur — savunmalar bir kernel→kernel erişimi görür ve sessiz kalır. İstismar edilen invariant: user-controlled içerik aynı zamanda bir kernel adresinde de mevcuttur.

Geriye kalan problem, kontrol ettiğin bir page'in physmap alias'ını bulmak (physmap spraying) ve onu payload'unu tutar hale getirmektir.

Walkthrough

Sadece yetkili test

Sahip olduğun bir VM/kernel üzerinde çalıştır. Layout (page_offset_base, KASLR) version ve config'e göre değişir; aşağıdaki offset'ler örnek amaçlıdır.

1. Physmap'e kontrol edilebilir içerik spray et. Bol miktarda user belleği allocate et ve onu payload (ROP chain / sahte yapılar) ile doldur, böylece birçok physical frame — ve dolayısıyla birçok physmap adresi — onu içersin.

#define SPRAY_MB 512
for (int i = 0; i < SPRAY_MB; i++) {
    char *p = mmap(NULL, 1<<20, PROT_READ|PROT_WRITE,
                   MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, -1, 0);
    fill_with_payload(p, 1<<20);   // ROP chain, fake cred struct, etc.
}

2. Bir physmap alias'ı bul. x86-64'te physmap, page_offset_base'teki linear map'tir; pa physical adresinin alias'ı page_offset_base + pa'dır. İki pratik yol:

# (a) Leak the physical frame of a sprayed page, then compute the alias:
#     /proc/self/pagemap (if readable) gives PFN -> pa = pfn << 12
#     alias = page_offset_base + pa
# (b) "physmap spraying": spray enough that a *known* physmap address is
#     overwhelmingly likely to contain your payload, no per-page leak needed.

3. Hijack edilen kernel pointer'ını alias'a yönlendir. Bug'ı (örneğin bozulmuş bir function pointer ya da bir write primitive) user adresi yerine physmap adresini kullanacak şekilde sür:

// Instead of: hijack_ptr = (void*)user_payload;   // blocked by SMEP/SMAP
hijack_ptr = (void*)(page_offset_base + payload_pa); // kernel-side alias: allowed
trigger_bug();   // kernel "returns into" / dereferences the physmap copy

page_offset_base + payload_pa senin byte'larını tutan bir kernel adresi olduğu için, kernel attacker verisini execute/deref ederken SMEP/SMAP yalnızca kernel-resident belleği gözlemler ve fault üretmez.

Beklenen etki: ret2usr hardening'ine rağmen attacker-controlled içeriğe control transfer (ya da data deref) — tipik olarak cred'leri root'a flip'leyen bir ROP chain'e pivot yapmak için kullanılır.

Detection

  • Yakın zamandaki büyük user allocation'larını yansıtan page'lerde, direct map içine düşen olağandışı kernel control flow / data deref.
  • Yoğun MAP_POPULATE spraying'i artı /proc/*/pagemap okumaları davranışsal bir ipucudur.

Mitigation

  • XPFO (eXclusive Page Frame Ownership): bir frame userspace'e ait olduğu sürece onu physmap'ten unmap et, böylece kernel alias mevcut değildir — ret2dir'in dayandığı ikinci adresi ortadan kaldırır (bir TLB-flush maliyetiyle).
  • /proc/self/pagemap PFN açığa çıkışını privileged user'larla sınırla (upstream'de yapıldı).
  • Direct map'i non-executable işaretle (code-exec varyantına karşı yardımcı olur).

References