Nuevas Entradas

Walkthrough Stack2 CLS Exploits

by hdbreaker

Con la debida autorización de Ricardo Narvaja y los agradecimientos respectivos al grupo CrackLatinos se da comienzo al solucionario del ejercicio Stack2 del grupo CLS Exploits.

Enunciado:

Autor: Ricardo Narvaja
----------------------

Abrir el idb en ida y tratar de entender y mirar estaticamente el programa. Mirar la distancia exacta que se necesita para pisar la primera cookie y para pisar la segunda y ponerla en el mail que me envian armar el script correcto y enviarmelo para que yo lo pruebe. Entre las cosas que se enviaron para bajar hay un esqueleto de script en python que puede servir cualquier duda ir al canal de telegram de exploit que alli estan en grupo trabajando en esto.

IDB: stack2.idb 
Binario: stack2.exe

Una vez listos procedemos a analizar estaticamente el IDB con IDA PRO y analizar su función principal:


En la dirección 0x004012D6 comienza la sección que nos interesa:


Lo que sucede aqui es exactamente lo mismo que sucedía en el ejercicio Stack1:

En esta dirección podemos apreciar cómo el offset Format que contiene el string buf: %08x cookie: %08x\n se mueve dentro del puntero [esp+78+Format], esto es una forma de pushear un argumento al stack, ya que el mismo será utilizado por la función printf en la dirección 0x004012DD, la cual se encarga de mostrar un mensaje en pantalla con el formato especificado.

En la dirección 0x004012E2 podemos ver cómo la instrucción lea eax, [ebp+Buffer] coloca el valor al que referencia el puntero [ebp+Buffer] en eax, el cual luego es movido al puntero [esp+78+Format] en la dirección 0x004012E5, el cual identificamos como un push al stack anteriormente.

Este valor es enviado como argumento de la función gets, la cual es vulnerable a overflow ya que no valida el largo del buffer donde escribe, en relación con la entrada dada por el usuario.

Luego del llamado a la función gets en la dirección 0x004012ED, se encuentra la siguiente comparación: 

cmp [ebp+var_14], 71727374

La misma modificará la conducta del salto condicional que se encuentra en la dirección 0x004012F4: jnz short loc_401323 (jz es equivalente a je)

Si la condición no se cumple (jmp if not equal) el salto condicional nos llevará al basic block que comienza en la dirección 0x00401323 el cual termina en un retn y concluye la aplicación.

Si la condición se cumple la aplicación sigue un flujo normal y llega al basic block que comienza en la dirección 0x004012F6, la cual checkea que el puntero [ebp+var_C] sea igual al valor 0x91929394.

Si la condición no se cumple (jmp if not equal) el salto condicional nos llevara al basic block que comienza en la dirección 0x00401323 el cual termina en un retn y concluye la aplicación.

Caso contrario la aplicación sigue su flujo normal y llega al basic block que comienza en la dirección 0x004012FF, en el que se genera y muestra el mensaje q estamos buscando.




La secuencia de eventos anteriores puede imaginarse como el siguiente código en C


if ( var_14 == 0x71727374) {
if( var_C == 0x91929394 ) {
printf("flag %x", &v7);
printf("you are a winnner man je\n");
}
} 

system("PAUSE");
return 0;

Habiendo analizado el programa, el objetivo sería explotar la vulnerabilidad existente en la función gets con el fin de sobrescribir el valor de var_14 y de var_C por los esperados en cada comparación y de esta forma guiar el flujo de ejecución hacia el basic block que muestra el mensaje buscado.

Como en el ejercicio anterior verificaremos el tamaño de Buffer y la cantidad de bytes necesarios al finalizar Buffer para sobrescribir las variables necesarias:


1) Nos colocaremos sobre la variable Buffer y daremos doble click, esto nos situara en la vista Stack Frame View, nos situamos sobre Buffer, realizamos click derecho sobre Buffer e ingresamos en el submenu Array.




En esta ventana entran en juego 2 elementos Array element size y Array size, el tamaño del Buffer es equivalente a la multiplicación de estos 2 elementos, debido a que Array element size en este caso es 1 el tamaño de Buffer es igual a 68 bytes. Es importante destacar que debemos cerrar esta ventana clickeando el botón Cancelar.

Teniendo en cuenta lo anterior, sabes que para desbordar Buffer debemos enviar un string mayor a 68 bytes, pero esto no es suficiente, debemos desbordar el buffer hasta el punto que logremos sobrescribir el valor del contenido en var_14 y var_C.


Para calcular cuántos bytes más debemos enviar, debemos bajar en el Stack Frame View hasta localizarnos en la próxima variable adyacente a Buffer.


Con esta información podemos apreciar que este ejercicio tiene 2 posibles soluciones:

1) Sobrescribir 68 bytes + 4 bytes (var_14 = 0x71727374) + 4 bytes (var_10 = JUNK) + 4 bytes (var_C = 0x91929394 )


2) Sobrescribir 68 bytes + 4 bytes (var_14) + 4 bytes (var_10) + 4 bytes (var_C) + 8 bytes + 4 bytes (s => ebp) + 4 bytes (r => eip)


Dicho esto se decidió solucionar el ejercicio de la primera forma:

. Sobrescribir 68 bytes + 4 bytes (var_14 = 0x71727374) + 4 bytes (var_10 = JUNK) + 4 bytes (var_C = 0x91929394 )


import struct
from subprocess import Popen, PIPE

stdin = Popen("stack2.exe", stdin=PIPE, stdout=PIPE) 

buffer = "\x90" * 68 # Buffer length
var_14 = struct.pack("<I", 0x71727374)
var_10 = "JUNK"
var_C = struct.pack("<I", 0x91929394)
payload = buffer + var_14 + var_10 + var_C # => jmp if not equal

print "[#] Sending Payload"
stdout = stdin.communicate(payload)[0]
print stdout

Resultado:



Sin más me despido hasta traerles la solución del próximo ejercicio.


Saludos!

Share this:

 
Copyright © 2014 Security Signal.
Designed by OddThemes | Distributed By Gooyaabi Templates