Smali - Decompiling/[Modifying]/Compiling

Reading time: 8 minutes

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Dit is soms interessant om die toepassingskode te wysig om toegang tot verborge inligting te kry (byvoorbeeld goed versluierde wagwoorde of flags). Dan kan dit handig wees om die apk te dekompileer, die kode te wysig en dit weer saam te stel.

Opcodes reference: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html

Fast Way

Met Visual Studio Code en die APKLab uitbreiding kan jy die toepassing automaties dekompileer, die kode wysig, weer saamstel, teken & installeer sonder om enige opdrag uit te voer.

Another script that facilitates this task a lot is https://github.com/ax/apk.sh

Decompile the APK

Met APKTool kan jy toegang kry tot die smali code and resources:

bash
apktool d APP.apk

As apktool jou enige fout gee, try installing the latest version

Some interesting files you should look are:

  • res/values/strings.xml (and all xmls inside res/values/*)
  • AndroidManifest.xml
  • Enige lêer met die uitbreiding .sqlite of .db

If apktool has problems decoding the application take a look to https://ibotpeaches.github.io/Apktool/documentation/#framework-files or try using the argument -r (Moenie resources dekodeer nie). Then, if the problem was in a resource and not in the source code, you won't have the problem (you won't also decompile the resources).

Verander smali kode

Jy kan instruksies verander, die waarde van sommige veranderlikes verander of nuwe instruksies byvoeg. Ek verander die Smali kode using VS Code, you then install the smalise extension and the editor will tell you if any instruction is incorrect.
Sommige voorbeelde kan hier gevind word:

Of jy kan check below some Smali changes explained.

Herkompileer die APK

Na aanpassing van die kode kan jy die kode herkompileer deur die volgende te gebruik:

bash
apktool b . #In the folder generated when you decompiled the application

Dit sal die nuwe APK compile binne die dist gids.

As apktool 'n fout gee, probeer installing the latest version

Onderteken die nuwe APK

Dan moet jy 'n sleutel genereer (jy sal gevra word vir 'n wagwoord en vir sommige inligting wat jy lukraak kan invul):

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

Laastens, sign die nuwe APK:

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

Optimaliseer nuwe toepassing

zipalign is 'n instrument vir argiefuitlyning wat belangrike optimalisering vir Android-toepassings (APK)-lêers bied. More information here.

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

Onderteken die nuwe APK (weer?)

Indien jy verkies om apksigner te gebruik in plaas van jarsigner, moet jy die apk onderteken nadat jy die optimalisering met zipaling toegepas het. LET WEL DAT JY SLEGS EEN KEER DIE AANSOEK MOET ONDERTEKEN MET jarsigner (voor zipalign) OF MET aspsigner (na zipaling).

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

Aanpassing van Smali

Vir die volgende Hello World Java code:

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

Die Smali code sou wees:

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

Die Smali instruksiestel is beskikbaar here.

Ligte veranderinge

Wysig aanvanklike waardes van 'n veranderlike binne 'n funksie

Sommige veranderlikes word aan die begin van die funksie met die opcode const gedefinieer; jy kan hul waardes wysig, of jy kan nuwe veranderlikes definieer:

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

Basiese Operasies

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

Groter Veranderinge

Logboek

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>"

Aanbevelings:

  • Indien jy verklaarde veranderlikes binne die funksie gaan gebruik (declared v0,v1,v2...) sit hierdie reëls tussen die .local en die verklarings van die veranderlikes (const v0, 0x1)
  • As jy die logging code in die middel van die kode van 'n funksie wil plaas:
  • Voeg 2 by die aantal verklaarde veranderlikes: Ex: van .locals 10 na .locals 12
  • Die nuwe veranderlikes moet die volgende nommers wees van die reeds verklaarde veranderlikes (in hierdie voorbeeld moet dit v10 en v11 wees, onthou dat dit by v0 begin).
  • Verander die kode van die logging funksie en gebruik v10 en v11 in plaas van v5 en v1.

Toasting

Onthou om 3 by die aantal .locals aan die begin van die funksie te voeg.

Dit kode is voorberei om in die middel van 'n funksie ingevoeg te word (verander die getal van die veranderlikes soos nodig). Dit sal die waarde van this.o neem, dit na String omskakel en dan 'n toast met sy waarde wys.

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

Laai 'n native biblioteek by opstart (System.loadLibrary)

Soms moet jy 'n native biblioteek vooraf laai sodat dit voor ander JNI-libs geïnisialiseer word (bv., om proses-lokaal telemetry/logging te aktiveer). Jy kan 'n oproep na System.loadLibrary() in 'n statiese initializer invoeg of vroeg in Application.onCreate(). Voorbeeld smali vir 'n statiese klas-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

Alternatiewelik, plaas dieselfde twee instruksies aan die begin van jou Application.onCreate() om te verseker dat die biblioteek so vroeg as moontlik gelaai word:

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

Aantekeninge:

  • Maak seker dat die korrekte ABI-variant van die biblioteek onder lib// (bv. arm64-v8a/armeabi-v7a) bestaan om UnsatisfiedLinkError te voorkom.
  • Laai baie vroeg (class static initializer) — dit verseker dat die native logger daaropvolgende JNI-aktiwiteit kan waarneem.

Verwysings

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks