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

8.6 KiB
Raw Blame History

Διπλό Δωρεάν

{% hint style="success" %} Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Υποστηρίξτε το HackTricks
{% endhint %}

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

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

Τώρα, όταν ζητάτε νέα μνήμη (χρησιμοποιώντας το 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 με αρκετά ελεύθερα κομμάτια (7), ο κώδικας ελευθερώνει το κομμάτι h, στη συνέχεια το κομμάτι i, και έπειτα ξανά το h, προκαλώντας ένα διπλό free (επίσης γνωστό ως Fast Bin dup). Αυτό ανοίγει τη δυνατότητα λήψης επικαλυπτόμενων διευθύνσεων μνήμης κατά την επαναδιάθεση, που σημαίνει ότι δύο ή περισσότεροι δείκτες μπορεί να δείχνουν στην ίδια τοποθεσία μνήμης. Η διαμόρφωση δεδομένων μέσω ενός δείκτη μπορεί να επηρεάσει τον άλλο, δημιουργώντας ένα κρίσιμο κίνδυνο ασφάλειας και δυνατότητα εκμετάλλευσης.

Εκτελώντας το, παρατηρούμε πώς οι 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

Παραδείγματα

  • Dragon Army. Hack The Box
  • Μπορούμε να εκχωρήσουμε μόνο κομμάτια μεγέθους Fast-Bin εκτός από το μέγεθος 0x70, το οποίο αποτρέπει την συνήθη αντικατάσταση του __malloc_hook.
  • Αντ' αυτού, χρησιμοποιούμε διευθύνσεις PIE που ξεκινούν με 0x56 ως στόχο για Fast Bin dup (1/2 πιθανότητα).
  • Ένα μέρος όπου οι διευθύνσεις PIE αποθηκεύονται είναι στο main_arena, το οποίο βρίσκεται μέσα στο Glibc και κοντά στο __malloc_hook.
  • Στοχεύουμε σε ένα συγκεκριμένο μετατροπέα του main_arena για να εκχωρήσουμε ένα κομμάτι εκεί και να συνεχίσουμε τις εκχωρήσεις μέχρι να φτάσουμε το __malloc_hook για να εκτελέσουμε κώδικα.
  • zero_to_hero. PicoCTF
  • Χρησιμοποιώντας Tcache bins και έκκληση μηδενικού byte, μπορούμε να επιτύχουμε μια κατάσταση διπλού ελεύθερου:
  • Εκχωρούμε τρία κομμάτια μεγέθους 0x110 (A, B, C)
  • Ελευθερώνουμε το B
  • Ελευθερώνουμε το A και εκχωρούμε ξανά για να χρησιμοποιήσουμε την έκκληση μηδενικού byte
  • Τώρα το πεδίο μεγέθους του B είναι 0x100, αντί για 0x111, οπότε μπορούμε να το ελευθερώσουμε ξανά
  • Έχουμε ένα Tcache-bin μεγέθους 0x110 και ένα μεγέθους 0x100 που δείχνουν στην ίδια διεύθυνση. Έτσι έχουμε ένα διπλό free.
  • Εκμεταλλευόμαστε το διπλό free χρησιμοποιώντας Tcache poisoning

Αναφορές