Hola kr0m_
Desde hace un tiempo gcc ha cambiado el prólogo y el epílogo de las funciones por cuestiones de alineamiento de la pila. Probablemente esa sea la razón por que no te funciona lo que has estado probando. Puedes encontrar más informacion aquí:
http://stackoverflow.com/questions/11886429/understanding-new-gcc-prologue.Te aconsejo que para realizar los ejercicios de protostar te descargues la maquina virtual que los creadores ofrecen en la web para evitar contratiempos:
https://exploit-exercises.com/download/. Los binarios presentes en la máquina virtual utilizan el prólogo/epílogo tradicional.
En esta imagen puedes observar el epílogo de la función main del binario presente en la máquina virtual:
Por el contrario este es el epílogo de la función main de un binario compilado con la última versión de gcc con los argumentos que tu has utilizado ( -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack ):
Si te fijas en esta última imagen después de la instrucción leave hay otra instrucción antes del ret. Justamente ésta instrucción modifica el contenido del registro esp y teniendo en cuenta que la siguiente instrucción es un ret podemos afirmar que está modificando la dirección de retorno de la función main.
Para comprobar lo que digo vamos a poner varios puntos de interrupción y hacer varias suposiciones:
El relleno necesario para sobreescribir la dirección de retorno si se utilizara el epílogo tradicional es de 76 bytes:
leave ;mov esp,ebp pop ebp
ret
La dirección de memoria de la función win() és 0x0804842b
1) Guardamos nuestro vector de ataque en un archivo y ejecutamos el depurador.
perl -e 'print "A"x76 . "\x2b\x84\x04\x08" ' > exploit; gdb vulnerable
2) Establecemos los puntos de interrupción y empezamos a depurar el programa( en la imagen anterior puedes ver los comandos ).
Después de recibir la entrada de datos el programa llega al primer punto de interrupción. ( antes de ejecutar la instrucción leave ).
Con la ayuda del comando x/32x $esp podemos comprobar que todo nuestro relleno está presente en la pila(empieza en 0xbfffef00 y termina en 0xbfffef5c).
La dirección de memoria 0xbfffef5c ( ebp + 0x4 ) contiene la dirección de retorno de la función main. Podemos ver en la imagen que el valor que contiene esta posición de memoria és 0x0804842b que como ya he especificado antes corresponde a la dirección de memoria de la función win().
Procedemos hasta el siguiente punto de interrupción después de la instrucción leave. Mediante el comando x $esp podemos comprobar por segunda vez que la dirección de retorno de main és 0x0804842b.
Podemos observar que si la siguiente instrucción a ejecutar-se fuera ret ( él epílogo tradicional) habríamos resuelto el reto. Por el contrario antes del ret tenemos una instrucción que nos modificara el contenido de esp y en consecuencia la dirección de retorno de la función.
En esta última imagen puedes observar lo que acabo de decir:
Nota: Aunque el epílogo sea algo diferente, la explotación de la vulnerabilidad para este caso concreto sigue siendo trivial.
Una vez lo hayas resuelto con el binario que te dan los creadores del reto, te animo a que resuelvas el reto con esta pequeña modificación en el epílogo.
SpoilerPara mi caso la solución és:
- perl -e 'print "\x2b\x84\x04\x08" . "A"x64 . "\x04\xef\xff\xbf" ' > exploit; gdb ./stack04
- run < cat exploit
Saludos,
Aerøx