A veces quieres sentarte a hacer reversing sin que te explote la cabeza. Para eso están los crackmes de dificultad 1. Este es babyFirstCrackme, de idanhajbeko, subido a crackmes.one (ID 680d04208f555589f3530fb5): un ELF de 64 bits en C que te pide una contraseña y te dice si está bien. Lo resolvemos de tres maneras distintas, de la más perezosa a la más “correcta”.
Primer contacto
Antes de abrir nada pesado, mira qué tienes entre manos:
file babyFirstCrackme
# babyFirstCrackme: ELF 64-bit LSB pie executable, x86-64, dynamically linked, not stripped
not stripped es buena señal: conserva los nombres de funciones. Lo ejecutas para ver el comportamiento:
./babyFirstCrackme
# Enter the password:
# test
# Wrong password! (en rojo)
Pide una contraseña, la compara y responde. Clásico.
Camino 1: strings
La vía rápida. Si la contraseña está escrita tal cual en el binario (spoiler: lo está), strings la saca:
strings babyFirstCrackme | grep -i -E 'pass|w0rd|@|!'
Entre el ruido aparece una cadena que canta a contraseña: !_-P@$$w0rD-_!. En un crackme de nivel 1 esto suele ser suficiente, pero no te dice por qué es la contraseña. Vamos a confirmarlo.
Sí, era así de fácil. No se lo cuentes a nadie y di que te costó toda la tarde.
Camino 2: ltrace
ltrace traza las llamadas a librería. Como la comparación la hace strcmp, verás los dos argumentos uno al lado del otro:
ltrace ./babyFirstCrackme
# printf("Enter the password:\n")
# ...
# strcmp("test", "!_-P@$$w0rD-_!") = -1
# puts("Wrong password!")
Ahí está, en bandeja: el programa compara tu entrada contra !_-P@$$w0rD-_!. No hace falta ni abrir un desensamblador.
Camino 3: Ghidra
Para entender el flujo de verdad, lo abres en Ghidra, importas el binario, dejas que lo analice y te vas a main. El decompilado es directo:
undefined8 main(void) {
char local_3f8 [1000];
printf("Enter the password:\n");
__isoc99_scanf(&DAT_...,local_3f8);
if (strcmp(local_3f8,"!_-P@$$w0rD-_!") == 0) {
getFlag(); // imprime la flag en verde
} else {
// "Wrong password!" en rojo
}
return 0;
}
No hay XOR, ni aritmética, ni ofuscación: una comparación directa contra la cadena incrustada. La contraseña es literalmente !_-P@$$w0rD-_!.
./babyFirstCrackme
# Enter the password:
# !_-P@$$w0rD-_!
# Correct! Here is your flag: (en verde)
El bonus de las pistas
El reto trae un segundo binario con las pistas, y ese sí tiene un poquito de chicha: un XOR para que practiques. La operación es 0x4D2 ^ 0x30 = 0x4E2, que en decimal es 1250. Nada del otro mundo, pero es la excusa perfecta para abrir la calculadora de Python y recordar que XOR es reversible:
>>> 0x4D2 ^ 0x30
1250
Conclusión
babyFirstCrackme no pretende ser difícil, y está bien que así sea: sirve para mecanizar el flujo file → ejecutar → strings/ltrace → Ghidra antes de meterte en binarios que sí se defienden. La lección que vale para retos más serios es que una contraseña comparada en claro con strcmp no protege absolutamente nada; está dentro del binario y cualquiera con cinco minutos la saca. Cuando empieces a ver strcmp sustituido por comprobaciones byte a byte, hashes o rutinas de descifrado, es cuando empieza lo divertido.