WeSeong Log in
← Back to posts
Android

안드로이드(Android) 간단 코드 분석, ADB(Android Debug Bridge)

안드로이드(Android) 간단 코드 분석, ADB(Android Debug Bridge)

Ⅰ. 개요

Android 악성 코드 분석을 위해 필요한 개념을 알아본다. apk파일을 디컴파일 했을 때 코드 분석을 어떻게 할 수 있는지 AndroidManifest.xml의 구성 위주로 살펴본다. ADB 실습을 통해 안드로이드 디바이스와 연결해서 리눅스 기반의 디렉토리 구조에 대해 간단히 알아본다.



Ⅱ. Android 악성 코드 분석을 위한 개념 잡기

'jadx-gui' 프로그램과 같이 안드로이드 애플리케이션(apk)파일을 디컴파일 했을 때 구조를 알아야 한다. 코드 분석을 통해 취약점을 찾기 위함이다. apk파일의 구조를 간단하게 알아보자.


jadx-gui 프로그램으로 샘플 apk 파일을 디컴파일했을 때의 구조이다. 어디서 많이 본 적 있지 않은가? Java로 개발을 진행해 본 사람이라면 익숙할 수 있을 것이다. Java 기반으로 된 안드로이드이기 때문에, 안드로이드 애플리케이션도 OOP(Object Oriented Programming)인 객체 지향 프로그래밍의 Java Class 구조를 가진다. 정확히 개발자가 작성한 코드를 원본 그대로 알려주는 것은 아니지만, 코드 분석을 하기엔 충분하다. 'com.metasploit.stage'은 이 애플리케이션의 전체 패키지를 의미하고 그 안에 a~g 클래스들이 별도의 기능들을 담당한다. MainActivity, MainBroadcastReceiver, MainService는 지난 게시글에 이야기한 안드로이드 앱 컴포넌트의 역할을 수행하고 있다. 물론, 실제 이렇게 클래스가 무슨 역할을 하는지 명확한 클래스명을 사용하지 않을 가능성이 높다. 개발 과정에선 명확한 클래스명을 사용했겠지만, 실제로 이렇게 디컴파일을 통해 코드 분석이 가능한 것을 개발진들도 모두 알 고 있기 때문에, 상용화(앱 배포) 단계에선 보안을 위해 감춰둘 것이다.


리소스 디렉토리는 애플리케이션이 사용하는 문자, 이미지 등의 정적 데이터들이 있거나 META-INF, AndroidManifest.xml, Classes.dex, Resources.arsc가 있다. META-INF는 앱 서명의 공개키가 담긴 인증서이고 AndroidManifest.xml은 패키지 정보나 권한 앱의 구성 요소(컴포넌트 Activity, BroadcastReceiver 등)의 정보가 담겨 있고 Classes.dex는 애플리케이션 실행을 위해 위의 소스 코드를 클래스별로 정리해서 바이트 코드로 변환 후 dex 형식으로 최적화한 형태이다. 마지막으로 Resources.arsc는 컴파일 된 리소스(문자열, 디자인 등)이 존재한다.






이제 코드 분석을 위해 살펴봐야할 점을 하나씩 알아보자. 먼저 위 사진은 AndroidManifest.xml이다. 안드로이드 애플리케이션을 구성하는 컴포넌트가 정리되어 있고 권한 관련 정보나 하드웨어 관련 정보가 담겨 있다. 이 파일을 먼저 열어보는 이유는 전체적으로 어떤 역할을 하는 앱인지 그림을 그릴 수 있기 때문이다. 물론, 이것으로 전부를 알 수 없다. 특정 앱 중에서는 실제 사용하지 않는 권한 관련 정보도 넣기 때문인데, 현재 앱이 설치된 안드로이드 핸드폰을 실사용하는지, 아닌지 구분하기 위함이다. 이를 일반적으로 uses-permission 항목을 추가하면서 알아보는데, 앱 로딩 시 블루투스를 키고 끄거나 네트워크 접속을 확인해보거나 기울기 센서를 이용해보는 등의 작업을 통해 알아본다. 이는 악성 코드 앱만이 아니라 일반 사용자 앱도 마찬가지의 이유로 uses-permission을 구성하는 경우가 있다.


※ 모든 안드로이드 애플리케이션들은 패키지 이름이 겹칠 수 없다. 리눅스 기반인 안드로이드 운영체제에서 이 패키지 이름과 PID를 통해 프로세스를 관리하기 때문이다. 그리고 위 사진에서 패키지명이 'com.metasploit.stage'일텐데, 보통 com.~으로 시작하지만 반드시 그럴 필요는 없다.


먼저, android:targetSdkVersion 부분을 간단히 얘기하고 가자면, 애플리케이션 구동을 위한 필요한 최소 버전이다. 우리가 Jar 파일을 실행할 때 Java 버전을 확인하듯 앱 실행이나 구동에 있어 위의 버전 정보를 충족해야 한다. uses-permission 부분을 보면 정확히는 모르더라도 간단하게 영어 해석을 해보면 안드로이드에 어떤 시스템의 권한을 쓴다는 걸 알 수 있을 것 같지 않은가? 즉, 앱이 구동하는데 필요한 필수적인 데이터, 하드웨어 등에 대해 권한을 사용하겠다고 명시해준 목록이다. 이 부분이 미리 정의되어 있어야 안드로이드 운영체제가 확인 후 실제 해당 하드웨어나 데이터를 사용할 수 있게 해준다.


※ 애플리케이션 설치시 혹은 사용시 권한을 물어본 적은 많은 경험이 있을 것이다. 이는 개발자가 책임지는 것이 아닌 사용자에게 책임을 전가하는 것인데, 이 부분은 그저 알아만둬도 된다...



application의 activity, receiver, service 부분은 안드로이드 컴포넌트가 어떻게 구성되는지를 정의한 부분으로 자세한 부분은 아직 공부가 더 필요하지만, intent는 지난 게시글에 이야기하긴 했지만, 진입점을 뜻하고 예시로 android.intent.category.LAUNCHER는 앱의 진입을 위해 사용자에게 보여주는 아이콘을 의미한다고 보면 된다. 컴포넌트를 다시 한 번 간단히 얘기하고 가자면, activity는 사용자에게 보여지는 부분(UI)이고 broadcastreceiver는 내부 이벤트 핸들링을 위한 것이고 services는 백그라운드 작업 부분, 여기에는 없지만 content provider는 공유 데이터를 제공하는 부분에 대한 것이다. 그래서 추가적인 예시로 receiver 부분에 android.intent.action.BOOT_COMPLETED는 핸드폰이 부팅이 완료된 이후 앱을 시작할 수 있게 해준다.


※ 안드로이드는 진입점이 많다. 앱 아이콘을 눌러서 실행하거나 알림 메시지, 백그라운드에서 음악 재생, 인터넷 광고 클릭 후 쿠팡이나 카카오톡 같은 어플로의 진입 등 그래서 반드시는 아니지만, 코드 분석할 때 activity부터 하는 경우가 있다.



Ⅲ. ADB 실습

ADB(Android Debug Bridge)는 안드로이드용으로 디버그를 위한 Tool이라고 생각하면 된다. 이를 활용해 여러 작업을 할 수 있을텐데, 디바이스의 내부 구조를 살펴보거나 여러 애플리케이션 중 악성 코드 앱을 판별해보는 과정을 윈도우에서 할 수 있게 도와준다.

SDK 플랫폼 도구 출시 노트  |  Android 개발자  |  Android Developers

여기서 다운로드받을 수 있으며,

Android 디버그 브리지(adb)  |  Android 개발자  |  Android Developers

사용법에 관련된 자세한 정보는 여기서 얻을 수 있다.


간단한 명령어를 소개하자면,

명령어

설명

adb devices

PC 와 연결된 디바이스 및 에뮬레이터 연결 목록 확인, “adb kill-server” 로 연결 종료

adb install [apkfilename.apk]

디바이스에 apk 파일 설치

adb uninstall [package name]

디바이스에 설치된 패키지 삭제

adb push [pc path] [android path]

PC 에 저장된 파일을 디바이스에 복사

adb pull [android path]

디바이스에 저장된 파일을 PC로 복사

adb shell

연결된 디바이스 쉘 실행

adb logcat

연결된 디바이스 로그 모니터링

adb connect 127.0.0.1:62001

127.0.0.1의 62001 포트에 adb 연결

adb shell pm list packages

연결된 디바이스에 설치된 모든 패키지 목록 확인

adb shell pm list permissions

연결된 디바이스에 어플리케이션에 대한 권한 목록

ADB를 통해 실습을 진행하려면 안드로이드 디바이스가 필요하기 때문에, Nox Player를 설치하고 진행했다.

녹스 앱플레이어 - PC에서 모바일 게임을 안전하고 렉 없이 즐기세요.

그리고 마지막으로 다운로드 받은 ADB의 파일 경로를 환경 변수로 등록해서 어느 경로에서든 사용하기 쉽게 만들었다.

방법은 설정 - 시스템에 들어간 후


정보에 들어간다. 들어가면 중간에 고급 시스템 설정이 나올텐데 눌러주면,


환경 변수가 있다. 들어가서


저 Path를 클릭해주고 새로 만들기를 누른 뒤 ADB 파일 경로를 그대로 넣어주면 된다.


이제 ADB 명령어로 디바이스에 연결을 시도해보자.(아 그전에 Nox를 꼭 실행시켜 놓자.)


이렇게 adb devices를 입력하면 아무 디바이스도 나오지 않을 것이다. 그렇다면 이제 실행되고 있는 Nox를 찾아볼텐데


tasklist는 현재 실행 중인 프로세스 목록을 알아보고 findstr 명령어는 특정 문자열에 해당하는 결과만을 출력시켜준다. netstat -ano는 현재 열려있는 모든 서버 IP와 포트가 나온다. 이 중에서 Nox의 경우 62001 포트로 접속한다.


마지막으로 이렇게 연결을 시도해서 정상적으로 되면 adb shell로 리눅스 쉘이 열리는 모습을 볼 수 있다. 그렇다면 정상적으로 연결된 것이다. 만약, 연결된 걸 삭제하고 싶다면, exit로 셸을 나간 후 adb kill-server로 연결을 초기화할 수 있다.


※ 알아두어야 할 디렉토리로 /data/app, /data/data, /system/vendor/lib, /proc, /storage/emulated/0이 있다. 맨 앞에서부터 /data는 애플리케이션 공유 디렉토리로 일반적인 데이터나 apk 실행 파일 등이 있다. /system은 시스템 설정 파일 관련 부분이고 /proc는 프로세스 관련 디렉토리이다. 리눅스의 파일 구조를 떠올리면 된다. 마지막으로 /storage 부분은 SD카드를 의미한다. 개인 사용자 정보의 경우 리눅스에서 /home/사용자계정 디렉토리가 만들어지듯 사용자 계정 디렉토리에 저장된다. 다른 일반 사용자가 접근할 수 없게 하기 위함이다.