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

6.1 KiB

Double Free

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!

Autres façons de soutenir HackTricks :

Informations de base

Si vous libérez un bloc de mémoire plus d'une fois, cela peut perturber les données de l'allocateur et ouvrir la porte aux attaques. Voici comment cela se produit : lorsque vous libérez un bloc de mémoire, il retourne dans une liste de morceaux libres (par exemple, le "fastbin"). Si vous libérez le même bloc deux fois de suite, l'allocateur détecte cela et génère une erreur. Mais si vous libérez un autre morceau entre-temps, la vérification de double libération est contournée, provoquant une corruption.

Maintenant, lorsque vous demandez une nouvelle mémoire (en utilisant malloc), l'allocateur pourrait vous donner un bloc qui a été libéré deux fois. Cela peut conduire à deux pointeurs différents pointant vers le même emplacement mémoire. Si un attaquant contrôle l'un de ces pointeurs, il peut modifier le contenu de cette mémoire, ce qui peut entraîner des problèmes de sécurité ou même lui permettre d'exécuter du code.

Exemple :

#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;
}

Dans cet exemple, après avoir rempli le tcache avec plusieurs tranches libérées, le code libère la tranche h, puis la tranche i, et ensuite h à nouveau, provoquant une erreur de double-libération. Cela ouvre la possibilité de recevoir des adresses mémoire chevauchantes lors de la réallocation, ce qui signifie que deux pointeurs ou plus peuvent pointer vers la même adresse mémoire. Manipuler des données via un pointeur peut alors affecter l'autre, créant un risque de sécurité critique et un potentiel d'exploitation.

En l'exécutant, notez comment i1 et i2 ont obtenu la même adresse :

Allocations initiales :
a : 0xaaab0f0c22a0
b : 0xaaab0f0c22c0
c : 0xaaab0f0c22e0
d : 0xaaab0f0c2300
e : 0xaaab0f0c2320
f : 0xaaab0f0c2340
g : 0xaaab0f0c2360
h : 0xaaab0f0c2380
i : 0xaaab0f0c23a0
Après les réallocations :
a1 : 0xaaab0f0c2360
b1 : 0xaaab0f0c2340
c1 : 0xaaab0f0c2320
d1 : 0xaaab0f0c2300
e1 : 0xaaab0f0c22e0
f1 : 0xaaab0f0c22c0
g1 : 0xaaab0f0c22a0
h1 : 0xaaab0f0c2380
i1 : 0xaaab0f0c23a0
i2 : 0xaaab0f0c23a0

Références

Apprenez le piratage AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!

Autres façons de soutenir HackTricks :