by hdbreaker
Walkthrough
Stack1: http://www.secsignal.org/2017/02/walkthrough-stack1-cls.html
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.
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.
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.
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