안드로이드 운영체제 구조
안드로이드 운영체제는 구글에서 개발한 리눅스 기반의 오픈소스 플랫폼이다. 리눅스 기반이라고 해서 우리가 PC에서 사용하는 리눅스 기반은 아니라 리눅스 커널을 기반으로 만들어진 오픈소스 플랫폼이다. 그래서 명령어나 파일 구조가 리눅스와 많이 유사하다. 구글 플레이 스토어 및 마켓 플레이스를 통해 타사 앱 설치를 지원하며, 오늘날 휴대전화, 태블릿, 웨어러블 기술, TV 및 스마트 디바이스와 같은 다양한 최신 기술의 토대이다.
아래 사진은 안드로이드 운영체제의 구조 아키텍쳐이다. 제일 하단을 보면 리눅스 커널과 HAL로 이루어져 있다. 이 부분은 커널 취약점 또는 하드웨어적인 부분을 분석하는 것이 아니라면 크게 신경쓰지 않아도 된다.
그 위쪽 부분이 안드로이드 개발을 하거나 분석을 할 때 주로 보는 부분이다. 각 구조는 다음과 같은 역할을 한다.
Android Runtime
- Android 버전 5.0 이상을 실행하는 디바이스의 경우, 각 앱이 자체 프로세스 내에서 자체 ART 인스턴스로 실행
- ART는 DEX 파일을 실행하여 저용량 메모리 디바이스에서 여러 가상머신을 실행하도록 함
- DEX 파일은 안드로이드용으로 특별히 설계된 바이트코드 형식으로, 최소 메모리 공간에 맞게 최적화되어 있음
Native C/C++ Libraries
- C/C++로 작성된 라이브러리
- ART 및 HAL 등의 많은 핵심 Android 시스템 구성 요소와 서비스가 C/C++로 작성된 네이티브 라이브러리를 필요로 하는 네이티브 코드 기반으로 이루어짐
- JAVA 프레임워크 API를 사용하여 일부 네이티브 라이브러리의 기능을 앱에서 사용 가능
Java API Framework
- 안드로이드 운영체제의 전체 기능은 JAVA로 작성된 API를 통해 접근 가능
- 개발자는 안드로이드 시스템 앱이 사용하는 것과 동일한 프레임워크 API에 대한 전체 접근 권한을 가짐
- 안드로이드 앱 제작에 필요한 빌딩 블록 구성(뷰 시스템, 리소스 매니저, 알림 매니저, 액티비티 매니저, 콘텐츠 프로바이더)
System Apps
- 이메일, SMS 메시징, 캘린더, 인터넷 검색, 주소록 등의 주요 애플리케이션이 제공됨
- 시스템 앱은 사용자를 위한 앱으로도 작동하고, 개발자가 자신의 앱에서 접근할 수 있는 주요 기능을 제공하기 위한 용도로도 작동함
안드로이드 4대 컴포넌트
앱 컴포넌트란 독립된 형태로 존재하면서 정해진 역할을 수행하는 안드로이드 앱의 필수적인 구성 요소이다. 안드로이드 앱은 동작할 때 이러한 앱 컴포넌트 구성 요소들이 서로 연결되면서 실행하는데 원할하게 동작을 하고 데이터 정보들을 교환하게 된다.
아래 그림을 보면 인텐트가 존재하며, 그 외에 Activity, Service, Content Provider, Broadcast Receiver 이렇게 4개의 컴포넌트(구성 요소)가 있다. 인텐트란 다른 앱 컴포넌트로부터 작업을 요청하는 데 사용할 수 있는 메시징 객체이다.
그 외의 4개의 컴포넌트는 다음과 같은 역할을 한다.
Activity
- 사용자와 상호작용하기 위한 진입점
- 사용자 인터페이스를 포함한 화면 하나를 나타냄
- 이메일 앱이라면 새 이메일 목록을 표시하는 액티비티 하나, 이메일을 작성하는 액티비티 하나, 이메일을 읽는 데 쓰는 액티비티 하나 등이 존재
- 이메일 앱에서 허용할 경우 다른 앱에서 이와 같은 액티비티 중 하나를 시작할 수 있음
Service
- 백그라운드에서 앱을 계속 실행하기 위한 다목적 진입점
- 사용자 인터페이스(UI)는 제공하지 않음
- 사용자가 다른 앱에 있는 동안 백그라운드에서 음악을 재생하거나, 사용자 액티비티 간의 상호작용을 차단하지 않고 네트워크를 통해 데이터를 가져올 수 있음
Broadcast Receiver
- 시스템이 정기적인 사용자 플로우 밖에서 이벤트를 앱에 전달하도록 지원하는 컴포넌트
- 대다수의 브로드캐스트는 시스템에서 발생(화면 꺼짐, 배터리 부족, 사진 캡쳐 알림 등)
Content Provider
- SQLite 데이터베이스, 웹상이나 앱이 접근할 수 있는 다른 모든 영구 저장소에 저장 가능한 앱 데이터의 공유형 집합을 관리함
- 다른 앱은 컨텐츠 제공자를 통해 해당 데이터를 쿼리하거나, 콘텐츠 제공자가 허용할 경우에는 수정도 가능
안드로이드 루팅
안드로이드 로팅이란 안드로이드 운영 체제 상에서 최상위 권한을 얻음으로 해당 기기의 생산자 또는 판매자 측에서 걸어 놓 은 제약을 해제하는 행위이다. 일반적으로 디바이스를 구매할 때 기술적으로 사용자는 디바이스의 소유자가 아니다. 이 때 루트 접근 권한을 얻어 디바이스를 완전히 제어하는 것이 루팅이다.
우리가 취약점 진단을 하기 위해서는 안드로이드 폰이 루팅 권한들이 부여되어 있어야 한다. 과거에는 가상 에뮬레이터를 이용하면 너무 느리고 분석이 힘들었다. 그래서 취약점 진단을 하기 위해서 실제 안드로이드 핸드폰에 루팅을 해서 진단을 했었다. 하지면 최근에는 녹스 플레이어 등 가상 에뮬레이터의 성능이 좋고, 루트 권한들을 다 부여해주기 때문에 별도로 루팅 작업을 하는 작업이 필요 없다.
안드로이드 루팅 장점
- 루트 접근 권한으로 파일 시스템 탐색 가능
- 루트 접근 권한이 있는 사용자는 특별한 기능이 있는 일부 앱 설치 가능
- 사용자 지정 복구 및 사용자 지정 ROM을 설치하면 공급 업체가 제공하는 것보다 더 나은 기능을 사용 가능
안드로이드 루팅 단점
- 루팅된 디바이스에서 루트 접근 권한이 있는 악성 앱에는 이 제한이 없어 실행중인 다른 앱에서 데이터 조회 가능
- 루팅 프로세스는 디바이스를 손상시켜 쓸모 없게 될 수 있음
- 루팅된 디바이스는 보증이 무효화됨
- 루팅한 후에는 보증기간 중이어도 수리비용을 지불할 수 있음
자바 컴파일 JVM & DVM
자바 가상 머신(Java Virtual Machine, JVM)은 자바 바이트 코드를 실행하기 위한 자바 가상 머신이다. 자바 바이트 코드는 JVM이 이해할 수 있는 언어로 JVM만 설치되어 있으면 어떤 운영체제에서도 실행 가능하다. 안드로이드 코드도 자바 소스 코드로 되어있다. 하지만 자바 소스 코드가 자바 바이트 코드로 변환 되는 것은 동일하나, 안드로이드 기반의 모바일에 맞춰서 최적화가 된다. 이것을 달빅 바이트 코드라고 한다. 이 때 Dex 파일인 달빅 바이트 코드를 동작시켜 주기 위한 가상 머신을 달빅 가상 머신(Dalvic Virtual Machine, DVM)이라고 한다.
DVM은 모바일 디바이스 환경에 최적화되어 개발된 가상 머신으로 낮은 메모리에서 실행되도록 설계되었다. 그래서 배터리 또는 성능 문제를 많이 고려하고 있다. 자바 프로그램들은 동작시키려면 많은 메모리를 사용하게 된다. 그래서 자바 바이트 코드를 달빅 바이트 코드로 변환한 Dex파일을 생성하고, 이 Dex파일을 DVM에서 실행하게 된다.
모바일은 가볍고 빨라야 하기 때문에 DVM은 스택 기반으로 동작하는 JVM과 달리 레지스트리 기반으로 동작한다. 레지스트리 기반은 CPU 레지스터를 기반으로 피연산자가 저장하고, PUSH, POP 연산자가 없어 간단한 명령으로 진행된다.
DVM은 앱 최초 실행 시에 컴파일을 수행하는 JIT(Just-In-Time) 컴파일 방식을 사용한다. 이 방식은 하드웨어 부하로 배터리 시간 등 부정적인 영향을 미친다. 그래서 퍼포먼스 개선 등을 위해 구글은 DVM에서 ART(Android Runtime)으로 변경하여 DVM의 JIT 컴파일 프로세스를 AOT(Ahead-of-time) 컴파일 프로세스로 변경하였다.
AOT 컴파일 방식은 앱 설치 시점에서 컴파일을 수행하여, 전력 소비를 줄이면서 성능을 향상시켰다. 이후 2016년 안드로이드 누가 이후 ART에서는 JIT와 AOT 컴파일을 모두 사용하고 있다. JIT와 AOT를 모두 사용하여 설치시에는 무조건 JIT를 사용하고 차후 상황에 따라 유연하게 적용되어 사용되고 있다.
안드로이드 디바이스 디렉터리 구조
APK 파일을 안드로이스 디바이스에 설치를 하게 되면 APK 파일들이 압축이 해제되면서 안드로이드 디바이스 여러 곳에 설치가 된다. 그러면 그 설치된 공간을 가지고 취약점 분석을 하게 된다.
디렉터리 | 설명 |
/ | - 루트 디렉터리 - 부트와 관련된 설정 파일을 참고하여 초기 프로세스 정보를 포함 |
/system | - 안드로이드 운영체제 홈 디렉터리 - 안드로이드 UI 및 사전에 설치된 앱이 포함되고 운영체제 파일이 존재 |
/system/app | - 시스템에 의해 미리 설치된 앱 경로 |
/data | - 사용자 앱 상태 정보가 포함된 파일 시스템 디렉터리 |
/data/app | - 사용자에 의해 설치된 앱 경로 |
/data/data/<package>/ | - 설치 앱 패키지 경로, 루트 권한으로 접근 가능 |
/data/data/<package>/files | - 애플리케이션이 소유한 데이터 또는 파일 저장 |
/data/data/<package>/lib | - 애플리케이션이 요청하는 라이브러리 파일 저장 |
/data/data/<package>/databases | - 설정 파일, 컨텐츠 파일 등의 쿼리 정보가 포함된 SQLite 데이터베이스 파일 |
/data/data/<package>/cache | - 브라우저 캐시같이 일시적인 사용자 상태정보 포함 |
/data/data/<package>/shared_prefs | - XML 파일로 저장되며, 앱에 공유되는 설정 파일 |
/cache | - 자주 사용하는 데이터 및 앱 컴포넌트를 저장하는 디렉터리 - 읽기/쓰기 권한이 존재 - 브라우저 캐시같이 일시적인 사용자의 상태정보 포함 |
/mnt/sdcard/sdcard | - External/Internal SD Card 경로 |