PTR_MANGLE / pointer guard bypass¶
glibc'in
pointer_guard'ını (fs:0x30'da) geri kazanmak; böylece PTR_MANGLE korumasına rağmen mangled function pointer'lar — exit handler'lar, TLS destructor'lar,_IO_cookiecallback'leri — forge edilebilir.
Mechanism¶
Invariant
glibc bazı saklanan function pointer'ları pointer mangling ile korur.
PTR_MANGLE makrosu bir pointer'ı yazılabilir belleğe yazılmadan önce
dönüştürür, PTR_DEMANGLE ise pointer kullanılmadan (örn. call edilmeden)
hemen önce dönüşümü tersine çevirir. x86-64'te şema şudur:
PTR_MANGLE(p)=rol( p XOR guard, 0x11 )— gizlipointer_guardile XOR, ardından 17 bit sola rotate.PTR_DEMANGLE(p)=( ror(p, 0x11) ) XOR guard— 17 bit sağa rotate, ardından XOR.
Gizli guard, Thread Control Block içinde fs:0x30'da yaşar ve process
başlangıcında kernel'in sağladığı entropy'den (AT_RANDOM) initialize edilir.
Güvenlik sınırı şudur: bir mangled pointer slot'unu bozan bir attacker (örn.
__exit_funcs ya da bir TLS dtor_list içine heap overflow ile),
byte'larının hangi cleartext adrese demangle olacağını tahmin edemez,
dolayısıyla control flow'u hedefleyemez.
Attacker guard'ı öğrenirse bu sınır çöker. XOR ve rotation tam olarak
tersinir olduğundan, bir tane leak edilmiş (mangled, known-cleartext)
çift gizliyi tamamen açığa çıkarır:
guard = ror(mangled, 0x11) XOR known_plaintext_pointer
O andan itibaren attacker herhangi bir hedef adresi kendisi mangle edip ona demangle olan bir forged pointer yazabilir.
Walkthrough¶
Tek bir leak'ten high-level recovery (örn. initial/__exit_funcs içindeki
mangled bir _dl_fini girdisinin arbitrary read'i; cleartext adresi bir libc
base leak'ten hesaplanabilir):
# pseudo-recovery, conceptual
guard = ror(leaked_mangled_ptr, 0x11) ^ (libc_base + dl_fini_offset)
# now forge any pointer:
forged = rol(target_addr ^ guard, 0x11)
Yaygın bir chain bunu exit-handler-hijack-via-ptr-mangle-bypass ile eşler: bir exit_function slot'unu forged ile overwrite et, böylece exit() çağrısında glibc onu target_addr'a geri demangle eder ve çağırır.
NULL/known-cookie kısayolu
Guard sıfırlanabiliyor ya da bilinen bir değere ayarlanabiliyorsa (örn. bir
arbitrary write fs:0x30'u null'lar, ya da eski/zayıf bir initialization),
mangling saf bir rotation'a indirgenir. O zaman hiçbir leak gerekmez —
attacker hedefi basitçe önceden rotate eder:
forged = rol(target_addr, 0x11) (guard == 0 olduğunda)
Kapsam ve uyarılar
- glibc pointer'larının yalnızca bir kısmı mangle edilir (exit handler'lar,
tls_dtor_list, bazıjmp_buf/__libc_start_maincallback'leri). GOT girdileri, vtable'lar ve çoğu heap function-pointer mangle edilmez — bunlara bu adım olmadan doğrudan saldırılır. - Rotate miktarı (
0x11) vefs:0x30offset'i x86-64'e özgüdür; diğer mimariler farklıdır. Kesin offset'leri versiyona/mimariye bağlı say. - Tarihsel olarak CVE-2013-4788, guard'ı başlangıçta sabit/sıfır bir değerde bırakılmış statically linked binary'ler için PTR_MANGLE'ın etkisiz olduğunu gösterdi (glibc 2.4–2.17 static build'leri). Ayrıca
LD_POINTER_GUARDenv değişkeni tarihsel olarak set-uid program'larda bile dikkate alınıyordu — yanlış yapılandırılmış privileged binary'lerde guard env'den sabitlenebilirdi.
Detection¶
- Bir process
__run_exit_handlers/__call_tls_dtors'tan beklenmedik bir adrese çağrı yapmadan kısa süre önce TCB'ye komşu belleğin (fs:0x30) ya da libc exit-handler yapılarının anomalik okunması. - Attacker verisine inen,
rol(x,0x11)pattern'leriyle tutarlı bir değer taşıyan crash'ler/control-flow transfer'ları; EDR, hedefi yazılabilir bir mapping'de olan indirect call'ları işaretleyebilir. - Mangled slot'u bozan upstream overflow'u yakalayan stack/heap canary ve ASan instrumentation.
Mitigation¶
- ASLR/PIE'yi güçlü tut ve info leak'lerden kaçın — libc-base + known-plaintext leak olmadan guard geri kazanılamaz.
pointer_guard'ın düzgün seed edildiğinden emin ol (modern glibc; CVE-2013-4788 static-binary regression'ı düzeltildi).- Full RELRO ve hardened allocator'lar, mangled slot'lara ulaşan corruption primitive'lerini azaltır.
- Intel CET shadow stack / IBT ve CFI, bir pointer forge edilse bile nihai indirect call'ı kırar.
References¶
- InfoSect — Bypassing Pointer Guard in Linux's glibc (Wayback archived copy)
- binholic — Notes on abusing exit handlers, bypassing pointer mangling and glibc ptmalloc hooks
- CVE-2013-4788 — eglibc PTR_MANGLE weakness (hmarco.org)
- HackTricks — Libc Protections
Ayrıca bkz: exit-handler-hijack-via-ptr-mangle-bypass, address-leak, arbitrary-write-primitive.