No se puede sobrescribir EIP en el ejemplo de explotación básica

1

Estoy intentando replicar un desbordamiento de búfer simple para el cual tengo el siguiente código (strcpy_ex.c):

#include <string.h>

int main( int argc, char** argv ) {
        char buffer[500];
        strcpy(buffer, argv[1]);
        return 0; 
}

que compilo utilizando:

  

gcc -m32 -z execstack strcpy_ex.c -fno-stack-protector -o strcpy

El objetivo es lograr un shell explotando la falla de desbordamiento del búfer cuando se llena el búfer con más de 500 caracteres.

De la literatura que he leído, esperaba sobrescribir el EIP para cambiar el flujo de ejecución y hacer que apunte a una dirección de memoria donde reside mi código de shell. Para lograr esto, intenté llenar el búfer con "A" seguido de "B" para ubicar donde se realiza la sobrescritura:

(gdb) r $(python -c "print 'A'*500+'B'*500")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/Examples/Buffer Overflow/strcpy $(python -c "print 'A'*500+'B'*500")

Program received signal SIGSEGV, Segmentation fault.
0x565555ec in main ()

Lamentablemente, parece que no he logrado sobrescribir el EIP. Esperaba encontrar un valor 0x42424242 en EIP, pero no lo hice.

(gdb) i r eip esp
eip            0x565555ec   0x565555ec <main+76>
esp            0x4242423e   0x4242423e

Información adicional sobre las instrucciones de ASM:

(gdb) disas main
Dump of assembler code for function main:
   0x565555a0 <+0>: lea    0x4(%esp),%ecx
   0x565555a4 <+4>: and    $0xfffffff0,%esp
   0x565555a7 <+7>: pushl  -0x4(%ecx)
   0x565555aa <+10>:    push   %ebp
   0x565555ab <+11>:    mov    %esp,%ebp
   0x565555ad <+13>:    push   %ebx
   0x565555ae <+14>:    push   %ecx
   0x565555af <+15>:    sub    $0x200,%esp
   0x565555b5 <+21>:    call   0x565555ed <__x86.get_pc_thunk.ax>
   0x565555ba <+26>:    add    $0x1a46,%eax
   0x565555bf <+31>:    mov    %ecx,%edx
   0x565555c1 <+33>:    mov    0x4(%edx),%edx
   0x565555c4 <+36>:    add    $0x4,%edx
   0x565555c7 <+39>:    mov    (%edx),%edx
   0x565555c9 <+41>:    sub    $0x8,%esp
   0x565555cc <+44>:    push   %edx
   0x565555cd <+45>:    lea    -0x1fc(%ebp),%edx
   0x565555d3 <+51>:    push   %edx
   0x565555d4 <+52>:    mov    %eax,%ebx
   0x565555d6 <+54>:    call   0x56555400 <strcpy@plt>
   0x565555db <+59>:    add    $0x10,%esp
   0x565555de <+62>:    mov    $0x0,%eax
   0x565555e3 <+67>:    lea    -0x8(%ebp),%esp
   0x565555e6 <+70>:    pop    %ecx
   0x565555e7 <+71>:    pop    %ebx
   0x565555e8 <+72>:    pop    %ebp
   0x565555e9 <+73>:    lea    -0x4(%ecx),%esp
=> 0x565555ec <+76>:    ret    

Debido a la simplicidad del código, ¿no debería sobrescribirse EIP inmediatamente después de que se llena el búfer?

Incluso si en esta situación no debería hacer ninguna diferencia, me gustaría aclarar que ASLR está desactivado.

¿Qué me estoy perdiendo?

Respecto a la plataforma:

# uname -a
Linux kali 4.9.0-kali4-amd64 #1 SMP Debian 4.9.30-2kali1 (2017-06-22) x86_64 GNU/Linux
    
pregunta Jausk 28.07.2017 - 21:32
fuente

1 respuesta

1

Es posible que me falte algo aquí, pero la forma más sencilla de explotar esto es que la llamada strcpy () esté en otra función. De esta manera, sobrescribe la dirección de retorno almacenada, lo que esencialmente le otorga el control de EIP.

Tu función principal no regresa realmente a un espacio que controlas.

Haz que el código sea algo como:

#include <string.h>

void vuln(char *arg) {
    char buffer[500];
    strcpy(buffer, arg);
}  

int main( int argc, char** argv ) {
    vuln(argv[1]);
    return 0; 
}

El desbordamiento se producirá cuando vuln () finalice y recupere la dirección de retorno almacenada (pero sobrescrita) para devolverlo a main ().

Eso debería ayudarte a comenzar.

    
respondido por el ndrix 28.07.2017 - 21:44
fuente

Lea otras preguntas en las etiquetas