Fastbin double free

Article pour comprendre & utiliser la double free.

Fastbin

Le fastbin est une liste de chunk free d'une certaine taille. Allant de 0x10 à 0x80.

Voici un schéma de l'état du fastbin :

|------------|         |------------|         |------------|
|    Chunk   |    -->  |    Chunk   |    -->  |    Chunk   |
|------------|         |------------|         |------------|
|   Size:16  |         |   Size:24  |         |   Size:32  |
|  Prev:NULL |         |  Prev:NULL |         |  Prev:NULL |
|  Next:---->|         |  Next:---->|         |  Next:---->|
|------------|         |------------|         |------------|

Pour résumer, le fastbin va permettre si le programme à besoin d'une allocation d'une similaire de pouvoir rapidement re-allouer le chunk.

Double Free

La double free est une vulnérabilité sur le heap. Dans le cas où un développeur oublie de mettre à NULL le pointer vers le chunk lors du free :

char *raphgui = malloc(0x30);
...
free(raphgui);
raphgui = NULL; // Si il oublie de faire ça, alors il y'aura une UAF

Des protections ont été mises en place pour empêcher de pouvoir faire des doubles free du style :

free(a)
free(a)

Mais il est possible de faire :

free(a)
free(b)
free(a)

Tcache

La glibc 2.26 a introduit une nouvelle fonctionnalité appelée tcache. Il s'agit d'une liste chaînée qui contient des blocs mémoire qui ont été free, permettant au tcache de stocker des blocs pour chaque taille de bin.

#if USE_TCACHE
  {
    size_t tc_idx = csize2tidx (size);
    if (tcache != NULL && tc_idx < mp_.tcache_bins)
      {
	tcache_entry *e = (tcache_entry *) chunk2mem (p);
	if (__glibc_unlikely (e->key == tcache_key))
	  {
	    tcache_entry *tmp;
	    size_t cnt = 0;
	    LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
	    for (tmp = tcache->entries[tc_idx];
		 tmp;
		 tmp = REVEAL_PTR (tmp->next), ++cnt)
	      {
		...
		if (tmp == e)
		  malloc_printerr ("free(): double free detected in tcache 2");

	      }
	  }
	  ...
	  }
      }
  }
#endif

Il s'agit d'un extrait du code de malloc. Avant de mettre un chunk dans le tcache, il va vérifier si il n'y est pas déja.

Le tcache a une taille maximun de 7. Si il y'a un 8 chunk d'une taille similaire qui est free alors il sera mis dans le bins qui lui correspond (Fastbin, largebin ...).

Last updated