EB Secret, c0r0n4con (iii/iii)

Para depurar en radare, vamos a preparar un poco el entorno. Sabemos que el binario pide un input y muestra por pantalla ciertos outputs. Para poder usar el debugger en estos casos suelo preparar un fichero con el input a pasarle al binario (le llamaré payload) y abrir otra terminal donde poder ver el output. Si usamos screen o tmux, podremos hacerlo en la misma ventana: Ctrl+a+| para hacer split vertical. Ctrl+a+tab para colocarnos en la sección derecha. Ctrl+a+c para crear una nueva región. Ctrl+a+: y tecleamos resize 40 para redimensionar la región. Tecleamos ahora tty para ver el identificador de terminal y lo apuntamos (/dev/pts/3, por ejemplo). Ctrl+a+tab para colocarnos en la sección izquierda. Editamos foo.rr2 con la configuración indicada:

stdio=/dev/pts/3 
stdin=./payload

En payload metemos el input inicial, por ejemplo ABCDEFGHIJK.

radare2 fue el campeón en la lucha ghidra vs. radare

Todo listo para comenzar a darle calor al debugger:

r2 -e dbg.profile=foo.rr2 -d cracked

Recuerda, aaa para analizar flags, strings, funciones… Le costará un rato. Ahora V (visual mode), p (modo desensamblado) , p (igual, pero viendo registros y pila).

:db main breakpoint en el main (intro)

_(buscar referencias), Good (sabemos por los strings que pondrá Good job). Intro. x. radare nos situará sobre el código que comprueba nuestro input.

El binario recibe nuestro input y luego concatena dos strings (strcat + strcat) para comparar el resultado con el input (strcmp). Si coinciden, muestra «Good job» y nuestro input es la flag que buscamos.

Podemos poner otro breakpoint al comienzo de esta sección (con F2 ponemos breakpoints en modo visual, sin tener que teclear «db 0xdirección») y otro tras el segundo strcat. Tecleamos :dc para saltar de breakpoint a breakpoint, analizando registros.

Aquí está el meollo de la cuestión

Tenemos un bucle que itera sobre el input y realiza las siguientes operaciones:

input = [0x41, 0x42, 0x43, ..., 0x49]  # el input que le pasamos
IV = 0x50
flag = ""
for i in range(len(input)):
   if i == 0:
      flag += chr(IV ^ input[i])
   else:
      flag += chr(input[i - 1] ^ input[i])

El resultado final lo compara con esta cadena de bytes:

La cadena de bytes que buscamos {1b,52, 3f,5e ,29,4c, 3a,55 ,33,5f, 3e,59,00,7f}

Así que hay que invertir el algoritmo.

sol = [0x1b, 0x52, 0x3f, 0x5e, 0x29, 0x4c, 0x3a, 0x55, 0x33, 0x5f, 0x3e, 0x59]


idx = 0
left = 0x50
newFileBytes = []
for i in range(0,len(sol)):
  right = sol[idx]
  sig = left ^ right
  print(sig)
  newFileBytes.append(sig)
  left = sol[idx]
  idx = idx + 1


newFile = open("flag.txt", "wb")
newFileByteArray = bytearray(newFileBytes)
newFile.write(newFileByteArray)

Y obtendremos la clave en flag.txt 🙂

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.