Smali - Decompilare/[Modificare]/Compilare
Reading time: 8 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
A volte è interessante modificare il codice dell'applicazione per accedere a informazioni nascoste per te (magari password ben offuscate o flags). In questo caso può essere utile decompilare l'apk, modificare il codice e ricompilarlo.
Riferimento opcodes: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
Metodo veloce
Usando Visual Studio Code e l'estensione APKLab, puoi decompilare automaticamente, modificare, ricompilare, firmare & installare l'applicazione senza eseguire alcun comando.
Un altro script che facilita molto questo compito è https://github.com/ax/apk.sh
Decompilare l'APK
Usando APKTool puoi accedere al codice smali e alle risorse:
apktool d APP.apk
Se apktool ti dà un errore, prova a installare la ultima versione
Alcuni file interessanti da controllare sono:
- res/values/strings.xml (and all xmls inside res/values/*)
- AndroidManifest.xml
- Any file with extension .sqlite or .db
Se apktool
ha problemi a decodificare l'applicazione dai un'occhiata a https://ibotpeaches.github.io/Apktool/documentation/#framework-files oppure prova a usare l'argomento -r
(Non decodificare le risorse). In questo modo, se il problema era in una risorsa e non nel codice sorgente, non avrai il problema (e non decompilerai nemmeno le risorse).
Modificare il codice smali
Puoi modificare le istruzioni, cambiare il valore di alcune variabili o aggiungere nuove istruzioni. Io modifico il codice Smali usando VS Code, poi installi l'smalise extension e l'editor ti dirà se qualche istruzione è errata.\
Alcuni esempi possono essere trovati qui:
Oppure puoi controllare sotto alcuni cambiamenti Smali spiegati.
Ricompilare l'APK
Dopo aver modificato il codice puoi ricompilare il codice usando:
apktool b . #In the folder generated when you decompiled the application
Questo compilerà il nuovo APK all'interno della cartella dist.
Se apktool genera un errore, prova a installare la versione più recente
Firma il nuovo APK
Poi devi generare una chiave (ti verrà chiesto di inserire una password e alcune informazioni che puoi compilare a caso):
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>
Infine, firma il nuovo APK:
jarsigner -keystore key.jks path/to/dist/* <your-alias>
Ottimizzare la nuova applicazione
zipalign è uno strumento di allineamento di archivi che fornisce un'importante ottimizzazione per Android application (APK) files. Maggiori informazioni qui.
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
Firma il nuovo APK (di nuovo?)
Se preferisci usare apksigner invece di jarsigner, dovresti firmare l'apk dopo aver applicato l'ottimizzazione con zipaling. MA NOTA CHE DEVI FIRMARE L'APPLICAZIONE UNA SOLA VOLTA CON jarsigner (prima di zipalign) O CON aspsigner (dopo zipaling).
apksigner sign --ks key.jks ./dist/mycompiled.apk
Modificare Smali
Per il seguente codice Java Hello World:
public static void printHelloWorld() {
System.out.println("Hello World")
}
Il codice Smali sarebbe:
.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
Il set di istruzioni Smali è disponibile qui.
Modifiche leggere
Modificare i valori iniziali di una variabile all'interno di una funzione
Alcune variabili sono definite all'inizio della funzione usando l'opcode const; puoi modificarne i valori, oppure definirne di nuovi:
#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"
Operazioni di base
#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
Modifiche principali
Registrazione dei log
#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>"
Raccomandazioni:
- Se intendi usare variabili dichiarate all'interno della funzione (dichiarate v0,v1,v2...) inserisci queste righe tra .local
e le dichiarazioni delle variabili (const v0, 0x1) - Se vuoi inserire il codice di logging nel mezzo del codice di una funzione:
- Aggiungi 2 al numero di variabili dichiarate: Es: da .locals 10 a .locals 12
- Le nuove variabili dovrebbero essere i numeri successivi rispetto alle variabili già dichiarate (in questo esempio saranno v10 e v11, ricorda che si parte da v0).
- Modifica il codice della funzione di logging e usa v10 e v11 invece di v5 e v1.
Toasting
Ricorda di aggiungere 3 al numero di .locals all'inizio della funzione.
Questo codice è pronto per essere inserito nel mezzo di una funzione (modifica il numero delle variabili se necessario). Prenderà il valore di this.o, lo trasformerà in String e poi mostrerà un toast con il suo valore.
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
Caricamento di una libreria nativa all'avvio (System.loadLibrary)
A volte è necessario precaricare una libreria nativa in modo che si inizializzi prima di altre librerie JNI (ad es., per abilitare telemetria/logging locale al processo). Puoi iniettare una chiamata a System.loadLibrary() in un static initializer o all'inizio di Application.onCreate(). Esempio smali per un static class initializer (
.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
In alternativa, posiziona le stesse due istruzioni all'inizio del tuo Application.onCreate() per assicurarti che la libreria venga caricata il prima possibile:
.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
Note:
- Assicurati che la variante ABI corretta della libreria esista sotto lib/
/ (ad es., arm64-v8a/armeabi-v7a) per evitare UnsatisfiedLinkError. - Il caricamento molto precoce (class static initializer) garantisce che il native logger possa osservare l'attività JNI successiva.
Riferimenti
- SoTap: Logger leggero in-app del comportamento JNI (.so) – github.com/RezaArbabBot/SoTap
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.