Smali - Decompiling/[Modifying]/Compiling
Reading time: 8 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Μερικές φορές είναι ενδιαφέρον να modify τον κώδικα της εφαρμογής για να αποκτήσετε κρυφές πληροφορίες (ίσως καλά obfuscated passwords ή flags). Τότε, μπορεί να είναι χρήσιμο να decompile το apk, να modify τον κώδικα και να recompile αυτό.
Opcodes reference: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
Γρήγορος Τρόπος
Χρησιμοποιώντας Visual Studio Code και την επέκταση APKLab, μπορείτε να automatically decompile, modify, recompile, sign & install την εφαρμογή χωρίς να εκτελέσετε καμία εντολή.
Ένα άλλο script που διευκολύνει πολύ αυτή την εργασία είναι https://github.com/ax/apk.sh
Decompile the APK
Χρησιμοποιώντας APKTool μπορείτε να έχετε πρόσβαση στον smali code and resources:
apktool d APP.apk
Αν το apktool σας δώσει κάποιο σφάλμα, δοκιμάστε installing the latest version
Κάποια ενδιαφέροντα αρχεία που πρέπει να κοιτάξετε είναι:
- res/values/strings.xml (and all xmls inside res/values/*)
- AndroidManifest.xml
- Οποιοδήποτε αρχείο με επέκταση .sqlite ή .db
Αν το apktool
έχει προβλήματα στην αποκωδικοποίηση της εφαρμογής ρίξτε μια ματιά στο https://ibotpeaches.github.io/Apktool/documentation/#framework-files ή δοκιμάστε να χρησιμοποιήσετε το όρισμα -r
(μην αποκωδικοποιήσετε τα resources). Τότε, αν το πρόβλημα ήταν σε ένα resource και όχι στον πηγαίο κώδικα, δεν θα έχετε το πρόβλημα (επίσης δεν θα αποσυμπιλοποιήσετε τα resources).
Αλλαγή κώδικα smali
Μπορείτε να αλλάξετε εντολές, να αλλάξετε την τιμή ορισμένων μεταβλητών ή να προσθέσετε νέες εντολές. Εγώ αλλάζω τον κώδικα Smali χρησιμοποιώντας VS Code, στη συνέχεια εγκαθιστάτε το smalise extension και ο editor θα σας πει αν κάποια εντολή είναι λανθασμένη.
Μερικά παραδείγματα μπορείτε να βρείτε εδώ:
Ή μπορείτε check below some Smali changes explained.
Επανασυγκρότηση του APK
Μετά την τροποποίηση του κώδικα μπορείτε να επανασυμπιλοποιήσετε τον κώδικα χρησιμοποιώντας:
apktool b . #In the folder generated when you decompiled the application
Θα compile το νέο APK inside τον φάκελο dist.
Αν apktool εμφανίσει ένα error, δοκίμασε installing the latest version
Sign the new APK
Έπειτα, χρειάζεται να generate a key (θα σου ζητηθεί να δώσεις password και κάποιες πληροφορίες που μπορείς να συμπληρώσεις τυχαία):
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>
Τέλος, υπογράψτε το νέο APK:
jarsigner -keystore key.jks path/to/dist/* <your-alias>
Βελτιστοποίηση νέας εφαρμογής
zipalign είναι ένα εργαλείο ευθυγράμμισης αρχείων που παρέχει σημαντική βελτιστοποίηση σε αρχεία εφαρμογών Android (APK). Περισσότερες πληροφορίες εδώ.
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
Υπογράψτε το νέο APK (ξανά?)
Εάν προτιμάτε να χρησιμοποιήσετε apksigner αντί για jarsigner, θα πρέπει να υπογράψετε το apk αφού εφαρμόσετε τη βελτιστοποίηση με zipaling. ΑΛΛΑ ΣΗΜΕΙΩΣΤΕ ΟΤΙ ΠΡΕΠΕΙ ΝΑ ΥΠΟΓΡΑΨΕΤΕ ΤΗΝ ΕΦΑΡΜΟΓΗ ΜΟΝΟ ΜΙΑ ΦΟΡΑ ΜΕ jarsigner (πριν το zipalign) Ή ΜΕ aspsigner (μετά το zipaling).
apksigner sign --ks key.jks ./dist/mycompiled.apk
Τροποποίηση Smali
Για τον παρακάτω Hello World Java κώδικα:
public static void printHelloWorld() {
System.out.println("Hello World")
}
Ο κώδικας Smali θα ήταν:
.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
Το σύνολο εντολών Smali είναι διαθέσιμο here.
Ελαφρές αλλαγές
Τροποποίηση αρχικών τιμών μιας μεταβλητής μέσα σε μια συνάρτηση
Κάποιες μεταβλητές ορίζονται στην αρχή της συνάρτησης χρησιμοποιώντας την opcode const, μπορείτε να τροποποιήσετε τις τιμές τους, ή να ορίσετε νέες:
#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"
Βασικές Λειτουργίες
#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
Μεγαλύτερες Αλλαγές
Καταγραφή
#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>"
Recommendations:
- Αν πρόκειται να χρησιμοποιήσετε δηλωμένες μεταβλητές μέσα στη συνάρτηση (declared v0,v1,v2...) τοποθετήστε αυτές τις γραμμές ανάμεσα στο .local
και στις δηλώσεις των μεταβλητών (const v0, 0x1) - If you want to put the logging code in the middle of the code of a function:
- Προσθέστε 2 στον αριθμό των δηλωμένων μεταβλητών: Ex: from .locals 10 to .locals 12
- Οι νέες μεταβλητές πρέπει να είναι οι επόμενοι αριθμοί των ήδη δηλωμένων μεταβλητών (σε αυτό το παράδειγμα πρέπει να είναι v10 και v11, θυμηθείτε ότι ξεκινά σε v0).
- Αλλάξτε τον κώδικα της logging function και χρησιμοποιήστε v10 και v11 αντί για v5 και v1.
Toasting
Να θυμάστε να προσθέσετε 3 στο νούμερο των .locals στην αρχή της συνάρτησης.
This code is prepared to be inserted in the middle of a function (change the number of the variables as necessary). It will take the value of this.o, transform it to String and them make a toast with its value.
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
Φόρτωση Native Library κατά την Εκκίνηση (System.loadLibrary)
Μερικές φορές χρειάζεται να προφορτώσετε μια native library ώστε να αρχικοποιηθεί πριν από άλλες JNI libs (π.χ., για να ενεργοποιηθεί process-local telemetry/logging). Μπορείτε να εισάγετε μια κλήση προς System.loadLibrary() σε έναν static initializer ή νωρίς στο Application.onCreate(). Παράδειγμα smali για 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
Εναλλακτικά, τοποθετήστε τις ίδιες δύο εντολές στην αρχή του Application.onCreate() σας για να διασφαλίσετε ότι η βιβλιοθήκη φορτώνει όσο το δυνατόν νωρίτερα:
.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
Σημειώσεις:
- Βεβαιωθείτε ότι η σωστή ABI παραλλαγή της βιβλιοθήκης υπάρχει στο lib/
/ (π.χ. arm64-v8a/armeabi-v7a) για να αποφευχθεί το UnsatisfiedLinkError. - Το φόρτωμα πολύ νωρίς (class static initializer) εγγυάται ότι ο native logger μπορεί να παρατηρήσει την επακόλουθη δραστηριότητα JNI.
Αναφορές
- SoTap: Ελαφρύ in-app logger συμπεριφοράς για JNI (.so) – github.com/RezaArbabBot/SoTap
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.