De 0 a exploiting (VI)

Buenas amigos, como ya sabéis soy Fare9, y vengo con otra entrada de "De 0 a exploiting", aquellos posts que van de eso de buscar vulnerabilidades en software, ya sabéis. Hoy tengo una técnica que más o menos se parece a la vista en el anterior post. Esta técnica se llama "Off-By-One", en la cual en lugar de poder modificar todo el valor de EBP, podemos modificar máximo 1 Byte.

antes de nada, ya sabemos, los preparativos:
###############################################

Desactivar la aleatoriedad en las direcciones de la pila, para ello debeis ejecutar el comando (como root):
echo 0 > /proc/sys/kernel/randomize_va_space

Compilar (hoy si) con:
gcc -g -fno-stack-protector -z execstack codigo.c -o programa

###############################################
(sabéis que Fare9, hace copy-paste siempre con los preparativos del anterior post...)


Bien, vamos a ver un código en C, con el cual intentaremos entender esto:

Como vemos, el código es muy parecido al que vimos en el post anterior, pero esta vez, en el límite en lugar de sumar 4 sumamos 1, y el objetivo es que al comparar "cookie" con 0xdefaced, salga lo mismo.
Bien "off-by-one" es referido a que esta vez, sobreescribimos 1 byte, con lo cual intentaremos que eso juege a nuestro favor.
En este reto es interesante ver como se realiza la comparación de "cookie" con 0xdefaced:
Ejecutamos el programa con cualquier argumento y dentro de nuestro debugger visual edb.
Después de navegar un poco por el código, vemos que la comparación es la siguiente, que se compara "cookie", pero esta variable se referencia como [ebp-28] y resulta que un byte de EBP lo podemos modificar (el último byte) ...

Bien, vamos a volver a ejecutar y veamos el valor de EBP que se metió en la pila a la hora de realizar el stack frame (recordais de anteriores posts, el stack frame), vamos mirando por la pila y lo tenemos antes de un return:

Vemos que ebp ha metido en la pila el valor "bffff168" (tenemos además luego la dirección de retorno y  el argumento que hemos pasado esta vez), pues el 68, lo podremos modificar, a nuestro antojo. Nuestro objetivo será, modificar ese 68, por ejemplo por 'A' o 41 en valor ASCII, y si le restamos 28 ([ebp-28]) tenemos que la dirección que se usará para comparar es:

bfff:f141 - 1Ch (valor 28 en hexadecimal) = bfff:f125

Bien la dirección donde tendrá que estar el 0xdefaced es bfff:f125, ahora veremos donde empieza a copiar nuestros valores, para ello ejecutamos realizamos un par de veces el bucle for, y vemos donde empieza a copiar, no hay más dificultad (guiño guiño):
Como vemos, empezó a copiarse en bfff:f030, y que podemos llegar a escribir hasta bfff:f135 (el lugar donde se realiza el off-by-one), bfff:f125 está entre medias...
Ahora realizamos los siguientes pasos:

  1. Calcular cuanta basura tenemos que meter antes de meter el 0xdefaced:
     bfff:f125 - bfff:f030 = f5h = 245 bytes 
  2. Meter 0xdefaced 
  3. Meter más basura hasta el último byte que meteremos una 'A' (yo meto un montón de 'A's y que se encargue el programa de parar, por tanto nunca falla).
Vamos entonces a montar un programita exploit en python:
 Con el método pack, de struct, pasamos el 0xdefaced a Little-endian, luego como vemos metemos 245 'A' antes del defaced y luego todo 'A' de basura. 
Ejecutemos y veamos que pasa en la pila (podemos establecer un breakpoint en el leave de la función, así el bucle for se ejecuará completo):
 Breakpoint en el leave, para ejecutar el for.
Vemos que al comienzo del buffer se han metido un montón de 'A's
Al final del buffer, hemos modificado el último byte que se metará en EBP, con una 'A', ahora vale bffff141.
Y como vemos, en bfff:f125, se empieza a meter defaced, al contrario (pues estamos en Little-Endian) y con un 0 al final, ya que para tener un total de 8 bytes había que meter eso. Por tanto se ha metido ed, ac, ef, 0d (Recordemos que son números en hexadecimal, no letras).
Sigamos ejecutando y veamos en qué acaba la comparación:
Vemos que, vamos a realizar la comparación y el debugger, ya nos muestra abajo el valor de la dirección de memoria [ebp-28]... Vaya parece que es 0x0defaced (como dijo Nostradamus). Por tanto la comparación sale correcta y tachaaaan, conseguimos una shell.
Bien, para ejecutarlo directamente en shell, vamos a comentar el primer os.system... y descomentar el segundo del código del exploit y ejecutamos:

Como vemos, ya tenemos nuestra rica shell. Para el programador que se le pasó por una:

Hasta aquí el post de "De 0 a exploiting" de hoy, en el siguiente post ya veremos "Return to libc", algo que cuando lo vi por primera vez, me pareció muy muy interesante.

Nos vemos en los próximos post de Fare9
--------------------------------------------------------FIN

Share this

Related Posts

Previous
Next Post »