Smali - Decompiling/[Modifying]/Compiling

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

때때로 숨겨진 정보를 얻기 위해 애플리케이션 코드를 수정하는 것이 흥미로울 수 있습니다(아마도 잘 난독화된 비밀번호나 플래그). 그런 다음, apk를 디컴파일하고 코드를 수정한 후 다시 컴파일하는 것이 흥미로울 수 있습니다.

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

Fast Way

Visual Studio CodeAPKLab 확장을 사용하면 자동으로 디컴파일, 수정, 재컴파일, 서명 및 애플리케이션을 설치할 수 있습니다. 어떤 명령도 실행할 필요가 없습니다.

이 작업을 많이 용이하게 하는 또 다른 스크립트https://github.com/ax/apk.sh입니다.

Decompile the APK

APKTool을 사용하면 smali 코드와 리소스에 접근할 수 있습니다:

apktool d APP.apk

If apktool gives you any error, try installing the latest version

Some interesting files you should look are:

  • res/values/strings.xml (and all xmls inside res/values/*)

  • 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

You can change instructions, change the value of some variables or add new instructions. I change the Smali code using VS Code, you then install the smalise extension and the editor will tell you if any instruction is incorrect. Some examples can be found here:

Or you can check below some Smali changes explained.

Recompile the APK

After modifying the code you can recompile the code using:

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

새 APK는 dist 폴더 내부컴파일됩니다.

만약 apktool오류를 발생시키면, 최신 버전을 설치해 보세요.

새 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) 파일에 중요한 최적화를 제공하는 아카이브 정렬 도구입니다. 자세한 정보는 여기에서 확인하세요.

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

새 APK 서명하기 (다시?)

만약 apksigner를 사용하고 싶다면 apksigner 대신 jarsigner, zipalign으로 최적화를 적용한 후 apk를 서명해야 합니다. 하지만 jarsigner로 애플리케이션을 한 번만 서명해야 한다는 점에 유의하세요 (zipalign 이전) 또는 aspsigner로 (zipalign 이후).

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

Smali 수정

다음 Hello World Java 코드:

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

스말리 코드는 다음과 같습니다:

.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

The Smali instruction set is available here.

Light Changes

함수 내 변수의 초기 값 수정

일부 변수는 함수의 시작 부분에서 const opcode를 사용하여 정의되며, 해당 변수의 값을 수정하거나 새로운 값을 정의할 수 있습니다:

#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 <number>_과 변수 선언(const v0, 0x1) 사이에 넣으세요.

  • 함수 코드 중간에 로깅 코드를 넣고 싶다면:

  • 선언된 변수의 수에 2를 추가하세요: 예: _.locals 10_에서 _.locals 12_로.

  • 새로운 변수는 이미 선언된 변수의 다음 숫자여야 합니다 (이 예에서는 _v10_과 _v11_이어야 하며, v0에서 시작한다는 것을 기억하세요).

  • 로깅 함수의 코드를 변경하고 _v5_와 v1 대신 _v10_과 _v11_을 사용하세요.

Toasting

함수 시작 부분에서 _.locals_의 수에 3을 추가하는 것을 잊지 마세요.

이 코드는 함수의 중간에 삽입되도록 준비되었습니다 (변수숫자는 필요에 따라 변경하세요). 이 코드는 this.o을 가져와 String으로 변환한 다음 그 값으로 토스트만들 것입니다.

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

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Last updated