-
level20war game Write up/ FTZ 2018. 11. 18. 05:24
이 문제는 FTZ의 마지막 문제이기도 하고 가장 어려운 문제라고 생각한다...
이 문제의 핵심은 바로 Format String 취약점 즉, FSB 취약점을 이용한 문제인데요.
먼저 Format String이란 무엇이냐
아마 내일 올라올 포스팅을 확인 해주시면 감사하겠습니다...
그 포스팅에 정리해두었거든요,,ㅎ 아직 포스팅중이라,,ㅎ헤헤헤ㅔㅔㅔ
음,, 이 사진에 다 담았는데요,,
하나 하나 설명을 해보자면
위의 코드에서 format string이 터지는 이유는 printf 함수를 보시면 알 수 있습니다.
printf(bleh); 라고 코딩되어 있는데요.
바로 여기서 취약점이 터지게됩니다..
왜 터지는지는 이 후 나올 포스팅을 확인하시구요,, (이 글을 적는 시간이 새벽 3시인 관계로 너무 피곤합니다.,,)
다음 을 보면 fgets함수를 보면 79byte까지만 받는 다는 것을 알 수 있습니다,
따라서 기존의 문제들처럼 풀 수는 없다는 얘기죠
인자값으로 %x를 줘버리면 (%x 는 16진수로 출력됩니다,)
%x를 format string으로 줘버리면 stack에서 pop 합니다.
그래서 인자로 준 값을 나타내게 되는 것 입니다.
스택 구조를 보면
일단 printf"%s %d", buf, x); 의 경우에는
buf / AAAA
x / 40
~~~~~
&x
&buf
~~~~~
어셈블리로 생각을 하면 x주소와 buf 의 주소를 push한 후 printf 함수를 호출한다는 것을 추측할 수 있습니다.
그렇게 되면 %s 는 &buf의 내용을 읽어오겟죠, %d는 마찬가지로 &x의 내용을 읽어올 것 입니다.
마찬가지로
AAAA %x %x %x %x라는 값을 인자로 줘버리면??
%x
%x
%x
%x
buf // AAAA
0x4207a750
0x4212ecc0
0xf4
&buf
printf(buf) 했으니 바로 buf 의 내용을 가져오게 되죠,
AAAA를 출력한 후 %x를 만나 다음 스택의 정보를 읽어오게 되고 또 %x를 만나 다음 스택 정보를 읽어옵니다.
이해 하셨을 진 모르지만,,(제 글쓰는 실력이 영 엉망이라,,,)
이런게 format string 취약점입니다.
그런 다음 %n을 이용해 원하는 위치에 값을 입력 할 것입니다.
"AAAA\xba\xf2\xff\xbfAAAA\xbffff2bc%c%n%c%n" 이라는 값을 인자로 줘보죠.
일단 AAAA\xba\xf2\xff\xbfAAAA\xbffff2bc 이 출력되겠죠?
그런 후 %c를 만나서 AAAA에 대해서 나오고 %n을 만나게 되는데 AAAA 위에 있는 스택 값은 0xbffff2ba입니다.
그럼 0xbffff2ba번지에 %n을 통해 현재까지 출력한 크기를 입력하게 됩니다.
AAAA\xba\xf2\xff\xbfAAAA\xbffff2bc 는 16byte가 입력되게 됩니다.
그 다음에 만나는 값은 %c 이므로 AAAA를 건너뛰고 다시 %n을 만나 그 다음 스택인 0xbffff2ba 주소에 16byte를 입력시키겠죠?
하지만 우리 입장에선 아주 큰 값을 입력해야 합니다..
그렇다면 %100d 라고 하면 공백이 100개 생기게 됩니다. 이런 방식으로 원하는 만큼의 입력이 가능해집니다.
attackme를 gdb로 열어보면
이렇게
No symbol "main" in current context. 라는 문구가 나오게 됩니다..
이럴 때 사용할 수 있는 것이 .dtors 영역입니다.
간단하게 소개하자면
GCC를 할 때 gcc의 속성상 .ctors와 .dtors 라는 segment를 생성하게 됩니다.
(ctors - constructor, dtors - destructor )
.ctors 속성의 함수는 main() 전에 실행
.dtors 속성의 함수는 main() 종료 후에 실행
라는 특징이 있습니다.
그러므로 main() 종료 후에 .dtors 속성의 함수가 실행되는 것을 이용해서 그 부분을 쉘 코드가 있는 주소 값으로 덮음으로써 쉘 코드가 실행되게 할 수 있다는 것입니다.
먼저 .dtors의 주소 값을 알아보면
뭐,, 그렇다네요..
.dtors segment 의 addr은 0x08049594 입니다.
여기서 +4를 한 08049598을 가지고 등록하면 됩니다.
이제 마지막으로
AAAA\x98\x95\x04\x08%3221224558c%n 이와 같이 입력해주면될 거 같은데
아직 미흡하다..
처음 AAAA를 입력하고 %x를 3번 사용하였다,. 따라서 AAAA를 받아오는 %c 앞에 %x를 3개 추가해야한다.
AAAA\x98\x95\x04\x08%x%x%x%3221224558c%n
또 여기서 문제가 발생한다... x86 pc 는 3221224558와 같은 큰 수를 입력 불가능하다..
따라서 3221224558 대신 0xBFFFFC6E를 반반 나눠서 입력해야한다,
다시 입력 값을 적어보면
AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%x%x%x%64622c%n%49151c%n
이제 끝..!!!
이 아니라
아직 더 남았습니다..
\n은 현재까지 즉 이전까지 입력 용량을 저장하는데
총 입력 용량은
4+4+4+4+?+?+?+64622 입니다.
%x에는 메모리에 어떤 값이 있느냐에 따라 출력 결과가 다르기 때문에 8byte로 통일 시켜줍니다.
AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%64622c%n%49151c%n
따라서
4+4+4+4+8+8+8+64622 입니다.
그런데 64622에 맞춰줘야 하므로 -(4+4+4+4+8+8+8) 값을 빼줍니다.. (귀찮지만 계산하니 40..)AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%64582c%n%49151c%n마찬가지로 49151 도 변경해야 합니다.이전 까지 출력한 값이 64622 이므로 빼주어야 하는데 음수가 발생하므로64622 -> 0xFC6E49151 -> 0x1BFFF0x1BFFF 에서 0xFC6E 를 뺀 값인 50065를 넣어주면 최종 완성"\x41"*4+"\x98\x95\x04\x08"+"\x42"*4+"\x9a\x95\x04\x08"+"%8x"*3+"%64582c%n"+"%50065c%n"라고 하면 쉘이 열려야 하는데 열리지 않는다,, 왜 그런진 모르겠다.,.
오늘 시간 나면 다시 시도해봐야 겠다..