Android의 앱은 apk이라는 파일로 되어 있으며 이것은 압축형태로 되어 있다.
apk를 압축 프로그램으로 열어보면 크게 AndroidManifest.xml, resources.arsc, classes.dex의 정보에 의해 앱이 실행되며, 때에 따라서는 Asset, lib 폴더도 존재하여 ndk를 이용한 Native Code나, Java Library, 그 밖의 리소스와 같은 부가적인 사용이 가능하다.
이 중, 가장 핵심적인 소스코드의 정보는 classes.dex 파일에 담겨져 있다.
이번 글에서는 apktool를 이용하여 apk를 디컴파일하고, 디컴파일된 Smali 코드와 실제 Java 코드를 간략하게 비교를 한다.
그리고 다시 apk로 리패키징하는 방법에 대해 간략히 설명한다.
apktool을 다운받는 URL은 다음과 같다.
APKTool : http://ibotpeaches.github.io/Apktool/
apktool은 Java기반으로 만들어졌으며, jar 형태로 배포하고 있다.
apktool를 이용하여 test.apk를 디컴파일을 수행하면 아래와 같은 절차를 따라 디컴파일이 수행된다.
명령어는 다음과 같다.
$ java -jar apktool_2.0.3.jar d 디컴파일할 앱.apk
아래는 apk 파일을 apktool을 이용하여 디컴파일 후 생성되는 파일들이다. 이 중 smali 폴더가 생성된 것을 확인할 수 있는데 이는 classes.dex를 디스어셈블링한 결과의 파일들이며 Android 환경에서 Java 기반의 소스코드가 dalvik 가상 머신 환경에서 동작하기 위한 코드이며, 마치 형태가 C언어 기반의 Assembly와 비슷한 형태의 코드를 얻을 수 있다.
smali 폴더 내부로 들어가면 class 단위의 smali 코드로 된 파일들을 확인할 수 있으며, 이를 열어보면 다음과 같은 형태의 코드가 존재한다. C언어 기반의 Assembly 코드보다 가독성은 좋지만 기존의 Java 코드와는 동떨어진 코드 형태를 보여준다.
Smali 코드와 원본 Java 코드를 비교한 그림이 아래에 있다. 일반 Java 코드에 비해 Smali는 그 양이 많은 것을 알 수 있다. 또한, 이 Smali 코드를 이용하여 수정하는 것이 가능하며, 이는 기존의 원본 apk의 기능을 사용자의 목적에 맞게 조작이 가능하다는 것을 의미한다.
리패키징 방법은 아래와 같다.
$ java -jar apktool_2.0.3.jar b 디컴파일한 apk 폴더 Path -o 리패키징할 파일 이름.apk
리패키징이 완료되고 파일이 생성되었지만, 해당 파일을 서명없이 바로 설치를 하게 되면, 다음과 같은 에러 메시지와 함께 패키지 설치가 실패된다.
signapk.jar 를 이용하여 리패키징 앱을 Test키로 서명하자. signapk.jar는 아래의 URL에서 다운 받을 수 있다.
signapk : https://github.com/appium/sign
서명 방법은 아래와 같다.
- java -jar signapk.jar 서명키.pem 서명키.pk8 리패키징.apk 서명된 리패키징 이름.apk
다음과 같이 서명 절차를 거치면 해당 앱이 정상적으로 기기에 설치되며, 앱 실행시 문제 없이 동작하는 것을 확인할 수 있다.
마지막으로 원본 앱과 Test키를 이용한 리패키징 앱에 대한 서명을 비교하여 서명 값이 변경된 것을 확인할 수 있는 방법을 소개한다.
해당 파일은 설치된 jdk의 bin 폴더에 존재하며, 앱의 서명 정보를 보는 명령어는 아래와 같다.
$ jarsigner -verbose -verify -certs 앱.apk
- 리패키징 전, 서명 값
- 리패키징 후, 서명 값
원본의 서명 키를 원본 앱을 만든 개발자에게서 구하지 않는 이상 동일한 키를 이용하여 리패키징 된 앱을 서명할 수는 없을 것이며, 따라서 원본 앱과 리패키징 앱을 구분 시, 다음과 같이 서명 값을 확인해서 비교하는 방법으로도 앱의 리패키지 여부를 알 수 있는 방법이 된다.