CANARY BYPASS
CANARY
Canary es una protección contra ataques del tipo "Smash the Stack" que se basa en incluir un número aleatorio justo después de la dirección de retorno. Este número se compara justo antes de ejecutar la instrucción ret. Si coinciden es que no ha habido un buffer overflow.
Si el atacante intenta realizar un Buffer Overflow, el programa lanzará un error ***stack smashing detected ***.
En Linux, los canarios terminan siempre en \x00. Esto es para cerrar cualquier string que nos hubieramos dejado abierta en la ejecución del programa pero también los hace más facilmente identificables.
BYPASSING CANARY
Existen dos formas de bypassear el canario:
Filtración del canario
Este proceso es muy amplio y dependerá del binario que estemos explotando pero la meta es leer el valor del canario.
La opción más sencilla es utilizando una vulnerabilidad de format string, ya que como el canario es una variable local, se encuentra almacenado en el stack y, por tanto, se puede acceder a él.
Código Fuente:
El código fuente es muy sencillo: da una vulnerabilidad de format string y después da acceso a un buffer overflow.
La vulnerabilidad de format string se puede utilizar para obtener el valor del canario, de tal manera que podemos sobreescribir el valor del canario por ese mismo valor después de haberlo sobreescrito con el buffer overflow.
Todo esto con el objetivo de ejecutar win().
Compilado en 32 bits
Primero comprobamos si efectivamente tiene canario:
Ahora tenemos que averiguar el offset del canario. Podemos utilizar para ello radare2.
El último valor es el canario. Lo podemos saber por que está más o menos 64 bytes después del inicio del buffer (que tiene 64 bytes) y el canario debe estar cerca del final de buffer. Además, empieza con 00 como y parece bastante aleatorio, no como las direcciones que empiezan siempre por ff o por 7f.
Vamos a comprobarlo utilizando el format string y vemos que es el offset 23.as
El canario está randomizado y por tanto, será diferente para cada instancia que iniciemos.
Ahora podemos automatizar esta acción con pwntools.
Ahora solo queda ver cual es la distancia entre el canario y la dirección de retorno.
Vemos el canario en 0xffea8afc
. Un poco despues, suponemos, el rp está en 0xffea8b0c. Si utilizamos un breakpoint justo después del siguiente gets() podemos ver el offset utilizando una plantilla ciclica:
Ahora podemos utilizar wop0 (una herramienta de radare2) para averiguar el offset de ambos:
El Return Pointer está 16 bytes por detrás del inicio del canario, o lo que es lo mismo, 12 bytes después del canario. Por tanto:
Fuerza Bruta al Canario
Es "posible" en arquitectura de 32 bits pero imposible en 64 bites.
Básicamente consiste en ejecutar el proceso con valores aleatorios para el canario hasta que uno funcione. Esto puede tomar mucho tiempo.
Última actualización