¿Compilando un ejemplo de desbordamiento de búfer en Linux moderno?

12

Estoy tratando de compilar un ejemplo simple de desbordamiento de búfer en una máquina virtual Debian i386. El ejecutable construye bien, pero el EIP no se sobrescribe correctamente a pesar de que se le proporcionó una entrada suficientemente grande para desbordar el búfer y sobrescribir el EIP insertado en la pila. Aquí están mis comandos como root:

sysctl -w kernel.randomize_va_space=0
gcc test.c -z execstack -z norelro -fno-stack-protector -D_FORTIFY_SOURCE=0 -ggdb -o test

Como puedes ver, tengo:

  • Hizo el ejecutable de la pila
  • Se eliminaron los canarios de pila
  • Deshabilitado todo el sistema ASLR
  • Se eliminaron las protecciones de relanzado
  • Deshabilitó las protecciones FORTIFY_SOURCE de gcc

Aquí está test.c:

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
  char buf[128];
  if(argc < 2) return 1;
  strcpy(buf, argv[1]);
  printf("%s\n", buf);
  return 0;
}

He experimentado con cuerdas de colisión (solo todas las As) de 128-256. En gdb, el EIP empujado nunca se sobrescribe. En realidad, solo debería ser una cadena de 132 bytes para sobrescribir el EIP ya que no hay otras variables de pila locales.

¿Hay alguna otra protección que necesito deshabilitar al compilar? ¿O hay algo más que deshabilitar con sysctl?

    
pregunta B-MO 15.09.2015 - 08:41
fuente

2 respuestas

4

Su ejemplo hace segfault aquí (o causa la terminación del programa si el protector de pila está activo).

Tal vez deberías intentar mover el desbordamiento del búfer a otra función. Quizás tu versión de gcc está convirtiendo return 0; de main en exit(0); .

    
respondido por el Ángel 15.09.2015 - 11:22
fuente
13

Si bien la respuesta aceptada es correcta al sugerir que mover todo a una función diferente no explica por qué.

Como puede ver en esta pregunta y respuesta main() de las funciones a menudo realiza una alineación de pila para garantizar que la pila está configurada correctamente. Se realiza la siguiente instrucción:

83 e4 f0 and esp, 0xfffffff0

Esto alineará la pila a 8 bytes. Lo que esto significa es que se realizó una operación de resta en esp . Así que para desbordar la dirección de retorno necesitas 128 bytes + <variable stack alignment> + <optional saved ebp> + <new_return_address> .

Compilé y ejecuté tu programa (tuve que agregar un -m32 ).

Starting program: /home/user/Private/misc/overflow_test  
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFaaaabbbbcccc
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFaaaabbbbcccc

Program received signal SIGSEGV, Segmentation fault.
0x63636363 in ?? ()

Usé 128 As, y luego 4 de cada nueva letra.

Al descomponer el programa vemos las siguientes líneas:

;      .//overflow_test.c:4
;-- main: 
;-- sym.main: 
0x0804842d    55             push ebp  
0x0804842e    89e5           mov ebp, esp  
0x08048430    83e4f0         and esp, 0xfffffff0 
0x08048433    81ec90000000   sub esp, 0x90 

Aquí vemos que 0x90 (144) se resta de la pila. Lo que significa que se asignan más de 128 bytes de espacio para las variables locales. Esta respuesta de SO da algunas razones por las que esto puede ocurrir. Por lo tanto, si tiene en cuenta los 128 bytes, los 16 bytes adicionales agregados para las variables locales y asume 8 bytes de alineación de pila: entonces, se ha sobrescrito el EBP con 0x62626262 y la dirección de retorno con 0x63636363 .

Las funciones normales generalmente no realizan este paso de alinear la pila. Es por eso que cuando lo movió a una función separada, todo funcionó como se esperaba. En la explotación real, es muy poco probable que esté explotando los parámetros que entran en un main() . Es más realista estar ejecutándose en el alcance de una función diferente.

    
respondido por el RoraΖ 15.09.2015 - 14:16
fuente

Lea otras preguntas en las etiquetas