Double Free

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

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 à des 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 “fast bin”). Si vous libérez le même bloc deux fois de suite, l’allocateur détecte cela et renvoie 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 de la nouvelle mémoire (en utilisant malloc), l’allocateur peut 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 causer des problèmes de sécurité ou même leur 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 *)i2);

return 0;
}

Dans cet exemple, après avoir rempli le tcache avec plusieurs chunks libérés (7), le code libère le chunk h, puis le chunk i, et ensuite h à nouveau, provoquant un double free (également connu sous le nom de Fast Bin dup). Cela ouvre la possibilité de recevoir des adresses mémoire qui se chevauchent lors de la réallocation, ce qui signifie que deux ou plusieurs pointeurs peuvent pointer vers la même localisation 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 réallocations :
a1 : 0xaaab0f0c2360
b1 : 0xaaab0f0c2340
c1 : 0xaaab0f0c2320
d1 : 0xaaab0f0c2300
e1 : 0xaaab0f0c22e0
f1 : 0xaaab0f0c22c0
g1 : 0xaaab0f0c22a0
h1 : 0xaaab0f0c2380
i1 : 0xaaab0f0c23a0
i2 : 0xaaab0f0c23a0

Exemples

  • Dragon Army. Hack The Box
  • Nous ne pouvons allouer que des chunks de taille Fast-Bin sauf pour la taille 0x70, ce qui empêche l’écrasement habituel de __malloc_hook.
  • Au lieu de cela, nous utilisons des adresses PIE qui commencent par 0x56 comme cible pour Fast Bin dup (1/2 chance).
  • Un endroit où les adresses PIE sont stockées est dans main_arena, qui se trouve à l’intérieur de Glibc et près de __malloc_hook.
  • Nous ciblons un offset spécifique de main_arena pour allouer un chunk là-bas et continuer à allouer des chunks jusqu’à atteindre __malloc_hook pour obtenir une exécution de code.
  • zero_to_hero. PicoCTF
  • En utilisant des bins Tcache et un débordement de null-byte, nous pouvons atteindre une situation de double-free :
  • Nous allouons trois chunks de taille 0x110 (A, B, C)
  • Nous libérons B
  • Nous libérons A et allouons à nouveau pour utiliser le débordement de null-byte
  • Maintenant, le champ de taille de B est 0x100, au lieu de 0x111, donc nous pouvons le libérer à nouveau
  • Nous avons un Tcache-bin de taille 0x110 et un de taille 0x100 qui pointent vers la même adresse. Donc nous avons un double free.
  • Nous exploitons le double free en utilisant Tcache poisoning

Références

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks