Hace poco me he interesado por hacer ingeniería inversa prácticamente a todo, y ahora estoy realizando ingeniería inversa a aplicaciones de Android. Y para aprender siempre viene bien recurrir a los crackme :) y la verdad es que no hay muchos por la red, espero hacerlos todos y publicar la solución de cada uno. Tras esta pequeña introducción, ¡comencemos!
Preparativos
Antes de nada:
- Descargamos el Android crackme01 de deurus de la web crackmes.de.
- Y necesitaremos también APKTool para pasar el archivo .apk a smali
- Previamente a esto, deberíais tener el Android SDK, con su emulador, Google APIs…
- Testsign: Es una herramienta de terceros desarrollada para “firmar” o generar certificados aleatorios para indicarle al sistema que el fichero que hemos modificado se trata de una aplicación Android.
Instalación y decompilado
Instalación
Instalo el crackme01 en un dispositivo físico (aunque pueden hacerlo en el simulador).
1
|
adb install crackme01.apk
|
Y una vez instalado, ¡lo probamos para ver que hace!
Probamos a introducir un serial, he probado “mgp25” pero cuando se introduce algo de texto, la aplicación no hace nada, lo que nos hace pensar que el serial será únicamente numérico, así que probamos algo…
Y en el título comprobamos que ahora aparece “Bad boy!”. ¡Bien! Es un primer paso.
Decompilado
Ahora pasaremos el .apk
a smali:
1
|
apktool d crackme01.apk crackme01
|
Ahora se habrá creado una carpeta llamada crackme01 y dentro habrá una que se llama smali, ahi es donde vamos a ir. Vamos al archivo Screen1.smali
y buscamos la cadena de texto “Bad boy!”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
.line 10032
sget-object v0, Lkawa/standard/Scheme;->numGrt:Lgnu/kawa/functions/NumberCompare;
sget-object v1, Lgnu/kawa/reflect/Invoke;->invoke:Lgnu/kawa/reflect/Invoke;
sget-object v2, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit24:Lgnu/mapping/SimpleSymbol;
invoke-static {v2}, Lcom/google/youngandroid/runtime;->lookupInCurrentFormEnvironment(Lgnu/mapping/Symbol;)Ljava/lang/Object;
move-result-object v2
sget-object v3, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit21:Lgnu/mapping/SimpleSymbol;
invoke-virtual {v1, v2, v3}, Lgnu/mapping/Procedure;->apply2(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v1
invoke-static {v1}, Lcom/google/youngandroid/runtime;->sanitizeComponentData(Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v1
sget-object v2, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit35:Lgnu/math/IntNum;
invoke-static {v1, v2}, Lgnu/lists/LList;->list2(Ljava/lang/Object;Ljava/lang/Object;)Lgnu/lists/Pair;
move-result-object v1
sget-object v2, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit36:Lgnu/lists/PairWithPosition;
const-string v3, ">"
invoke-static {v0, v1, v2, v3}, Lcom/google/youngandroid/runtime;->callYailPrimitive(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v0
sget-object v1, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
if-eq v0, v1, :cond_0
sget-object v0, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit0:Lgnu/mapping/SimpleSymbol;
invoke-static {v0}, Lcom/google/youngandroid/runtime;->lookupInCurrentFormEnvironment(Lgnu/mapping/Symbol;)Ljava/lang/Object;
move-result-object v0
sget-object v1, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit13:Lgnu/mapping/SimpleSymbol;
const-string v2, "Crackme01! << by deurus >> - Good boy!"
sget-object v3, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit14:Lgnu/mapping/SimpleSymbol;
invoke-static {v0, v1, v2, v3}, Lcom/google/youngandroid/runtime;->$PcSetAndCoerceProperty$Ex(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v0
:goto_0
return-object v0
:cond_0
sget-object v0, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit0:Lgnu/mapping/SimpleSymbol;
invoke-static {v0}, Lcom/google/youngandroid/runtime;->lookupInCurrentFormEnvironment(Lgnu/mapping/Symbol;)Ljava/lang/Object;
move-result-object v0
sget-object v1, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit13:Lgnu/mapping/SimpleSymbol;
const-string v2, "Crackme01! << by deurus >> - Bad boy!"
sget-object v3, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit14:Lgnu/mapping/SimpleSymbol;
invoke-static {v0, v1, v2, v3}, Lcom/google/youngandroid/runtime;->$PcSetAndCoerceProperty$Ex(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v0
goto :goto_0
|
Análisis
Como podemos observar lo que hace que vaya a “Good boy!” o “Bad boy!” es una simple condición if-eq
. Esta en concreto es una condición sencilla, pero para ejemplos más avanzados, es recomendable echar un ojo a los Dalvik opcodes
Nosotros queremos ir a “Good boy!” y lo importante se encuentra aquí:
1
2
3
|
sget-object v1, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
if-eq v0, v1, :cond_0
|
Solución
Lo primero que se me ocurre, es cambiar el FALSE
y poner un TRUE
, de esa manera no iremos a la condición cond_0 que es la que nos sacará “Bad boy!”.
1
|
sget-object v1, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;
|
Ya tenemos el archivo modificado, ahora toca reconstruir el .apk a partir de nuestras modificaciones.
1
|
apktool b crackme01 crackme01-solucionado.apk
|
Ya tenemos creado el .apk, ahora lo firmamos con testsign.jar
1
|
java -jar testsign.jar crackme01-solucionado.apk
|
Ahora se debería usar zipalign sobre el .apk para que el rendimiento en el dispositivo Android sea el óptimo, pero como no es especialmente importante en este caso, me he saltado este paso, y procedo a instalarlo en el dispositivo.
1
|
adb install crackme01-solucionado.apk
|
¡Lo hemos conseguido! Ahora cualquier número de serie será aceptado y conseguiremos el “Good boy!”. Este crackme era muy sencillo y ya estoy haciendo algunos de más pensar, intentaré publicar todas las soluciones de los crackme que vaya haciendo.
Un saludo :)