hacktricks/binary-exploitation/heap/double-free.md

6.6 KiB
Raw Blame History

Διπλός Ελεύθερος

Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (Ειδικός Ερυθρός Συνεργάτης AWS του HackTricks)!

Άλλοι τρόποι υποστήριξης του HackTricks:

Βασικές Πληροφορίες

Αν ελευθερώσετε ένα τμήμα μνήμης περισσότερες από μία φορές, μπορεί να δημιουργήσετε προβλήματα στα δεδομένα του διαχειριστή μνήμης και να ανοίξετε την πόρτα σε επιθέσεις. Εδώ είναι πώς συμβαίνει: όταν ελευθερώνετε ένα τμήμα μνήμης, επιστρέφει σε μια λίστα ελεύθερων τμημάτων (π.χ. το "fastbin"). Αν ελευθερώσετε το ίδιο τμήμα δύο φορές συνεχόμενα, ο διαχειριστής ανιχνεύει αυτό και εκτοξεύει ένα σφάλμα. Αλλά αν ελευθερώσετε ένα άλλο τμήμα μεταξύ τους, ο έλεγχος διπλής ελευθέρωσης παρακάμπτεται, προκαλώντας διαφθορά.

Τώρα, όταν ζητάτε νέα μνήμη (χρησιμοποιώντας malloc), ο διαχειριστής μπορεί να σας δώσει ένα τμήμα που έχει ελευθερωθεί δύο φορές. Αυτό μπορεί να οδηγήσει σε δύο διαφορετικούς δείκτες που δείχνουν στην ίδια τοποθεσία μνήμης. Αν ένας επιτιθέμενος ελέγχει έναν από αυτούς τους δείκτες, μπορεί να αλλάξει το περιεχόμενο αυτής της μνήμης, το οποίο μπορεί να προκαλέσει θέματα ασφαλείας ή ακόμα και να τους επιτρέψει να εκτελέσουν κώδικα.

Παράδειγμα:

#include <stdio.h>
#include <stdlib.h>

int main() {
// Allocate memory for three chunks
char *a = (char *)malloc(10);
char *b = (char *)malloc(10);
char *c = (char *)malloc(10);
char *d = (char *)malloc(10);
char *e = (char *)malloc(10);
char *f = (char *)malloc(10);
char *g = (char *)malloc(10);
char *h = (char *)malloc(10);
char *i = (char *)malloc(10);

// Print initial memory addresses
printf("Initial allocations:\n");
printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i);

// Fill tcache
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);

// Introduce double-free vulnerability in fast bin
free(h);
free(i);
free(h);


// Reallocate memory and print the addresses
char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10);

// Print initial memory addresses
printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i1);

return 0;
}

Σε αυτό το παράδειγμα, μετά τον γέμισμα του tcache με αρκετά ελεύθερα τμήματα, ο κώδικας ελευθερώνει το τμήμα h, στη συνέχεια το τμήμα i, και μετά ξανά το h, προκαλώντας ένα σφάλμα διπλής απελευθέρωσης. Αυτό ανοίγει τη δυνατότητα λήψης επικαλυπτόμενων διευθύνσεων μνήμης κατά την επαναδιάταξη, που σημαίνει ότι δύο ή περισσότεροι δείκτες μπορεί να δείχνουν στην ίδια τοποθεσία μνήμης. Η διαμόρφωση δεδομένων μέσω ενός δείκτη μπορεί να επηρεάσει τον άλλο, δημιουργώντας ένα κρίσιμο κίνδυνο ασφάλειας και δυνατότητα εκμετάλλευσης.

Εκτελώντας το, παρατηρήστε πώς i1 και i2 πήραν την ίδια διεύθυνση:

Αρχικές εκχωρήσεις:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
d: 0xaaab0f0c2300
e: 0xaaab0f0c2320
f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
Μετά τις επαναδιατάξεις:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
d1: 0xaaab0f0c2300
e1: 0xaaab0f0c22e0
f1: 0xaaab0f0c22c0
g1: 0xaaab0f0c22a0
h1: 0xaaab0f0c2380
i1: 0xaaab0f0c23a0
i2: 0xaaab0f0c23a0

Αναφορές