AVILX
REVERSING WRITEUP · CRACKMES.ONE · 2026
crackme1 by adamziaja
Keygen via ltrace — alternancia tolower/toupper
| Autor reto | adamziaja |
| Plataforma | crackmes.one |
| Dificultad | 1.0 / 5.0 |
| Arquitectura | x86-64 — Unix/Linux |
| Modo | Normal Mode — ltrace + análisis estático |
| Analista | Jesús Ávila (Avilx) |
| Fecha | 07 de Septiembre 2026 |
| Portafolio | avilx.dev |
Documentación de aprendizaje en reversing | Entorno controlado
Información del Binario
| Campo | Valor |
|---|---|
| Nombre | crackme1 |
| Tipo | ELF 64-bit LSB executable |
| Arquitectura | x86-64 |
| Enlazado | dynamically linked |
| Stripped | not stripped (with debug_info) |
| Stack Canary | No Canary Found |
| NX | Enabled |
| PIE | PIE Disabled |
| RELRO | Partial RELRO |
Sin PIE significa que las direcciones son fijas, lo que facilita el análisis con GDB. Sin canary el stack no está protegido. El binario tiene debug_info y símbolos completos (104 símbolos).
Reconocimiento
Análisis inicial
Strings
$ strings -a ./crackme1 | grep -v "^_Z\|GLIBC\|\.so\|\."
[Mensajes del programa]
username:
username must be between 8 and 12!
serial number:
s/n OK!
s/n WRONG!
[Variables relevantes]
serialstring
serialstring2
usernamelength
serial
username
[Funciones relevantes]
tolower
toupper
strcmp
A diferencia de los crackmes anteriores, no hay password hardcodeado. El programa pide un username y un serial number. El username debe tener entre 8 y 12 caracteres. Las funciones
tolower y toupper sugieren que el serial se genera transformando el username. Las variables serialstring y serialstring2 indican que hay dos strings involucrados en el cálculo.El serial se genera a partir del username aplicando
tolower y toupper de forma alternada por posición. El resultado se convierte a valores ASCII que forman el serial. El siguiente paso es usar ltrace para capturar las llamadas a funciones en runtime y ver exactamente cómo se construye el serial.Ejecución inicial
$ ./crackme1
username:
jesussss
serial number:
12
s/n WRONG!
$ ./crackme1
username:
jesus
username must be between 8 and 12!
El username
jesus (5 caracteres) es rechazado. El username jesussss (8 caracteres) es aceptado pero el serial 12 es incorrecto. El programa valida la longitud antes de procesar el serial.Análisis del Flujo
Análisis con ltrace
ltrace intercepta las llamadas a funciones de librería en tiempo de ejecución y muestra sus argumentos y valores de retorno. Es ideal para entender cómo el programa procesa el input sin necesitar analizar el assembly completo.
$ ltrace ./crackme1 | grep -E "strcmp|tolower|toupper"
# Con username=jesussss, serial=12345
tolower('j') = 'j' # posicion 0 (par) -> minuscula
toupper('e') = 'E' # posicion 1 (impar) -> mayuscula
tolower('s') = 's' # posicion 2 (par)
toupper('u') = 'U' # posicion 3 (impar)
tolower('s') = 's' # posicion 4 (par)
toupper('s') = 'S' # posicion 5 (impar)
tolower('s') = 's' # posicion 6 (par)
toupper('s') = 'S' # posicion 7 (impar)
El programa alterna
tolower y toupper por posición: posiciones pares usan tolower y posiciones impares usan toupper. Para jesussss el resultado es jEsUssSS.Construcción del serial
El ltrace también capturó las llamadas al operador += de std::string que construye el serial:
_ZNSspLEc(0x..., 49, ...) # agrega ASCII 49 = '1'
_ZNSspLEc(0x..., 48, ...) # agrega ASCII 48 = '0'
_ZNSspLEc(0x..., 54, ...) # agrega ASCII 54 = '6'
_ZNSspLEc(0x..., 54, ...) # agrega ASCII 54 = '6'
_ZNSspLEc(0x..., 57, ...) # agrega ASCII 57 = '9'
_ZNSspLEc(0x..., 49, ...) # agrega ASCII 49 = '1'
_ZNSspLEc(0x..., 49, ...) # agrega ASCII 49 = '1'
_ZNSspLEc(0x..., 53, ...) # agrega ASCII 53 = '5'
_ZNSspLEc es el operador += de std::string en C++. El segundo argumento es el valor ASCII del carácter que se agrega al serial. Leyendo los 8 valores en orden: 49 48 54 54 57 49 49 53 = 10669115.El serial para el username
jesussss es 10669115. Cada carácter del serial es el dígito ASCII del carácter transformado del username. El ltrace permitió leer el serial construido sin necesidad de analizar el assembly completo.Solución
Algoritmo identificado
El programa toma el username, alterna tolower/toupper por posición (par/impar), y construye el serial concatenando los valores ASCII de cada carácter transformado.
Verificación
$ ./crackme1
username:
jesussss
serial number:
10669115
s/n OK!
Serial encontrado
SERIAL: 10669115
SERIAL ENCONTRADO
El serial
10669115 fue verificado exitosamente con el username jesussss. El programa respondió: “s/n OK!”Reflexión Final
Qué salió bien
El uso de ltrace fue la técnica clave. Interceptar las llamadas a tolower, toupper y el operador += de std::string permitió entender el algoritmo y extraer el serial sin analizar el assembly completo.
Qué salió mal
El primer intento con GDB falló con SIGSEGV al poner breakpoints en medio del loop de procesamiento. El binario de 2016 tiene compatibilidad limitada con versiones modernas de GDB. ltrace fue la alternativa correcta para este caso.
Lecciones aprendidas
Este crackme introdujo el concepto de keygen: el serial no está hardcodeado sino que se calcula a partir del username. Para cada username diferente el serial será diferente.
ltrace es una herramienta muy eficiente para crackmes con algoritmos de generación de serial. Captura las llamadas a funciones de librería con sus argumentos exactos, permitiendo reconstruir el algoritmo sin analizar assembly.
La diferencia entre los valores ASCII y los caracteres que representan fue un aprendizaje clave: el valor 49 no es el número 49 sino el carácter ’1’ en ASCII.
Tiempo total
| Fase | Tiempo |
|---|---|
| Reconocimiento inicial | 10 minutos |
| Intento con GDB (fallido) | 20 minutos |
| Análisis con ltrace | 15 minutos |
| Verificación | 5 minutos |
| Total | 50 minutos |