안드로이드 앱 프로그래밍이나 apk 파일 설치 또는 adb를 이용한 안드로이드 기기 내의 콘솔작업을 하기 위해서는 기기의 USB 디버깅 모드를 활성화 시켜야 한다.

USB 디버깅 모드 활성화는 마치 이스터 에그처럼 안드로이드 OS 내부에 숨겨져 있는데 방법은 아주 간단하며 방법은 다음과 같다.

 

안드로이드의 설정으로 들어가서 맨 하단의 휴대전화 정보를 터치한다.

 

 

다시 맨 하단의 빌드 번호를 7번 터치한다.

 

 

7번 터치 후, 다음과 같이 개발자가 되셨습니다. ​라는 문구를 확인할 수 있다.

 

 

다시 설정으로 되돌아가서 맨 하단으로 내려가면, 이스터 에그처럼 개발자 옵션 메뉴가 추가된 것을 확인할 수 있다. 이를 터치한다.

 

 

USB 디버깅 메뉴의 체크박스를 터치한다.

 

 

다음의 문구에서 확인을 터치한다.

 

 

PC와 안드로이드 기기를 USB로 연결하였다면 다음과 같이 PC의 컴퓨터 RSA 키 지문에 대한 내용과 함께 접근 허용 질문에 대한 팝업이 뜬다. 확인을 터치한다.

 

 

다음과 같이 최종적으로 PC의 컴퓨터 RSA 키 지문에 대한 접근을 허용해야 USB를 통한 안드로이드 기기 접근이 가능하며, 접근 허용을 하지 않을 경우 USB 디버깅 모드를 활성화 하였다고 하더라도 PC를 이용한 adb 콘솔 접근은 불가능하다.

 

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

 

기본적으로 안드로이드 앱의 구성요소는 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를 생성하고 호출 하는 코드를 삽입하여, 리패키징된 앱을 배포를 한다면 그에 따른 정보는 고스란히 넘어가게 될 것이다. 따라서 이러한 리패키징 앱에 대한 위험성을 염두하고 있어야 하며 앱 사용시 각별히 주의를 해야할 것이다.

안드로이드 환경에서 root권한을 가지고 있다고 하더라도 다음과 같이 /system 폴더의 접근이 제한된다.

 


 

시스템 앱을 지우고 싶거나 추가를 하고 싶지만, 루팅을 하더라도 ro(Read-only) 권한으로 수정이 불가능하다.

이는 다시 remount하여 접근권한을 변경하면 수정이 가능하다. 명령어는 다음과 같다.

$ mount -o remount,rw 폴더명

 

 


다음과​ 같이 remount하여 접근 권한을 변경하고 앱을 /system/app에 복사된 것이 확인 가능하다.

​만약 다시 Read-only로 변경하고 싶다면, 옵션을 바꾸어 명령어를 입력하면 된다.

$ mount -o remount,ro 폴더명

 

 

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

 

  - 리패키징 전, 서명 값

 


 

  - 리패키징 후, 서명 값

 

 


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

 

 

기본적으로 Manifest, Resource, Certificate, Assembly, Decompiled Java, Strings, Constants, Notes 기능을 제공하며, 자체적으로 만든 dex 디컴파일 엔진을 이용해서인지, 일부 dex파일에 대한 바이너리 난독화에서도 에러 없이 디컴파일이 된다.

파이썬을 응용한 다양한 난독화 플러그인을 지원한다.

 

 

 

 

 

 

 

 

JEB Decompiler : https://www.pnfsoftware.com

 

 

 

안드로이드 apk 분석을 위한 무료 디컴파일 도구 중에 가장 막강한 기능을 제공한다.

기본 지원하는 파일 포맷은 jar, class, apk, dex 이며, 다양한 디컴파일러의 결과에 대한 비교 분석이 가능하다.


다음과 같이 여러 종류의 Decompiler 및 Smalicode, Bytecode, Hexcode Viewer 기능을 제공하며, 분할 창을 이용하여 서로 다른 디컴파일 결과나 Java 소스코드와 Smali 소스코드의 비교도 가능하다.


 

스트링 난독화에 대한 복호화 및 다양한 플러그인 기능

 

 

코드 흐름에 대한 시퀀스 다이어그램 기능

 

 

BytecodeViewer : https://github.com/konloch/bytecode-viewer/releases

 

 

안드로이드 apk 분석 디컴파일러인 jadx-gui 디컴파일러는 기존 jd-gui의 불편한 점(dex2jar를 이용한 dex→jar 변환)을 개선하여, dex2jar 도구의 없이도 apk 디컴파일이 가능하다.

또한, 소스코드 뿐만 아니라 리소스 부분도 확인이 가능하도록 기능을 확장하였다.

 

jadx-gui : https://github.com/skylot/jadx/releases

 

안드로이드 앱은 Java 언어 기반으로 프로그래밍되며, 작성된 소스는 Dalvik 가상 머신 기반에 동작하도록 컴파일 된다.

즉, jd-gul 도구에서 apk 앱을 분석을 하기전에 apk 내부의 dex 파일을 dex2jar 도구를 이용하여 class 파일로 전환하기만 한다면, Java 처럼 원본 코드와 흡사한 디컴파일이 가능하기 때문에 분석에 용이하다.

 

 

아래 그림에서 왼쪽은 Eclipse를 이용한 실제 원본코드이고, 오른쪽은 dex2jar와 dj-gui를 이용하여 디컴파일한 결과를 보여주는 코드이다.

 

 

dex2jar : https://github.com/pxb1988/dex2jar

jd-gui : http://jd.benow.ca

 

 

안드로이드의 앱은 기본적으로 .apk라는 파일 확장자 명을 가진다. 하지만, 사실상 이 파일의 Magic Number을 보면 다음과 같이 zip 형태의 파일 포맷을 가지는 것을 확인할 수 있다.

 

 

apk 파일의 압축을 해제하면 아래와 같은 구조를 확인할 수 있는데, 간단하게 3가지로 구분된다.

 

 

 

1. AndroidManifest.xml

  - 안드로이드 앱의 속성들을 주로 다루게 되는데 Activity, Service, Receiver, Persmission 등의 속성은 이 파일에서 정의된다. apk 파일을 단순히 압축을 해제 하였을 때 AndroidManifest.xml은 바이너리 형태의 xml로 인코딩 되어 형태를 알아보기 어렵지만, 이를 apktool과 같은 디컴파일러를 통하여 확인하면 디코딩된 xml 정보를 얻을 수 있다. 아래의 그림은 AndroidManifest.xml에 대해 디컴파일 전과 후의 xml 파일에 대한 정보를 비교한 그림이다.

 

 

 

2. Resource

  - 안드로이드의 Image, Style 등과 같은 정보는 Resource에서 관리하게 된다. 이것 또한 Apktool을 통하여 확인 가능하다.

 

 

 

3. DEX (Dalvik EXecutable)

  - Dex는 안드로이드에서 앱이 구동하기 위한 핵심적인 파일 포맷이다. dex 포맷형식에 대한 내용은 차후 포스팅에서 자세히 다루도록 하겠다. dex의 포맷형식에 대한 문서는 Android Source 사이트에 있으며 주소는 다음과 같다.

Dex Format : https://source.android.com/devices/tech/dalvik/dex-format.html


 

+ Recent posts