Ingeniería inversa Android Crackme02 de deurus

  • crackme01 de deurus solucionado aquí

  • Pueden descargar el crackme02 de deurus aquí

Como siempre, antes de empezar a trastear con el código vamos a ver como es el programa:

normal

Tenemos dos campos a introducir, uno el nombre y otro el serial, dos botones (‘Check!’ y otro ‘Exit’). Procedo a introducir un nombre y un serial cualquiera, y pulsamos ‘Check!’:

fallo1

Como podemos ver, al introducir un nombre y un serial que no es correcto, la pantalla se muestra en rojo. Pues vayamos al código, ¡a ver que encontramos!

Lo primero será pasarlo a smali. Tras comprobar un rato el smali, sé podría ver el código desde el smali pero sería bastante laborioso, así que mejor lo pasamos a un nivel más alto, y con la herramienta dex2jar, pasamos el classes.dex a un empaquetado .jar del cual extraeremos los archivos .class. Para descompilar los archivos .class he utilizado esta herramienta. Y analizamos el código, hasta que observamos dónde se genera el serial:

public Object Button1_check$Click()
{
runtime.addToCurrentFormEnvironment(Lit12, Lit28);
runtime.addToCurrentFormEnvironment(Lit14, Lit11);
if (runtime.isYailEqual(runtime.sanitizeComponentData(Invoke.invoke.apply2(runtime.lookupInCurrentFormEnvironment(Lit37), Lit22)), "") != Boolean.FALSE)
{
runtime.callComponentMethod(Lit53, Lit54, LList.list3("Please Enter the Name", "Error", "Ok"), Lit55);
runtime.$PcSetAndCoerceProperty$Ex(runtime.lookupInCurrentFormEnvironment(Lit37), Lit22, "", Lit20);
return runtime.$PcSetAndCoerceProperty$Ex(runtime.lookupInCurrentFormEnvironment(Lit47), Lit22, "", Lit20);
}
while (runtime.callYailPrimitive(Scheme.numLEq, LList.list2(runtime.lookupInCurrentFormEnvironment(Lit12), runtime.callYailPrimitive(strings.string$Mnlength, LList.list1(runtime.sanitizeComponentData(Invoke.invoke.apply2(runtime.lookupInCurrentFormEnvironment(Lit37), Lit22))), Lit56, "length")), Lit57, "<=") != Boolean.FALSE)
{
runtime.addToCurrentFormEnvironment(Lit10, runtime.callComponentMethod(Lit58, Lit59, LList.list1(runtime.callComponentMethod(Lit58, Lit60, LList.Empty, LList.Empty)), Lit61));
runtime.addToCurrentFormEnvironment(Lit14, runtime.callYailPrimitive(AddOp.$Pl, LList.list2(runtime.lookupInCurrentFormEnvironment(Lit14), runtime.callYailPrimitive(MultiplyOp.$St, LList.list2(runtime.lookupInCurrentFormEnvironment(Lit10), runtime.lookupInCurrentFormEnvironment(Lit12)), Lit62, "*")), Lit63, "+"));
runtime.addToCurrentFormEnvironment(Lit14, runtime.callYailPrimitive(AddOp.$Pl, LList.list2(runtime.lookupInCurrentFormEnvironment(Lit14), runtime.callYailPrimitive(numbers.modulo, LList.list2(runtime.lookupInCurrentFormEnvironment(Lit14), Lit64), Lit65, "modulo")), Lit66, "+"));
runtime.addToCurrentFormEnvironment(Lit12, runtime.callYailPrimitive(AddOp.$Pl, LList.list2(runtime.lookupInCurrentFormEnvironment(Lit12), Lit28), Lit67, "+"));
}
if (runtime.isYailEqual(runtime.sanitizeComponentData(Invoke.invoke.apply2(runtime.lookupInCurrentFormEnvironment(Lit47), Lit22)), runtime.lookupInCurrentFormEnvironment(Lit14)) != Boolean.FALSE) {
return runtime.$PcSetAndCoerceProperty$Ex(runtime.lookupInCurrentFormEnvironment(Lit0), Lit16, Lit68, Lit18);
}
return runtime.$PcSetAndCoerceProperty$Ex(runtime.lookupInCurrentFormEnvironment(Lit0), Lit16, Lit69, Lit18);
}

Lo primero de todo tenemos esto:

runtime.addToCurrentFormEnvironment(Lit12, Lit28);
runtime.addToCurrentFormEnvironment(Lit14, Lit11);

Que es equivalente a dar valores a las variables. De tal forma:

tam_nombre = 1
temp = 0

Lit12 es “tam_nombre” y lit28 es IntNum.make(1). De la misma manera, será la variable temp.

Podemos apreciar la condición ‘if’, la cual nos mostrará un error (‘Please Enter the Name’) si no introducimos un nombre.

Luego podemos ver otra condición, ‘while’. numLEq significa <=. La condición es la siguiente:

while(tam_nombre <= len(nombre))

Es decir, si no utilizamos la variable ‘nombre’ sino la longitud de ese string, el serial sólo dependerá de esta longitud, por lo que el nombre deja de ser relevante.

De la misma manera, atribuímos valores dentro de las condición ‘while’. Las operaciones se sacan leyendo la secuencia. La variable ‘ano’ es el año actual.

temp += ano * tam_nombre
temp += temp % 1638 # temp mod(1638)
tam_nombre += 1

Una vez que sale del bucle while. El serial es el resultado guardado en la variable ‘temp’.

Por lo que el keygen que hice sería así:

#!/usr/bin/python

import sys
from datetime import date

tam_nombre = 1
temp = 0
ano = date.today().year

print '''
######################################
#                                    #
#    Keygen for crackme02 deurus     #
#                                    #
######################################

Author: @_mgp25 - github.com/mgp25 - mgp25.com

'''

if len(sys.argv) < 2:
	sys.exit("Usage: python serial.py <name>\n")
else:
	nombre = sys.argv[1]

def generateSerial(nombre, tam_nombre, ano, temp):
	if nombre == "":
		sys.exit("Enter a valid name")
	else:
		while tam_nombre <= len(nombre):
			temp += ano * tam_nombre
			temp += temp % 1638
			tam_nombre += 1

		print "Your serial is",  temp

generateSerial(nombre, tam_nombre, ano, temp)

Ahora utilizamos el keygen para generar un serial válido para mi nombre:

keygen

Ya que hemos obtenido el serial, lo probamos en el crackme02.

exito1

¡Perfecto! Ya hemos completado el crackme02 :) Pero esto no termina aquí, ahora a parte del keygen, modificaremos el bytecode para que acepte cualquier serial.

Si nos fijamos, después del bucle while, hay una condición if, que comprueba si el serial es correcto. Ahora nos vamos al archivo Screen1.smali, y buscamos esa condición:

Linea 4282


sget-object v1, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;

if-eq v0, v1, :cond_2

Esta es la condición que hace que vaya a mostrar la pantalla roja, o la pantalla verde. Solo cambiamos el FALSE por un TRUE. Quedaría así:

sget-object v1, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;

Construímos el nuevo .apk, lo firmamos y lo instalamos:

instalarSolucion

Y ahora probamos, el serial y el nombre que probamos al comienzo:

exitoSolucion

¡Perfecto! :D Pues ya hemos completado totalmente este crackme02 de deurus.

Como la última vez, os dejo el crackme parcheado para que lo probéis vosotros mismos:

crackme02-solved.apk - Descargar

SHA1 Checksum: fa4553bf0fa80fe4095da1b86f547c79

Un saludo y hasta la próxima :)

Updated: