이 문제를 풀기위한 고비가 크게 3번 있었다. 그 고비를 중심으로 설명하겠다.
먼저 문제 프로그램을 살펴보자
(프로그램)
1번째 고비…
: 프로그램이 단순한 executable 파일이 아니다??...
이 프로그램은 shared object 파일이었다.
(파일 정보)
왜 이게 고비였냐 하면, 메인함수로 찾아가기가 힘들었다.
게다가 심볼이 없다. Start address를 찾아서 브레이크를 걸고 실행하여 일일이 뒤져가 main 함수를 찾아내었다.
* Main 함수까지 가는법.
먼저 gdb로 열고 한번 그냥 실행해 주어야한다. 아까 말했든 이 파일은 so 파일이어서 처음에는 메모리에 존재하지 않는다… 한번 실행해주고 중단 시킨 후 재실행할 때 break를 잡아준다.
Break 잡아주는 위치는 _dl_start_user 여기로 잡아준다. 이건 내가 찾아낸 부분인데 이 부분 전에 starter 어쩌구 함수에서 실행이 되고 이 함수로 넘어오는데 여기에 break 잡아준다.
(main 찾아가기(1))
main 찾아가기(2)
그 후 위 사진처럼 저 위치에서 si로 함수 안으로 들어가준다.
main 찾아가기(3)
여기 call rax에서 si로 함수 안으로 들어가주면 여기서부터 main 함수이다.
main 함수
(여기 main함수 까지 찾아오는데 정말 오래걸렸다.)
두번째 고비…
: 스택과 힙? 힙은 취약점이 없어보이는데??...
두번째 고비는 힙 영역에 취약점이 없어 보인다는 점이었다. 스택 영역은 스택 카나리가 존재해서 bof를 생각도 안했다. 그리고 heap영역에는 다양한 취약점이 존재한다는 걸 알고 있었기에 노려보려 했지만 쉽지 않았다.
그 이유는 heap영역에 취약점은 기본적으로 heap overflow에 기반했다. 하지만 여기서는 입력할 데이터 수를 받고 그 데이터길이만큼 malloc으로 할당해준다. 그리고 그 영역에 read함수를 통해서 해당 데이터 길이만 입력을 받기 때문에 overflow가 일어나기 힘들었다.
여기서 한참 방황한뒤 취약한 틈새를 발견하게 되었다. 바로 print하는 부분이다.
바로 입력한 문자열을 출력할 때 null 값까지 쭉 출력한다는 점을 이용하여 스택영역에 값들을 노출 시킬수 있겠다는 생각이 들었다.
(스택 모양)
카나리를 노출시킬 수 있으면 카나리 위치에 카나리를 넣을 수 있고 그렇다면 stack overflow를 할 수 있다는 생각이 들었다.
(카나리 구하기 함수)
3번째 고비…
: 쉘을 따기 위해서는 system함수를 불러야하고 인자를 넘겨야하는데 어떻게…
3번째 고비는 인자 문제였다.
Ret 까지 system 함수를 호출하는건 문제가 없었다.
하지만 인자를 넘겨주는데 문제가 있었다. 리눅스 64비트 환경에서 인자를 넘겨줄 때는 첫번째 인자는 rdi 레지스터를 이용해 넘겨준다. 그렇다는건 rdi 레지스터에 /bin/sh 이라는 문자열 주소를 넣고 ret으로 system을 실행시켜야하는데….
** 맞다.! 나는 stack smashed가 카나리 변조만으로 이루어지는 줄 알았다. 하지만 카나리 값을 제대로 넣어도 stack smased가 나오는 경우가 있었다. 바로 rsp의 위치였다. 리눅스 64비트에서 디버깅을 해보니 rsp 가 아무역할을 안하는거 같길래 무시했더니, rsp가 rbp보다 큰주소(아래)주소에서 놀고 있을 때 stack smashed가 일어났다. 즉, 함수 시작 앞에서 rsp를 sub로 조정하는 부분이 불필요한 부분은 아니었던 것이다.
이 부분으로 또 한참이 걸렸다.
이 과정에서 나는 ROP를 생각했다. 이 때 fake rbp를 이용해 스택 포인터를 마음대로 움직여야겠다는 생각도 하였다. 그러면서 ROP를 해야겠다는 생각이 들었다.
그래서 ROP 가젯을 찾기 위해 새로운 프로그램들을 받으면서 경험했다.
문제 해결에 도움을 준 프로그램은 ROPgadget이라는 프로그램이었다. 여기서 엄청 핵심인 가젯을 찾아주었다.
(퍼펙트 가젯)
Fake rbp를 이용해 스택 포인터를 버퍼쪽으로 가져간 후 여기서 pop rdi 할 때 스택 위치에 /bin/sh 문자열을 넣을 주소를 넣어주고 ret 에 system 주소를 넣어준다. 그리고 /bin/sh 문자열은 버퍼의 어딘가 위치에 넣고 그 offset만 맞추어서 pop rdi에 들어가게 하면 된다.
(exploit 코드)
exploit 해주면
(문제 해결)
'WarGame > 500 Project' 카테고리의 다른 글
(63/500) pwnable.kr - syscall (2) | 2017.10.22 |
---|---|
(62/500) NOE.systems - BURYBURY (0) | 2017.10.01 |
(60/500) pwnable.kr - crypto1 (0) | 2017.08.27 |
(59/500) pwnable.kr - dragon (0) | 2017.08.17 |
(58/500) pwnable.kr - fsb (0) | 2017.08.12 |