Nombre:Crackme edu
Dificultad:1-2
Compilador:Visual Basic
Autor del crack:$Edu$
Cargamos el crackme desde OllyDBG, Notamos claramente que es un Visual Basic 6.0:
Veamos las API'S que utiliza el crackme (Ctrl+N):
Notaremos dos API'S muy interesantes coloquemos BP'S en ellas:
La primera se encarga de comparar string's y la segunda se encarga de obtener el número de caracteres de una string, las veremos más detalladamente a continuación mientras vayamos desarrollando el tutorial
Iniciamos el crackme (F9) e introducimos ID,SERIAL y luego verificar:
Vemos que se detiene en la API __vbaStrCmp:
Llegamos hasta la call __vbaStrComp, si nos fijamos en el stack podremos ver la comparación que se va a realizar (arg2 con arg3) notaremos que comprueba el serial falso con 0, por lo que lo más probable es que esté comprobando que si es que NO introdujimos algún valor.(para ver los datos que compara debemos hacer click derecho en alguno de los dos argumentos y seleccionar follow in dump):
Pasando la call __vbaStrComp y estando detenidos en RETN 8 veremos que EAX=1 por lo que deducimos que la API __vbaStrCmp retornará 1 si es que los string comparados no son iguales:
Luego mueve el valor de EAX a EDX y luego de algunas operaciones toma el EDX(1)y lo mueve dentro de [EBP-E4] :
Ahora realizará los mismos pasos pero con la string ID:
Compara 0 con la ID que introdujimos esto devolverá 1 al retornar de la CALL:
una vez realizada las mismas operaciones mueve respectivamente ambos valores obtenidos de las llamadas a __vbaStrCmp (Ambos retornaron 1) a EAX y ECX:
realizando un TEST EAX,ECX:
Sabemos que la única forma de que no se active el flag Z (para que salte) es que EAX y ECX sean 1 con lo cual contamos de manera correcta
Si no se cumpliera nos mostrará un mensaje diciendo que debemos ingresar los datos
Si continuamos traceando el programa hará un llamado a la API __vbaLenBstr:
retornando la call EAX contiene el número de caracteres del serial que en este caso son 4 (serial falso:1234):
Continuando se llamará nuevamente a la API:
en esta nos retornará el valor 5 ya que UND3R contiene 5 caracteres
Luego se realiza una comparación entre EAX y ECX en donde EAX es el largo de la ID y ECX el largo del serial, notaremos que si no se realiza el salto obtendremos como resultado que el serial es incorrecto, para que pueda saltar el serial no puede ser mayor(más largo) que el ID en este caso cumplimos con el requisito:
Luego de esto no creo que se utilice nuevamente la API __vbaLenBstr debido a que ya se ha calculado el largo que hemos ingresado tanto del serial y del ID por lo que lo borraremos:
Ahora si damos nuevamente F9 se detiene en la API __vbaStrCmp:
si pusheamos hasta el call __vbaStrComp y miramos el stack notaremos que se está comparando 1 con Z, siendo 1 el primer digito que introdujimos en el serial falso:
Retornando de la API EAX toma el valor de FFFFFFFF y este es movido a ESI para luego pasar por un TEST SI,SI
:
en donde la única forma de que no salte es que ESI=0, por lo que podemos colocar un BP en el salto JNZ e introducir como serial Z234 o modificar el flag Z para que no salte ya que si salta notaremos se dirigirá a la string "Serial incorrecto"
Si seguimos traceando llegaremos a la siguiente address:
previamente vemos una comparación que es 1 con 3 en donde saltará si lo que está en DI sea mayor a 3, si vemos hacia donde salta notaremos que es hacia el cartel de que el serial es correcto, aquí veo un posible pequeño bug en la programación del crackme ya lo comentaré
[EBP-D0]:
Si seguimos traceando sin alterar el salto que nos dirige al cartel de serial correcto llegaremos hasta la siguiente address:
Si bajamos un poco notaremos un salto que anteriormente habíamos pasado por el, lo más probable es que tengamos a continuación la manera de como el crackme obtuvo la letra Z como respuesta correcta para el primer carácter del serial. obviamente en este caso obtendremos el valor del segundo carácter correcto:
Lleguemos hasta la siguiente address:
Aquí notamos algo muy interesante si miramos el registro y el OP-Code del address en donde estamos detenidos:
Sabemos que ECX apunta a nuestro ID, aquí moverá a DX el valor de ECX+2 por lo que moverá el segundo carácter a DX que en este caso es una N:
Quedando EDX con de la siguiente manera:
luego a EDX le suma 5, una vez sumado mueve a EAX el valor de DX y lo pushea para la API __vbaStrCmp:
luego llega nuevamente a una comprobación que es la misma en la que nos detuvimos cuando se comparó 1 con Z:
si vemos en el stack notaremos la comparación entre nuestro segundo caracter del serial con S:
Por lo que ya contamos con la fórmula y de alguna manera el entendimiento de como trabaja el crackme
Resumimos:
-verifica que ambas cajas de textos no estén vacías
-luego verifica que el SERIAL introducido no sea mayor a la ID
-luego toma el primer carácter del serial y le suma 5
-compara el resultado del primer carácter+5 con el primer carácter del serial
-luego continua sucesivamente con un contador que es hasta el tercer carácter
-Cumpliéndose los 3 primeros caracteres obtendremos el cartel de serial correcto
Aquí el problema de $Edu$, quizás es intencional pero la comprobación es solo hasta el tercer carácter por lo que podríamos colocar tan solo 3 caracteres este sería el pequeño bug del crackme
UND3R
U=55+5=Z
N=4e+5=S
D=44+5=I
3=3+5=8
R=52+5=W
Otra forma de crackearlo es nopear el salto que viene a continuación de la comparación del serial ya que si recordamos $Edu$ colocó un contador que si se pasa por el por tercera vez es considerado el serial como correcto:
Saludos a $Edu$
EDIT:
Adjunto el keygen hecho en OllyScript:
Código
VAR CONT VAR VMEMORY VAR SIZE VAR AUX VAR RESP PREG: ASK "Introduzca su ID" MOV RESP,$RESULT LEN RESP MOV SIZE,$RESULT ALLOC 100 MOV VMEMORY,$RESULT MOV VMEMORY2,VMEMORY CMP VMEMORY,0 JE ERROR1 MOV [VMEMORY],RESP OPERACION: CMP CONT,SIZE JE EXIT MOV AUX,[VMEMORY],1 ADD AUX,5 MOV [VMEMORY],AUX,1 INC VMEMORY INC CONT JMP OPERACION ERROR: MSG "Debe ingresar un serial" JMP PREG ERROR1: MSG "Error inesperado" RET EXIT: MOV AUX,[VMEMORY2], SIZE BUF AUX STR AUX EVAL "ID:{RESP} SERIAL:{AUX}" MSG $RESULT FREE VMEMORY2 RET