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

Μερικές φορές είναι ενδιαφέρον να 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:

bash
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

Μετά την τροποποίηση του κώδικα μπορείτε να επανασυμπιλοποιήσετε τον κώδικα χρησιμοποιώντας:

bash
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 και κάποιες πληροφορίες που μπορείς να συμπληρώσεις τυχαία):

bash
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>

Τέλος, υπογράψτε το νέο APK:

bash
jarsigner -keystore key.jks path/to/dist/* <your-alias>

Βελτιστοποίηση νέας εφαρμογής

zipalign είναι ένα εργαλείο ευθυγράμμισης αρχείων που παρέχει σημαντική βελτιστοποίηση σε αρχεία εφαρμογών Android (APK). Περισσότερες πληροφορίες εδώ.

bash
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk

Υπογράψτε το νέο APK (ξανά?)

Εάν προτιμάτε να χρησιμοποιήσετε apksigner αντί για jarsigner, θα πρέπει να υπογράψετε το apk αφού εφαρμόσετε τη βελτιστοποίηση με zipaling. ΑΛΛΑ ΣΗΜΕΙΩΣΤΕ ΟΤΙ ΠΡΕΠΕΙ ΝΑ ΥΠΟΓΡΑΨΕΤΕ ΤΗΝ ΕΦΑΡΜΟΓΗ ΜΟΝΟ ΜΙΑ ΦΟΡΑ ΜΕ jarsigner (πριν το zipalign) Ή ΜΕ aspsigner (μετά το zipaling).

bash
apksigner sign --ks key.jks ./dist/mycompiled.apk

Τροποποίηση Smali

Για τον παρακάτω Hello World Java κώδικα:

java
public static void printHelloWorld() {
System.out.println("Hello World")
}

Ο κώδικας Smali θα ήταν:

java
.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, μπορείτε να τροποποιήσετε τις τιμές τους, ή να ορίσετε νέες:

bash
#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"

Βασικές Λειτουργίες

bash
#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

Μεγαλύτερες Αλλαγές

Καταγραφή

bash
#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.

bash
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 ():

smali
.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() σας για να διασφαλίσετε ότι η βιβλιοθήκη φορτώνει όσο το δυνατόν νωρίτερα:

smali
.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.

Αναφορές

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