AVILX

REVERSING WRITEUP · CRACKMES.ONE · 2026

crackme1 by adamziaja

Keygen via ltrace — alternancia tolower/toupper

Autor retoadamziaja
Plataformacrackmes.one
Dificultad1.0 / 5.0
Arquitecturax86-64 — Unix/Linux
ModoNormal Mode — ltrace + análisis estático
AnalistaJesús Ávila (Avilx)
Fecha07 de Septiembre 2026
Portafolioavilx.dev
SERIAL ENCONTRADO REVERSING · KEYGEN · CRACKME · x86-64

Documentación de aprendizaje en reversing | Entorno controlado

Información del Binario

Campo Valor
Nombrecrackme1
TipoELF 64-bit LSB executable
Arquitecturax86-64
Enlazadodynamically linked
Strippednot stripped (with debug_info)
Stack CanaryNo Canary Found
NXEnabled
PIEPIE Disabled
RELROPartial RELRO
Nota
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
Hallazgo
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.
Hipótesis
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!
Hallazgo
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)
Hallazgo
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'
Hallazgo
_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.
Hallazgo
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

USERNAME: jesussss
SERIAL: 10669115
SERIAL ENCONTRADO
Hallazgo
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 inicial10 minutos
Intento con GDB (fallido)20 minutos
Análisis con ltrace15 minutos
Verificación5 minutos
Total50 minutos