Explorando el heap
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *buffer = malloc(16);
char *filename = malloc(23);
strcpy(filename, "/tmp/heap-overflow.txt");
gets(buffer);
printf("%s\n" ,buffer);
printf("%s\n" ,filename);
FILE *fd = fopen(filename, "w");
if (fd != NULL) {
fputs(buffer, fd);
fclose(fd);
}
return 0;
}
En C9.io lo compilamos usando la opción de debug:
gcc -g ho.c
Notamos que los espacios reservados viven a 0x20 bytes de distancia.
(gdb) p buffer
$2 = 0x602010 ""
(gdb) p filename
$3 = 0x602030 ""
Si inspeccionamos varios bytes antes del primero, vemos su contenido.
(gdb) x/10wx buffer-8
0x602008: 0x00000021 0x00000000 0x00000000 0x00000000
0x602018: 0x00000000 0x00000000 0x00000000 0x00000000
Si huberamos reservado 64 bytes para el filename
, el contenido sería 0x00000051
. De modo los 4 bytes antes del comienzo del espacio reservado para data contienen el largo del espacio reservado y un bit adicional para qué?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *buf1 = malloc(16);
char *buf2 = malloc(16);
char *buf3 = malloc(16);
char *buf4 = malloc(16);
free(buf3);
free(buf2);
gets(buf1);
buf3=malloc(16);
gets(buf3);
return 0;
}
(gdb) p buf1
$1 = 0x602010 ""
(gdb) p buf2
$2 = 0x602030 ""
(gdb) p buf3
$3 = 0x602080 ""
(gdb) p buf4
$4 = 0x6020d0 ""
El contenido del heap luego de los mallocs pero antes del free:
(gdb) x/100x buf1-8
0x602008: 0x00000021 0x00000000 0x00000000 0x00000000
0x602018: 0x00000000 0x00000000 0x00000000 0x00000000
0x602028: 0x00000051 0x00000000 0x00000000 0x00000000
...
0x602078: 0x00000051 0x00000000 0x00000000 0x00000000
...
0x6020c8: 0x00000051 0x00000000 0x00000000 0x00000000
...
0x602118: 0x00020ef1 0x00000000 0x00000000 0x00000000
Segun borramos pedazos (usando free)
0x602078: 0x00000051 0x00000000 0x00602020 0x00000000
Envenenamos el prev o next de uno de los chunks vacíos. Al tratar de reservar con malloc un nuevo espacio:
*** Error in `/home/ubuntu/workspace/a.out': malloc(): memory corruption (fast): 0x0000000000602030 ***
Program received signal SIGABRT, Aborted.
0x00007ffff7a4af89 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
0x0000000000602030
es la dirección que habíamos modificado. Bajo condiciones normales ¿Será que malloc valida el contenido de los punteros?
Si apagamos las verificaciones:
export MALLOC_CHECK_=0
Al correr el programa y pasar un string envenenado al buf1, logramos que el buf3 apunte a otra dirección muy lejos del heap:
(gdb) p buf3
0x7ffff00008c0
Referencias
-
https://www.sans.edu/student-files/presentations/heap_overflows_notes.pdf
-
https://csg.utdallas.edu/wp-content/uploads/2012/08/Heap-Based-Exploitation.pdf
*