원래는 안드로이드 어플리케이션에서 어떻게 루팅을 탐지하는지에 대해서만 발표하려고 하였으나, 처음 안드로이드 공부할 때 많이 막막했던 것이 생각나기도 하고, 처음 하는 분들에게 조금이라도 도움을 드릴수 있고자 안드로이드에 대한 기본적인 내용을 추가하고, 루팅 탐지 부분의 비중을 낮춰서 안드로이드 101으로 발표 주제를 정했습니다.
목차는 크게 다음과 같습니다.
- APK에 대한 기본적인 지식들
- APK 분석 방법
- 루팅 탐지 방법
아시다시피 요즘 날의 모바일 어플리케이션 생태계는 크게 안드로이드와 iOS로 나눌 수 있습니다.
그중에서 non-native code 인 달빅 바이트 코드를 사용하며, 상대적으로 디버깅하기 쉬운 안드로이드 어플리케이션에 대하여 이야기해보려고 합니다.
앞에서 non-native code에 대하여 언급했는데, 조금은 헷갈릴 수 있는 개념이라 간단하게 정리하고 넘어가겠습니다. 정확하게 까지는 아니더라도 대충 native 한 게 어떤 느낌인지 정도만 아셔도 괜찮을 것 같습니다.
우선은 managed code입니다.
이 managed code는 microsoft에서 2003년에 비주얼 스튜디오 2003을 출시하면서 발표한 개념입니다. 마이크로소프트 사의 C#이나 VB .NET 이 managed code에 포함되며, 그리고 많이들 사용하는 Python, Java 등도 여기에 포함됩니다.
소스코드가 실행되기까지의 과정에 대하여 간단하게 이야기해보면, 사용자가 작성한 소스코드는 IL 즉 중간 언어로 컴파일되는데, 이 IL 은 어셈블리어 정도로 생각하시면 될 것 같습니다. 그 후 IL 파일이 정상인지 확인한 후 runtime에 사용되는 메소드를 호출합니다.
이 지터에서 runtime 시에 사용되는 메모리나 예외 등을 처리해주기 때문에, 파이썬처럼 변수를 따로 할당하지 않아도 알아서 메모리를 할당해 주고 해제해줍니다.
다음으로는 unmanaged code입니다.
managed code에 반대되는 개념으로 예전부터 있던 전통적인 C 등이 여기에 포함됩니다.
소스코드는 각 환경에 맞게 바로 컴파일되어 기계어로 된 프로그램의 형식으로 실행되며, C언어를 하면서 많이들 느꼈겠지만 필요한 메모리를 직접 할당(malloc) 및 해제를 해줘야 합니다.
참고로 알고리즘 할 때 많이 사용되는 C++ 은 managed code 가 될 수도, unmanaged code 가 될 수도 있습니다.
마지막으로 좀 모호하다고 생각되는 native code입니다.
보통은 native code를 unmanaged code의 동의어의 일종으로 생각해서, 크게 managed code와 native code로 나누기도 합니다. 이전 슬라이드에서 말한 것처럼 native code와 non-native code로 나눈 것처럼 말이죠.
하지만 native code는 unmanaged code 일 수도, managed code의 산출물인 machine code 인 기계어도 될 수 있습니다.
이 부분에 대해서는 pwnwiz 님이 더 잘 아시니, 잘 모르겠다 싶은 것은 pwnwiz 님께 질문하면 잘 알려주실 겁니다.
apk 해킹? 이 맞는 말인지 모르겠지만, apk 해킹에서 제가 가장 중요하다고 생각하는 것은
리패키징 방지 우회 및 루팅 탐지를 우회하는 것이라고 생각합니다.
왜냐하면 리패키징 방지와 루팅 탐지 2개에서 자유롭다면 분석의 난이도는 다르지만, 그래도 코드를 변조해서 무엇인가는 할 수 있기 때문입니다.
안드로이드 어플리케이션인 apk의 경우 iOS 어플리케이션인 ipa에 비하여 단순한 zip 구조로 구성되어 있으며, 별다른 절차(루팅) 없이도 개발자 도구 중 하나인 usb 디버깅 모드로 apk의 설치 및 삭제가 가능합니다.
그래서 사용자는 설치된 apk를 추출하거나 외부에서 apk를 구하여, 수정한 후 리패키징하여 다시 설치할 수 있습니다.
이렇게 되면 악의적인 사용자는 apk를 수정하여하고 싶은 것을 할 수 있게 됩니다.
apk의 구조를 조금 더 자세히 보자면,
소스코드는 dex 파일로 컴파일되며 여기에 apk에서 사용할 여러 리소스 파일들과 네이티브 코드들을 압축하여
apk를 생성합니다.
이 apk를 설치하면,
반대로 압축을 풀면서 설치가 되고 달빅이가 바이트코드를 해석하고 실행이 됩니다.
앞에서 말한 바와 같이 apk 해킹하는데 첫 번째로 중요하다고 생각하는 리패키징 방지입니다.
리패키징 과정은 apk 만드는 과정을 거꾸로 포함하고 있습니다.
정상적이라면 소스코드에서 컴파일을 한 후, 패키징 과정을 거친 후에 서명을 하고 배포를 합니다.
하지만 리패키징 과정은 apk를 언패킹 해서, 디컴파일을 거쳐 소스코드를 획득하고, 수정을 한 후에 다시 apk를 만듭니다.
따라서 이렇게 리패키징을 통해 소스코드를 수정할 가능성이 있기 때문에, apk 가 리패키징되지 못하도록 방지해야 합니다.
이름은 밝힐 수 없는 한 게임이 있습니다. 물론 이 게임에서도 여러 보안 방식들로 자사의 어플리케이션을 보호하고 있습니다.
하지만 이렇게도 할 수 있다는 것을 보면서, 리패키징 방지의 중요성을 한번 더 생각해 봤으면 좋겠습니다.
우선 이러한 짓을 한 개요는 다음과 같습니다. 게임을 플레이하는 게 귀찮아서
“한 가지 색상으로만 나온다면 가만히 있어도 편하게 게임을 끝낼 수 있지 않을까?"
라는 생각으로, 파란색 캔디만 생성되도록 바꿔 보았습니다. 하지만 당연히 끝날 거라 생각했던 게임은 끝나지가 않았습니다,,
그다음으로 두 번째로 중요하다고 생각하는 루팅 탐지입니다.
여기서 루팅이란 정확히 뭘 말하는 것일까요? 루팅이란 최고 권한인 root를 획득하는 것을 말하며, 안드로이드 운영체제에서는 최고 권한인 superuser 권한을 획득하는 것을 말합니다.
이 권한으로는 일반적으로 할 수 없는 것들을 할 수 있게 해 줍니다.
예를 들면 접근이 불가능한 시스템 폴더 같은 곳에 접근해서 삭제 불가능한 좀비 어플을 삭제하거나, 어플리케이션이 사용하는 메모리에 접근해서 수정하는 것이 가능합니다.
초등학교, 중학교 때 게임을 많이 해보신 분들은 한 번은 써봤을 러키패처와 치트엔진입니다.
일반적으로 안드로이드에서는 각 어플리케이션별로 uid를 생성하고 각 uid 별로 관리되지만, 이 어플리케이션들은 루팅을 이용하여 다른 프로세스에서 사용하는 메모리를 수정할 수 있게 해 줍니다.
따라서 메모리 무결성 등이 중요한 금융이나 게임 어플리케이션의 경우 루팅이 되어 있는지를 확인해야 합니다.
앞에서 소개한 루팅을 탐지하는 것과 리패키징을 방지하는 것 외에도 여러 보호 기법들이 있습니다.
[*] 안드로이드 카카오톡을 대상으로 분석하였기에, 아래에 나오는 카카오톡은 안드로이드 버전의 카카오톡을 지칭합니다.
프로젝트를 진행하면서, 재미있어 보였지만 끝까지 하지는 못한 카카오톡 DB의 복호화에 관한 글을 적어 봅니다.
프로젝트 당시에는 많은 제약 조건들로 인하여 복호화 쪽은 다른 것들에 밀려 끝까지 분석해 보지 못했었습니다. 따라서 예전 분석한 것을 바탕으로 이번 기회에 시간을 더 투자하여 다시 한번 복호화를 진행하여 보았습니다. 결과부터 말하자면, 안드로이드 KakaoTalk 의 최신 버전인 v8.5.4 에서 진행하였으며 성공적으로 복호화 하였습니다.
메시지 원문
복호화할 대상을 생성하기 위하여 카카오톡 버전에 관한 정보와 DB 파일등을 주고 받았습니다.
카카오톡에서 메시지를 주고 받으면 위와 같이 평문으로 확인을 할 수 있습니다. 여기서 조금 추측을 해보자면 카카오톡이 네트워크에 연결되어 있지 않아도 채팅창에서 평문의 메시지를 확인할 수 있습니다. 따라서 서버에서 키와 관련된 정보는 받아오지 않는 것을 추측해 볼 수 있을 것 같습니다.
암호화된 DB
위는/data/data/com.kakao.talk/databases/KakaoTalk.db에서 추출한 카카오톡 메시지 관련 DB 입니다.
PC 버전 KakaoTalk의 경우에는 DB 자체가 암호화되어 있습니다. 반면에 안드로이드 KakaoTalk 의 경우에는 모바일이라는 특성 때문인지 messsage 부분과 attachment 부분만 암호화되어 있습니다.
즉 사용자가 주고 받은 메시지와 첨부파일에 대한 정보들만을 암호화하고 있습니다.
메시지 복호화
위는 DB를 성공적으로 복호화하여 CSV 형식으로 저장한 것입니다.
리버싱을 통해 암호화 루틴을 파악하고, smali로 되어 있는 코드를 java 코드로 구현하여 복호화를 진행하였습니다.
텍스트 메시지의 경우에는 메시지 부분에, 사진과 같은 첨부파일들은 첨부파일 부분에 카카오톡 파일 서버의 URL 과 같은 정보 등이 저장되어 있는 것을 확인할 수 있습니다.
Outro
카카오톡은대칭키를 사용하여 message 와 attachment 부분을 암호화합니다. 따라서 카카오톡 DB 복호화의 핵심 요소는암호화와 복호화할 때 사용하는 키입니다.
이 키는 서버에서 받아오거나 로컬에서 생성할 수 있을 텐데, 위에서 추측한 바와 같이 네트워크 연결이 없음에도 평문으로 내용을 확인할 수 있기에 로컬에서 생성할 것입니다. 실제로 DB에 저장되어 있는 값과 여러 고정 값들을 이용하여 키를 생성합니다. 이 부분은 내용이 길어지므로 나중에 별도의 글로 작성하겠습니다.
또한 필자와 같이 리버싱하여 사용자들이 카카오톡의 암호화 알고리즘을 파악할 수 있습니다. 이에 대한 변화가 필요하지만 기존에 암호화한 DB 와의 호환성을 위하여 무작정 암호화 알고리즘를 변경하기도 힘들다고 생각합니다. 따라서 카카오톡은 호환성을 유지하며 버전별로 조금씩 변화를 주며 키를 생성 하고 있습니다. 역시 이에 대한 자세한 내용은 길어질 것 같기에 나중에 별도의 글로 작성하겠습니다.