Smali - Descompilar/[Modificar]/Compilar
Reading time: 8 minutes
tip
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
A veces es interesante modificar el código de la aplicación para acceder a información oculta para ti (quizá contraseñas bien ofuscadas o flags). Entonces, puede ser interesante descompilar el APK, modificar el código y recompilarlo.
Opcodes reference: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
Método rápido
Usando Visual Studio Code y la extensión APKLab, puedes descompilar automáticamente, modificar, recompilar, firmar e instalar la aplicación sin ejecutar ningún comando.
Otro script que facilita mucho esta tarea es https://github.com/ax/apk.sh
Descompile el APK
Usando APKTool puedes acceder al código smali y los recursos:
apktool d APP.apk
Si apktool te da algún error, intenta installing the latest version
Algunos archivos interesantes que deberías revisar son:
- res/values/strings.xml (and all xmls inside res/values/*)
- AndroidManifest.xml
- Any file with extension .sqlite or .db
Si apktool
tiene problemas decoding the application echa un vistazo a https://ibotpeaches.github.io/Apktool/documentation/#framework-files o prueba usando el argumento -r
(No decodificar los recursos). Entonces, si el problema estaba en un recurso y no en el código fuente, no tendrás ese problema (tampoco decompilarás los recursos).
Cambiar código smali
Puedes change instructions, cambiar el value de algunas variables o add nuevas instrucciones. Yo modifico el código Smali usando VS Code, luego instalas la smalise extension y el editor te dirá si alguna instruction is incorrect.
Some examples can be found here:
O puedes check below some Smali changes explained.
Recompilar el APK
Después de modificar el código puedes recompile el código usando:
apktool b . #In the folder generated when you decompiled the application
Se compilará el nuevo APK dentro de la carpeta dist.
Si apktool lanza un error, prueba installing the latest version
Firmar el nuevo APK
Luego, necesitas generar una clave (se te pedirá una contraseña y algunos datos que puedes rellenar aleatoriamente):
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>
Finalmente, firma el nuevo APK:
jarsigner -keystore key.jks path/to/dist/* <your-alias>
Optimizar la nueva aplicación
zipalign es una herramienta de alineación de archivos que proporciona una optimización importante a los archivos de aplicación Android (APK). More information here.
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
Firma el nuevo APK (¿otra vez?)
Si prefieres usar apksigner en lugar de jarsigner, deberías firmar el apk después de aplicar la optimización con zipaling. PERO TEN EN CUENTA QUE SOLO TIENES QUE FIRMAR LA APLICACIÓN UNA VEZ CON jarsigner (antes de zipalign) O CON aspsigner (después de zipaling).
apksigner sign --ks key.jks ./dist/mycompiled.apk
Modificando Smali
Para el siguiente código Java Hello World:
public static void printHelloWorld() {
System.out.println("Hello World")
}
El código Smali sería:
.method public static printHelloWorld()V
.registers 2
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "Hello World"
invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
return-void
.end method
El conjunto de instrucciones de Smali está disponible here.
Cambios ligeros
Modificar los valores iniciales de una variable dentro de una función
Algunas variables se definen al principio de la función usando el opcode const; puedes modificar sus valores o definir nuevas:
#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"
Operaciones básicas
#Math
add-int/lit8 v0, v2, 0x1 #v2 + 0x1 and save it in v0
mul-int v0,v2,0x2 #v2*0x2 and save in v0
#Move the value of one object into another
move v1,v2
#Condtions
if-ge #Greater or equals
if-le #Less or equals
if-eq #Equals
#Get/Save attributes of an object
iget v0, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Save this.o inside v0
iput v0, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Save v0 inside this.o
#goto
:goto_6 #Declare this where you want to start a loop
if-ne v0, v9, :goto_6 #If not equals, go to: :goto_6
goto :goto_6 #Always go to: :goto_6
Cambios mayores
Registro
#Log win: <number>
iget v5, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Get this.o inside v5
invoke-static {v5}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; #Transform number to String
move-result-object v1 #Move to v1
const-string v5, "wins" #Save "win" inside v5
invoke-static {v5, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I #Logging "Wins: <num>"
Recomendaciones:
- Si vas a usar variables declaradas dentro de la función (declaradas v0,v1,v2...) coloca estas líneas entre la .local
y las declaraciones de las variables (const v0, 0x1) - Si quieres poner el logging en medio del código de una función:
- Suma 2 al número de variables declaradas: Ej: de .locals 10 a .locals 12
- Las nuevas variables deben ser los siguientes números de las ya declaradas (en este ejemplo deben ser v10 y v11, recuerda que empieza en v0).
- Cambia el código de la función de logging y usa v10 y v11 en lugar de v5 y v1.
Toasting
Recuerda sumar 3 al número de .locals al inicio de la función.
Este código está preparado para ser insertado en el medio de una función (cambia el número de las variables según sea necesario). Tomará el valor de this.o, lo transformará a String y luego hará un toast con su valor.
const/4 v10, 0x1
const/4 v11, 0x1
const/4 v12, 0x1
iget v10, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I
invoke-static {v10}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
move-result-object v11
invoke-static {p0, v11, v12}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v12
invoke-virtual {v12}, Landroid/widget/Toast;->show()V
Cargar una librería nativa al iniciar (System.loadLibrary)
A veces necesitas precargar una librería nativa para que se inicialice antes que otras JNI libs (p. ej., para habilitar telemetría/registro local del proceso). Puedes inyectar una llamada a System.loadLibrary() en un inicializador estático o al inicio de Application.onCreate(). Ejemplo smali para un inicializador de clase estática (
.class public Lcom/example/App;
.super Landroid/app/Application;
.method static constructor <clinit>()V
.registers 1
const-string v0, "sotap" # library name without lib...so prefix
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
return-void
.end method
Como alternativa, coloca las mismas dos instrucciones al inicio de tu Application.onCreate() para asegurar que la biblioteca se cargue lo antes posible:
.method public onCreate()V
.locals 1
const-string v0, "sotap"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
invoke-super {p0}, Landroid/app/Application;->onCreate()V
return-void
.end method
Notas:
- Asegúrate de que la variante ABI correcta de la biblioteca exista bajo lib/
/ (p. ej., arm64-v8a/armeabi-v7a) para evitar UnsatisfiedLinkError. - Cargar muy pronto (inicializador estático de clase) garantiza que el logger nativo pueda observar la actividad JNI posterior.
Referencias
- SoTap: logger ligero in-app de comportamiento JNI (.so) – github.com/RezaArbabBot/SoTap
tip
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.