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.
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.
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.
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:
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 🙂