-
Welcome write upSystem hacking training/pwnable.xyz 2019. 12. 22. 19:11
pwnable.xyz의 첫번째 문제다.
64bit 바이너리이며 dynamically linked되어있고, stripped되어있다.
모든 메모리 보호기법이 적용되어있는 녀석이다.
IDA로 main()함수를 디컴파일 해보면 다음과 같은 결과가 나오는데,
결론적으로 system("cat /flag")가 수행되기 위해서 v3이 가리키는 값이 0이여야만 한다.
코드상에서 v3에 대한 사용자의 input이 없기 때문에 불가능해 보인다.
하지만 v10과 malloc() 함수의 특성 덕분에 *v3에 0을 넣을 수 있는데,
바이너리는 다음과 같이 동작한다.
1. v3 = malloc(0x40000uLL)
2. leak v3 address
3. User input v10
4. v5 = malloc(v10)
5. read(0, v5, v10)
6. if *v3 == 0 -> system("cat /flag")처음에 v3에 malloc()함수로 0x40000 만큼 동적할당을 해주고, 해당 주소를 leak해준다.
그리고 v10에 다음 malloc()함수에 사용될 사이즈를 입력받고, v5에 사용자가 입력한 크기의 메모리를 할당해준다.
이후 해당 영역에 입력을 받고, 마지막으로 v3가 가리키는 값이 0일 경우 flag를 뱉는다.
malloc() 함수는 할당된 메모리 공간의 포인터를 return하거나, 메모리 공간이 부족할 경우 NULL을 리턴한다.
그렇다면 v5 = malloc(v10)이 실패할 경우 v5에는 NULL값이 들어가게 될 것이다.
직접 큰 수를 넣어서 확인해보면 다음과 같이 NULL이 return되는 것을 확인 할 수 있다.
size가 4294967295인 큰 메모리를 할당하려 하였고,
그 결과 return 값이 저장되는 RAX에 0이 담겨있는 것을 확인할 수 있다.
또한 바로 아래 실행될 명령을 보면 rbp에 rax값을 넣는 것을 확인 할 수 있다.
(이 부분이 문제 풀이에 중요한 역할을 했다.)
이로 인해 앞서 변조해야했던 *v3에 접근할 수 있게 되는데,
이 부분이 *((char *)v5+v10-1) = 0을 하는 부분이고,
여기서 rdx는 앞서 input한 size, rbp는 큰 값의 메모리 할당으로 인해 malloc()이 return한 NULL이므로
rdx = leak해주는 v3의 주소 + 1
이와 같이 넣어주게 되면 malloc()에서 NULL을 return하고, 그 결과 rbp에 0이 세팅되며 rdx에는 v3의 주소+1한 값이 들어가 결과적으로 v3가 가리키는 주소에 0을 넣을 수 있게 된다.
따라서 위와 같이 leak한 주소를 받고, +1한 결과를 send하는 페이로드를 작성하여 풀이를 하면..!
⚡ root@ubuntu /mnt/hgfs/vm_shared/pwnable.xyz/image/challenge python a.py [+] Opening connection to svc.pwnable.xyz on port 30000: Done 0x7f3726f43010 [*] Switching to interactive mode FLAG{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}[*] Got EOF while reading in interactive $ [*] Closed connection to svc.pwnable.xyz port 30000
flag를 뱉는다.
반응형'System hacking training > pwnable.xyz' 카테고리의 다른 글
note write up (1) 2020.01.10 GrownUp write up (0) 2020.01.02 misalignment write up (0) 2020.01.01 add write up (0) 2020.01.01 sub write up (0) 2019.12.31