1. 프로그램 분석
![](https://blog.kakaocdn.net/dn/barvZp/btqHEeDxJmz/Z4RU23enzy0OWZMxK6xGn0/img.png)
![](https://blog.kakaocdn.net/dn/P8r6i/btqHLZFDU40/EuTPxm14arXrRbXP4wqOrK/img.png)
프로그램을 보면 유명한 베스킨라빈스31 게임을 하는 프로그램임을 알 수 있다.
우선 How many numbers do you want to take ? (1-3) 라는 문자열 뒤에
숫자를 입력 받고,
해당 숫자를 출력해준다.
바로 입력을 받을 때 BufferOverFlow를 할 수 있다는 것을 알 수 있다.
그럼 보호기법을 확인해 보자
![](https://blog.kakaocdn.net/dn/CCGYv/btqHEfia3ry/cWXDeDdonrthCjjLK4fuJ0/img.png)
NX 보호기법이 켜져 있는 것을 알 수 있다.
그러므로 지금까지 했던 방법을 할 수 없다는 것을 알 수 있다. (FSB제외)
오늘은 Memory Leaking을 하는 다른 방법인 ROP를 해볼 것이다.
2. 버퍼의 길이 구하기
gdb-peda로 프로그램의 흐름을 보자
![](https://blog.kakaocdn.net/dn/cL6DOW/btqHBSHzU7K/7MgQr8qBlgZLyKEFlehmo1/img.png)
1. 프로그램 분석에서 봤듯이 프로그램이 실행될때 규칙을 설명하고 사용자에게 your_turn함수로 가는 것을 알 수 있다.
IDA나 Ghidra같은 정적디버거를 사용해서 your_turn함수의 코드를 확인해 보자
보면 사용자에게 입력을 받는 부분이다.
s라는 변수로 입력을 받는데 이 s의 길이는 0xB0이라는 것을 알 수 있다.
![](https://blog.kakaocdn.net/dn/bHVjEx/btqHEFBveZ5/Zk1wVg8eAXn0nnbJwaQRGK/img.png)
3. Exploit 코드 짜기
1. 먼저 입력 받기 전인 (1-3)이 있는 구간까지 문자열을 받는다.
![](https://blog.kakaocdn.net/dn/bo4vJY/btqHNxhQS84/9N0We5l1Fex1NscFCn6uI0/img.png)
2. 그리고 SFP까지 아무값이나 채워준다.
![](https://blog.kakaocdn.net/dn/bGgj3M/btqHA3JnMfe/bHWkhpwxZqOVTCDlDKomSK/img.png)
3. 가젯을 이용해서 인자를 받고, got를 이용해서 printf함수의 주소를 구한뒤, plt로 puts를 실행시켜준다.
그러면 puts([printf함수의 주소]);가 출력된다.
![](https://blog.kakaocdn.net/dn/EWVPW/btqHO0jMiHO/JTEfWBID8w6zoyYNSF6U9k/img.png)
4. main함수의 주소를 대입해준다.
(printf의 주소를 출력하면 ret값이 달려져 코드가 망가지기 때문에 다시 복구시켜 주는 것이다.)
![](https://blog.kakaocdn.net/dn/cgK9er/btqHMvK6Ldf/PlOfvyklIiWicuBGvxKDjK/img.png)
5. 문자를 잘못 입력하면 아래 문자열이 출력된다는 것을 이용해서
![](https://blog.kakaocdn.net/dn/eCq4wG/btqHQGSRVAM/G8inTg3wnxxEGqGOBMjw80/img.png)
위 문자열까지 받고, 그뒤에 출력될 문자열인 printf함수의 주소를 리틀엔디안 방식으로 6자리 받는다.
그리고 언패킹의 방식을 지키기 위해서 8자리를 비어있는 값으로 꽉 채워준다.(\x00\x00)
그 뒤, printf의 Offset을 빼주면 라이브러리의 베이스주소를 구할 수 있다.
![](https://blog.kakaocdn.net/dn/MoYfa/btqHP3ndGpw/NltAUSfVed5h8LZFmz5sQk/img.png)
6. 그 뒤, 프로그램이 재시작되니까 다시 문자열을 입력받고
![](https://blog.kakaocdn.net/dn/dz1KXo/btqHK48hyZO/lzdDnsNqoXvjKFAKQT5vU1/img.png)
7. rdi를 넣어주고,
+ pwntools의 search기능으로 "/bin/sh"의 문자열의 Offset을 찾은 뒤 라이브러리 베이스 주소를 더해주어서
"/bin/sh"을 더해준다. (symbols는 only 함수만)
+ 라이브러리 베이스 주소에 system의 Offset을 더해서 system함수를 호출 해 준다.
![](https://blog.kakaocdn.net/dn/1wUOj/btqHR7ilyRZ/v3QbRreAE85GfTPsIy65TK/img.png)
8. 마지막으로 작성한 payload를 입력해준다.
![](https://blog.kakaocdn.net/dn/bkwwCS/btqHJo6NwTs/KGalmwvmmshxhUhQjlbY8K/img.png)
4. 시행착오
1. ASCII 문자열이 아닌 \web 문자열이 있다면서 오류를 뿜어냈다.
![](https://blog.kakaocdn.net/dn/su61z/btqHLfPcukl/gkqsb037KkoTxhe7wVPYpk/img.png)
Sol) 아래 코드를 맨 위에 삽입해준다.
![](https://blog.kakaocdn.net/dn/dhI1n9/btqHEfJaTSu/Hgc1t6M8CIFmiKw9Jz9qD1/img.png)
2. 버퍼의 크기 0x190? 0xB0?
처음에 read 0x190을 보고 영락없이 버퍼의 크기가 190인줄 알았다. 그런데 B0이다.
![](https://blog.kakaocdn.net/dn/GOQoD/btqHEe4G6y2/JSJZ2VrocYtyVzRl7TYxEk/img.png)
Sol) 왜 0xB0일까? MSDN을 보자
![](https://blog.kakaocdn.net/dn/3EuRY/btqHEfoU2Qa/NIOUdkD58CNKNI2888lwRK/img.png)
190은 받을 수 있는 버퍼의 크기를 의미한다.
그래서 버퍼의 크기는 0xB0이고, 입력할 수 있는 버퍼의 크기는 0x190이 되는 것이다.
그래서 BufferOverFlow가 일어나는 것이다.
3. 라이브러리 베이스 주소를 구할 때 처음에는 라이브러리 함수가 0x7F부터 시작한다는 규칙을 이용해 아래 주석처럼 받을려고 했지만, 잘 되지 않았다.
![](https://blog.kakaocdn.net/dn/zLqRs/btqHQH5gA9I/MgkvAgX9EFml42QViFbYT1/img.png)
Sol) 그래서 알아보니 주소위에 AAAAAAAAAAAAAA...까지 다 받고 있었던 것이다.
Sol-Err) 7f.. 으로 시작하는데 7F로 적어서 그런거일 수도 있다.
![](https://blog.kakaocdn.net/dn/YVhba/btqHLfPcD4S/L2mRidAyAlSMo6UBNU2Q01/img.png)
그러면 :( 까지 받아주고, 진짜는 그 뒤부터 6자리 (라이브러리주소는 6자리)를 받으면 되지 않을까? 해서 아래처럼 코드를 고쳤다.
![](https://blog.kakaocdn.net/dn/q0zi0/btqHEfbu9fG/pqtFtJbL2TUFuWQJwwS93k/img.png)
5. 결과 확인
6. 참고
Exploit 코드
![](https://blog.kakaocdn.net/dn/cTCO8T/btqHR6jqVDz/mTiGOCGv9ROcCOlkYW4xi0/img.png)
![](https://blog.kakaocdn.net/dn/bwJQgd/btqHO0jLPcF/bTi1pgpC4XMUSR6SdYj7k0/img.png)
'Layer7 > 동아리 숙제' 카테고리의 다른 글
객체지향 프로그래밍(Object-Oriented Programming) (0) | 2020.09.09 |
---|---|
운영체제의 메모리 할당 알고리즘 (0) | 2020.09.02 |
NX-bit binary exploit ( with ASLR ) (0) | 2020.08.28 |
NX-bit binary exploit (0) | 2020.08.25 |
rev-basic-1 (선택 과제) (0) | 2020.08.20 |