STACK-FIVE amd64
Este nivel presenta el uso de los shellcode para ejecutar código arbitrario.
UTILIZANDO EL DEPURADOR
Como en todos los anteriores, lo primero es utilizar rabin2
para obtener más información del binario:

Después lo podemos abrir en nuestro depurador, analizar todo y comprobar las funciones para ver qué estamos buscando:

Vemos que el binario utiliza las funciones gets, puts. Las conocemos de los ejemplos anteriores así que ya sabemos que gets es explotable.
Además de eso, vemos que hay llamadas a dos funciones que conocemos pero no hay una función complete_level que nos permita vencer el nivel. En este caso, tendremos que abrir una shell remota para obtener la victoria.
Vamos a analizar el desensamblado de ambas:
sym.start_level:

Podemos observar que la llamada a la función vulnerable gets() se encuentra en esta función.
sym.main:
ATENCIÓN
Un apunte importante es ver que la ejecución de la función main no termina con exit(), de hecho, la funcion exit() no se utiliza en ninguna parte del binario. Esto se debe a que en la función main() es opcional indicar el retorno.
Si no existe un entero de retorno definido para la función main(), se tomará como 0.
Ya hemos analizado lo más importante de éste binario, a continuación vamos a preparar el exploit:
PREPARANDO EL EXPLOIT
Como ya hemos mencionado, nuestro objetivo es ejecutar una shell en nuestro objetivo, en este caso, en la máquina phoenix. Los pasos a seguir para conseguir que el shellcode se ejecute son los siguientes:
Comprobar si el stack es ejecutable.
Identificar el tamaño del Buffer.
Colocar nuestra shellcode en el Buffer.
Añadir un tobogán de NOPS para facilitar la ejecución.
Sobrescribir la dirección de retorno para que retorne a la posición de nuestra shellcode.
Obtener una shell interactiva.
Comprobar si el stack es ejecutable:
Para identificar los permisos que tenemos sobre los diferentes segmentos del binario podemos utilizar la aplicación readelf con el argumento -l para ver las secciones del binario:

Vemos que en el Stack tenemos permisos de lectura, escritura y ejecución.
Identificar el tamaño del Buffer
Para identificar el tamaño del Buffer podemos calcular cuantos bytes tenemos desde la dirección de memoria en la que se almacena el primer carácter del buffer hasta la dirección de retorno:
Vamos a marcar un Breakpoint justo después de la llamada a la función gets() e introducimos "AAAA" por stdin en dicha función.
Del desensamblado de la función main() podemos averiguar que la dirección de retorno es 0x004005c7

Si calculamos el número de bytes que existen entre los dos datos obtenemos que son 136 bytes. Ese es el espacio que tenemos para nuestra shellcode y nuestro tobogan de nops.
Colocar nuestra shellcode en el Buffer.
Para este paso necesitamos un shellcode, en este caso vamos a utilzar el siguiente shellcode predefinido de shell-storm:
Añadir un tobogán de NOPS para facilitar la ejecución.
Vamos a empezar a preparar nuestro exploit en python con todo lo que hemos visto anteriormente y nuestro tobogán listo:

Sobrescribir la dirección de retorno para que retorne a la posición de nuestra shellcode.
Por ultimo necesito una dirección de retorno dentro del tobogán de NOPs que permita que nuestro shellcode se ejecute. Por ejemplo: 0x7fffffffe600
(Lo podemos sacar de la imagen del stack.
Por tanto, nuestro exploit quedaría de la siguiente manera:

EXPLOTANDO LA VULNERABILIDAD
Para introducir el input por stdin vamos a utilizar rarun2. La plantilla quedaría como sigue:

Última actualización
¿Te fue útil?