level13으로 로그인 후 hint 파일을 확인해보면 마찬가지로 소스코드가 주어진다. 확인해보면 인자 값을 1024 크기의 char형 배열 buf로 strcpy 함수를 이용해 복사하는데, 문제는 strcpy 함수가 bof에 취약한 함수라는 것이다.
이를 통해 stack buffer overflow를 일으켜 ret를 쉘 코드의 스택 위치나 환경 변수의 주소로 변조한다면 쉘을 얻을 수 있을 것이다.
하지만 문제는 ssp 보호기법의 canary와 비슷한 로직이 존재하다는 것이다. i에 0x1234567을 넣고 마지막 함수를 끝내기전에 i의 값이 그대로인지 검사하는데, 만약 bof를 일으켜 더미 값을 채워 ret를 조작하려 시도한다면, buf와 ret 사이에 있는 i를 변조하게 돼 canary 검증 로직을 통과할 수 없을 것이다.
따라서 bof을 일으켜 ret를 변조하는 것까지는 맞지만 그전에 i와 buf의 거리를 구해 i에 해당하는 영역은 0x1234567을 넣어줘야한다. 나머지는 더미를 넣으면 된다.
일단 canary가 정상적으로 작동하는지 테스트해봤다. 엄청나게 많은 'A' 값을 삽입해주니 i 변수의 값 검증 로직에 걸려 Warning 문구와 함께 프로그램이 종료됐다.
exploit 전 ret, buf, i의 위치를 gdb로 구해보겠다. ./attackme 파일은 권한 문제 때문에 디버깅을 하기 힘드니, hint에 주어진 소스 코드를 복사해 tmp 폴더에서 새로운 파일을 빌드했다.
main의 함수 프롤로그, strcpy, cmp(i 값 check) 부분에 bp를 걸고 실행한 후 스택을 확인한다면 각각의 주소를 구할 수 있다.
ret : 0xbfffe5ec
buf : 0xbfffe1d0
i : 0xbfffe5dc
ret와 buf 사이의 거리는 1052byte고 i와 buf 사이의 거리는 1036byte인 것을 알 수 있다.
그렇다면 payload는 dummy*1036 + "\x67\x45\x23\x01" + dummy*12로 구성한다면 검증 로직에 걸리지 않고 ret에 접근할 수 있다.
그러면 ret를 쉘 코드의 스택 주소 혹은 환경 변수 주소로 변조하면 되므로, 쉘 코드를 삽입해야겠다. 나는 환경 변수를 이용할 것이다.
환경 변수 lev13에 혹시 몰라 \x90과 함께 쉘 코드를 삽입해줬고 환경 변수의 주소를 구하는 코드를 작성한 후 빌드해 주소도 구했다.
앞서 구상한 payload에 환경 변수의 주소를 더해 ret를 쉘 코드의(쉘 코드가 들어 있는 환경 변수) 주소로 overwrite했다.
'Wargame > FTZ' 카테고리의 다른 글
[FTZ] level 15 (0) | 2021.06.06 |
---|---|
[FTZ] level 14 (0) | 2021.06.04 |
[FTZ] Level 12 (0) | 2021.05.29 |
[FTZ] Level 11 (0) | 2021.05.28 |
[FTZ] Level 10 (0) | 2021.05.28 |