Translated ['src/binary-exploitation/libc-heap/use-after-free/first-fit.

This commit is contained in:
Translator 2025-07-30 12:29:41 +00:00
parent fbff3911c6
commit 4d80fcb359

View File

@ -12,10 +12,10 @@
Παράδειγμα:
- Αποδεσμεύετε 300 bytes (`a`), στη συνέχεια 250 bytes (`b`), απελευθερώνετε το `a` και ζητάτε ξανά 250 bytes (`c`).
- Όταν απελευθερώνετε το `a`, πηγαίνει στο unsorted bin.
- Αποδεσμεύετε 300 bytes (`a`), στη συνέχεια 250 bytes (`b`), στη συνέχεια απελευθερώνετε `a` και ζητάτε ξανά 250 bytes (`c`).
- Όταν απελευθερώνετε `a`, πηγαίνει στο unsorted bin.
- Αν ζητήσετε ξανά 250 bytes, ο αλγόριθμος αναθέσεων βρίσκει το `a` στην ουρά και το χωρίζει, επιστρέφοντας το μέρος που ταιριάζει με το αίτημά σας και κρατώντας το υπόλοιπο στο bin.
- Το `c` θα δείχνει στο προηγούμενο `a` και θα είναι γεμάτο με τα `a's`.
- Το `c` θα δείχνει στο προηγούμενο `a` και θα είναι γεμάτο με τα περιεχόμενα του `a`.
```c
char *a = malloc(300);
char *b = malloc(250);
@ -24,13 +24,9 @@ char *c = malloc(250);
```
### Fastbins
Τα Fastbins χρησιμοποιούνται για μικρές μνήμες. Σε αντίθεση με τα unsorted bins, τα fastbins προσθέτουν νέα κομμάτια στην κεφαλή, δημιουργώντας μια συμπεριφορά last-in-first-out (LIFO). Αν ζητήσετε ένα μικρό κομμάτι μνήμης, ο allocator θα αντλήσει από την κεφαλή του fastbin.
Τα Fastbins χρησιμοποιούνται για μικρά κομμάτια μνήμης. Σε αντίθεση με τα unsorted bins, τα fastbins προσθέτουν νέα κομμάτια στην κεφαλή, δημιουργώντας μια συμπεριφορά last-in-first-out (LIFO). Αν ζητήσετε ένα μικρό κομμάτι μνήμης, ο allocator θα τραβήξει από την κεφαλή του fastbin.
Παράδειγμα:
- Εσείς δεσμεύετε τέσσερα κομμάτια των 20 byte το καθένα (`a`, `b`, `c`, `d`).
- Όταν τα απελευθερώσετε με οποιαδήποτε σειρά, τα απελευθερωμένα κομμάτια προστίθενται στην κεφαλή του fastbin.
- Αν ζητήσετε στη συνέχεια ένα κομμάτι 20 byte, ο allocator θα επιστρέψει το πιο πρόσφατα απελευθερωμένο κομμάτι από την κεφαλή του fastbin.
Example:
```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
```
## Άλλες Αναφορές & Παραδείγματα
---
### 🔥 Σύγχρονες εκτιμήσεις glibc (tcache ≥ 2.26)
Από την glibc 2.26, κάθε νήμα διατηρεί το δικό του **tcache** που ερωτάται *πριν* από το unsorted bin. Επομένως, ένα σενάριο first-fit θα **φτάσει μόνο αν**:
1. Το ζητούμενο μέγεθος είναι **μεγαλύτερο από το `tcache_max`** (0x420 σε 64-bit από προεπιλογή), *ή*
2. Το αντίστοιχο tcache bin είναι **ήδη γεμάτο ή έχει αδειάσει χειροκίνητα** (με την εκχώρηση 7 στοιχείων και τη διατήρησή τους σε χρήση).
Σε πραγματικές εκμεταλλεύσεις, συνήθως θα προσθέσετε μια βοηθητική ρουτίνα όπως:
```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]);
```
Μόλις εξαντληθεί το tcache, οι επόμενες απελευθερώσεις πηγαίνουν στο unsorted bin και μπορεί να ενεργοποιηθεί ξανά η κλασική συμπεριφορά first-fit (αναζήτηση ουράς, εισαγωγή κεφαλής).
---
### 🚩 Δημιουργία ενός overlapping-chunk UAF με first-fit
Το παρακάτω απόσπασμα (δοκιμασμένο σε glibc 2.38) δείχνει πώς μπορεί να καταχραστεί ο διαχωριστής στο unsorted bin για να δημιουργήσει 2 **overlapping pointers** μια ισχυρή πρωτοβουλία που μετατρέπει μια μόνο απελευθέρωση σε write-after-free.
```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. **Αδειάστε** το tcache για το στοχευμένο μέγεθος.
2. **Απελευθερώστε** ένα chunk ώστε να καταλήξει στο unsorted bin.
3. **Κατανείμετε** ένα ελαφρώς μικρότερο μέγεθος ο allocator χωρίζει το unsorted chunk.
4. **Κατανείμετε** ξανά το υπόλοιπο μέρος επικαλύπτεται με ένα υπάρχον chunk σε χρήση → UAF.
5. Επαναγράψτε ευαίσθητα πεδία (δείκτες συναρτήσεων, FILE vtable, κ.λπ.)
Μια πρακτική εφαρμογή μπορεί να βρεθεί στην πρόκληση *Setjmp* των 2024 HITCON Quals όπου αυτή η ακριβής πρωτοβουλία χρησιμοποιείται για να μεταβεί από ένα UAF σε πλήρη έλεγχο του `__free_hook`.{{#ref}}
../../../../references/2024_setjmp_firstfit.md
{{#endref}}
---
### 🛡️ Mitigations & Hardening
* **Safe-linking (glibc ≥ 2.32)** προστατεύει μόνο τις απλά συνδεδεμένες λίστες *tcache*/**fastbin**. Οι unsorted/small/large bins εξακολουθούν να αποθηκεύουν ακατέργαστους δείκτες, οπότε οι επικαλύψεις που βασίζονται σε first-fit παραμένουν βιώσιμες αν μπορείτε να αποκτήσετε ένα heap leak.
* **Κρυπτογράφηση δείκτη heap & MTE** (ARM64) δεν επηρεάζουν ακόμα την x86-64 glibc, αλλά οι σημαίες σκληροποίησης διανομής όπως το `GLIBC_TUNABLES=glibc.malloc.check=3` θα τερματίσουν σε ασυνεπείς μεταδεδομένες πληροφορίες και μπορούν να σπάσουν απλές PoCs.
* **Γέμισμα tcache κατά την απελευθέρωση** (προτεινόμενο το 2024 για glibc 2.41) θα μειώσει περαιτέρω τη χρήση unsorted; παρακολουθήστε τις μελλοντικές εκδόσεις κατά την ανάπτυξη γενικών exploits.
---
## Other References & Examples
- [**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. Χρήση μετά την απελευθέρωση: Δημιουργήστε ένα αντικείμενο χρήστη, απελευθερώστε το, δημιουργήστε ένα αντικείμενο που θα πάρει το απελευθερωμένο κομμάτι και επιτρέψτε να γραφτεί σε αυτό, **επικαλύπτοντας τη θέση του user->password** από το προηγούμενο. Επαναχρησιμοποιήστε τον χρήστη για να **παρακάμψετε τον έλεγχο κωδικού πρόσβασης**
- ARM64. Χρήση μετά την απελευθέρωση: Δημιουργήστε ένα αντικείμενο χρήστη, απελευθερώστε το, δημιουργήστε ένα αντικείμενο που αποκτά το freed chunk και επιτρέψτε να γράψει σε αυτό, **επικαλύπτοντας τη θέση του user->password** από το προηγούμενο. Επαναχρησιμοποιήστε τον χρήστη για **να παρακάμψετε τον έλεγχο κωδικού πρόσβασης**
- [**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)
- Το πρόγραμμα επιτρέπει τη δημιουργία σημειώσεων. Μια σημείωση θα έχει τις πληροφορίες της σημείωσης σε μια malloc(8) (με έναν δείκτη σε μια συνάρτηση που θα μπορούσε να κληθεί) και έναν δείκτη σε άλλη malloc(\<size>) με το περιεχόμενο της σημείωσης.
- Η επίθεση θα ήταν να δημιουργηθούν 2 σημειώσεις (note0 και note1) με μεγαλύτερο περιεχόμενο malloc από το μέγεθος των πληροφοριών της σημείωσης και στη συνέχεια να απελευθερωθούν ώστε να μπουν στο γρήγορο bin (ή tcache).
- Στη συνέχεια, δημιουργήστε μια άλλη σημείωση (note2) με μέγεθος περιεχομένου 8. Το περιεχόμενο θα είναι στη note1 καθώς το κομμάτι θα επαναχρησιμοποιηθεί, όπου θα μπορούσαμε να τροποποιήσουμε τον δείκτη συνάρτησης ώστε να δείχνει στη συνάρτηση win και στη συνέχεια να χρησιμοποιήσουμε την μετά την απελευθέρωση της note1 για να καλέσουμε τον νέο δείκτη συνάρτησης.
- Το πρόγραμμα επιτρέπει τη δημιουργία σημειώσεων. Μια σημείωση θα έχει τις πληροφορίες της σημείωσης σε ένα malloc(8) (με έναν δείκτη σε μια συνάρτηση που θα μπορούσε να κληθεί) και έναν δείκτη σε άλλο malloc(<size>) με το περιεχόμενο της σημείωσης.
- Η επίθεση θα ήταν να δημιουργηθούν 2 σημειώσεις (note0 και note1) με μεγαλύτερο περιεχόμενο malloc από το μέγεθος των πληροφοριών της σημείωσης και στη συνέχεια να απελευθερωθούν ώστε να μπουν στο fast bin (ή tcache).
- Στη συνέχεια, δημιουργήστε μια άλλη σημείωση (note2) με μέγεθος περιεχομένου 8. Το περιεχόμενο θα είναι στη note1 καθώς το chunk θα επαναχρησιμοποιηθεί, όπου θα μπορούσαμε να τροποποιήσουμε τον δείκτη συνάρτησης ώστε να δείχνει στη συνάρτηση win και στη συνέχεια να χρησιμοποιήσουμε το Use-After-Free στη note1 για να καλέσουμε τον νέο δείκτη συνάρτησης.
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
- Είναι δυνατόν να δεσμεύσετε κάποια μνήμη, να γράψετε την επιθυμητή τιμή, να την απελευθερώσετε, να την επαναδεσμεύσετε και καθώς τα προηγούμενα δεδομένα είναι ακόμα εκεί, θα αντιμετωπιστούν σύμφωνα με τη νέα αναμενόμενη δομή στο κομμάτι, καθιστώντας δυνατή την ρύθμιση της τιμής για να αποκτήσετε τη σημαία.
- Είναι δυνατόν να δεσμεύσετε κάποια μνήμη, να γράψετε την επιθυμητή τιμή, να την απελευθερώσετε, να την επαναδεσμεύσετε και καθώς τα προηγούμενα δεδομένα είναι ακόμα εκεί, θα αντιμετωπιστούν σύμφωνα με τη νέα αναμενόμενη δομή στο chunk, καθιστώντας δυνατή την ρύθμιση της τιμής για να αποκτήσετε τη σημαία.
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
- Σε αυτή την περίπτωση είναι απαραίτητο να γράψετε 4 μέσα σε ένα συγκεκριμένο κομμάτι το οποίο είναι το πρώτο που έχει δεσμευτεί (ακόμα και μετά την αναγκαστική απελευθέρωση όλων τους). Σε κάθε νέο δεσμευμένο κομμάτι, ο αριθμός του αποθηκεύεται στον δείκτη του πίνακα. Στη συνέχεια, δεσμεύστε 4 κομμάτια (+ το αρχικά δεσμευμένο), το τελευταίο θα έχει 4 μέσα του, απελευθερώστε τα και αναγκάστε την επαναδέσμευση του πρώτου, το οποίο θα χρησιμοποιήσει το τελευταίο απελευθερωμένο κομμάτι που είναι αυτό με το 4 μέσα του.
- Σε αυτή την περίπτωση είναι απαραίτητο να γράψετε 4 μέσα σε ένα συγκεκριμένο chunk το οποίο είναι το πρώτο που έχει δεσμευτεί (ακόμα και μετά την αναγκαστική απελευθέρωση όλων τους). Σε κάθε νέο δεσμευμένο chunk, ο αριθμός του αποθηκεύεται στον δείκτη του πίνακα. Στη συνέχεια, δεσμεύστε 4 chunks (+ το αρχικά δεσμευμένο), το τελευταίο θα έχει 4 μέσα του, απελευθερώστε τα και αναγκάστε την επαναδέσμευση του πρώτου, το οποίο θα χρησιμοποιήσει το τελευταίο chunk που απελευθερώθηκε, το οποίο είναι αυτό με 4 μέσα του.
- 2024 HITCON Quals Setjmp write-up (Quarkslab) πρακτική επίθεση first-fit / unsorted-split overlap: <https://ctftime.org/writeup/39355>
- Angstrom CTF 2024 *heapify* write-up εκμετάλλευση του splitting του unsorted-bin για να διαρρεύσει libc και να αποκτήσει επικαλύψεις: <https://hackmd.io/@aneii11/H1S2snV40>
{{#include ../../../banners/hacktricks-training.md}}