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 
*