12 KiB
Smali - Dekompilowanie/[Modyfikowanie]/Kompilowanie
Dowiedz się, jak hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć swoją firmę reklamowaną w HackTricks lub pobrać HackTricks w formacie PDF, sprawdź SUBSCRIPTION PLANS!
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do HackTricks i HackTricks Cloud github repos.
Czasami interesujące jest zmodyfikowanie kodu aplikacji, aby uzyskać dostęp do ukrytych informacji (może to być dobrze zaszyfrowane hasła lub flagi). W takim przypadku warto zdekompilować plik apk, zmodyfikować kod i ponownie go skompilować.
Odwołanie do instrukcji: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
Szybki sposób
Korzystając z Visual Studio Code i rozszerzenia APKLab, można automatycznie dekompilować, modyfikować, rekompilować, podpisać i zainstalować aplikację bez wykonywania żadnych poleceń.
Innym skryptem, który bardzo ułatwia to zadanie, jest https://github.com/ax/apk.sh
Dekompilacja APK
Korzystając z APKTool, można uzyskać dostęp do kodu smali i zasobów:
apktool d APP.apk
Jeśli apktool wyświetla jakikolwiek błąd, spróbuj zainstalować najnowszą wersję.
Niektóre interesujące pliki, na które powinieneś zwrócić uwagę, to:
- res/values/strings.xml (oraz wszystkie xml-e wewnątrz res/values/*)
- AndroidManifest.xml
- Dowolny plik z rozszerzeniem .sqlite lub .db
Jeśli apktool
ma problemy z dekodowaniem aplikacji, zajrzyj na stronę https://ibotpeaches.github.io/Apktool/documentation/#framework-files lub spróbuj użyć argumentu -r
(Nie dekoduj zasobów). Wtedy, jeśli problem występował w zasobie, a nie w kodzie źródłowym, nie będziesz mieć tego problemu (nie zdekodujesz również zasobów).
Zmiana kodu smali
Możesz zmieniać instrukcje, zmieniać wartość niektórych zmiennych lub dodawać nowe instrukcje. Ja zmieniam kod Smali za pomocą VS Code, następnie instalujesz rozszerzenie smalise i edytor powie Ci, czy któraś instrukcja jest niepoprawna.
Kilka przykładów można znaleźć tutaj:
Możesz również sprawdzić poniżej wyjaśnienia niektórych zmian w Smali.
Ponowne skompilowanie APK
Po zmodyfikowaniu kodu możesz ponownie skompilować kod za pomocą:
apktool b . #In the folder generated when you decompiled the application
Skompiluje nowy plik APK wewnątrz folderu dist.
Jeśli apktool wygeneruje błąd, spróbuj zainstalować najnowszą wersję.
Podpisz nowy plik APK
Następnie musisz wygenerować klucz (zostaniesz poproszony o hasło i pewne informacje, które możesz wypełnić losowo):
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>
W końcu, podpisz nowy plik APK:
jarsigner -keystore key.jks path/to/dist/* <your-alias>
Optymalizacja nowej aplikacji
zipalign to narzędzie do wyrównywania archiwów, które zapewnia ważne optymalizacje plików aplikacji Android (APK). Więcej informacji tutaj.
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
Podpisz nowy APK (ponownie?)
Jeśli wolisz używać apksigner zamiast jarsigner, powinieneś podpisać apk po zastosowaniu optymalizacji za pomocą zipalign. ALE ZWRÓĆ UWAGĘ, ŻE MUSISZ PODPISAĆ APLIKACJĘ TYLKO RAZ Z jarsigner (przed zipalign) LUB Z aspsigner (po zipalign).
apksigner sign --ks key.jks ./dist/mycompiled.apk
Modyfikowanie Smali
Dla następującego kodu Hello World w języku Java:
public static void printHelloWorld() {
System.out.println("Hello World")
}
Kod Smali będzie wyglądał następująco:
.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
Zestaw instrukcji Smali jest dostępny tutaj.
Lekkie zmiany
Modyfikowanie początkowych wartości zmiennej wewnątrz funkcji
Niektóre zmienne są definiowane na początku funkcji za pomocą opcode'u const, możesz zmieniać ich wartości lub definiować nowe:
#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"
Podstawowe operacje
Tworzenie nowej klasy
Aby utworzyć nową klasę w pliku Smali, należy utworzyć nowy plik o rozszerzeniu .smali
i umieścić go w odpowiednim katalogu zgodnie z hierarchią pakietów. Następnie należy zdefiniować nazwę klasy, używając dyrektywy .class
i określić dziedziczenie, jeśli jest to konieczne, za pomocą dyrektywy .super
.
Przykład:
.class public Lcom/example/MyClass;
.super Ljava/lang/Object;
Dodawanie pól
Aby dodać pole do klasy, należy użyć dyrektywy .field
i określić modyfikatory dostępu, typ pola oraz jego nazwę.
Przykład:
.field private static myField:I
Dodawanie metod
Aby dodać metodę do klasy, należy użyć dyrektywy .method
i określić modyfikatory dostępu, typ zwracany, nazwę metody oraz listę argumentów. Następnie należy zdefiniować ciało metody, używając instrukcji Smali.
Przykład:
.method public static myMethod(II)I
.registers 3
add-int v0, p0, p1
return v0
.end method
Dodawanie instrukcji
Aby dodać instrukcję do metody, należy użyć odpowiedniej instrukcji Smali, takiej jak move
, add-int
, invoke-static
, itp. Instrukcje Smali są podobne do instrukcji Javy, ale mają nieco inną składnię.
Przykład:
add-int v0, p0, p1
Modyfikowanie istniejących instrukcji
Aby zmodyfikować istniejącą instrukcję w metodzie, należy znaleźć odpowiednią instrukcję w pliku Smali i zmienić jej argumenty lub operacje. Można to zrobić, edytując plik Smali ręcznie lub za pomocą narzędzi do automatycznego modyfikowania plików Smali.
Przykład:
invoke-static {p0}, Landroid/util/Log;->d(Ljava/lang/String;)I
Usuwanie instrukcji
Aby usunąć instrukcję z metody, należy znaleźć odpowiednią instrukcję w pliku Smali i usunąć ją. Można to zrobić, edytując plik Smali ręcznie lub za pomocą narzędzi do automatycznego modyfikowania plików Smali.
Przykład:
return-void
Dodawanie adnotacji
Aby dodać adnotację do klasy, pola lub metody, należy użyć dyrektywy .annotation
i określić typ adnotacji oraz jej parametry.
Przykład:
.annotation system Ldalvik/annotation/EnclosingClass;
value = Lcom/example/MyClass;
.end annotation
#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
Większe zmiany
Rejestrowanie działań
#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>"
Rekomendacje:
- Jeśli zamierzasz używać zadeklarowanych zmiennych wewnątrz funkcji (zadeklarowane v0,v1,v2...), umieść te linie między .local <number> a deklaracjami zmiennych (const v0, 0x1)
- Jeśli chcesz umieścić kod logowania w środku kodu funkcji:
- Dodaj 2 do liczby zadeklarowanych zmiennych: np. z .locals 10 na .locals 12
- Nowe zmienne powinny mieć kolejne numery po już zadeklarowanych zmiennych (w tym przykładzie powinny to być v10 i v11, pamiętaj, że zaczynamy od v0).
- Zmień kod funkcji logowania i użyj v10 i v11 zamiast v5 i v1.
Toastowanie
Pamiętaj, aby dodać 3 do liczby .locals na początku funkcji.
Ten kod jest przygotowany do wstawienia w środku funkcji (zmień liczbę zmiennych według potrzeb). Będzie on pobierał wartość this.o, przekształcał ją na String i następnie wyświetlał tost z jej wartością.
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
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć reklamę swojej firmy w HackTricks lub pobrać HackTricks w formacie PDF, sprawdź PLAN SUBSKRYPCJI!
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na GitHubie.