인터넷을 검색하다가 보니 안드로이드 앱이 디컴파일 및 리컴파일이 된다는 게시글을 보고 한번 해 보기로 했습니다.
( 참고한 사이트 : http://forum.xda-developers.com/showthread.php?t=2195680 )
위 사이트에서 필요한 툴을 받아서 압축을 해제합니다.
원본 apktool은 http://ibotpeaches.github.io/Apktool 에서 받을 수 있습니다.
우선 androidstudio에서 디버깅시 많이 사용하는 Log API를 사용하여 2개의 로그를 찍는 간단한 안드로이드용 어플리케이션을 아래와 같이 코딩하였습니다.
APK를 생성하면 app-release.apk가 생성되는데 위의 압축을 푼 디렉토리로 copy해 넣습니다.
"apktool d app-release.apk" 명령어로 decompile을 합니다.
해당 디렉토리내의 app-release\smali\com\example\logcat\MainActivity.smail 파일을 열어 보면 아래와 같습니다.
아랫 부분의 OnCreate를 보시면 윗 그림에서 Log.e로 출력되는 2개의 부분을 찾을 수 있습니다.
.class public Lcom/example/logcat/MainActivity;
.super Landroidx/appcompat/app/AppCompatActivity;
.source "MainActivity.java"
# instance fields
.field TAG:Ljava/lang/String;
# direct methods
.method public constructor <init>()V
.locals 1
.line 8
invoke-direct {p0}, Landroidx/appcompat/app/AppCompatActivity;-><init>()V
const-string v0, "rudalskim.log"
.line 9
iput-object v0, p0, Lcom/example/logcat/MainActivity;->TAG:Ljava/lang/String;
return-void
.end method
# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
.locals 2
.line 13
invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
const p1, 0x7f0a001c
.line 14
invoke-virtual {p0, p1}, Lcom/example/logcat/MainActivity;->setContentView(I)V
.line 16
iget-object p1, p0, Lcom/example/logcat/MainActivity;->TAG:Ljava/lang/String;
const-string v0, "Hello World"
invoke-static {p1, v0}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
.line 18
iget-object p1, p0, Lcom/example/logcat/MainActivity;->TAG:Ljava/lang/String;
new-instance v0, Ljava/lang/StringBuilder;
invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V
const-string v1, "id="
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
const/16 v1, 0x4d2 <-- 1234의 HEX값
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v0
invoke-static {p1, v0}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
return-void
.end method
또한 이렇게 디컴파일된 소스는 아래와 같이 리컴파일도 가능합니다.
to recompile :
apktool b app-release
to sign :
java -jar SignApk.jar testkey.x509.pem testkey.pk8 .\app-release\dist\app-release.apk app-release_signed.apk
SignApk는 github.com/techexpertize/SignApk를 참고하시기 바랍니다.
to zipalign :
zipalign -fv 4 app-release_signed.apk logcatTestapp-release_signed_zipaligned.apk
위의 apktool은 smali 코드를 보여주는데 반하여 JD-GUI(http://jd.benow.ca/)라는 디컴파일러가 있는데, 이 툴은 한 걸음 더 나가 가능한 범위내에서 원본 소스코드를 재구성해서 보여 줍니다. 그러나 아쉽게도 JD-GUI가 더 이상 업데이트가 안되는데다가 오래된 버전이라 최신버전의 apk를 디컴파일하면 코드가 제대로 디컴파일이 안됩니다.
다른분이 JADX(github.com/skylot/jadx)라는 것으로 업그레이드 하였는데, 확실히 더 편리합니다.
기존 JD-GUI는 APK파일의 압축을 해제 후 dex2jar로 jar을 불러와야 했는데, JADX는 APK파일을 지원합니다.
압축 해제 없이 APK파일을 불러오면 자동으로 압축해제 후 디컴파일까지 해 줘서 편리합니다.
이 게시글의 맨 윗쪽 그림의 제가 작성한 원본 소스코드와 위 디컴파일러를 거친 후 재구성된 소스코드를 비교하면 거의 원본 소스코드에 가깝게 코드를 재구성 해 주는것을 볼 수 있습니다.
따라서 소스코드를 분석할 때에는 JADX를 사용해서 분석을 하고, 수정은 smali코드를 직접 수정 후 리컴파일을하여 적용하시면 패치된 APK를 사용할 수 있습니다.
'Software > Android' 카테고리의 다른 글
[Android] smali code 디버깅 방법 (0) | 2021.01.08 |
---|---|
[Android Studio] USB Accessory 사용하기 (0) | 2021.01.06 |
[Android Studio] ConstraintLayout 사용하기 (0) | 2021.01.05 |
[Android Studio] 키 생성 오류(Key was created with errors) (0) | 2021.01.04 |
[안드로이드] 디컴파일을 통한 crackme0.apk 크랙 - 방법1 (0) | 2020.12.21 |
댓글