[Toddler's Bottle] uaf
uaf.cpp 코드의 일부이다.
give_shell() 함수를 호출할 수 있으면 될 것으로 보인다.
아래는 main() 코드이다.
이 때, switch문의 case 2를 이용하면 uaf가 가능할 듯하다.
gdb로 보면 fastbin에 들어가는 것을 볼 수 있다.
따라서 argv[1]으로 같은 크기를 주고 실행한 뒤
3 -> 2 순으로 입력하여 free로 인해 반환된 메모리를 다시 할당받으면 된다.
이제 해당 메모리에 덮어쓸 데이터만 결정하면 된다.
이 때, 다시 uaf.cpp 코드를 보면 give_shell()과 introduce()가 virtual 함수인 것을 볼 수 있다.
free하기 이전의 힙 상태를 다시 보면 아래와 같다.
vtable의 주소가 담겨 있는 것을 볼 수 있다.
안에 give_shell()의 주소가 있다.
introduce()를 호출하는 부분을 보면, 여기에 0x8을 더해서 호출하게 된다.
따라서 0x8을 뺀 주소로 덮어쓴 뒤, introduce()를 호출하게 하면 give_shell()이 호출될 것이다.
정리하면,
3 -> 2 -> 1 순으로 입력할 것이다.
그 이유는,
3: free
2: free된 메모리를 다시 할당 받아서 덮어쓰기
1: introduce() 호출 (실제로는 give_shell() 호출을 위해)
이 때, 우리가 덮어쓸 값은 파일에서 읽어오기 때문에 원하는 주소를 넣고 저장한다.
그 뒤, 실행할 때 argv[1]에는 size를 주고 argv[2]에는 파일 경로를 준다.
(free되는 메모리와 같은 크기를 입력해 준다.)
위에서 말한 것처럼 3 -> 2 -> 1 순으로 입력하면 되는데
2는 두 번 입력해 주어야한다.
main()을 보면, m->introduce()가 먼저 호출되기 때문이다.
(delete 순서가 m -> w 이기 때문에 fastbin에서 w가 먼저 나옴)
위와 같이 실행하면 플래그를 얻을 수 있다.
여기서 16대신 3 ~ 24 사이의 값을 입력해도 동작하는 것을 볼 수 있다.
우선 16 이하의 값을 입력해도 되는 이유는 64비트에서 heap header 크기가 16이고, 데이터 부분의 최소 사이즈가 16이므로
3 ~ 16까지의 값을 입력해도 동일한 크기로 할당되기 때문이다.
17 ~ 24까지의 값이 동작하는 이유는 heap header의 prev_size 부분때문이다.
위 그림은 24를 입력하고 A가 23개 입력된 파일의 경로를 주고 실행한 것이다.
( r 24 /tmp/morae/a )
24을 입력하였지만 size 부분을 보면 21인것을 볼 수 있다.
그리고 A가 prev_size 부분까지 쓰여진 것을 볼 수 있다.
이전 노드가 free되기 이전에는 prev_size 영역을 사용하지 않는다.
따라서 메모리를 할당할 때 이 것을 고려하여 16(헤더)+24인 40을 할당하지 않고 16(헤더)+16인 32를 할당해준 것이다.
즉 16(헤더)+16+8(prev_size) 부분을 사용하게 된다.
'Wargame > pwnable.kr' 카테고리의 다른 글
pwnable.kr unlink (0) | 2019.03.12 |
---|---|
pwnable.kr horcruxes (0) | 2019.03.06 |
pwnable.kr memcpy (0) | 2019.02.13 |
pwnable.kr blukat (0) | 2019.02.11 |
pwnable.kr leg (0) | 2019.02.11 |
댓글