안드로이드 리버스 엔지니어링
리버스 엔지니어링(Reverse Engineering)
소프트웨어 공학의 한 분야로, 이미 만들어진 시스템을 역으로 추적하여 처음의 문서나 설계기법 등의 자료를 얻어 내는 일을 말한다. 이것은 시스템을 이해하여 적절히 변경하는 소프트웨어 유지보수 과정의 일부이다.
[네이버 지식백과] 리버스엔지니어링 [reverse engineering] (두산백과)
리버스 엔지니어링은 위의 내용과 같이 이미 만들어진 소프트웨어를 디컴파일해서 앱의 구성이나 설계구조를 분석하여 개발에 도움을 줄 수 있다. 주로 소스코드를 구하기 힘든 악성 소프트웨어와 같은 프로그램을 분석해서 이를 미리 알고 공격을 예방하는 부분에서 사용되기도 한다. 다른 방식으로는, 이미 만들어진 소프트웨어로부터 프로그램의 구성이나 사용된 라이브러리 정보를 보고 새롭게 만들어질 프로그램에 과거의 프로그램으로부터 좋은 반응을 얻었던 부분을 참고하여 추가 할 수 있게 해준다.
위에서 서술하였듯이, 리버스 엔지니어링은 해커에게도, 개발자에게도 도움을 준다고 할 수 있다. 이번에 하게될것은 안드로이드 어플리케이션 디컴파일 및 분석이다.
디컴파일 대상은 원스토어라는 어플리케이션이다. 여러 어플리케이션을 둘러보던 도중, 일반적인 오프라인형 게임과 같은 어플리케이션보다 온라인 결제모듈을 가지고 있는 대기업의 어플리케이션을 디컴파일 해보는것이 더 도움이 될것 같아 원스토어를 디컴파일 해보기로 결정했다.
1. APK 파일 추출
디컴파일하기 위해서는 먼저 APK 파일이 필요하다. 나는 안드로이드 스마트폰을 가지고 있지 않기 때문에, 블루스택을 이용했다. 블루스택과 함께 플레이스토어에서 배포되고있는 Apk Extractor을 이용해서 Apk 파일을 추출했다.
2. 디컴파일
디컴파일에 사용한 툴로는 apktool과 jadx가 있다. jadx는 이미 만들어진 apk 파일을 디컴파일하여 java 언어로 보여주는 툴이다. 하지만, java 코드로 apk를 수정 할 수 는 없다. 기계어로 되어있는 dex 파일을 직접 수정해야하기 때문이다. 따라서 apktool을 이용해 기계어를 그나마 사람이 읽을 수 있는 코드인 smali 코드로 디컴파일한 후, 리패키징해야 실제로 앱을 수정 할 수 있다.
실제 수정은 하지않고 분석만 할 것이므로, 디컴파일 한 후 java 코드와 smali 코드 각각 살펴보았다.
화면을 보았을 때, 학교에서 안드로이드 개발을 배울 때 봤던 익숙한 단어들이 보인다. 학교에서 안드로이드 앱 개발을 배울 때에도 xml과 kotlin, java를 같이 사용해서 개발했었는데, 원스토어 어플리케이션도 비슷한 방법으로 개발된것으로 보인다.
com 패키지를 열어보니, 몇몇 패키지가 난독화 되어있었다. 이렇게 패키지명에 기능을 직접적으로 써놓지 않으면, 해커들에의해 디컴파일되어 크랙 될 때 해커들이 코드를 분석하기 어려워진다.
jadx는 기본적인 난독화 해제툴이 탑재되어 있으므로, 이를 사용해보았다.
위에서 a.a.a.a나 b.a로 표현되던 패키지명들이 난독화가 해제된것이 아니라 사라졌다. 이러한 기본적인 난독화 해제 툴로는 해제가 불가능해 보인다. 따라서 기본적인 기능에대해서만 찾아보았다. 고도의 역공학 지식을 가지고있지 않기 때문에, smali코드 - java코드 간 차이를 살펴보고 평소 익숙했던 java 언어와 다른 smali 언어에대한 학습이 주를 이룰것이다.
java 코드
package com.google.android.flexbox;
import android.view.View;
import java.util.List;
smali 코드
.class interface abstract Lcom/google/android/flexbox/a;
.super Ljava/lang/Object;
.source "FlexContainer.java"
기본적인 클래스명, 상속, 패키지 경로도 조금 다르게 표현되는것을 알 수 있고, java에서 기본적으로 사용하는 Object 클래스도 smali 코드에서는 자세하게 나와있다.
마지막 .souce 부분은 파일의 원본명을 알 수 있다.
java 코드
int a(int i, int i2, int i3);
int a(View view);
int a(View view, int i, int i2);
smali 코드
# virtual methods
.method public abstract a(III)I
.end method
.method public abstract a(Landroid/view/View;)I
.end method
.method public abstract a(Landroid/view/View;II)I
.end method
# virtual methods 부분은 메소드 호출이 direct인지 virtual인지 나타냄
smali 코드에서 메소드는 .method로 시작, .end method로 끝남. java 코드를 보면 리턴타입이 모두 int인데, smali 코드에서 각 메소드의 첫번째 줄 끝에 보이는 I가 리턴타입인 int를 가리킨다. 해당 파일은 코드 내용이 전부 메소드 정의 이므로, 이번 코드 분석은 여기에서 끝내겠다.
3. 정리
- smali 코드에서 메소드 호출은 # virtual methods, # direct methods 와 같은 형식으로 표시한다.
- 메소드 정의는 .method로 시작해서 .end method로 끝난다.
- 리턴타입은 I(int), V(void)등과 같이 .end method 전 대문자 한글자로 표기한다.