Intro
Hoy tenemos un crackme realizado en ensamblador y sin empacar. Consiste en el típico serial asociado a un nombre sin mucha complicación excepto en lo que a la utilización de memoria se refiere. Como veremos más adelante si no tenemos cuidado se solapan en memoria el nombre y el serial y como siempre evitaremos eso.
El algoritmo
Abrimos el crackme con Olly y buscamos las string references, pinchamos sobre cualquiera y encima encontramos el código que no interesa.
Subimos hasta las funciones que recojen el nombre y serial (GetDlgItemTexA) y nos fijamos que guarda el nombre a partir de la dirección de memoria 403014 y el serial a partir de 40301A. Además el nombre debe tener por lo menos tres caracteres.
El algoritmo consiste en lo siguiente, recorre el nombre y comprueba si el dígito se corresponde con 5A(Z), 7A(z) y 39(9). Si coincide los deja como está y si no les suma 1 al valor ascii. A continuación concatena después de cada conversión de dígito el caracter 61(a) aumentándole en 1 para cada nuevo dígito del nombre.
Ejemplo:
Nombre: ZZZZZ Serial: ZaZbZcZdZe Nombre: zzzzz Serial: zazbzczdze Nombre: 99999 Serial: 9a9b9c9d9e
Como veréis a continuación, para el nombre «deuru» el serial correcto sería «eafbvcsdve«. Simplemente a los caracteres del nombre les suma 1, d es e, e es f, u es v, etc, y los concatena con digito+a+digito+b+digito+c…
Nombre: deuru Serial: eafbvcsdve Bucle se repite tantos veces como dígitos tenga el nombre d e u r u 64 65 75 72 75 e a f b v c s d v e 65 61 66 62 76 63 73 64 76 65 DUMP ---- 00403010 00 00 00 00 64 65 75 72 75 00 65 61 66 62 76 63 ....deuru.eafbvc 00403020 73 64 76 65 00 05 00 00 00 00 00 00 00 00 00 00 sdve...........
La asignación de memoria
El problema viene cuando elegimos un nombre >5 caracteres, ya que, éste se solapa con la memoria del serial (recordemos 40301A y siguientes) haciendo que sea una chapuza. En la siguiente imagen queda claro. No se si es un error o es intencionado, pero nos conviene no utilizar nombres mayores de 5 dígitos para que nuestro keygen sea lo más limpio posible.
El KeyGen
Está realizado en C++ y como véis el nombre debe tener entre 3 y 5 dígitos para que todo vaya bien.
char Nombre[10]; GetWindowText(hwndEdit1, Nombre, 10); SetWindowText(hwndEdit2, ""); string serial = ""; int len = strlen(Nombre); char consecutivo[5] = {'a','b','c','d','e'}; if (len <=5 && len >=3){ for(int i = 0; i <= len; i++) { if (Nombre[i] == 0x5A || Nombre[i] == 0x7A || Nombre[i] == 0x39) { serial+=Nombre[i]; serial+=consecutivo[i]; }else{ serial+=Nombre[i]+1; serial+=consecutivo[i]; } } serial = serial.substr(0, len*2); LPCTSTR Sfinal = serial.c_str(); SetWindowText(hwndEdit2, Sfinal); }else{ MessageBox(NULL,"Nombre demasiado largo/corto","Info",MB_OK | MB_ICONINFORMATION); }