Cómo explotar el valor de la variable

4

Estoy intentando explotar un archivo binario que tengo acceso al código fuente.

int flag = 0;

int main() {
    char buf[0x50];
    puts("Who are you? ");
    printf("> ");
    fgets(buf, 0x50, stdin);
    printf(buf);

    if (flag == 1337) {
        puts("Enjoy your shell!");
        system("/bin/sh");}
    else {
        puts("Not allowed");
    }
    return 0;
}

Como se puede ver en el código fuente, si el indicador es 1377 obtendré un shell. Puedo ver eso con gdb también.

 0x4007ec <main+175>       mov    eax, DWORD PTR [rip+0x200892]       # 0x601084 <flag>
 0x4007f2 <main+181>       cmp    eax, 0x539

Las medidas de seguridad se configuran de esta manera:

Canary                        : Yes
NX                            : Yes
PIE                           : No
Fortify                       : No
RelRO                         : Partial

Entonces, en primer lugar no puedo hacer el desbordamiento del búfer clásico porque el programa utiliza fgets para recopilar información. Por supuesto, canary también está allí, pero no hará ningún daño porque si pudiera cambiar el valor de la bandera (antes de que se hiciera el cheque de Canary) tendría éxito en obtener esa cáscara. No sé si lo que pienso es correcto, corríjame si me equivoco.

Mi primera conclusión sobre esto fue que, no podría explotar buf para reescribir el valor de flag. (Supuse que buf y flag se colocarían uno al lado del otro en la pila). Creo que tengo razón en esto porque cuando miré el registro $rsp y encontré que solo la cantidad permitida de "A" se colocó en la pila. Entonces, incluso si la bandera se colocara justo debajo de ella, el valor de la bandera no se sobrescribiría. ¿Tengo razón hasta ahora? Esa sería mi primera pregunta

0x7fffffffdaf0: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffdb00: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffdb10: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffdb20: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffdb30: 0x41414141  0x41414141  0x41414141  0x00414141
0x7fffffffdb40: 0x00400840  0x00000000  0x96703f00  0x948afed7
0x7fffffffdb50: 0xffffdc40  0x00007fff  0x00000000  0x00000000

Entonces, ¿cómo podré variar ese valor? Creo que la vulnerabilidad debe provenir de la carga útil proporcionada por un usuario malintencionado, pero buf es la única forma de obtener esa carga útil en la pila. Ya que no puedo sobrescribir los registros desbordando buf estoy un poco perdido.

    
pregunta fish202 01.12.2017 - 02:16
fuente

2 respuestas

3

Tienes razón en que el búfer no puede desbordar la bandera debido a la verificación de límites. Fgets también incluye el carácter nulo en su comprobación enlazada.
enlace

Sin embargo, existe una vulnerabilidad de formato de cadena aquí:

printf(buf);

La variable controlada por el usuario buf se usa en una declaración printf, lo que causa una vulnerabilidad de cadena de formato.

enlace

Usando una combinación de %x %n puedes sobrescribir la bandera con "1337". % x se usa para sacar valores de la pila, y% n se usa para escribir el número de caracteres en esa dirección. El "1337u" expande el número de caracteres para que pueda escribir el valor correcto. Por ejemplo, si la ubicación de memoria de la bandera es "0xffffff80"

$(python -c 'print "\x80\xff\xff\xff"+"%x%1337u%n"')

Esto escribirá un número que es mayor que 1337 debido a las otras cosas antes del "1337u", por lo que simplemente restas ese número por la cantidad que superas, y tendrás el número correcto. O, si quieres hacer algunos cálculos, el valor de "u" es: “El byte que se escribirá” - “el byte de salida” + “el ancho del% x especificado justo antes del% n”

    
respondido por el Daniel Grover 01.12.2017 - 15:53
fuente
1

flag no es local para ninguna función y tiene un alcance global. Por lo tanto, no se encuentra en la pila de tiempo de ejecución. Actualice el binario o aproveche el hecho de que la entrada a buf no está saneada y que buf un argumento a printf (manipule el valor del argumento de la cadena de formato de manera que 1337 se escriba en la dirección 0x601084 ).

flag es una variable asignada estáticamente cuyo valor se almacenará en el segmento data o bss del proceso en lugar de en la pila de tiempo de ejecución. Si tiene acceso al binario, puede parchearlo de tal manera que el valor 1337 se almacene en la dirección 0x601084 , que debería estar en la sección .data o .bss . Como aquí la variable global flag se inicializa a 0, probablemente estará en la sección .bss del segmento binario y bss del proceso (este no sería el caso si se inicializara con algún otro valor) .

Incluso si uno no supiera cómo el compilador asigna memoria a las variables en función de su ubicación en el código fuente, todavía se podría determinar que flag no se almacena en la pila de tiempo de ejecución al comparar su dirección con la del puntero de pila %rsp : la ubicación 0x601084 es mucho más baja en memoria que 0x7fffffffdaf0 .

    
respondido por el SYS_V 01.12.2017 - 06:38
fuente

Lea otras preguntas en las etiquetas