* 64비트 단말기로 진행하다가 32비트 단말기로 진행하여 실제 진행시 달라질 수 있습니다.
실행시키면 1번 문제와 똑같다. 1번 문제와 똑같이 루팅 우회를 시도하였다.
동일하게 루팅이 우회되었고 이제 Secret String을 찾으면 된다.
JEB로 apk를 Open한 뒤 Launcher Activity인 MainActivity로 갔다.
분석하던 중 verify라는 함수에서 실행했을 때 뜬 문자열이 보였다.
조건문을 보면 this.m.a(v0)가 true면 성공했을 때의 문자열이 출력되는 것을 볼 수 있다.
해당 함수에 들어가보자.
해당 함수에 들어가면 입력한 문자열을 같은 클래스 내의 bar 함수로 전송시키는데 아래에 있는 bar 함수에는 코드가 존재하지 않는 것을 볼 수 있다.
앞에 native가 있는 것으로 보아 라이브러리안에 해당 함수의 코드가 존재한다는 것을 알 수 있다.
다시 MainActivity로 가면 "foo"라는 라이브러리를 호출하고 있는 것을 알 수 있다.
apkManager로 디컴파일한 뒤 Libraries 폴더 내 자신이 테스트 중인 플랫폼에 맞는 폴더에 들어가면 libfoo.so 파일이 존재함을 볼 수 있다.
* .so 파일이란?
- 리눅스의 동적 라이브러리로 윈도우에서의 dll과 완벽하게 일치하는 개념의 라이브러리
- 런타임에 호출될 코드가 결정되고, 로드된다.
- 무결성 탐지를 위한 네트워크 통신이나 루팅탐지 등 중요하다고 생각되는 부분을 라이브러리로 만들어 분석을 더 어렵게 하기 위해 주로 사용됨.
- Android 공식 홈페이지의 경우 별로 비추천하는 방식이긴 하다.. (https://developer.android.com/ndk/guides/index.html?hl=ko)
해당 라이브러리 파일을 IDA를 통해 열어보았다.
파일에서 Export되는 모든 함수 목록을 보여주는 Exports windows에 가면 [Java_패키지명_클래스명_함수명] 으로 명명된 두 함수를 볼 수 있다.
이 중 우리는 CodeCheck 클래스의 bar 함수에 관심이 있다!
그 전에 혹시 패스워드가 코드 내에 하드코딩되어 있을 수 있으므로 [View - Open subviews - Strings] 혹은 [ Shift+F12 ] 를 통해 Strings 탭을 보자.
.data 쪽을 보면 abcdefghijklmnopqrstuvw가 있다. 해당 문자열이 혹시 답일까하여 입력 후 Verify 버튼을 클릭하였지만 틀렸다고 나온다.
그렇다면! 방금 찾은 CodeCheck_bar 함수에 더블클릭하여 들어가보자. (Exports 탭에서 더블클릭해야한다)
무언가 코드가 쭈우욱 있는데 아직..리버싱 초짜라 뭔지 모르겠다 ㅇ_ㅇ 하면서 읽고 있는데 .strncmp가 보인다.
strncmp의 경우 문자열을 비교할 때 특정 길이까지만 비교하는 함수이다! 그렇다면 몇번째까지 비교를 할지 알아보자.
스페이스바를 누르면 Graph형식으로 나타나 조금 더 분석하기 용이해진다.
분기문을 보면 CMP W0, #0x17 이라고 되어있고 이를 B.NE(Branch Not Equal = 플래그가 0이 아니면 분기)를 하여 분기문이 일어나는 것을 볼 수 있다.
W0에 대해 알아보자면 ARM의 범용 레지스터에는 30개의 범용 레지스터가 존재한다.
64-bit의 경우 X0-X30으로 이루어져있고 32-bit에는 W0-W30으로 이루어져있다.
(참고 : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/BABHDEEJ.html)
즉, 32비트 레지스터에 들어있는 값을 0x17과 비교하여 분기를 시키므로 23과 비교를 하는 것을 알 수 있다.
눈치가 빠르다면 문자열의 길이가 23인 것과 비교한다는 것을 생각할 수 있는데 W0에 클릭을 하면 X0과 같이 표시가 되는 것으로 보아 한 레지스터를 32비트만큼 사용하냐 64비트만큼 사용하냐에 따라 표시를 달리 하는 듯 하다.
MOV a,b의 의미가 b의 값을 a로 넣는다는 것을 잘 생각해서 분석을 하다보면 .... 음 ㅠㅠ 모르겠다.. 일단 23개의 문자를 넣어야겠다는 생각을 가지고 진행해보자.
.strncmp하는 것을 보면
MOV X1, SP
MOV W2, #0x17
MOV X0, X21
을 한 뒤 .strncmp를 하는 것을 알 수 있다.
strncmp가 비교할 두 문자열과 비교 길이를 넣는 것이므로 X0와 X1 레지스터 내 문자열을 비교하며 0x17만큼 비교한다는 것을 알 수 있다.
그렇다면 둘 중 하나는 내가 입력한 문자열일 것이고 하나는 패스워드일 것이다.
동적디버깅으로 가보자.
먼저 [ IDA 설치 폴더 - dbgsrv 폴더 ]에 가서 자신의 플랫폼에 맞는 android_server 파일을 /data/local/tmp 폴더에 올려준다.
그 후 권한을 준 뒤 실행시켜준다.
아래의 사진이 위의 과정을 한 명령어와 그 결과이다. 잘 실행시키면 Listening on 0.0.0.0:23946... 이 뜰 것이다.
이제 새로 cmd창을 열어 adb forward tcp:23946 tcp:23946 을 작성한다. 이는 컴퓨터의 23946 포트를 루팅폰의 23946 포트로 포워딩하는 명령어이다. 이를 진행해야 IDA에서 루팅폰이 연 23946으로 접근할 수 있다.
열려있던 libfoo.so에 대한 창을 [ File - Close ]를 통해 닫고 [ Debugger - Attach - Remote ARMLinux/Android debugger ] 를 클릭해준다.
나타나는 창에 Hostname에는 localhost, Port는 루팅폰에서 열린 23946(default port)로 한 뒤 OK를 누르면 아래와 같이 프로세스 목록이 뜬다.
여기서 우리가 하기로 한 sg.vantagepoint.uncrackable2 프로세스를 선택 후 OK를 눌러준다.
잠시 로딩 후 디버깅 창이 뜬다.
우측 Path 창에서 우리가 디버깅 중인 libfoo.so를 찾아 더블클릭하면 함수 목록이 뜨며 그 중 패스워드를 확인하는 CodeCheck_bar 함수를 더블클릭하면 해당 코드가 왼쪽 Debug View에 나타난다.
코드 중 .strncmp에 BP를 걸고싶었지만 보이지 않았다. 그래서 스페이스바를 눌러 Graph 형식으로 바꿔준 뒤 위에서 봤던 형식과 동일한 부분이 B509B25C에 있는 것을 확인하였다.
.strncmp로 생각되는 25C에 BP를 건 뒤 실행시켰다.
실행시킨 뒤 문자열을 23자보다 적게 입력하면 BP까지 도달하지도 않기 때문에 반드시 23자리를 적어주어야한다.
[ 12345678901234567890123 ] 으로 23자리를 입력한 뒤 Verify를 누르면 아래와 같이 BP에 걸린 것을 확인할 수 있다.
이 때 우리는 첫번쨰와 두번째 레지스터의 스트링 값을 확인해야한다.
우측 상단을 보면 아래 사진과 같이 Gerneral registers 창이 있는 것을 볼 수 있다.
코드를 보면 R0와 R1이 쓰인 것을 확인할 수 있으므로 해당 레지스터에 들어있는 주소(R0 : 9F0770B8 / R1 : BE890C38 )를 아래 Hex View에서 검색하였다.
Hex View를 클릭한 뒤 G 버튼을 누르면 Jump to address 창이 뜨는데 여기에 주소값을 넣어주면 해당 주소로 이동한다.
R0에 들어있는 주소로 가니 내가 입력한 문자열이 있는 것을 확인할 수 있다.
다음으로 R1에 들어있는 주소로 가니 패스워드로 예상되는 값이 들어있었다.
해당 문자열을 나열해보면 [ thanks for all the fish ]로 정확히 23자리인 것을 알 수 있다.
디버깅을 풀고 위의 문자열을 입력하면 문제가 풀린다!
* 참고
- ARM 어셈블리어 명령어 : http://egloos.zum.com/orangetigger/v/359478
- 어셈블리어 정리 :
'Hacking > Mobile' 카테고리의 다른 글
Cydia Impactor를 이용한 ipa 설치 (0) | 2018.04.30 |
---|---|
[아이폰] 아이폰5(IOS 10.3.3) 탈옥 및 진단환경 세팅 (1) | 2018.04.02 |
[OWASP] UnCrackable App for Android Level 1 (2) | 2018.02.22 |
[2016-SU-CTF] Android 100 (0) | 2018.02.13 |
[2014_SU_CTF] Commercial Application ( Reverse 200 ) (0) | 2018.02.13 |