Smali - Decompiling/[Modifying]/Compiling
Reading time: 8 minutes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Manchmal ist es interessant, den Anwendungscode zu verändern, um für dich versteckte Informationen zu erhalten (z. B. gut obfuskierte Passwörter oder flags). Dann kann es sinnvoll sein, die apk zu dekompilieren, den Code zu ändern und wieder zu kompilieren.
Opcodes-Referenz: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
Schneller Weg
Mit Visual Studio Code und der Erweiterung APKLab kannst du die Anwendung automatically decompile, ändern, recompile, signieren & installieren, ohne einen Befehl auszuführen.
Ein weiteres Skript, das diese Aufgabe stark erleichtert, ist https://github.com/ax/apk.sh
APK dekompilieren
Mit APKTool kannst du auf den smali code und die Ressourcen zugreifen:
apktool d APP.apk
Wenn apktool dir einen Fehler meldet, versuche installing the latest version
Einige interessante Dateien, die du dir ansehen solltest, sind:
- res/values/strings.xml (und alle xml-Dateien in res/values/*)
- AndroidManifest.xml
- Jede Datei mit der Erweiterung .sqlite oder .db
Wenn apktool
Probleme beim Decodieren der Anwendung hat, sieh dir https://ibotpeaches.github.io/Apktool/documentation/#framework-files an oder versuche das Argument -r
zu verwenden (Ressourcen nicht decodieren). Wenn das Problem also in einer Ressource und nicht im Quellcode lag, wirst du das Problem nicht mehr haben (du wirst die Ressourcen dann auch nicht dekompilieren).
Smali-Code ändern
Du kannst Anweisungen ändern, den Wert einiger Variablen ändern oder neue Anweisungen hinzufügen. Ich ändere den Smali-Code mit VS Code, du installierst dann die smalise extension und der Editor zeigt dir, ob eine Anweisung inkorrekt ist.\ Einige Beispiele findest du hier:
Oder du kannst check below some Smali changes explained.
APK neu kompilieren
Nachdem du den Code geändert hast, kannst du den Code rekompilieren mit:
apktool b . #In the folder generated when you decompiled the application
Es wird die neue APK compile innerhalb des dist Ordners.
Wenn apktool einen error wirft, versuche, die latest version zu installieren
Sign the new APK
Anschließend musst du generate a key (du wirst nach einem password und nach einigen Informationen gefragt, die du beliebig ausfüllen kannst):
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>
Zum Schluss das neue APK signieren:
jarsigner -keystore key.jks path/to/dist/* <your-alias>
Neue Anwendung optimieren
zipalign ist ein Tool zur Ausrichtung von Archiven, das wichtige Optimierungen für Android-Anwendungen (APK-Dateien) bereitstellt. Weitere Informationen hier.
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
Signiere die neue APK (nochmals?)
Wenn du lieber apksigner statt jarsigner verwendest, solltest du die APK signieren nachdem du die Optimierung mit zipaling angewendet hast. ABER BEACHTE, DASS DU DIE ANWENDUNG NUR EINMAL DIE ANWENDUNG NUR EINMAL SIGNIEREN MIT jarsigner (vor zipalign) ODER MIT aspsigner (nach zipaling).
apksigner sign --ks key.jks ./dist/mycompiled.apk
Smali ändern
Für den folgenden Hello World Java-Code:
public static void printHelloWorld() {
System.out.println("Hello World")
}
Der Smali-Code wäre:
.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
Das Smali-Instruktionsset ist hier.
Leichte Änderungen
Initialwerte einer Variable innerhalb einer Funktion ändern
Einige Variablen werden am Anfang der Funktion mit dem Opcode const definiert; du kannst deren Werte ändern oder neue definieren:
#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"
Grundlegende Operationen
#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
Größere Änderungen
Logging
#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>"
Empfehlungen:
- Wenn du deklarierte Variablen innerhalb der Funktion verwenden willst (deklarierte v0,v1,v2...) setze diese Zeilen zwischen der .local
und den Deklarationen der Variablen (const v0, 0x1). - Wenn du den Logging-Code in die Mitte des Codes einer Funktion einfügen möchtest:
- Erhöhe die Anzahl der deklarierten Variablen um 2: z. B. von .locals 10 auf .locals 12.
- Die neuen Variablen sollten die nächsthöheren Nummern der bereits deklarierten Variablen sein (in diesem Beispiel sollten es v10 und v11 sein, denk daran, dass es bei v0 beginnt).
- Ändere den Code der Logging-Funktion und verwende v10 und v11 statt v5 und v1.
Toasts
Denk daran, am Anfang der Funktion 3 zur Anzahl der .locals hinzuzufügen.
Dieser Code ist dafür vorbereitet, in die Mitte einer Funktion eingefügt zu werden (ändere die Anzahl der Variablen bei Bedarf). Er nimmt den value of this.o, wandelt ihn in einen String um und zeigt dann einen toast mit dessen Wert an.
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
Laden einer nativen Bibliothek beim Start (System.loadLibrary)
Manchmal müssen Sie eine native Bibliothek vorladen, damit sie sich vor anderen JNI libs initialisiert (z. B. um process-local telemetry/logging zu ermöglichen). Sie können einen Aufruf von System.loadLibrary() in einen statischen Initialisierer oder früh in Application.onCreate() injizieren. Beispiel-smali für einen statischen Klasseninitialisierer (
.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
Alternativ platzieren Sie dieselben zwei Anweisungen am Anfang Ihrer Application.onCreate(), um sicherzustellen, dass die Bibliothek so früh wie möglich geladen wird:
.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
Hinweise:
- Stellen Sie sicher, dass die korrekte ABI-Variante der Bibliothek unter lib/
/ (z. B. arm64-v8a/armeabi-v7a) vorhanden ist, um UnsatisfiedLinkError zu vermeiden. - Sehr frühes Laden (class static initializer) garantiert, dass der native Logger nachfolgende JNI-Aktivität beobachten kann.
Referenzen
- SoTap: Leichter In-App-JNI (.so)-Verhaltenslogger – github.com/RezaArbabBot/SoTap
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.