Execute
문제에서 fsb라고 대놓고 주고 있기 때문에 일부러 포맷 스트링을 넣을 결과도 확인해 보았다.
Fsb를 이용해서 푸는 문제인 것이 거의 확실해 졌다.
Analyze
프로그램의 동작을 정확하게 알아 보고 어떤 부분에서 fsb가 발생하는지 확인하기 위해 IDA를 통해 열어보자.
Main
Mina 함수는 별다른 동작을 하지 않는데 누가봐도 수상한 함수인 vuln함수를 호출한다.
Vuln
- Line 7 : fget을 통해 1024byte만큼 s변수에 저장한다.
- Line 8 : snprintf를 통해 format에 0x400byte만큼 s변수의 내용을 복사해준다.
- Line 9 : printf함수를 통해 format의 내용을 출력한다.
Line9에서 printf함수를 보면 포맷 스트링을 지정해주지 않아 이부분에서 fsb가 트리거 가능한 것을 확인할 수 있다.
Flag
해당 함수에서 shell을 띄워 주는 것을 확인 할 수 있다.
Solve
여기서 우리는 어떻게 프로그램의 흐름을 flag함수로 보내줄지 생각해야 한다. 일단 buffer overflow는 불가능한데 s변수에 입력 받는 크기와 snprintf를 통해 fomat변수에 복사해주는 크기가 1024로 동일 하기 떄문이다. 따라서 다른 방법을 생각해야한다.
다른 방법으로 return printf(&foramt) 부분에서 printf함수의 got를 flag함수의 시작 주소로 덮어주면 프로그램의 흐름을 변경시킬수 있을 것이다. 따라서 정확한 payload를 작성하기 위해 프로그램을 실행해서 %p포맷을 주어 확인해보자
우리가 입력한 aaaa가 두번쨰 %p에 들어가 있는 것을 확인 할수 있다. 이 말은 내가 입력한 값을 토대로 내가 원하는 메모리 address에 접근 할 수 있다는 것이다. 앞서 test때는 0x61616161에 접근 할 수 있는것이다. 따라서 printf의 got의 address를 여기에 넣어주면 앞선 목표처럼 flag함수로 흐름을 제어 할 수 있을 것이다. 그럼 이번에는 해당 address에 어떻게 원하는 값을 넣을지 생각해보아야한다.
여기서는 포맷스트링 %n을 사용한다. %n은 포인터 변수에 지금까지 출력된 내용의 크기를 해당 포인터에 넣어주는 역할을 한다. 따라서 flag함수의 address를 10진수로 전환해서 그만큼을 공백으로 출력해준다면 %n 덕분에 prinf의 got에 원하는 값을 쓸 수 있을 것이다. 따라서 flag함수의 address를 확인해보자.
0x080485b4인 것을 확인 할 수 있다. 해당 값을 10진수로 바꾸면 아래와 같다 .
따라서 페이로드의 전체적인 구성은 다음과 같을 것이다. 4byte를 빼주는 이유는 printf의 got address의 크기가 4byted이기 때문이다.
Printf의 got address + 134514100-4byte의 공백%n
Exploit 코드는 아래와 같이 작성하였다.
성공적으로 flag를 얻을 수 있었다.
'Wargmae > HackCTF' 카테고리의 다른 글
[Hack CTF – x64 Buffer Overflow] (0) | 2021.01.05 |
---|---|
[Hack CTF – 내 버퍼가 흘러넘친다!!!] (1) | 2021.01.03 |
[Hack CTF - Basic_BOF #2] (0) | 2021.01.02 |
[HackCTF - offset] (0) | 2021.01.02 |
[Hack CTF - Basic_BOF # 1] (0) | 2021.01.02 |