티스토리 뷰

카테고리

BABY’S FIRST


풀이

서버에 접속하면 usernamePass를 입력 받는다.

알맞은 계정을 입력하면 다섯 개의 메뉴를 사용할 수 있다.


login 함수를 보면 checkuser 함수와 checkpass 함수로 계정을 검사하는 것을 볼 수 있다.


각각의 함수로 들어가면 입력 값을 어떤 값과 비교하는 것을 볼 수 있는데 확인한 결과 usernamemcfly, passawesnap이다.

이 계정을 이용하여 메뉴에 접근할 수 있다.



1번 메뉴인 Request Exploit add_request 함수로 연결된다.

56 bytes 만큼을 malloc 해서 reqlist 라는 전역 변수 배열에 할당된 순서대로 포인터를 저장한다.

그 후 힙 영역에 쓸 text0x80 bytes 만큼 입력 받는데, 이때 72 bytes 만큼의 Heap Overflow 가 발생한다.


2번 메뉴인 Print Requests print_list 함수로 연결된다.

할당되어 있는 request의 개수 만큼 반복문을 돌며 각 requesttext를 출력한다.


3번 메뉴인 Delete Request delete_request 함수로 연결된다.

이 함수에서는 print_list 함수를 호출하여 request들을 보여주고, .

reqlist의 해당 requestfree된다.

Request 는 update_request 함수로 연결된다.

print_list 함수를 호출하여 request들을 보여주고, 이 중 몇 번째 request를 수정할 것인지 입력 받는다.

reqlist의 해당 requesttext 내용을 수정할 수 있고 마찬가지로 72 bytesHeap Overflow가 발생한다.


5번 메뉴인 Go Away 를 선택하면 프로그램이 종료된다.


이 프로그램의 메모리 맵과 보호기법 여부는 위와 같다.

쓰기 권한과 실행 권한을 동시에 갖는 메모리 영역이 많고, Heap 영역 또한 쓰기 권한과 실행 권한을 동시에 갖는다.


1.     ChunkOverflow가 발생한다.

2.     Chunk를 포인팅하는 전역 변수(reqlist)가 있다.

그렇다면 unsafe unlink를 이용해서 unlink 에서 수행하는 FD, BK 검사를 우회하고 원하는 주소에 원 하는 값을 쓸 수 있다.

실행 권한이 있는 메모리 영역에 쉘 코드를 올리고, puts 함수가 수시로 불리고 있으니 putsGOT에 쉘 코드의 주소를 써 놓으면 쉘 코드를 실행시킬 수 있다.


자세한 익스플로잇 과정

먼저 mcfly, awesnap 을 이용해 로그인 한다.


그 후에 1번 메뉴를 통해 두 개의 chunk를 할당한다.


이번엔 4번 메뉴를 통해 0번 request를 업데이트한다.

0request에서 Overflow를 일으켜서 위 그림과 같이 0x10 bytes 만큼 “A”를 쓰고 reqlist 전역 변수의 주소인 0x609e80에서 0x18만큼 뺀 값과 0x10만큼 뺀 값을 쓰고 다음 chunkprev_size 부분에는 chunk의 크기보다 0x10 작은 값을 쓰고 p 플래그를 지운다.

 

이제 3번 메뉴를 통해 1 request를 삭제한다.

chunk_1free 하려고 하면 p 플래그가 0으로 설정되어 있기 때문에 이전 chunk와 병합하게 된다.

그 과정에서 unlink 매크로가 불린다.

unlink에서는 fdbk의 치환이 일어나는데 그 전에 FDBK의 유효성에 대해 검사한다.

그 내용은 대략 아래와 같다.

FD->bk P인지, BK->fdP인지를 확인하여 FD, BK의 조작 여부를 검사한다.


하지만 우리가 조작한 chunk의 경우,

prev_sizechunk의 크기보다 0x10 만큼 작게 설정했기 때문에 이전 chunkchunk_0의 시작 주소보다 0x10만큼 뒤의 주소로 인식한다.

그 주소로부터 0x10만큼 떨어진 위치의 값을 FD, 0x18만큼 떨어진 위치의 값을 BK로 인식한다.

해당 값들의 bkfd를 계산해보면 다음과 같다.

reqlist[0]에는 제일 처음 할당된 chunkchunk_0의 주소가 들어있다. 정확히는 chunk_0의 데이터 시작 부분인 chunk_0+0x10 의 주소가 들어있다.

이것이 chunk_1의 이전 chunkchunk_0+0x10 위치로 인식하게 만든 이유이다.

unlink 매크로를 부른 대상인 Pchunk_0+0x10 인데 조작해 놓은 FDBKbkfd를 계산해보면 둘 다 reqlist를 가리키고 있고 reqlist[0]에는 chunk+0x10, P가 있으므로 FD, BK의 유효성 검사를 통과할 수 있다.

 

이제는 FD->bk BK, BK->fdFD 치환이 일어날 차례다.

FD->bk = BK 를 통해 reqlist[0]0x609e70 이 들어가고, BK->fd = FD를 통해 reqlist[0]0x609e68 이 들어가므로 최종적으로는 reqlist[0]0x609e68이 들어간다.

 

이번엔 4번 메뉴를 이용해서 0request를 수정한다.

reqlist[0]이 가리키는 값이 chunk_0에서 reqlist-0x18로 바뀌었다.

여기에 0x18만큼 데이터를 쓴 후 원하는 주소를 쓰면 reqlist[0]이 해당 주소를 가리키게 되고, 다시 4번 메뉴를 통해 데이터를 쓰면 원하는 주소에 원하는 값을 쓸 수 있다.

 

putsGOT를 쉘 코드의 주소로 바꾸기 위해 reqlist[0]putsGOT 썼다.

그리고 다시 한 번 4번 메뉴를 통해 putsGOT(putsGOT + 0x10) 주소를 쓰고, 뒤쪽에 nop 코드와 함께 쉘 코드를 올렸다.


익스플로잇 코드

(PC로 봐야함)






댓글
댓글쓰기 폼
공지사항
Total
8,807
Today
2
Yesterday
3
링크
TAG
more
«   2019/08   »
        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
글 보관함