Doble Liberación
Reading time: 5 minutes
tip
Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a HackTricks y HackTricks Cloud repos de github.
Información Básica
Si liberas un bloque de memoria más de una vez, puede desordenar los datos del asignador y abrir la puerta a ataques. Así es como sucede: cuando liberas un bloque de memoria, vuelve a una lista de fragmentos libres (por ejemplo, el "fast bin"). Si liberas el mismo bloque dos veces seguidas, el asignador detecta esto y lanza un error. Pero si liberas otro fragmento en medio, se omite la verificación de doble liberación, causando corrupción.
Ahora, cuando pides nueva memoria (usando malloc
), el asignador podría darte un bloque que ha sido liberado dos veces. Esto puede llevar a que dos punteros diferentes apunten a la misma ubicación de memoria. Si un atacante controla uno de esos punteros, puede cambiar el contenido de esa memoria, lo que puede causar problemas de seguridad o incluso permitirles ejecutar código.
Ejemplo:
#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;
}
En este ejemplo, después de llenar el tcache con varios chunks liberados (7), el código libera el chunk h
, luego el chunk i
, y luego h
nuevamente, causando un doble free (también conocido como Fast Bin dup). Esto abre la posibilidad de recibir direcciones de memoria superpuestas al reallocar, lo que significa que dos o más punteros pueden apuntar a la misma ubicación de memoria. Manipular datos a través de un puntero puede afectar al otro, creando un riesgo crítico de seguridad y potencial de explotación.
Al ejecutarlo, nota cómo i1
e i2
obtuvieron la misma dirección:
Asignaciones iniciales:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
d: 0xaaab0f0c2300
e: 0xaaab0f0c2320
f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
Después de las reallocaciones:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
d1: 0xaaab0f0c2300
e1: 0xaaab0f0c22e0
f1: 0xaaab0f0c22c0
g1: 0xaaab0f0c22a0
h1: 0xaaab0f0c2380
i1: 0xaaab0f0c23a0
i2: 0xaaab0f0c23a0
Ejemplos
- Dragon Army. Hack The Box
- Solo podemos asignar chunks del tamaño de Fast-Bin excepto para el tamaño
0x70
, lo que impide la habitual sobrescritura de__malloc_hook
. - En su lugar, usamos direcciones PIE que comienzan con
0x56
como objetivo para Fast Bin dup (1/2 de probabilidad). - Un lugar donde se almacenan las direcciones PIE es en
main_arena
, que está dentro de Glibc y cerca de__malloc_hook
. - Apuntamos a un desplazamiento específico de
main_arena
para asignar un chunk allí y continuar asignando chunks hasta alcanzar__malloc_hook
para obtener ejecución de código. - zero_to_hero. PicoCTF
- Usando bins de Tcache y un desbordamiento de byte nulo, podemos lograr una situación de doble free:
- Asignamos tres chunks de tamaño
0x110
(A
,B
,C
) - Liberamos
B
- Liberamos
A
y asignamos nuevamente para usar el desbordamiento de byte nulo - Ahora el campo de tamaño de
B
es0x100
, en lugar de0x111
, por lo que podemos liberarlo nuevamente - Tenemos un Tcache-bin de tamaño
0x110
y uno de tamaño0x100
que apuntan a la misma dirección. Así que tenemos un doble free. - Aprovechamos el doble free usando Tcache poisoning
Referencias
tip
Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a HackTricks y HackTricks Cloud repos de github.