안드로이드 실행파일은 APK파일로, 컴파일 한 결과물을 ZIP으로 묶은 것이다.
파일 내부를 살펴보면 기본적으로 다음과 같은 구조로 되어 있다.
o META-INF
o res
- AndroidManifest.xml
- classes.dex
- resources.arsc
oMETA-INF : 개발자의 키로 APK파일을 사인한 결과값들이 저장되어 있다. 파일마다 SHA1값이 저장되어 있기 때문에 파일 변조시 기기에 설치가 되지 않는다.
ores : 소스의 그림파일들과 바이너리화된 xml파일들이 저장되어 있다.
-AndroidManifest.xml : 바이너리화되어 있음
-classes.dex : 컴파일된 소스
-resources.arsc : 컴파일된 리소스 관련 파일
이 상태에선 파일을 수정할 수 없지만, apktool이란 툴을 사용하면 수정이 가능하게 된다.
APKTOOL : http://code.google.com/p/android-apktool/
이 툴을 사용하여 apk파일을 디코드 해보자. 디코딩 후 결과를 보면 다음과 같다.
o res
o smali
- AndroidManifest.xml
- apktool.yml
res폴더와 AndroidManifest.xml는 주석을 제외하면 기존 소스의 res폴더와 동일하게 얻을 수 있다.
xml파일은 일반 텍스트문서로 디코딩된다.
apktool.yml은 apktool 내부에서 사용하는 파일이다.
남은 smali폴더는 기존소스의 src폴더와 대응되는데, smali폴더를 살펴보면 기존 소스의 src폴더와 동일한 구조에 확장자가 smali로 바뀐 것을 알 수 있다.(크기가 큰 클래스는 여러 파일로 분리되어 있다.)
1 package com.test; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 6 public class TestActivity extends Activity { 7 /** Called when the activity is first created. */ 8 @Override 9 public void onCreate(Bundle savedInstanceState) { 10 super.onCreate(savedInstanceState); 11 setContentView(R.layout.main); 12 } 13 }
위 소스가 smali문으로 바뀌면 다음과 같이 변한다.
1 .class public Lcom/atest/AtestActivity; 2 .super Landroid/app/Activity; 3 .source "AtestActivity.java" 4 5 # direct methods 6 .method public constructor <init>()V 7 .locals 0 8 9 .prologue 10 .line 7 11 invoke-direct {p0}, Landroid/app/Activity;-><init>()V 12 13 return-void 14 .end method 15 16 # virtual methods 17 .method public onCreate(Landroid/os/Bundle;)V 18 .locals 2 19 .parameter "savedInstanceState" 20 21 .prologue 22 .line 11 23 invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V 24 25 .line 12 26 const/high16 v0, 0x7f03 27 28 invoke-virtual {p0, v0}, Lcom/atest/AtestActivity;->setContentView(I)V 29 30 .line 15 31 return-void 32 .end method 33
쉽게 생각하면 smali는 dex포맷을 사람이 쉽게 읽을 수 있도록 표현된 형식으로, C와 어셈블리의 관계 정도로 생각하면 된다.
이제 적절한 수정을 한 후 재컴파일 하면 dist폴더에 apk파일이 생성된다.
이 파일을 기기에 설치하려 하면 설치가 되지 않는데, 인증관련 파일이 빠져있기 때문이다.
개인키 또는 motizen-sign으로 사인후 설치할 수 있다.
추가로 dex2jar와 jad를 사용하면 java코드로도 디컴파일할 수 있다.
문제는 이렇게 하면 파일 변조가 가능하기 때문에 개발자들, 특히 유료 앱을 개발하는 경우 조금 더 신경써야 한다.
예를 들어, 번들로 들어간 앱들을 보면 특정 기기에만 동작하도록 되어 있는데, 코드 구조를 생각해보면 다음과 같다.
1 ... 2 const-string v0, 기기명 3 const-string v1, "SHW-M200K" 4 if-eq v1, v2, :cond_0 5 # 기기명이 틀리니 종료 6 cond_0: 7 # 기기명이 같으니 계속 8 ...
여기서 다른 기기들은 if문에서 분기되어 종료되는데, if-eq를 if-ne로만 바꾸어도 기기락을 풀어버리게 된다.
물론 요즘 출시되는 폰들의 어플들은 기기 의존적인 라이브러리를 필요로 하는 경우가 많아서 이렇게 간단하게 풀리지는 않는다.
이번에는 구입한 제품인지를 인증하는 경우를 생각해보자.
1 const v0, 인증결과; 2 if-eqz v0, cond_0 3 # 인증실패, 종료 4 cond_0: 5 # 인증성공, 계속 6
코드 내용이 어떠하던지, 결국 위와 같은 분기가 있을 것이기 때문에, 마찬가지로 코드를 수정해주면 인증과정이 풀리게 된다.
인증 실패시 나오는 문자열의 resource id값과 logcat을 활용하면 도움이 된다.
NDK와 JNI를 사용하면 코드 내용을 숨길 수 있지만, 결국 인증되어 있는지 여부는 JAVA 코드에서 판정하고, C코드에서 처리한다고 하더라도 작성 및 디버깅이 어렵기 때문에 쉽지 않은 일이다.
Twitter와 Facebook같이 서버와 통신하기 위해 인증을 하는 어플들은 어플 등록을 할때 받게 되는 APP ID와 같은 값이 필요하다.
이런 값들은 소스에 포함되는데, 암호화 되어 있지 않기 때문에 apktool이나 strings.exe 등으로 쉽게 확인할 수 있다.
그렇다면 값을 암호화해서 저장한 후 필요할 때 복호화 한다면 어떨까?
이런 경우 코드상으로는 알 수 없으나 실행시 로그를 출력하게 한다면 충분히 알아낼 수 있다.
1 ...복호화해서 v1에 저장한다... 2 const-string v0, "Test" 3 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I 4 ...v1으로 인증요청... 5
위와 같이 코드 사이에 Log.d()함수를 추가시키면 값이 고스란히 드러나게 된다.
트위터나 페이스북의 인증키 값은 그렇게 중요하지 않지만, 특정 서버에 접속하기 위한 패스워드 등 중요한 값들은 저장 및 사용에 신경을 써야 할 것이다.
JNI에서 직접 자바 메소드를 호출 할 수도 있다.
하지만 그러면 디버깅이 복잡해지는 문제가 발생한다.
이외에 proguard라는 툴로 코드를 난독화할 수도 있다.
클래스나 메소드, 변수명 등을 a, b, dd등과 같이 의미 없는 이름으로 바꾸어주는 것으로, 이렇게 된 어플 들은 임의 수정이 어려워지게 된다.
그러나 난독화하면 안되는 부분을 구분해야 하고, 디버깅이 극단적으로 어려워지게 되는 등의 문제들이 있고, 변수 값들은 보호되지 않는다.
그리고 분석이 매우 어려워지는 것이지 절대 불가능 한 것은 아니기 때문에, 오랜 시간과 노력으로 풀 수도 있다.
=========================================================================================================================
Android Decompile - http://sailerya.tistory.com/47
오늘은 Android 최종 package 형태인 apk 파일에 대해서 Decompile 하는 방법을 소개 하겠습니다.
최종 APK 파일이 나오기 까지는 아래 그림처럼 많은 단계를 거칩니다.
대충 간단하게 정리해보면 리소스 파일들과 java 컴파일된 dex 파일 그리고 signature 정보가 들어가게 됩니다.
여튼 자세한 정보는 여기를 참고 하시고… http://developer.android.com/guide/developing/building/index.html
우리가 열심히 개발한 소스는 classes.dex 라는 파일 안에 들어가게 되는데.. 이 dex 파일을 풀면 class 파일들이 나옵니다.
이 class 파일을.. decompile 하면 소스 코드가 보이는 것이죠..
이런 코드가
이렇게까지 디컴파일 됩니다.
그럼 자세한 decompile 순서를 알아보겠습니다.
- Apk 파일을 압축을 풉니다.
알집을 사용해도 되고.. 간단하게 jar xf hello.apk 하면 apk 파일이 풀립니다.
위 그림처럼 android manifest파일과 사용한 resource들 그리고 classes.dex 파일과 META-INF의 signature 정보들이 보입니다.
- Dex를 jar로 변환합니다.
Classes.dex 파일은 android의 dalvik 에서 사용하기 위한 일종의 jar 패키지 형태인데.. 이를 다시 jar로 변환이 가능합니다.
http://code.google.com/p/dex2jar/
여기에서 간단히 쓸 수 있는 변환툴을 다운로드 할 수 있다.
실행해보면
Jarfile이 하나 생긴 것을 알 수 있다.
- Jar를 class로 압축을 풀어줍니다.
다시 jar xf classed_dex2jar.jar 하면 압축이 풀리면서.. class 파일들이 나온다.
Class 파일은 아시다시피 중간 바이너리 형태라 디컴파일이 가능하다.
- Class 파일을 디컴파일 하여 보는 툴을 사용하여 소스를 본다.
소스를 보기위해.. jd 라는 툴을 사용하면 된다.
http://java.decompiler.free.fr/?q=jdgui 여기서 다운 받을수 있다.
다운받아 간단히 실행하여 class 파일을 열어보면 소스가 나온다..
정말 무서운 세상이다…
다음에 시간이 되면.. 소스를 디컴파일로부터 보호하는 방법을 블로깅 해보겠다..
==============================================================================================================================================
개발자가 아니더라도 쉽게 apk를 분석해보자
http://raimsoft.com/xe/index.php?mid=guide&document_srl=1890
여러 커뮤니티에서 많은 apk를 받아보신 분들이라면 한번쯤은 apk가 어떤 구조를 가지고 있나 궁금하신 분들이 계실 껍니다.
APK는 Android PacKage의 약자입니다.
안드로이드에서 제공하는 패키지와 같은 의미 인데요.
자세한정보: http://en.wikipedia.org/wiki/APK (file_format)
먼저 아무 apk를 잡아다가 뜯어봅시다.
방법은 아주 쉽습니다.
알집이나 winzip, winrar, 7-Zip 같은 유틸로 쉽게 압축을 풀 수 있습니다.
그런데 뜯어서 뭐하냐고요? 개발자의 경우는 dex파일을 이용하 디컴파일할 경우 합법적인 방법에는 어긋나지만 프로그래밍 공부를 할 수도 있고
유저의 경우에는 정보파일만 봐도 이 파일이 내 폰에서 돌아가는지 등의 여부를 알 수 있답니다.
저는7-Zip을 이용하여 압축을 풀어보겠습니다.
여기서 일반 압축 응용 프로그램으로 쉽게 풀린다는 뜻은 안드로이드 SDK 툴에서 컴파일시에 java와 리소스 파일들을 암호화하지 않고 압축시킨다는 것입니다.
자 그러면 대부분의 apk는 6가지의 무언가가 나옵니다.
assets : 패키지가 가지고 있는 외부리소스 폴더입니다.
res : 패키지가 가지고 있는 내부리소스 폴더입니다.
META-INF : 프로그램 자체 정보 데이터. 배포시 인증서로 서명한 내용입니다.
classes.dex : 클래스들의 정보를 함축적으로 가지고 있는 파일입니다.
resources.arsc : 별도로 컴파일된 리소스 파일입니다.
AndroidManifest.xml : 안드로이드 어플리케이션에 대한 전반적인 정보입니다.
AndroidManifest.xml 파일의 경우 바이너리로 암호화 되어있기 때문에 이를 복호화 하려면 별도의 툴이 필요합니다.
AXMLPrinter2.jar 파일을 다운받아 봅시다.
그리고 이 jar파일을 AndroidManifest.xml가 있는 동일경로에 둡니다.
※ jar파일을 실행하려면 java JRE가 설치 되어있어야 합니다. (http://java.com)
그리고, 윈도우의 경우 [시작]-[실행]-[cmd]를 적고 다음과 같이 적어 줍니다.
cd .. cd android/ : 경로로 가는 작업
java -jarAXMLPrinter2.jarAndroidManifest.xml> print.txt
이 명령어는 이런 뜻입니다.
JRE의 java.exe를 jar옵션을 사용하여 AXMLPrinter2.jar를 실행시킨다.
AXMLPrinter2.jar 는 AndroidManifest.xml을 print.txt로 복호화하여 새 파일을 생성한다.
자, 그러면 위와 같이'print.txt'파일이 생성 되었습니다.
그러면 이제 그냥 열어보시면 됩니다.
초록색은 다음과 같은 의미입니다.
android:versionCode="13" // 버전 코드 13 (13번째 버전)
android:versionName="2.1.10" // 버전 이름
package="com.herocraft.game.farmfrenzy" // 패키지의 이름은 herocraft.com의 farmfrenzy
붉은색은 다음과 같은 의미입니다.
android:minSdkVersion="4"
사용한 SDK버전의 API Level은 4 제가 옆에 써놓은 표를 보시면 쉽게 아시겠죠?
(즉, 이 게임은 안드로이드 버전 1.6 이상에서 설치가 가능하다는 것입니다.)
푸른색은 핸드폰에게 퍼미션 (권한)을 요구하는 부분입니다.
android:name="android.permission.INTERNET" // 이 어플이 인터넷을 사용할 수 있다.
android:name="android.permission.READ_PHONE_STATE" // 폰의 정보를 요구할 수 있다.
android:name="android.permission.SEND_SMS" // SMS을 발신할 수 있다.
android:name="android.permission.READ_CONTACTS" // 연락처를 읽을 수 있다.
android:name="android.permission.VIBRATE" // 진동을 요청할 수 있다.
마지막 갈색은 호환되는 스크린의 목록을 말합니다.
android:anyDensity="true" // 모든 해상도를 지원한다.
android:smallScreens="true" // 작은 스크린을 지원한다. HVGA (320x480)을 말합니다.
android:normalScreens="true" // 일반 스크린을 지원한다. WVGA (480x800, 480x854)를 말합니다.
android:largeScreens="true" // 큰 스크린을 지원한다.
==============================================================================================================================================
dex 파일 디컴파일(decompile) - [http://blog.naver.com/PostView.nhn?blogId=gigar&logNo=60115566766]
안드로이드 어플리케이션 파일인 APK(Android PacKage)파일은 zip과 같은 하나의 압축 파일입니다.
어플리케이션에 관계된 파일들을 하나로 압축해 놓은 파일일 뿐이기 때문에. 압축 프로그램을 사용하여 압축을 풀수 있습니다.
APK파일이 만들어지는 구조도를 보면 다음과 같습니다.
apk파일의 압축을 풀면 나오는 *.dex 파일은
안드로이드 가상 머신인 dalvik이 인식할 수 있도록 *.class파일을 바이트 코드로 변환 된 파일이다.
*.dex 파일을 jvm 바이트 코드로 디컴파일 하여 .class 파일을 추출 할 수 있다면, 안드로이드 어플리케이션의 java 코드의 추출이 가능하다.
dex 파일을 디컴파일 하기 위해선 다음과 같은 준비물이 필요하니 다운로드 하여 주십시오.
※ *.dex파일을 *.class파일로 디컴파일 하는데 필요 ※
- undx.jar ( http://www.illegalaccess.org/undx.html ) - dxdump.zip ( http://dex-decomplier.googlecode.com/files/dexdump.zip ) |
※ *.class 파일을 *.java파일로 디컴파일 하는데 필요 ※
- jd-gui ( http://java.decompiler.free.fr/?q=jdgui#downloads ) |
디컴파일 테스트를 위한 HelloWorld-debug.apk파일을 미리 준비하였다.
패키지 파일중 액티비티를 상속 받은 java 클래스 파일에 테스트를 위한 비교값으로 statiic 으로 선언된 String 변수와 int 변수를 선언하여 각각 값을 넣었다.
.dex파일의 디컴파일 과정은 다음과 같다.
1) .dex 파일을 .jar파일의 형태로 디컴파일.
2) 디컴파일된 .jar파일을 .java 형태로 다시 디컴파일.
앞서 미리 만들어 놓은 HelloWorld-debug.apk 파일의 압축을 풀어 디컴파일 테스트를 준비한다.
그리고 준비한 undx.jar 파일과 dexdump 관련 파일을 압축을 풀어놓은 디렉토리에 위치시킨다.
디컴파일을 하기 위한 명령어는 다음과 같다.
java -DASDKLoc={Location of dexdump} -jar undx.jar {dexfile}
압축을 푼 디렉토리에 있는 classes.dex파일을 디컴파일 하기 위한 명령어를 cmd 창에서 실행한 화면이다.
.dex파일을 디컴파일 하는 과정
프로젝트 폴더 밑의 gen 폴더를 확인하면 classes.dex 파일이 ,jar 파일로 디컴파일 된 파일을 확인 할 수 있다.
이제 .jar파일을 다시 디컴파일 하여 내용을 확인해 보자.
원본의 내용
디컴파일된 내용
디컴파일을 한다고 하여 컴파일 되기 이전의 형태와 완전히 동일하지는 않다.
그러나 디컴파일을 통해 컴파일 되기 이전의 클래스 파일의 정보는 확인 가능하다.
참고 사이트
http://teamcrak.tistory.com/268 http://kozazz.tistory.com/tag/decompil http://aquarium.72pines.com/2010/02/24/using-undx-to-decompile-android-dex-bytecode/ |
'Mobile Development > Android ' 카테고리의 다른 글
안드로이드 자바 개발환경 및 유용한 개발 툴들 (0) | 2013.04.09 |
---|---|
Android Apk De compile 하는 방법 (0) | 2013.03.19 |
Apk Manager 안드로이드 APK 디컴파일-컴파일 하기 (5.0.2 버전 - ICS 가능) (0) | 2013.03.19 |
[안드로이드] framework-res.apk 수정방법(테마수정, 시스템어플수정) (0) | 2013.03.19 |
dex 파일 디컴파일(decompile) (0) | 2013.03.18 |
SAMSUNG DEVELOPER DAY 2012 (0) | 2012.11.14 |
안드로이드 SDK 설치(Android sdk Install) (0) | 2012.11.14 |
안드로이드 자바 개발환경 및 유용한 개발 툴들 (0) | 2012.11.14 |
안드로이드의 발전 과정: 1.0에서 젤리빈(Jelly Bean)까지 (0) | 2012.11.10 |
안드로이드 해킹 툴 ‘Anti’ 공개 (0) | 2012.05.09 |