2010.08.22 00:08 WarGame

*이 풀이는 Vnsecurity 에 올라온 ISEC 2009 Challenge6 풀이를 제 나름대로 정리하여 포스팅한 글임을 알립니다

ISEC 2010 일정이 최근에 공개 되었습니다

지난해 ISEC에 참여는 못했지만 CTF 풀이 문서는 남아 있을 것 같아서

뒤적 거렸더니 풀이 문서는 발견할 수 있었습니다

아쉽게도 문제 링크는 다 죽었더군요 -.-

풀이중에 GOT를 Overwrite 해서 그것도 꽤 특이한 방법을 쓴 것이 있어서

정리하여 둡니다

6번 문제는 Remote BOF 문제라고 합니다

핵심이 되는 주요 함수는 다음과 같습니다



23번째 줄에 있는 strcpy가 첫번째 관문입니다

이후에 있는 34번째 줄의 strncmp의 조건을 만족하기 위해서 이를 활용해야겠죠

randbuf 는 이후로 memset에 의해 초기화가 되니 이를 손댈수는 없고

randnum을 손대야 합니다

buf128에서 32byte를 입력받고

16byte의 destbuf16에 strcpy를 하니까 16byte가 Overflow 됩니다

여기서 randnum을 수정해줘야 하는데

소스상으로 약간 잘못된거 같네요

풀이자가 hand ray 로 풀어낸 모양입니다

아무튼 , 사실 randnum이 destbuf16보다 먼저 선언 되어 있어서

덮어쓸수 있다는 거죠

Dummy byte를 포함해서 쭉 덮어씌워야 합니다

속편하게 32byte 쭉 채워주면 되겠죠

첫번째 입력은 32byte만큼 특정 값을 채워줍니다

그 다음에 32번째에서 다시한번 입력을 받는데요

이번엔 128byte만큼 받습니다

바로 이곳이 Core 라는 겁니다

strncmp로 조금 전에 넣어두었던 randnum에 일치하는 수를 넣어줍니다

예를 들어 A로 채워주었다면

buf128에도 A를 채워넣어주면 되겠죠

는 풰이크고 사실 25번째 줄

snprintf(randbuf12, 5, "%d", randnum)

 에서 5자리만큼 잘려들어갔기 때문에

16337 이 들어갔을 겁니다

사실 randnum 에는 AAAA가 들어갔다고 했을 때 , 1633771873 이라는 값이 들어갔을 것이고

이는 int형의 MAX 값. 2^31-1 = 2147483647 을 넘지 않기 때문에 고스란히 들어갔겠죠

여기서 5자리가 잘려서 16337이 됩니다

또 34번째

if ( strncmp(buf128, randbuf12, 4) ) 

 에서 앞 4자리만 비교를 하게 되니

1633만 넣어주면 되겠죠

처음 4byte 는 1633 입니다

그 다음이 문젠데요

키를 읽어놓고 정작 출력을 해주지 않습니다

황당하기 그지 없는 경우죠

여기서 주목해야 할 점은 printf문 앞의 두 strcpy 문입니다

  strcpy(randbuf12, buf128);  
  strcpy(buf_ptr, buf128);

괜히 집어 넣은게 아니겠죠

buf_ptr이 가리키는게 없던것도 걸립니다

두번째에는 buf_ptr의 값을 맘대로 변경할 수 있게 했구요

네, 그러니까 buf_ptr는 '어디든지 문'이라고 보시면 됩니다

마법의 포인터죠

buf_ptr가 가리키고자 하는 곳의 주소를 입력하면

그 후의 strcpy에서 그 값을 바꿀수 있게 합니다

정말 멋집니다

이제 뭘 해야 할까요?


....




Local 이라면 이것저것 해보겠는데 Remote 라는게 뭐 어쩔 수가 없네요

Printf 문의 "eldhkcalb"  문자열을 keystr 의 주소를 바꾸면 되..

지 않겠네요

포인터로 가리키고 있다면 keystr를 가리키도록 바꾸면 될텐데 직접 문자열로 접근하고 있습니다

주소를 알아봤자 말짱 헛것이라는 거죠

생각해보니 우리가 원하는 것은 printf 문도 아닙니다

그렇다면 소켓으로 keystr을 보내주는 sendsocket 함수를 짜서 보내야될텐데

남은 버퍼에 그것이 다 들어가지도 않을 것이고 , Return Address를 손 댈 상황도 아니며

정확한 Buffer의 주소도 알 수 없습니다






정신을 추스리고 다시 살펴보죠

printf 문의 호출을 다른 함수로 바꿀수 있다면?

Windows의 Hooking 떠오릅니다

여기서 접근 한 것이 GOT 입니다

Global Offset Table의 줄임말로 함수의 정보를 담고 있는 Table 인데요

Windows에서 따지자면 IAT와 같은 역할을 하고 있다고 보시면 됩니다

흡사 Windows 에서 Hooking 하듯이 Linux에 적용해보는 겁니다

다만, 이 경우는 코드의 자유도는 떨어집니다

전에 있던 코드들을 짜깁기 해야만 하죠

흡사 ROP의 개념을 보는 것 같군요

Binary 가 없어서 직접 캡처해서 찍을수 없어 풀이자의 자료를 첨부합니다

<그림1. printf 와 fread의 GOT>

우리의 목적을 먼저 정의해봅시다

sendtosocket(fd , keystr, 32) 함수를 호출 하는 것입니다

이는 fread( keystr, 32, 1 , stream) 과 sendsocket( fd , "~~" );

로 합성될 수 있습니다


마침 인자 순서도 적절하군요

그림1을 보시고 뭔가 감이 오시나요?

printf 문을 호출 할 때 fread의 함수 일부를 호출 - fread를 호출할 때 sendsocket의 일부를 호출

이렇게 연쇄적으로 호출하면 우리가 원하는 목적을 달성할 수 있습니다

이런 류의 문제를 본적이 없어서 이해하는데 꽤 걸려버렸습니다




이를 토대로 Exploit 코드를 짜봅시다

처음 입력 받을 때 a 등의 문자로 32 byte 입력합니다

두번째 입력을 받을 때는 초기 4byte는 첫번째에 넣어주었던 값을 고려해서 strncmp를 통과할 수 있도록 넣어줍니다

이후 code가 핵심인데요

1) buf_ptr 가 우리가 원하는 값을 가리킬수 있도록 dummy byte를 넣어줍니다

<그림2. buf_ptr 하위의 메모리 구조>
* buf_ptr의 값은 아직 미정

2) dummy byte에는 printf의 GOT를 덮어씌울 주소가 들어갑니다

GOT 구조에 따라 이 dummy byte의 구성이 달라집니다

문제 풀이를 보니

0x0804A2FC : waitpid GOT
0x0804A304 : fread GOT
.....
0x0804A316 : printf GOT

이런 식으로 구성이 되어 있는것 같습니다

초기 4byte 때문에 fread 전에 있던 어떤 함수의 GOT부터 수정해 나가야 합니다

그게 바로 waitpid 로군요

이를 토대로 짜보면..

<그림3. Exploit 을 위한 메모리 구조, 변경 전>

그림1 을 참고 했을 때, printf 에는 fread의 일부가

fread 는 sendtosocket이 들어갑니다

<그림3. Exploit 을 위한 메모리 구조, 변경 후>

이를 토대로 짠 Exploit Code 입니다



** 제 나름대로 이해한 방법으로 글을 풀어보았습니다만, 제가 이해를 잘못했다거나 풀이자의 의도를 오해했을 수 있습니다

뭔가 틀린것 같다면 댓글로 남겨주세요 시정하겠습니다 :D
Posted by LinkC
이전버튼 1 2 3 4 5 6 7 8 9 10 ··· 47 이전버튼

블로그 이미지
LinkC

태그목록

Tistory Cumulus Flash tag cloud by BLUEnLIVE requires Flash Player 9 or better.

공지사항

Yesterday73
Today54
Total320,227

달력

 « |  » 2018.10
  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      

최근에 받은 트랙백

글 보관함


. .