Aab 디 컴파일 - Aab di keompail

Apk는 zip으로 압축된 파일입니다. 압축을 풀면 여러 리소스 파일들과 실행 파일인 dex(Dalvik Executable)파일이 있습니다. 하지만 압축을 푼다고 볼 수 있는 것이 거의 없습니다. AndroidManifest.xml이나 다른 스트링 리소스들은 깨진 것처럼 보이고, dex(덱스) 파일 또한 사람이 읽을 수 없는 형식으로 되어있기 때문입니다. 몇개의 툴을 이용하여 이 파일들을 decompile하면 사람이 읽을 수 있는 코드 형태로 변환이 가능합니다.(자바 소스 추출 가능)

Apk를 디컴파일하는 방법은 불편한 방법과 편한 방법이 있습니다. 다음 3개의 툴을 이용하면 단계적으로 apk를 decompile할 수 있습니다.

  • Apktool: apk의 리소스를 변환하는데 사용됩니다.
  • dex2jar: dex를 jar로 변환하는데 사용됩니다.
  • jd-cmd: jar를 java 코드로 변환하는데 사용됩니다.

하지만, 위의 방법 외에도 명령어 한번에 apk를 쉽게 디컴파일해주는 툴도 있습니다. jadx가 그런 툴 중에 하나 입니다.

  • jadx : Apk를 decompile하며, GUI와 Command line 툴 모두 제공합니다

가장 먼저 디바이스에서 apk를 추출하는 방법을 알아보고, 다음으로 위에서 말한 두개의 방식으로 apk를 decompile하는 방법에 대해서 모두 알아보겠습니다.

디바이스에서 Apk 추출하는 방법

분석할 apk가 준비되어있다면 이 단계를 건너뛰어도 됩니다. 하지만 PlayStore에서만 받을 수 있는 apk라면 여기서 apk 추출 방법을 알려드립니다.

먼저 PlayStore에서 분석하고 싶은 앱을 설치합니다. 그리고 아래 명령어로 설치된 패키지 정보를 추출합니다. 추출된 파일을 열어보면 설치된 패키지 정보들이 있습니다.(PC에 adb가 설치되었다는 전제로 진행합니다)

$ adb shell dumpsys package p > package_info.txt

저는 Play Books라는 앱을 다운받았습니다. 위에서 추출한 패키지 정보에서 내가 다운받은 앱의 패키지 이름을 찾아야 합니다. books로 검색해보면 이런 패키지가 있습니다. 제가 설치한 앱의 패키지 이름은 com.google.android.apps.books인거같네요.

Package [com.google.android.apps.books] (7c73afd):
  userId=10085
  pkg=Package{9df90b0 com.google.android.apps.books}
  codePath=/data/app/com.google.android.apps.books-TlsKiNze7ahFgAhZuk2T1Q==
  .....
  timeStamp=2019-02-08 20:40:13
  firstInstallTime=2019-02-08 20:40:14
  lastUpdateTime=2019-02-08 20:40:14

패키지 이름을 찾는 쉬운 방법은 없습니다. 앱 이름을 구글링하면 나올 수 있고, 앱을 실행하고 다른 로그로 확인할 수도 있습니다. 또는 위처럼 설치 시간으로 찾아볼 수도 있겠네요.

위의 패키지 정보에서 codePath는 apk파일이 위치한 폴더 경로입니다. 저 폴더를 추출하면 그 안에 apk가 존재합니다. 다음 명령어를 사용하여 폴더를 추출합니다.

$ adb pull /data/app/com.google.android.apps.books-TlsKiNze7ahFgAhZuk2T1Q==

이 명령어를 사용하면 단말의 특정 위치에 있는 파일을 PC로 가져올 수 있습니다. 아래와 같이 단말의 파일을 PC로 가져왔습니다. 그리고 폴더 안에는 base.apk라는 이름으로 apk가 존재합니다. 이 apk가 Play Books의 apk입니다.

$ ls
'com.google.android.apps.books-TlsKiNze7ahFgAhZuk2T1Q=='
$ cd 'com.google.android.apps.books-TlsKiNze7ahFgAhZuk2T1Q=='/
$ ls
base.apk  lib

Tool 설치 방법

위에서 소개한 Tool들은 Window/Linux 모두 사용가능합니다. 저는 Linux 기준으로 설명하겠습니다.

Apktool은 Apktool에서 버전별로 다운받을 수 있습니다. dex2jar은 Dex2Jar에서 컴파일된 파일을 받을 수 있습니다. 그리고 jd-cmd는 Jd-cmd에서 컴파일된 파일을 받을 수 있습니다. 모두 최신버전으로 받으시면 됩니다.

위의 툴들을 폴더 하나에 모두 다운받아놨습니다.

apktools$ ls
apktool_2.3.4.jar  dex2jar-2.0.zip  jd-cli-0.9.2-dist.zip

압축 파일은 모두 풀고, zip파일은 삭제하였습니다. 모든 작업을 끝낸 저의 파일 상태는 이렇습니다.

$ ls
apktool_2.3.4.jar  dex2jar-2.0  jd-cli-0.9.2-dist

위의 툴 다운로드 사이트에서 사용방법을 읽어보시면, 이 파일들은 jar 또는 쉘스크립트입니다. 매번 명령어를 입력하기 번거롭기 때문에 ~/.bashrc에 아래처럼 명령어를 alias로 등록해두었습니다. (Windows는 d2j-dex2jar.bat 파일을 사용해야 할 것 같습니다)

# tools
alias apktool='java -jar ~/apps/apktools/apktool_2.3.4.jar'
alias dex2jar='~/apps/apktools/dex2jar-2.0/d2j-dex2jar.sh'
alias jd-cli='java -jar ~/apps/apktools/jd-cli-0.9.2-dist/jd-cli.jar'

이제 설치는 모두 마쳤습니다. 명령어를 쳐보면 실행이 잘 됩니다.

$ apktool
Apktool v2.3.4 - a tool for reengineering Android apk files
....

$ dex2jar
d2j-dex2jar -- convert dex to jar
....

$ jd-cli
jd-cli version 0.9.2 - Copyright (C) 2015 Josef Cacek
....

만약에 명령어를 쉘에서 실행했을 때, 실행할 수 없다는 에러가 출력되면 chmod로 스크립트파일을 실행가능한 파일로 만들어주시면 됩니다.

$ chmod 755 ~/apps/apktools/dex2jar-2.0/*

Apk decompile (소스 추출)

Apk가 있는 파일로 이동합니다. 먼저 Apktool을 이용하여 apk파일을 decompile하겠습니다. Apktool은 dex를 java로 변환해주진 못하고 smali라는 파일까지 변환해줄 수 있습니다. 저희가 필요한 것은 java파일이기 때문에, Apktool은 dex를 제외한 다른 파일을 변환하는데 사용할 것입니다. dex는 dex2jar과 jd-cli를 사용하여 변환할 것입니다.

apktool의 help를 보시면 명령어에 대한 자세한 내용을 알 수 있습니다. 여기서는 필요한 명령어만 소개하겠습니다. 아래 명령어는 소스파일(dex)은 제외하고 base.apk를 decompiled 폴더에 decompile하라는 의미입니다.

$ apktool d -s -o decompiled base.apk

decompiled 폴더가 생겼고, 이 폴더의 내용을 보면 변환된 파일들이 있습니다. 여기서 리소스들은 모두 decompile되었기 때문에 읽을 수 있습니다. 소스파일들은 classes.dex에 있고 아직 읽을 수 없습니다.

$ ls
base.apk  decompiled  lib
$ cd decompiled/
$ ls
AndroidManifest.xml  assets        classes3.dex  classes.dex  res
apktool.yml          classes2.dex  classes4.dex  original     unknown

파일들을 보면 classes(숫자).dex라는 이름으로 dex가 4개나 있습니다. 이것은 이 앱이 Multi-dex의 형태이기 때문입니다. 만약 Multi-dex가 아니라면 classes.dex뿐이 없습니다. Multi-dex이기 때문에 모든 소스를 보려면 4개의 dex를 모두 java로 변환해야 합니다.

지금까지 Apktool을 이용하여 apk의 리소스를 모두 읽을 수 있는 형태로 변환하였습니다. 이제 dex만 변환하면 됩니다. dex파일은 아래와 같이 두개의 툴을 이용하여 java파일로 변환해야 합니다.

  • dex2jar: dex파일을 jar파일로 변환합니다.
  • jd-cli: jar파일을 java파일로 변환합니다.

먼저 dex파일을 jar파일로 변환하겠습니다. 다음 명령어를 이용하여 classes.dex를 변환합니다. 변환된 결과는 입력파일이름-dex2jar.jar형태로 생성됩니다. 변환할 때 문제가 있었던 것은 classes-error.zip파일로 리포팅 됩니다.

decompiled$ dex2jar classes.dex
dex2jar classes.dex -> ./classes-dex2jar.jar
Detail Error Information in File ./classes-error.zip

decompiled$ ls
AndroidManifest.xml  assets        classes3.dex  classes.dex          classes-error.zip  res
apktool.yml          classes2.dex  classes4.dex  classes-dex2jar.jar  original           unknown

그 외의 다른 dex 파일들도 모두 decompile합니다.

decompiled$ dex2jar classes2.dex
decompiled$ dex2jar classes3.dex
decompiled$ dex2jar classes4.dex

이렇게 dex를 모두 jar파일로 변환하였습니다. 총 4개의 jar파일이 생성되었습니다.

decompiled$ ls | grep dex2jar
classes2-dex2jar.jar
classes3-dex2jar.jar
classes4-dex2jar.jar
classes-dex2jar.jar

다시 정리해보면 apk의 리소스들은 이미 apktool이 변환하였고, dex파일은 dex2jar를 이용하여 jar파일로 변환하였습니다. 이제 마지막으로 jar를 java파일로 변환하면 됩니다.

아래의 jd-cli 명령어는 classes-dex2jar.jar를 src폴더에 java파일로 decompile하라는 의미입니다. 4개의 dex를 모두 src에 decompile하면 됩니다.

decompile$ jd-cli classes-dex2jar.jar -od src
decompile$ jd-cli classes2-dex2jar.jar -od src
decompile$ jd-cli classes3-dex2jar.jar -od src
decompile$ jd-cli classes4-dex2jar.jar -od src

자, 이제 모든 작업이 끝났습니다. apk의 리소스와 소스들은 모두 decompile되었습니다. 소스파일들은 아래와 같이 java로 변환되어 사람이 읽을 수 있는 형태가 되었습니다.

~/test/com.google.android.apps.books-TlsKiNze7ahFgAhZuk2T1Q==/decompiled/src$ tree -L 3
.....
├── com
│   ├── a
│   │   ├── a
│   │   ├── b
│   │   ├── c
│   │   └── d
│   ├── b
│   │   └── a
│   └── google
│       ├── android
│       ├── api
│       ├── common
│       ├── devtools
│       ├── firebase
│       ├── internal
│       ├── ocean
│       ├── play
│       ├── protobuf
.....

파일을 보시면 아시겠지만, 대부분의 앱들이 난독화(Proguard)를 하기 때문에 변수 이름이 간단한 문자로 되어있어 분석하기엔 어렵습니다.

Jadx로 디컴파일하는 방법

Jadx는 Jadx-release에서 빌드된 파일을 다운받을 수 있습니다. Jadx는 command line과 GUI 툴을 모두 제공합니다.

툴을 다운받고 압축을 풉니다. bin 폴더를 보면 실행 파일이 있습니다. jadx는 command line 툴이고, jadx-gui는 GUI 툴입니다. 저는 command line을 사용하겠습니다. (Windows 사용자의 경우 jadx-gui.bat을 사용해야 합니다)

jadx-0.8.0$ ls
bin  lib  LICENSE  NOTICE  README.md
jadx-0.8.0$ ls bin
jadx  jadx.bat  jadx-gui  jadx-gui.bat

위와 마찬가지로 ~/.bashrc에 alias로 jadx를 등록하였습니다.

#jadx
alias jadx='/home/user/test/jadx-0.8.0/bin/jadx'

jadx를 실행해보면 설치가 잘 된 것을 확인할 수 있습니다.

$ jadx -h
jadx - dex to java decompiler, version: 0.8.0
usage: jadx [options] <input file> (.apk, .dex, .jar or .class)
...

위에서는 번거롭게 여러번 명령어를 입력해주었지만, jadx는 간단합니다. 아래 명령어는 base.apk를 out 폴더에 decompile하라는 의미입니다.

decompile이 끝나면 다음과 같이 파일들이 생성됩니다. 리소스들은 resources 폴더에, 소스는 sources폴더에 decompile됩니다.

out$ tree -L 2
.
├── resources
│   ├── AndroidManifest.xml
│   ├── assets
│   └── res
└── sources
    ├── a
    ├── android
    ├── androidx
    ├── b
    ├── c
    ├── com
    ├── d
    └── org

정리

이글에서 우리는 단말에서 apk파일을 추출하고 apk의 리소스와 소스를 사람이 볼 수 있는 형태로 변환하는 방법을 알아보았습니다. decompile을 도와주는 오픈소스 툴들이 많기 때문에 자신에게 편한 툴을 사용하면 됩니다. apk를 분석할 때 Jadx가 매우 편하지만 Jar로 제공되는 라이브러리를 분석하는 경우 jd-cli가 도움이 될 수 있습니다. 또는, 만약 리소스만 decompile하고 싶다면 Apktool를 사용하여 빠르게 처리할 수도 있습니다.

대부분의 앱은 난독화가 되어있기 때문에 java로 변환한다고 해서 읽기 어려울 수 있습니다. 하지만 이 방법을 통해서 자신이 만든 앱이 난독화가 잘 되었는지, 다른 개발자로부터 코드를 분석하기 어렵게 만들었는지 확인할 수 있습니다.

참고

  • apktool
  • dex2jar
  • jd-cmd
  • jadx