WRITEUP CTF CaixaBank Tech - RETO 7 #
Ejecución del binario #
Al descargar el desafío, nos proporcionan un binario llamado “crackme”. Le damos permisos de ejecución utilizando el siguiente comando.
chmod +x crackme
Una vez hemos otorgado los permisos, ejecutamos el binario para ver qué contiene en su interior:
Como vemos, al ejecutarlo nos pide que introduzcamos una contraseña para poder ejecutarlo correctamente.
Visualización de cadenas legibles #
Vamos a utilizar la utilidad strings antes que nada para ver si podemos encontrar alguna cadena que nos llame la atención:
Como observamos, hay algunas cadenas de texto interesantes, entre ellas las siguientes:
- Welcome to the bank platform!
- Enter your the secret key:
- Congratulations! You now have access to the plaftorm!
- Wrong key. I hope you are not a bank thief!
- ABCDEFGH
- IJKLMNOP
- QRSTUVWX
- YZabcdef
- ghijklmn
- opqrstuv
- wxyz0123
- 456789+/
- PDY7PSEx
- aSMFLGko
- GkoIwUpa
- TkoaS4n
- xor_encrypt
- base64_encrypt
Uso de ltrace #
Ahora vamos a utilizar la herramienta ltrace para poder ver más a fondo el programa y su funcionamiento interno:
Aquí podemos ver que cuando ponemos la contraseña “prueba”, el programa obtiene su longitud y también la convierte en hexadecimal:
strlen("prueba") = 6
strdup("prueba") = 0x5b0d828fcb40
Luego lo pasa a una cadena de texto y la compara con otra:
strcpy(0x5b0d828fcb40, "KigvPzg7") = 0x5b0d828fcb40
strcmp("KigvPzg7", "PDY7PSExaSMFLGkoIwUpaTkoaS4n")
Analizando el binario con Ghidra #
Habiendo visto esto, vamos a usar la herramienta Ghidra para ver el binario por dentro:
Abrimos la función “main”:
- Solicita una clave secreta al usuario.
- Verifica la clave utilizando una función externa (
verify_key
). - Informa al usuario si la clave es correcta o incorrecta.
Vemos que nos pregunta la clave y la almacena en local_10, también vemos que llama a otra función verify_key
, vamos a ver la función verify_key
para ver como identifica y si es válida o no:
La función verify_key
realiza los siguientes pasos:
- Inicializa una serie de variables con valores específicos en hexadecimal.
- Duplica la clave proporcionada.
- Cifra la clave duplicada llamdo a otras funciones (
xor_encrypt
,base64_encrypt
) - Compara la clave cifrada con un valor interno predefinido.
- Retorna
true
si la clave cifrada coincide con el valor predefinido, yfalse
en caso contrario.
Esto es muy interesante ya que el valor con el que lo compara lo hemos podido ver antes con ltrace
:
PDY7PSExaSMFLGkoIwUpaTkoaS4n
Solo nos queda decodificar esta cadena de la forma en la que codifica la clave que nosotros proporcionamos, para esto vamos a ver las funciones xor_encrypt
y base64_encrypt
:
La función base64_encrypt
simplemente encodea en base64
La función xor_encrypt
:
Aplica la operación XOR entre el byte actual y el valor 0x5a
Creación del script para decodificar la cadena #
Ahora que ya hemos visto como funciona la codificación vamos a hacer un script aplicando esto pero al reves para decodificarlo:
import base64
# Las cadenas codificadas en base64 que se comparan con la entrada del usuario
encoded_strs = ["PDY7PSExaSMFLGkoIwUpaTkoaS4n"]
# La clave original
key = ""
# Para cada cadena codificada en base64
for encoded_str in encoded_strs:
# Decodificar la cadena de base64
decoded_str = base64.b64decode(encoded_str).decode('utf-8', 'ignore')
# Realizar la operación XOR para obtener la parte de la clave original
for i in range(len(decoded_str)):
# Convertir cada carácter a su valor ASCII
ascii_val = ord(decoded_str[i])
# Realizar la operación XOR con 0x5a
xor_val = ascii_val ^ 0x5a
# Convertir el valor resultante de nuevo a un carácter
char = chr(xor_val)
# Comprobar si el carácter es imprimible
if char.isprintable():
# Añadir el carácter a la clave
key += char
print("La flag es: " + key)
Ejecutamos el script:
Verificamos que sea esta:
Ya tenemos la Flag!