Smali - Decompiling/[Modifying]/Compiling

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

HackTricks를 지원하는 다른 방법:

가끔은 응용 프로그램 코드를 수정하여 숨겨진 정보에 액세스하는 것이 흥미로울 수 있습니다(아마도 잘 난독화된 비밀번호 또는 플래그). 그런 다음, apk를 디컴파일하여 코드를 수정하고 다시 컴파일하는 것이 흥미로울 수 있습니다.

Opcode 참조: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html

빠른 방법

Visual Studio CodeAPKLab 확장 프로그램을 사용하면 명령을 실행하지 않고도 자동으로 디컴파일, 수정, 재컴파일, 서명 및 응용 프로그램을 설치할 수 있습니다.

이 작업을 매우 간단하게 해주는 스크립트https://github.com/ax/apk.sh입니다.

APK 디컴파일

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

apktool d APP.apk

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

조사해볼만한 흥미로운 파일들은 다음과 같습니다:

  • res/values/strings.xml (그리고 res/values/* 안의 모든 xml 파일)

  • AndroidManifest.xml

  • .sqlite 또는 .db 확장자를 가진 어떤 파일이든

만약 apktool애플리케이션을 디코딩하는 데 문제가 있다면, https://ibotpeaches.github.io/Apktool/documentation/#framework-files를 확인하거나 -r 인자를 사용해보세요 (리소스를 디코딩하지 않음). 그러면, 만약 문제가 소스 코드가 아닌 리소스에 있었다면, 문제가 해결될 것입니다 (리소스도 디컴파일되지 않을 것입니다).

Smali 코드 변경

명령어를 변경하거나, 일부 변수의 값을 변경하거나, 새로운 명령어를 추가할 수 있습니다. 저는 VS Code를 사용하여 Smali 코드를 변경합니다. 그런 다음 smalise 확장 프로그램을 설치하면 편집기가 잘못된 명령어를 알려줍니다. 다음에서 일부 예시를 찾을 수 있습니다:

또는 아래에서 일부 설명된 Smali 변경 사항을 확인할 수 있습니다.

APK 재컴파일

코드를 수정한 후에는 다음을 사용하여 코드를 재컴파일할 수 있습니다:

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에 서명하기 (다시?)

만약 jarsigner 대신 apksigner을 사용하고 싶다면, zipalign을 적용한 후에 apk에 서명해야 합니다. 그러나 주의해야 할 점은 jarsigner로 (zipalign 이전에) 애플리케이션에 한 번만 서명하거나, zipalign 이후에 aspsigner로 한 번만 서명해야 한다는 것입니다.

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 명령어 집합은 여기에서 확인할 수 있습니다.

경량 변경

함수 내부에서 변수의 초기값 수정

일부 변수는 함수의 시작 부분에서 const 옵코드를 사용하여 정의됩니다. 이 값을 수정하거나 새로운 값을 정의할 수 있습니다:

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

기본 작업

Smali 파일 수정

Smali 파일은 안드로이드 애플리케이션의 소스 코드를 포함하는 파일입니다. Smali 파일을 수정하여 애플리케이션의 동작을 변경할 수 있습니다.

Smali 코드 분석

Smali 코드는 Dalvik 가상 머신에서 실행되는 안드로이드 애플리케이션의 바이트 코드입니다. Smali 코드를 분석하여 애플리케이션의 동작을 이해할 수 있습니다.

Smali 코드 인젝션

Smali 코드 인젝션은 애플리케이션의 Smali 파일에 악성 코드를 삽입하는 기술입니다. 이를 통해 애플리케이션의 동작을 조작하거나 악성 기능을 추가할 수 있습니다.

Smali 코드 변조

Smali 코드 변조는 애플리케이션의 Smali 파일을 수정하여 원하는 동작을 수행하도록 변경하는 기술입니다. 이를 통해 애플리케이션의 보안 기능을 우회하거나 악용할 수 있습니다.

Smali 코드 역어셈블

Smali 코드 역어셈블은 애플리케이션의 Smali 파일을 원래의 소스 코드로 변환하는 기술입니다. 이를 통해 애플리케이션의 동작을 분석하거나 수정할 수 있습니다.

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

추천 사항:

  • 함수 내에서 선언된 변수를 사용할 경우 (선언된 v0,v1,v2...), 이러한 줄을 _.local <number>_와 변수의 선언 (const v0, 0x1) 사이에 넣으세요.

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

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

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

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

토스팅

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

이 코드는 함수의 중간에 삽입되도록 준비되어 있습니다 (변수를 필요에 따라 변경하세요). 이 코드는 this.oString으로 변환한 다음 그 값을 가지고 토스트를 만듭니다.

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
htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

HackTricks를 지원하는 다른 방법:

Last updated