## HDCON_2017(Fabuary, rev)
[Summary]
1. Android APK 리버싱 & native library 리버싱 문제이다.
2. 가위바위보를 하는 어플리케이션이 있는데 17916점을 넘기면 이기는 어플이다.
3. 한번 이길 때마다 1점씩오르며 각 가위,바위,보를 34999번이상 시도할 수 없다.(수동 방지인듯..)
4. rpc_calc()함수에서 score가 17916점을 넘기면 하드코딩된 값과 xor연산을 하여 키값을 생성해냄.
5. CallMe에서 해당 키값을 이용하여 하드코딩된 encrypt된 flag를 ck()를 호출하여 decrypt함.
[Analysis]
이 문제는 간단하게 요약하면 가위바위보를 하는 어플리케이션이 있는데 이기면 Score가 1점 올라가는 시스템이다.
해당 어플리케이션은 아래 [그림 1]과 같다.
[그림 1] HDcon 어플리케이션 UI
이제 이 apk를 jadx로 분석해보면 크게 2개의 중요한 루틴이 있다. 첫 번째는 가위, 바위, 보 버튼을 눌렀을 때 동작하는
ClickListener인데 코드는 아래 [그림 2]와 같다.
[그림 2] Paper button ClickListener 코드
위 [그림 2]에 나온 코드는 보를 클릭했을 때의 동작을 나타내는 코드인데 나머지도 코드가 비슷하므로 이것만
분석하면 된다.
우선 qq라는 변수에 시스템이 랜덤으로 생성해 낸 가위, 바위, 보 중 하나를 넣고 '보'를 의미하는 3을 첫번째 인자로
qq를 2번째 인자로 rps_calc라는 함수를 호출하는데 이는 native library에 있으므로 해당 라이브러리를 IDA로
분석해야한다. 일단은 코드를 쭉 보면 rps_calc()함수의 리턴 값을 setText()로 어플리케이션에 출력하는데
2017일 경우는 특별한 동작을 한다. "mm"에다가 rps_calc()함수의 리턴 값을 넣고 send broadcast를 한다.
대충 딱 봐도 이게 문제를 풀었을 때 동작하는 루틴이겠구나라고 알 수 있는 부분이다.
이제 그럼 rps_calc()를 분석해보도록 하겠다. IDA로 library를 열어서 rps_calc()함수를 들여다보면 아래 [그림 3]
과 같다.
[그림 3] rps_calc() 함수 디컴파일
다른 부분은 볼필요가 거의 없다. 그냥 이겼을 때 "You Win"을 출력하고 졌을 때 "You Lose"를 출력하고 뭔가 이상한
걸 탐지하면 이상하다고 출력하는 부분이다. [그림 3]의 코드를 보면 score > 17916인 분기문을 볼 수 있는데 딱봐도
score가 17916이상이면 뭔가를 하고 아까 분석했던 것처럼 2017이 들어있는 문자열이 나오겠구나 생각할 수 있다.
그럼 그안에를 보면 하드코딩된 값과 0x58을 xor하는 것을 볼 수 있는데 이걸 그냥 직접 해보면 "HD-C-O-N-2-0-1-7"
이 나온다. 이제 이걸로 아까 [그림 2]에서 분석했던 걸 참조하면 mm변수에 해당 키값을 넣고 send한다는 것을
알 수 있다.
그럼 이제 apk에서 봐야한다고 했던 2번째 부분을 보면 되는데 바로 CallMe이다. 코드는 아래 [그림 4]와 같다.
[그림 4] CallMe 코드
이 코드를 보면 mmm 변수에 mm으로 받은 값을 집어넣고 하드코딩된 encrypted flag와 뭔가
쿵짝쿵짝을 하는걸 알 수 있는데 키 값이 16자이므로 16자넘어가면 첨부터 key값 사용하는 루틴이 보이고
핵심 decrypt하는 루틴은 ck()함수에서 하는 것이라고 생각할 수 있다. ck()함수는 index를 첫 번째 인자로,
key값dmf 2번째 인자로, decrypted flag를 3번째 인자로 받고 호출된다. 그럼 이제 IDA로 ck()함수를
분석하면 되는데 디컴파일된 결과는 아래 [그림 5]와 같다.
[그림 5] ck() 함수 디컴파일
위 [그림 5]의 코드도 굉장히 간단한데 index값을 기준 삼아 case문으로 분기를 나누고 그냥 시프트 연산
xor연산으로 쿵짝쿵짝하고 리턴하는 간단한 함수이다. 따라서 이건 파이썬으로 똑같이 짜주면 decrypt가
가능하다. 그렇게 나온 결과는 "[*] flag is : W@tching_7th_Sunse7_in_B@li" 이었다.
[Exploit Code] - rock_exploit.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | key = list("HD-C-O-N-2-0-1-7") enc_flag = list("SBtbhfle_7tg]Runsj5]io_MBmi") dec_flag = [] def ck(i, key, enc_flag): if(i%6 == 0): result = chr(((ord(key) & 0xfff0) >> 4) ^ ord(enc_flag)) return result elif(i%6 == 1): result = chr(((ord(key) & 0xffe0) >> 5) ^ ord(enc_flag)) return result elif(i%6 == 2): result = chr(((ord(key) & 0xff80) >> 7) ^ ord(enc_flag)) return result elif(i%6 == 3): result = chr(((ord(key) & 0xffc0) >> 6) ^ ord(enc_flag)) return result elif(i%6 == 4): result = chr(ord(enc_flag)) return result elif(i%6 == 5): result = chr(ord(enc_flag) ^ 0xf) return result else: result = chr(67) return result for i in xrange(len(enc_flag)): if(i<16): dec_flag.append(ck(i, key[i], enc_flag[i])) else: dec_flag.append(ck(i, key[i-16], enc_flag[i])) print "[*] flag is : " + "".join(dec_flag) | cs |
[Get Flag~~!!!!]
[그림 6] flag
끝~!
'CTF writeup' 카테고리의 다른 글
[HITCON CTF_2017] start(pwnable) (0) | 2017.11.22 |
---|---|
[CSAW CTF_2017] prophecy(reversing) (0) | 2017.09.21 |
[ASIS CTF_2017] mrs. hudson(pwnable) (0) | 2017.09.13 |
[Tokyo Westerns CTF_2017] swap(pwnable) (0) | 2017.09.13 |
[Samsung CTF_2017] Easyhaskell(reversing) (0) | 2017.07.23 |