Si miras bien en la linea 123 hay hay un doCheck este llama a un metodo en la misma clase
LicenseCheck pero que hace realmente este metodo veamos:
.method private doCheck()V
.locals 2
.prologue
.line 106
iget-object v0, p0, Lcom/hpys/crackmes/LicenseCheck;->mChecker:Lcom/android/vending/licensing/LicenseChecker;
iget-object v1, p0, Lcom/hpys/crackmes/LicenseCheck;->mLicenseCheckerCallback:Lcom/android/vending/licensing/LicenseCheckerCallback;
invoke-virtual {v0, v1}, Lcom/android/vending/licensing/LicenseChecker;->checkAccess(Lcom/android/vending/licensing/LicenseCheckerCallback;)V
.line 107
return-void
.end method
Ahora es claro que el metodo doCheck hace la revision, y llama a la clase LicenseChecker y aparentemente le pasa un callback LicenseCheckerCallback probablemente para informar que el licensamiento se realizo de forma correcta. Entonces el paso mas logico ahora sera ir a explorar la clase
com/android/vending/licensing/LicenseChecker
Explorando del LicenseChecker
Antes de empezar a leer todo el LicenseChecker y sus derivados, mejor ve directamente a la invocacion del metodo checkAccess que es el que invoca la clase LicenseCheck recuerdas?.
invoke-virtual {v0, v1}, Lcom/android/vending/licensing/LicenseChecker;->checkAccess(Lcom/android/vending/licensing/LicenseCheckerCallback;)V
Probablemente este metodo nos proporcione mejores pista que cualquier otro por que es donde se lleva acabo la revision de la licencia.
El metodo checkAccess, es bastante grande así que procurare resumir las partes relevantes, por ejemplo:
# virtual methods
.method public declared-synchronized checkAccess(Lcom/android/vending/licensing/LicenseCheckerCallback;)V
.locals 9
.parameter "callback"
.prologue
.line 133
monitor-enter p0
:try_start_0
iget-object v1, p0, Lcom/android/vending/licensing/LicenseChecker;->mPolicy:Lcom/android/vending/licensing/Policy;
invoke-interface {v1}, Lcom/android/vending/licensing/Policy;->allowAccess()Z
move-result v1
if-eqz v1, :cond_0
.line 134
const-string v1, "LicenseChecker"
if-eqz v1, :cond_0 esta condicion es muy importante por que en caso de cumplirse te envia a cond_0 y mas abajo indica que es la instanciacion del validador de licencias. Si nos saltamos esta parte tendremos el ejercicio terminado!!. Es bien facil de hacer esta condicion tiene una operacion antagonica la cual es:
if-nez vx,target asi que al cambiar las operaciones deberia funcionar.
Pero no funciona.... ¬¬
Si, si, cambiamos esta linea y ejecutamos el paso de recompilación de codigo y reempaquetamiento (lo explicare luego), el reto nos regala un obstaculo adicional, al pasar la licencia el MyAndroidAppActivity no parece invocar al metodo onCreate, y te genera el siguiente error en
logcat:
¿Así que pasa? ¿por que no funciona?, Bueno la respuesta del por que no funciona es clara la clase MyAndroidAppActivity no tiene la invocación al metodo onCreate hara falta agregarselo con
backsmali.
.class public Lcom/hpys/crackmes/MyAndroidAppActivity;
.super Lcom/hpys/crackmes/LicenseCheck;
.source "MyAndroidAppActivity.java"
# direct methods
.method public constructor ()V
.locals 0
.prologue
.line 6
invoke-direct {p0}, Lcom/hpys/crackmes/LicenseCheck;->()V
return-void
.end method
# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
.locals 0
.parameter "savedInstanceState"
.prologue
.line 11
invoke-super {p0, p1}, Lcom/hpys/crackmes/LicenseCheck;->onCreate(Landroid/os/Bundle;)V
.line 15
return-void
.end method
El codigo anterior demuestra muchas faltas en la clase MyAndroidAppActivity, siendo un codigo pequeño y sencillo es facil reconocerlas todas:
- El metodo onCreate no llama al super.onCreate.
- El metodo onCreate tampoco tiene layout asignado deberia tener main.xml con setContentView.
- La clase MyAndroidAppActivity hereda de LicenseCheck en vez de Activity y tambien en el metodo init se hace la invocacion especial a este metodo.
Aqui el codigo del MyAndroidAppActivity con las fallas anteriores resueltas:
.class public Lcom/hpys/crackmes/MyAndroidAppActivity;
.super Landroid/app/Activity;
.source "MyAndroidAppActivity.java"
# direct methods
.method public constructor ()V
.locals 0
.prologue
.line 6
invoke-direct {p0}, Landroid/app/Activity;->()V
return-void
.end method
# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
.locals 1
.parameter "savedInstanceState"
.prologue
.line 15
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
.line 17
const/high16 v0, 0x7f03
invoke-virtual {p0, v0}, Lcom/hpys/crackmes/MyAndroidAppActivity;->setContentView(I)V
.line 20
return-void
.end method
Podemos realizar los siguientes apuntes, como la invocacion del metodo
onCreate() y de
setContentView con la variable
v0, en este tienes que tener sumo cuidado en declarar
locals 1 que es el numero de variables que utilizaras.
¿Ya terminamos?, algo así lo unico que falta es recompilarlo y empaquetarlo para regresarlo a un APK.
De regreso a un APK
A como mencione inicialmente
apktool tambien te permite recompilar la aplicación y regresarla a un APK, pero vas a necesitara un poco mas de eso para colocarla devuelta en el telefono. Para recompilar la aplicacion ejecuta el comando:
$ apktool b out crackemecracked.apk
Tambien necesitas firmarlo, para ello necesitas de un keystore, puedes crearlo facilmente con
keytool
$ keytool -genkey -v -keystore my-release-key.keystore
Ahora ya tienes tu keystore para firmar tu aplicacion
jarsigner -verbose -keystore keystore.keystore crackemecracked.apk crackmecracked
Si deseas saber mas de como firmar aplicaciones android desde consola no te olvides pasar por la
documentación oficial.
Ahora si tenemos la aplicacion firmada, es muy sencillo desintalarla y volverla instalar con el adb.
$ adb uninstall com.hpys.crackmes
$ adb install crackemecracked-za.apk
Si todo esta bien, la imagen que deberia aparecer es la siguiente:
Y LISTO!!
¿Algunos Tips adicionales ?
En lo particular nunca habia realizado esto, y la informacion de como modificar codigo backsmali no es muy amplia, pero es posible y no es tan dificil.
- Te recomiendo que veas algo de codigo Assembler por que es similar al backsmali basicamente son operadores y cambios registros.