흔히 구글 플레이와 같은 공식 스토어에서 제공하는 앱 스토어 이외의 유료 앱의 경우 사용자가 이에 대한 금액을 지불하지 않고, 블랙마켓과 같은 사이트에서 무료로 제공하는 앱들을 받아서 사용하는 경우가 많다.

 

기본적으로 안드로이드 앱의 구성요소는 iOS에 비해 단순하며(DRM, 암호화, 인증 등등), iOS 탈옥처럼 안드로이드에서는 루팅 절차를 거치지 않고 USB 디버깅 모드를 통하여 콘솔로 apk 파일을 설치하고 지우는것이 가능하다.

 

그래서 유료 앱을 결제하여 설치를 하더라도 해당 앱을 다운 받은 기기에서 apk 추출이 손쉽게 가능하며, 이를 이용해서 유료 앱을 블랙마켓과 같은 스토어 사이트나 커뮤니티 사이트에서 재 업로드 하여 무료로 배포하는 사이트들이 무수히 많이 성행하고 있다.

 

단순히 무료로 사용하기 위해 이와 같은 방법을 사용하여 앱을 사용함에 있어서 도덕적인 문제의 소지는 있을수도 있겠으나 정상적인 원본 앱이라면 사용자에게 미치는 영향은 없다고 무방하다.

 

하지만 안드로이드 앱의 특성상 앱의 위/변조가 손쉬우며, 이와 같이 안드로이드의 개방성과 앱의 위/변조의 쉬운점으로 인해 사용자에게 일반 유료 앱을 위/변조하여 악의적인 행위를 수행한 리패키징 앱을 제공할 가능성도 존재하게 된다.


이번 글에서는 이와 같은 리패키징앱에 대한 위험성과 발생할 수 있는 가능성에 대한 내용을 설명하고자 한다.

 

앞서 설명한 포스팅 글처럼(2017/05/02 - [Analysis/Android] - Apktool을 이용한 안드로이드 apk 파일 디컴파일 및 리패키징) apk는 디컴파일 및 리패키징을 위한 방법을 설명하며, 그 절차가 까다롭지 않다.


다음과 같이, 리패키징 과정을 거쳐 보여줄 예시의 샘플 앱을 선정하였다. 일단, 심플하면서도 변조하기 손쉬울 앱으로 선정하였기 때문에 설명할 내용은 간단하겠지만, 그 위험성에 대한 잠재력은 방대한 응용에 있다고 보여진다.


다음의 앱은 구글 플레이 스토어에서 무료로 설치할 수 있는 안드로이드용 메모장 앱이다.
 

Notepad for Android : https://play.google.com/store/apps/details?id=com.blogspot.logpedia.note2

 

다음과 같은 앱은 말그대로 단순히 메모장 기능만 제공하며, 기입한 내용들을 단순 저장하는 방식으로 동작한다.

 

 

이번 포스팅에서는 이 메모장 앱을 디컴파일하여 해당 앱에서 저장되는 시점에 Log.e() API를 호출하고 Eclipse에서 사용자에 의해 저장되는 문자를 Logcat으로 출력하도록 변조하는 과정에 대해 설명할 것이다.

 

먼저, 안드로이드용 메모장 앱을 디컴파일 도구를 이용하여 소스를 분석한다.

 

 

다음과 같이 저장하는 시점은 onPause()가 수행될 때인 것을 확인할 수 있다. 또한 이 변수는 최종적으로 String을 Byte형으로 변형하여 저장한다. 따라서, 이 시점 사이에 Log.e() API를 호출하는 기능을 넣어 editText1에 있는 문자열을 Logcat으로 찍을 수 있는 기능을 추가해야 할 것이다.

 

앞서 설명한 Logcat으로 문자열을 찍어낼 수 있는 기능을 추가하기 위해서는 Log.e()을 호출하는 Smali 코드를 얻어야 할 것이다.
Log.e()의 Smali 코드를 얻기 위해 간단한 Project를 생성하여 Log.e() API를 호출하는 코드를 추가하고 이를 컴파일한 후, 다시 디컴파일을 하여 Smali 코드를 얻어 낸다.

 

 

다음으로, 안드로이드용 메모장 앱을 디컴파일하여 Smali 코드를 분석한다. 실제 원본코드와 비교해 보면, 다음과 같이 Smali 코드가 흘러 가는 것을 확인할 수 있다. 또한, 여기서 사용자가 작성한 내용에 대한 내용을 담는 변수는 v1이라는 것이 유추 가능하다.

 

 

다음과 같이 디컴파일된 이 2개의 Smali 코드를 적절히 버무려서 저장하는 시점에 Log.e() API를 호출하도록 기능을 수정한다.

v1 변수는 이미 메모장 앱에서 사용자가 입력한 내용을 저장하기 위한 용도로 사용 중이다. 따라서 변수명을 변경해주고, Byte를 String형으로 바꿔주는 부분에서는 이 v1을 삽입하여 사용자가 입력한 내용의 Byte 변수가 String형으로 변환하는 흐름을 타도록 한다.

 

 

수정이 완료되면 이를 저장하여 다시 리패키징을 진행한다. 그리고 리패키징된 apk를 디컴파일 도구를 이용하여 제대로 소스코드가 삽입되었는지 확인한다.

 

 

이제 리패키징된 apk를 설치하여 실제 Eclipse환경에서 사용자가 입력하고 저장되는 내용이 Logcat에 정상적으로 Log가 남겨지는지 확인해본다.

 

 

 

다음과 같이 정상적으로 Log가 찍힌것을 확인할 수 있다.


지금까지 Smali 코드 수정으로 리패키징을 통해 간단히 보여준 사례 예시는 다른 방법으로도 응용이 가능하다. 예를 들어 Log.e() API를 호출하는 지점에 E-mali이나 특정 서버에 해당 메시지를 전송하게 한 Class를 생성하고 호출 하는 코드를 삽입하여, 리패키징된 앱을 배포를 한다면 그에 따른 정보는 고스란히 넘어가게 될 것이다. 따라서 이러한 리패키징 앱에 대한 위험성을 염두하고 있어야 하며 앱 사용시 각별히 주의를 해야할 것이다.

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

 

  - 리패키징 전, 서명 값

 


 

  - 리패키징 후, 서명 값

 

 


원본의 서명 키를 원본 앱을 만든 개발자에게서 구하지 않는 이상 동일한 키를 이용하여 리패키징 된 앱을 서명할 수는 없을 것이며, 따라서 원본 앱과 리패키징 앱을 구분 시, 다음과 같이 서명 값을 확인해서 비교하는 방법으로도 앱의 리패키지 여부를 알 수 있는 방법이 된다.

 

+ Recent posts