mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/libc-heap/use-after-free/first-fit.
This commit is contained in:
parent
a8fd931d06
commit
dab88aff83
@ -8,14 +8,14 @@ Bir programda glibc kullanarak bellek serbest bıraktığınızda, bellek parça
|
||||
|
||||
### Sıralanmamış Kutular
|
||||
|
||||
Hızlı bir parça olmayan bir bellek parçasını serbest bıraktığınızda, bu sıralanmamış kutuya gider. Bu kutu, yeni serbest bırakılan parçaların ön tarafa (baş) eklendiği bir liste gibi davranır. Yeni bir bellek parçası talep ettiğinizde, allocator sıralanmamış kutuya arka taraftan (kuyruk) bakarak yeterince büyük bir parça bulur. Sıralanmamış kutudan bir parça, ihtiyaç duyduğunuzdan büyükse, bu parça bölünür; ön kısmı geri döner ve kalan kısım kutuda kalır.
|
||||
Hızlı bir parça olmayan bir bellek parçasını serbest bıraktığınızda, bu sıralanmamış kutuya gider. Bu kutu, yeni serbest bırakılan parçaların ön tarafa (baş) eklendiği bir liste gibi davranır. Yeni bir bellek parçası talep ettiğinizde, allocator sıralanmamış kutuya arka taraftan (kuyruk) bakarak yeterince büyük bir parça bulur. Eğer sıralanmamış kutudan bir parça, ihtiyacınız olandan büyükse, bu parça bölünür; ön kısım geri döner ve kalan kısım kutuda kalır.
|
||||
|
||||
Örnek:
|
||||
|
||||
- 300 bayt (`a`) ayırırsınız, ardından 250 bayt (`b`), `a`yı serbest bırakır ve tekrar 250 bayt (`c`) talep edersiniz.
|
||||
- 300 bayt (`a`) ayırırsınız, sonra 250 bayt (`b`), ardından `a`yı serbest bırakır ve tekrar 250 bayt (`c`) talep edersiniz.
|
||||
- `a`yı serbest bıraktığınızda, bu sıralanmamış kutuya gider.
|
||||
- Eğer tekrar 250 bayt talep ederseniz, allocator `a`yı kuyrukta bulur ve onu böler, talebinize uyan kısmı geri döner ve geri kalanını kutuda tutar.
|
||||
- `c`, önceki `a`ya işaret edecek ve `a'nın` içeriği ile doldurulacaktır.
|
||||
- `c`, önceki `a`ya işaret edecek ve `a`nın içeriği ile doldurulacaktır.
|
||||
```c
|
||||
char *a = malloc(300);
|
||||
char *b = malloc(250);
|
||||
@ -24,13 +24,9 @@ char *c = malloc(250);
|
||||
```
|
||||
### Fastbins
|
||||
|
||||
Fastbins, küçük bellek parçaları için kullanılır. Sıralanmamış kutuların aksine, fastbins yeni parçaları başa ekler ve son giren ilk çıkar (LIFO) davranışı oluşturur. Küçük bir bellek parçası talep ettiğinizde, allocator fastbin'in başından alır.
|
||||
Fastbins, küçük bellek parçaları için kullanılır. Sıralanmamış kutuların aksine, fastbins yeni parçaları başa ekler ve son giren ilk çıkar (LIFO) davranışı oluşturur. Küçük bir bellek parçası talep ederseniz, allocator fastbin'in başından alır.
|
||||
|
||||
Örnek:
|
||||
|
||||
- Dört adet 20 baytlık parça ayırırsınız (`a`, `b`, `c`, `d`).
|
||||
- Bunları herhangi bir sırayla serbest bıraktığınızda, serbest bırakılan parçalar fastbin'in başına eklenir.
|
||||
- Daha sonra 20 baytlık bir parça talep ederseniz, allocator fastbin'in başından en son serbest bırakılan parçayı döndürecektir.
|
||||
```c
|
||||
char *a = malloc(20);
|
||||
char *b = malloc(20);
|
||||
@ -45,18 +41,89 @@ b = malloc(20); // c
|
||||
c = malloc(20); // b
|
||||
d = malloc(20); // a
|
||||
```
|
||||
## Diğer Referanslar ve Örnekler
|
||||
---
|
||||
### 🔥 Modern glibc dikkate alındığında (tcache ≥ 2.26)
|
||||
|
||||
glibc 2.26'dan itibaren her bir thread kendi **tcache**'ini *unsorted bin*'den *önce* sorgular. Bu nedenle bir first-fit senaryosu **yalnızca** aşağıdaki durumlarda **ulaşılabilir**:
|
||||
|
||||
1. İstenen boyut **`tcache_max`'dan daha büyükse** (64-bit'te varsayılan olarak 0x420), *veya*
|
||||
2. İlgili tcache bin **zaten dolu veya manuel olarak boşaltılmışsa** (7 eleman tahsis edilip kullanılırken tutulduğunda).
|
||||
|
||||
Gerçek istismarlarınızda genellikle şu şekilde bir yardımcı rutin ekleyeceksiniz:
|
||||
```c
|
||||
// Drain the tcache for a given size
|
||||
for(int i = 0; i < 7; i++) pool[i] = malloc(0x100);
|
||||
for(int i = 0; i < 7; i++) free(pool[i]);
|
||||
```
|
||||
Bir kez tcache tükenirse, sonraki serbest bırakmalar sıralanmamış kutuya gider ve klasik ilk uygun davranış (kuyruk araması, başa ekleme) tekrar tetiklenebilir.
|
||||
|
||||
---
|
||||
### 🚩 İlk uygun ile üst üste binen parça UAF oluşturma
|
||||
|
||||
Aşağıdaki parça (glibc 2.38 üzerinde test edilmiştir) sıralanmamış kutudaki bölücünün nasıl kötüye kullanılabileceğini gösterir ve 2 **üst üste binen işaretçi** oluşturur - tek bir serbest bırakmayı yazma-sonrası serbest bırakmaya dönüştüren güçlü bir ilke.
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(){
|
||||
setbuf(stdout, NULL);
|
||||
|
||||
/* 1. prepare 2 adjacent chunks and free the first one */
|
||||
char *A = malloc(0x420); // big enough to bypass tcache
|
||||
char *B = malloc(0x420);
|
||||
strcpy(A, "AAAA\n");
|
||||
free(A); // A → unsorted
|
||||
|
||||
/* 2. request a *smaller* size to force a split of A */
|
||||
char *C = malloc(0x400); // returns lower half of former A
|
||||
|
||||
/* 3. The remainder of A is still in the unsorted bin.
|
||||
Another 0x400-byte malloc will now return the *same*
|
||||
region pointed to by B – creating a UAF/overlap. */
|
||||
char *C2 = malloc(0x400);
|
||||
|
||||
printf("B = %p\nC2 = %p (overlaps B)\n", B, C2);
|
||||
|
||||
// Arbitrary write in B is immediately visible via C2
|
||||
memset(B, 'X', 0x10);
|
||||
fwrite(C2, 1, 0x10, stdout); // prints Xs
|
||||
}
|
||||
```
|
||||
Exploitation recipe (common in recent CTFs):
|
||||
|
||||
1. **Hedef boyut için** tcache'i boşaltın.
|
||||
2. **Bir parça serbest bırakın** böylece sıralanmamış kutuya düşer.
|
||||
3. **Biraz daha küçük bir boyut ayırın** – allocator sıralanmamış parçayı böler.
|
||||
4. **Tekrar ayırın** – kalan kısım mevcut bir kullanımda olan parça ile örtüşür → UAF.
|
||||
5. Hassas alanları (fonksiyon işaretçileri, FILE vtable, vb.) üzerine yazın.
|
||||
|
||||
Pratik bir uygulama, bu tam ilkenin `__free_hook` üzerinde tam kontrol sağlamak için UAF'den geçiş yapmak için kullanıldığı 2024 HITCON Quals *Setjmp* zorluğunda bulunabilir.{{#ref}}
|
||||
../../../../references/2024_setjmp_firstfit.md
|
||||
{{#endref}}
|
||||
|
||||
---
|
||||
### 🛡️ Önlemler & Sertleştirme
|
||||
|
||||
* **Güvenli bağlantı (glibc ≥ 2.32)** yalnızca tek bağlı *tcache*/**fastbin** listelerini korur. Sıralanmamış/küçük/büyük kutular hala ham işaretçileri saklar, bu nedenle bir heap leak elde edebilirseniz, ilk uygun tabanlı örtüşmeler geçerliliğini korur.
|
||||
* **Heap işaretçi şifreleme & MTE** (ARM64) henüz x86-64 glibc'yi etkilemiyor, ancak `GLIBC_TUNABLES=glibc.malloc.check=3` gibi dağıtım sertleştirme bayrakları tutarsız meta verilerde abort yapar ve naif PoC'leri bozabilir.
|
||||
* **Serbest bırakıldığında tcache doldurma** (2024'te glibc 2.41 için önerildi) sıralanmamış kullanımı daha da azaltır; genel exploitler geliştirirken gelecekteki sürümleri izleyin.
|
||||
|
||||
---
|
||||
## Diğer Referanslar & Örnekler
|
||||
|
||||
- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
|
||||
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
|
||||
- ARM64. Kullanımdan sonra serbest bırakma: Bir kullanıcı nesnesi oluşturun, serbest bırakın, serbest bırakılan parçayı alan bir nesne oluşturun ve buna yazma izni verin, **önceki kullanıcı->şifre konumunu üzerine yazarak**. Kullanıcıyı **şifre kontrolünü atlamak için yeniden kullanın**.
|
||||
- ARM64. Kullanımdan sonra: Bir kullanıcı nesnesi oluşturun, serbest bırakın, serbest bırakılan parçayı alan bir nesne oluşturun ve buna yazma izni verin, **önceki nesneden user->password konumunu üzerine yazın**. Kullanıcıyı **şifre kontrolünü atlamak için yeniden kullanın**.
|
||||
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
|
||||
- Program notlar oluşturulmasına izin verir. Bir not, bir malloc(8) içinde not bilgilerini (çağrılabilecek bir işlevin işaretçisi ile) ve notun içeriği ile başka bir malloc(\<size>) işaretçisini içerecektir.
|
||||
- Saldırı, not bilgisi boyutundan daha büyük malloc içeriklerine sahip 2 not (not0 ve not1) oluşturmak ve ardından bunları serbest bırakmak olacaktır, böylece hızlı kutuya (veya tcache) gireceklerdir.
|
||||
- Ardından, içerik boyutu 8 olan başka bir not (not2) oluşturun. İçerik, parçanın yeniden kullanılacağı not1'de olacak, burada işlev işaretçisini kazanan işlevine işaret edecek şekilde değiştirebiliriz ve ardından Not1'i Kullanımdan Sonra Serbest Bırakma ile yeni işlev işaretçisini çağırabiliriz.
|
||||
- Program notlar oluşturulmasına izin verir. Bir not, bir işlevi çağırabilecek bir işlev işaretçisine sahip bir malloc(8) içinde not bilgilerini ve notun içeriği ile başka bir malloc(<boyut>) için bir işaretçi içerecektir.
|
||||
- Saldırı, not bilgisi boyutundan daha büyük malloc içeriklerine sahip 2 not (note0 ve note1) oluşturmak ve ardından bunları serbest bırakmak olacaktır, böylece hızlı kutuya (veya tcache'e) gireceklerdir.
|
||||
- Daha sonra, içerik boyutu 8 olan başka bir not (note2) oluşturun. İçerik, not1'de olacak çünkü parça yeniden kullanılacak, burada işlev işaretçisini kazanan işlevine işaret edecek şekilde değiştirebiliriz ve ardından Not1'i Kullanımdan Sonra serbest bırakıp yeni işlev işaretçisini çağırabiliriz.
|
||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
|
||||
- Bazı bellek ayırmak, istenen değeri yazmak, serbest bırakmak, yeniden ayırmak ve önceki veriler hala orada olduğu için, parçadaki yeni beklenen yapı ile işlenmesi mümkün hale gelir, bu da değeri ayarlayıp bayrağı almayı sağlar.
|
||||
- Bazı bellek ayırmak, istenen değeri yazmak, serbest bırakmak, yeniden ayırmak ve önceki veriler hala orada olduğundan, yeni beklenen yapı ile parçanın içinde işlenmesi mümkün hale gelir, bu da değeri ayarlamayı veya bayrağı almayı mümkün kılar.
|
||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
|
||||
- Bu durumda, belirli bir parçanın içine 4 yazmak gereklidir, bu da tahsis edilen ilk parçadır (hepsini zorla serbest bıraktıktan sonra bile). Her yeni tahsis edilen parçanın dizideki numarası saklanır. Ardından, 4 parça (+ başlangıçta tahsis edilen) ayırın, sonuncusu içinde 4 olacak, bunları serbest bırakın ve ilk parçanın yeniden tahsis edilmesini zorlayın, bu da içinde 4 olan son serbest bırakılan parçayı kullanacaktır.
|
||||
- Bu durumda, belirli bir parçanın içine 4 yazmak gereklidir, bu da ilk tahsis edilen parçadır (hepsini zorla serbest bıraktıktan sonra bile). Her yeni tahsis edilen parçanın dizideki numarası saklanır. Ardından, 4 parça (+ başlangıçta tahsis edilen) ayırın, sonuncusu içinde 4 olacak, bunları serbest bırakın ve ilk parçanın yeniden tahsis edilmesini zorlayın, bu da son serbest bırakılan parçayı kullanacaktır, bu da içinde 4 olan parçadır.
|
||||
- 2024 HITCON Quals Setjmp yazısı (Quarkslab) – pratik ilk uygun / sıralanmamış-bölme örtüşme saldırısı: <https://ctftime.org/writeup/39355>
|
||||
- Angstrom CTF 2024 *heapify* yazısı – sıralanmamış kutu bölme istismar ederek libc'yi sızdırma ve örtüşme sağlama: <https://hackmd.io/@aneii11/H1S2snV40>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user