CodeGate 2015 Quals - Sokoban

Posted by ORANG ORANG(오랑)
2015.05.15 00:25 System Hacking/CTF


CodeGate 2015 Quals - Pwnable 1000pt, sokoban


로컬 환경 구성 -> Ubuntu Linux 14.04 x86_64 ( 라이브러리 : libc-2.19.so )


코드게이트 예선 때 못 푼 문제였는데, 롸업이 올라왔길래 정독해보고 다시 풀어보았다.



바이너리로 주어진 파일을 실행시켜보니 위와 같이 "[]"를 골인 지점으로 옮기는 게임 형식이다.

소스 분석 중, 가장 먼저 눈에 띈 부분은 아래 그림과 같이 stage 6 에서 게임 모드를 선택하는 부분이 있다.





랜덤-무한 모드를 선택할 경우, 낮은 확률로 아래와 같이 히든 맵(공간이 막혀있지 않은 맵)이 나온다.

코드게이트 때는 저 부분도 발견하지 못했었는데, 롸업을 보고 발견하니 허탈했다. 이걸 발견했어도 풀진 못했을 것 같긴 하지만..



코드 상에는 FLAG를 출력해주는 함수가 존재한다. 하지만 PRINT_FLAG() 함수가 실행되려면, GAME()의 반환값이 1이어야 하는데, 소스 상으로 분석해보면 GAME()의 반환값은 0 아니면 2이므로 일반적인 방법으로는 PRINT_FLAG()함수를 호출할 수 없다.



getch 외에 다른 입력 부분이 없어서, 공격벡터를 찾기 까다로웠다. 이 문제에 존재하는 벡터는 아래 그림과 같다. USER_INPUT을 받는 함수 내부중 일부인데, 조건에 따라 입력받은 방향(H, J, K, L)으로 메모리 상의 값을 옮길 수 있다. 먼저 메모리 상의 위치를 계산하는 방식을 보면 생각보다 간단하다. [0x60c8e0 + 32 * 세로 + 가로]으로 계산하면 된다.


먼저, USER_INPUT 에 따라 변하는 값은

H    -> 가로 -1

L    -> 가로 +1

J    -> 세로 +1

K    -> 세로 -1        이 된다.


 src_ptr, dst_ptr 이라고 생각해보면 이해하기 쉽다. dst_ptr이 1일 경우 5값을 넣어주고, 0일 경우에는 src_ptr 로부터 값을 옮기게 된다. 아까 그림처럼 히든 맵?의 경우 가로-세로 움직이는데 제한이 없기 때문에, 데이터 영역의 값을 조작하는게 가능하다.





데이터 영역에서 조작 가능한 부분으로 GOT-테이블을 살펴보면, 위와 같다. ptr을 통해 데이터를 옮기는 조건들 때문에 접근할 수 있는 부분은 werase@GOT나 rand@GOT 뿐이다. 롸업 보다가 이 부분에서 좀 컬쳐쇼크였는데, ASLR이 걸린다는 점을 역으로 이용한다는 발상 때문이다. 메모리를 보호하기 위해 적용된 ASLR을 이용해 공격을 한다는 것 자체가 충격이었다. 라이브러리가 로딩되는 주소가 항상 바뀌기 때문에, 낮은 확률로 rand의 주소값이 (하위 2바이트 값만 쓰자면) 0x0060인 경우가 나타난다. 이 때, 아래와 같은 gadget의 주소로 rand@GOT를 조작하게 된다면, 프로그램의 흐름을 바꿀 수 있다. 아래 gadget을 통해 GAME()함수를 바로 종료시킬 수 있다. 이 때 RAX는 따로 세팅되지 않음.


라이브러리 상의 rand@LIBC = 0x3d060 이고 gadget@LIBC = 0x3e260 이므로 두 값의 차이는 정확히 0x1200이다.



USER_INPUT() 함수의 스위치 문을 보면, "v" 인풋의 경우 0x60c121에 18(0x12) 값을 더해준다. 이 부분을 이용하면 된다.



0x60c121 에 세팅된 0x12 값을 rand@GOT의 2번째 바이트로 옮겨주면 된다. ( ASLR이 정확히 맞아떨어져 \x00이 될 경우 익스플로잇 성공 )



반환 값으로 세팅되는 부분은 아래의 getch 이다.



익스플로잇 코드를 짜는데 생각보다 많이 헤맸다. 랜덤-무한 모드에서 히든 맵을 발견할 수 있게끔 하고 싶었는데, 맵을 리셋하는 과정에서 USER_GARO, USER_SERO 값이 계속 변했기 때문에 ptr의 정확한 계산을 할 수 없었다. 색을 추가하는 부분들 때문에 같은 위치인데도 받아온 문자열의 길이를 보면 다르게 나오는 것 같길래 그냥 브루트 포싱 쪽으로 했다. 생각보다 확률이 너무 낮아서 오래 걸림..






공부한 롸업 - https://github.com/ctfs/write-ups-2015/tree/master/codegate-ctf-2015/pwnable/sokoban

'System Hacking > CTF' 카테고리의 다른 글

CodeGate 2015 Quals - Mashed Potato  (0) 2015.06.24
DEFCON 2015 prequals - wwtw  (2) 2015.05.19
CodeGate 2015 Quals - Sokoban  (0) 2015.05.15
Codegate 2015 - Bookstore  (2) 2015.03.21
B-Sides Vancouver 2015 - Ownable 400  (0) 2015.03.18
CSAW 2014 pwn_500 xorcise  (0) 2015.01.07
이 댓글을 비밀 댓글로