CODEGATE2013 BIN200

Games/CTF 2013. 3. 5. 23:29


CODEGATE2013 BIN200.pdf





주말에 CODEGATE 2013 예선이 있는것을 3일전에 알았다 -_-

스케줄도 차있었고 팀구성도 제대로 안됬기때문에 본선은 포기하고 연습삼아 몇개 풀어봤다.

연구실 형님이 BIN100 을 풀어놓으셨길래 BIN200 을 봤다.


32bit PE 가 주어진다.

실행시켜보면 zlib.dll 이 필요하다고한다.

내부적으로 압축알고리즘을 쓰는 모양이다.


인터넷에서 zlib.dll 을 구한다음 실행시켜보니 다음과같은 창이뜬다



Drive Name 을 입력하라고하는데, 아무거나 입력하면 그냥 끝난다.

IDA 로 열어서 조금 분석하다보니 PHYSICALDRIVE 0 번을 여는등 파일시스템의

MBR 에 접근을 한다.  가상머신에서 분석해야하나 싶었으나 설마 Codegate 예선문제가

실제로 부트섹터를 날리는 등 해를 끼칠리야 없겠지 싶어서 그냥 동적분석 하기로했다.


부트섹터등에 접근한다는것은 관리자 권한이 필요하다는 것이므로

관리자권한으로 프로그램을 실행시켜보니 아래와같이 드라이브 파티션과 섹터에 대한 정보들, 덤프가 나왔다.




눈에 띄는것은 "8pFHHoMssjtoucpX4EdPgcrdzuKXgEFV7iNur4YzDrOdfyNOA/bp7lX=" 라는 System Message 였다

해당 메시지는 단순히 데이터섹션에 하드코딩된 것이 printf 로 출력되는 것이었다.



마지막에 = 패딩이 붙는것이 딱 Base64 스러우므로 일단 Base64 디코딩부터 해봤는데, 별건 안나왔다.

기본적으로 IDA 정적분석을 통해 알아낸 사실들은 C++ 으로 만들어진 콘솔 바이너리이고 MBR 관련 정보들을 

Query 해서 출력한다는 점들, zlib 라이브러리의 compress 기능을 쓴다는 점들 정도였다.  



IDA 로 동적분석을 하면서 내가 준 Input 이 zlib compress 함수를 통해 압축되고

그 압축된 결과가 뭔가 복잡한 Encoding 연산을 수행하는 함수에 의해 인코딩되서

마지막에 Message: 로 다음과 같이 나타나는 것을 알아냈다.



이게도데체 뭐지? 라고 생각하면서 Input 을 여러가지로 주면서 나오는 Message 들을 그저 바라만 보고 있었는데

그 와중에 메시지가 위에서 출력됬던 System Message 와 비슷한 형태로 길게 출력될 때도 있는것을 발견하고

문득 내 Input 을 통해 생성된 Message 가 System Message 와 같아질 조건을 찾아야 하는게 아닌가? 라는 생각이 들었다.

그래서 마지막의 "8pFH6OJ=" 가 어떤 과정을 통해 생성된 것인지 추적해 들어가기 시작했다.


일단 내가 준 Drive Name Input 은 zlib.dll 의 compress 함수에 의해 압축이 되었는데, 확인해보니

이건 unix compress 툴의 압축 결과와 동일했다.  이렇게 압축된 데이터가 뭔가 복잡한 과정을 거쳐서

마지막의 Message 가 생성되는데, 메모리 스캐닝 꼼수를 써서 13B43B9 번지의 call 명령이 수행될 때

(주소는 실행시마다 바뀐다) 메시지가 메모리에 나타나는 것을 확인했다.



내가 준 Input 이 Xref 되는 모든 부분들에 대해서 검사해 나가면서 분석을 했는데 하다보니 다음과 같은

부분을 발견했다. EBP-18 이라는 지역변수의 값을 1 증가시키고 1291AD0 번지의 JNB 명령이

이 지역변수의 값과 sub_1291465 함수의 리턴값을 비교해서 종료조건을 검사한다.

그리고 이 카운터 변수를 sub_1291299 의 인자로 넘겨준뒤에 함수의 리턴값을 EBP-144h 에

저장하고 그것을 포인터로서 참조하여 1바이트를 가져온다(movsx edx, byte ptr[ecx])

이것을 3 과 XOR 하고 그 결과를 원래의 위치에 쓴다.



그다음의 루틴을 분석하다보니 이전에 참조했던 메모리 값들에 대해서 이번에는

0xFC 와 AND 연산을 하고 2비트 SAR 연산을 하는 것을 발견했다.



그리고 조금더 분석을 하다보니 메모리상에 "ABCDEFGHI.... 0123456789+/" 이런식으로 쭉 들어있는

데이터를 아래와 같이 "QwErTyUi....." 로 수정하는 루틴을 발견했다.



여기까지 본순간 이건 Custom Table 을 사용하는 Base64 인코딩 알고리즘이라는 느낌이 왔다.

이것을 비교적 빠르게 눈치챌 수 있었던건, 옜날에 딱 이렇게 동작하는 custom base64 인코딩프로그램을 

개인적인 암호화를 위해 만든적이 있었기 때문이다.


Base64 는 8비트의 데이터 3개를 6비트의 데이터 4개의 Index로 쪼개기 때문에 위에서 봤던 2비트 SAR 연산을

해야하고, 각각의 Index 를 통해서 테이블을 참조하는데, 그 방식은 아래와 같다.



원래 Base64 테이블은 ABCDEFG... 0123456789+/ 로 구성되어있다.

하지만 여기서는 이 공식적인 기본 테이블을 사용하지 않고 QwErTyU... 로 구성된 커스텀 테이블을 사용한 것이다.

결론은 내 Input 이 zlib 의 compress 함수로 압축되고, 그 압축된 바이너리가 여기서의 Custom Base64 로 인코딩

되는 것이다.  따라서 나는 문제와 동일한 Custom 테이블을 사용하는 Base64 디코더를 만들었다



이걸로 System Message "8pFHHoMssjtoucpX4EdPgcrdzuKXgEFV7iNur4YzDrOdfyNOA/bp7lX=" 를 디코딩했다.

그리고 그 결과를 zlib decompress 시켰다.  compress 툴을 구하다가 openssl 에 zlib 라이브러리 기능이

구현되어있는것을 알고 다음과 같이 decompress 했다.

decompress 가 된 결과는 flag 가 담긴 메시지였다.



부트섹터에 대한 작업들은 훼이크였고 compress 와 커스텀 Base64 인코딩 부분을 파악하는게 핵심인 문제였다

풀이시간은 4~5시간정도 걸린것 같다.




'Games > CTF' 카테고리의 다른 글

DEFCON20 PWN100  (0) 2013.03.19
Forbidden BITS x96  (0) 2013.03.19
CODEGATE2013 BIN200  (1) 2013.03.05
PHDays 2012 pwn200  (0) 2013.01.25
PHDays 2012 Misc400  (0) 2013.01.23
PHDays 2012 Realword 200  (0) 2013.01.23
Posted by daehee87

댓글을 달아 주세요

  1. Rookiss 2014.01.18 20:23  댓글주소  수정/삭제  댓글쓰기

    ㄷㄷㄷㄷㄷ 대..대단하다