Smali - Decompiling/[Modifying]/Compiling
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
๋๋ก๋ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ฅผ ์์ ํ์ฌ ์จ๊ฒจ์ง ์ ๋ณด๋ฅผ ์ป๋ ๊ฒ์ด ํฅ๋ฏธ๋ก์ธ ์ ์์ต๋๋ค(์: ์ ๋๋ ํ๋ ๋น๋ฐ๋ฒํธ๋ ํ๋๊ทธ). ๊ทธ๋ฐ ๊ฒฝ์ฐ apk๋ฅผ decompileํ๊ณ ์ฝ๋๋ฅผ modifyํ ๋ค recompileํ๋ ๊ฒ์ด ์ ์ฉํ ์ ์์ต๋๋ค.
Opcodes reference: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
๋น ๋ฅธ ๋ฐฉ๋ฒ
Visual Studio Code์ APKLab ํ์ฅ(extension)์ ์ฌ์ฉํ๋ฉด ๋ช ๋ น์ ์คํํ์ง ์๊ณ ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ 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
If apktool gives you any error, installing the latest version์ ์๋ํด๋ณด์ธ์
Some interesting files you should look are:
- res/values/strings.xml (๋ฐ res/values/* ๋ด๋ถ์ ๋ชจ๋ xml ํ์ผ)
- AndroidManifest.xml
- Any file with extension .sqlite or .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 (Do not decode resources). 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).
Change smali code
๋ช
๋ น์ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ผ๋ถ ๋ณ์์ ๊ฐ์ ๋ฐ๊พธ๊ฑฐ๋ ์ ๋ช
๋ น์ ์ถ๊ฐํ ์ ์์ต๋๋ค. ์ ๋ Smali ์ฝ๋๋ฅผ VS Code์์ ํธ์งํฉ๋๋ค. ๊ทธ ํ smalise extension์ ์ค์นํ๋ฉด ์๋ํฐ๊ฐ ์๋ชป๋ instruction์ด ์๋์ง ์๋ ค์ค๋๋ค.
Some examples can be found here:
Or you can check below some Smali changes explained.
Recompile the APK
์ฝ๋๋ฅผ ์์ ํ ํ ๋ค์ ๋ช ๋ น์ผ๋ก APK๋ฅผ ๋ค์ ์ปดํ์ผํ ์ ์์ต๋๋ค:
apktool b . #In the folder generated when you decompiled the application
์ APK๋ dist ํด๋ ๋ด๋ถ์์ ์ปดํ์ผ๋ฉ๋๋ค.
๋ง์ฝ apktool๊ฐ ์ค๋ฅ๋ฅผ ๋ฐ์์ํค๋ฉด, installing the latest version์ ์๋ํด๋ณด์ธ์
์ APK์ ์๋ช ํ๊ธฐ
๊ทธ๋ฐ ๋ค์, ํค๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค (๋น๋ฐ๋ฒํธ์ ๋ฌด์์๋ก ์ ๋ ฅํด๋ ๋๋ ๋ช ๊ฐ์ง ์ ๋ณด๋ฅผ ์๊ตฌํฉ๋๋ค):
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) ํ์ผ์ ์ค์ํ ์ต์ ํ๋ฅผ ์ ๊ณตํ๋ ์์นด์ด๋ธ ์ ๋ ฌ ๋๊ตฌ์ ๋๋ค. More information here.
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
์ APK์ ์๋ช (๋ค์?)
jarsigner ๋์ apksigner๋ฅผ ์ ํธํ๋ค๋ฉด, zipalign์ผ๋ก ์ต์ ํ๋ฅผ ์ ์ฉํ ํ APK์ ์๋ช ํด์ผ ํฉ๋๋ค. ํ์ง๋ง ์ฃผ์: ์ ํ๋ฆฌ์ผ์ด์ ์ jarsigner(์ด์ ์ zipalign)์ผ๋ก ๋๋ apksigner(์ดํ์ zipalign)๋ก ํ ๋ฒ๋ง ์๋ช ํ๋ฉด ๋ฉ๋๋ค.
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
๋ ํฐ ๋ณ๊ฒฝ์ฌํญ
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>"
๊ถ์ฅ ์ฌํญ:
- ๋ง์ฝ ํจ์ ๋ด๋ถ์์ ์ ์ธ๋ ๋ณ์๋ฅผ ์ฌ์ฉํ ์์ ์ด๋ผ๋ฉด(์ ์ธ๋ v0,v1,v2โฆ) ์ด ์ค๋ค์ _.local
_๊ณผ ๋ณ์ ์ ์ธ๋ค(const v0, 0x1) ์ฌ์ด์ ๋ฃ์ผ์ธ์ - ํจ์ ์ฝ๋์ ์ค๊ฐ์ logging ์ฝ๋๋ฅผ ๋ฃ๊ณ ์ถ๋ค๋ฉด:
- ์ ์ธ๋ ๋ณ์ ์์ 2๋ฅผ ๋ํ์ธ์: ์: _.locals 10_์์ .locals 12
- ์ ๋ณ์๋ค์ ์ด๋ฏธ ์ ์ธ๋ ๋ณ์์ ๋ค์ ๋ฒํธ์ฌ์ผ ํฉ๋๋ค(์ด ์์ ์์๋ _v10_๊ณผ _v11_์ด์ด์ผ ํฉ๋๋ค, v0๋ถํฐ ์์ํ๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์ธ์).
- logging ํจ์์ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ์ฌ _v10_๊ณผ _v11_์ _v5_์ v1 ๋์ ์ฌ์ฉํ์ธ์.
ํ ์คํธ ํ์
ํจ์ ์์ ๋ถ๋ถ์ .locals ์์ 3์ ๋ํด์ผ ํฉ๋๋ค.
์ด ์ฝ๋๋ ํจ์์ ์ค๊ฐ์ ์ฝ์ ๋๋๋ก ์ค๋น๋์ด ์์ต๋๋ค (ํ์์ ๋ฐ๋ผ ๋ณ์์ ์๋ฅผ ๋ณ๊ฒฝํ์ธ์). ์ด ์ฝ๋๋ this.o์ ๊ฐ์ ๊ฐ์ ธ์ String์ผ๋ก ๋ณํํ ๋ค์ ํด๋น ๊ฐ์ผ๋ก toast๋ฅผ ์์ฑํฉ๋๋ค.
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
์์ ์ ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋ (System.loadLibrary)
๋๋๋ก ๋ค๋ฅธ JNI ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ณด๋ค ๋จผ์ ์ด๊ธฐํ๋๋๋ก ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ ๋ก๋ํด์ผ ํ ๋๊ฐ ์์ต๋๋ค (์: ํ๋ก์ธ์ค ๋ก์ปฌ ํ
๋ ๋ฉํธ๋ฆฌ/๋ก๊น
์ ํ์ฑํํ๊ธฐ ์ํด). ์ ์ ์ด๊ธฐํ์๋ Application.onCreate() ์ด๊ธฐ์ System.loadLibrary() ํธ์ถ์ ์ฃผ์
ํ ์ ์์ต๋๋ค. ์ ์ ํด๋์ค ์ด๊ธฐํ์ (
.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 activity๋ฅผ ๊ด์ฐฐํ ์ ์์ต๋๋ค.
์ฐธ๊ณ ์๋ฃ
- SoTap: ๊ฒฝ๋ ์ธ์ฑ JNI (.so) ๋์ ๋ก๊ฑฐ โ github.com/RezaArbabBot/SoTap
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


