Format String Bug (FSB)
개념
Fortmat String Bug(이하 FSB) 는 printf()를 사용할 때 프로그래머의 실수로 인해 배열 안의 값을 printf("%s", buf)로 사용하는 것이 아니라 printf(buf)로 사용함에 있어서 나타나는 버그를 말한다.
printf(buf)와 같이 소스코드를 작성하여 실행할 경우 buf안에 문자를 넣는 것이 아니라 서식문자, 지시자를 넣었을 경우 스택에 쌓여있는 값을 출력하는 버그를 발생한다.
설명
먼저 Format String에 대해서 알아보도록 하겠습니다.
Format String은printf("num is %d \n, num"); 과 같이 작성된 코드에서 "num is %d \n"를 말합니다. 쉽게 생각하면 printf()안에서 출력할 내용을 뜻 합니다.
FSB는 printf(buf)와 같은 구문에서 %x와 같은 서식문자를 넣게 될 때, 스택의 값을 출력하는 것을 말합니다.
간단한 C코드를 작성하고 확인해 보도록 하겠습니다.
main함수에서 각 내용을 출력하고 input함수로 넘어갑니다. 그리고 input 함수에서는 buf에 입력을 받고, 해당 값을 출력합니다.
앞서 설명한 것 처럼 printf(buf)와 같이 프로그래머의 실수로 코딩을 한 경우 FSB가 발생할 수 있습니다.
AAAA %x %x %x 를 입력한 결과 입니다.
AAAA가 출력되고 어디서 나온지 모를 값이 출력되었습니다. 앞서 설명할 때 스택의 값을 가져온다고 했었는데, 어느 시점에서의 스택을 가져온 것인지 확인해 보죠.
printf가 실행 되고 난 후의 스택상태를 확인했습니다.
스택에 있는 값이 출력된 것을 알 수 있습니다.
자 그러면 스택에 있는 값을 출력한다는 건 알겠는데, 이걸 가지고 어떻게 쉘을 실행시킬 수 있을까요?
먼저 알아야할 개념이 있습니다. 바로 RTL과 plt and got 입니다.
RTL : http://kblab.tistory.com/218
plt and got : http://kblab.tistory.com/217
그리고 한가지 더 필요한 개념이 있는데 %n 지시자 입니다.
%n 지시자는 출력되는 내용을 카운팅 하여 %n으로 받아 값을 저장시키는 역할을 합니다.
간단히 예를 들어, AAAA %x %x %n을 입력했다면 AAAA(4) + 공백(1) + 400(3) + 공백(1) + 8자리(8) + 공백(1) = 18이라는 값을 0x41414141에 넣게 되는 것입니다.
%n 지시자와 plt and got를 이용하여 쉘을 실행시키는 것이 Format String Bug 입니다.
plt와 got를 이용한다고 했는데, 이걸 어떻게 이용하는지 알아보도록 하겠습니다.
ecx의 값이 0x12인데 이 값은 십진수로 18이 됩니다. 해당 값을 eax의 주소에 넣고 있는 것을 알 수 있습니다.
여기까지 생각해 봤을 때 AAAA 부분을 원하는 주소로 주고 값을 계산해서 %n으로 넘겨주면 쉘을 실행 시킬 수 있겠다. 라고 생각이 듭니다.
이때 이용하는 것이 plt와 got입니다.
함수가 한번 실행이 되고 난 뒤 다시 실행이 될때는 plt에서 바로 got로 이동한다는 것을 알고 있습니다. 바로 이것을 이용하는 것이죠.
Got Overwrite를 하는 것입니다.
puts의 got는 0x804a014가 됩니다.
해당 주소에 값을 넣어서 puts가 실행되면 원하는 주소로 넘어가게 하는 것이죠.
get_shell함수의 주소는 0x804853b 입니다.
페이로드를 작성해 보겠습니다.
puts@got + %x + %x + %n 을 이용해야 하는데, get_shell의 주소는 0x804853b, 십진수로 하면 134513979이 됩니다.
즉, %n을 이용해 넘겨야 할 값이 134513979이 되는 것이죠.
puts@got가 8자리, %x가 3자리 이므로 134513979에서 11를 뺀 값을 넣습니다.
python -c 'print "\x14\xa0\x04\x08" + "%x" + "%134513968x" + "%n"' 과 같은 형식이 되죠.
gdb에 넣고 한번 확인 해 보도록 하겠습니다.
804a014의 값이 8048537이 들어가 있는 것을 알 수 있습니다. 804853b가 들어가야 하는데 말이죠. 차이 만큼 더 넣어서 실행시킵니다.
4만큼 차이나므로 python -c 'print "\x14\xa0\x04\x08" + "%x" + "%134513972x" + "%n"' 를 넣어줘야 합니다.
쉘이 실행 된 것을 알 수 있습니다.
정리
1. %n 지시자를 이용한다.
2. 한번 실행이 된 함수를 이용한다. (plt에서 got로 바로 넘어가는 것을 이용.)
3. 값이 정확이 들어갔는지 확인한다.
'High Level Technique > System Hacking' 카테고리의 다른 글
Return Oriented Programming (ROP) - step 1 (0) | 2016.04.28 |
---|---|
Return to Library Chain (RTL Chain) (0) | 2016.04.28 |
Return To Library (RTL) (2) | 2016.04.20 |
Plt 와 Got (0) | 2016.04.20 |
Fake EBP (0) | 2016.04.19 |