欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

微软MS11-006 Windows Shell图形处理漏洞原理及补丁分析(上)(下)

微软MS11-006 Windows Shell图形处理漏洞原理及补丁分析(上)(下)

微软MS11-006 Windows Shell图形处理漏洞原理及补丁分析(上)

QQ  : 279933462
杂记: http://hi.baidu.com/tapeout

看微软公告说是公开的漏洞,但是网上搜了下没有找到相关的细节,应该只是发现者在POC2010演讲的话题。
这里只有POC2010演讲者摘要没有paper(http://www.powerofcommunity.net/speaker.html)于是自己尝试分析了下。
由于之前在一家IC Fabless公司从事芯片设计相关工作,打交道的最上层也只是firmware的同事, 对这块接触时间不长,相关的知识或是术语理解还很肤浅,
如果文中哪里出现那些错误,那怕是用词的偏差,还请大家不吝给小弟指出,感谢!

0x00 总体信息概要
---------------------
    == 调试环境:    VMware7.0 + en_windows_xp_professional_with_service_pack_3_x86
        
    == 主要软件:    MetaSploit Framwork 6.4, OllyDBG 2.0, IDA Pro 5.5
    
    == 漏洞编号:    MS11-006, CVE-2010-3970
    == 相关文件:    shimgvw.dll, shell32.dll
    == 漏洞描述:    Windows Shell 图形处理器中一个公开披露的漏洞。 如果用户查看特制缩略图,此漏洞可能允许远程执行代码。
                    成功利用此漏洞的攻击者可以获得与登录用户相同的用户权限。 那些帐户被配置为拥有较少系统用户权限的用户比
                    具有管理用户权限的用户受到的影响要小。 
     
                    详见: http://www.microsoft.com/china/technet/security/bulletin/MS11-006.mspx
        

0x02 重现漏洞现场
--------------------
    
    == POC/EXP :    http://www.exploit-db.com/exploits/16660/
    == 触发漏洞:    1) 创建文件夹,设置查看模式为缩略图。
                    2) 用MSF产生EXP, 指定输出到创建的文件夹内,进入文件夹,弹出calc, explorer提示关闭。
                    3) 知道现象后,用MSF产生用于Debug的POC, 进行调试分析。

0x03 确定问题所在
--------------------
   == 定位范围:     将OD attach 到explorer.exe进程, 中断在: (ecx过大,超出申请stack,从而照成stack溢出.)
                        ----------------------------------------------------------
                         5CB1FC42: REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
                        ----------------------------------------------------------
                    
   ==动态调试:     1). shimgvw.dll的导出函数ConvertDIBSECTIONToThumbnail的子函数CreateSizeDIBSECTION: 在判断ecx的传入参数时,
                       通过有符号判断最大上限,但是数据复制是用无符号数, 从而导致stack溢出.
    
                   2). 漏洞函数被调用的大概过程 (这里只是doc的,没有包含media的, media类似)
                
                     explorer.exe --> [ntdll.dll/shlwapi.dll/browseui.dll等] --> shell32.dll(CExtractImageTask:Run) -->
                     shimgvw.dll(CDocThumb::Extract) --> shimgvw.dll(GetDocFileThumbnail) --> 
                     shimgvw.dll(ConvertDIBSECTIONToThumbnail --> shimgvw.dll(CreateSizeDIBSECTION)

0x04 倒推分析Stream细节:
----------------------
    静态逆向分析:            

    == 函数: CreateSizeDIBSECTION (shimgvw.dll)
                          
            .text:5CB1FB63                 sub     esp, 430h                                ; 开辟0x430栈空间, 之后溢出的地方
            .text:5CB1FB69                 mov     eax, [ebp+arg_10]
                           
                                      ......                                                ; 此处省略98个字, :)
       
            .text:5CB1FB72                 call    ds:__imp__GetDC@4 ; GetDC(x)
            .text:5CB1FB78                 cmp     eax, ebx
            .text:5CB1FB7A                 mov     [ebp+hDC], eax
            .text:5CB1FB7D                 jz      loc_5CB1FD05
            .text:5CB1FB83                 push    edi
            .text:5CB1FB84                 push    eax             ; hdc
            .text:5CB1FB85                 call    ds:__imp__CreateCompatibleDC@4           ; 获取设备无关内存环境句柄
                                      ......                                                ; 中间省略N个字
            .text:5CB1FBAA                 lea     eax, [ebp+bmi]
            .text:5CB1FBB0                 push    eax             ; struct tagBITMAPINFO *
            .text:5CB1FBB1                 mov     [ebp+bmi.bmiHeader.biSize], 28h
            .text:5CB1FBBB                 mov     [ebp+bmi.bmiHeader.biWidth], ecx
            .text:5CB1FBC1                 mov     [ebp+bmi.bmiHeader.biPlanes], 1
            .text:5CB1FBCA                 mov     [ebp+bmi.bmiHeader.biBitCount], si
            .text:5CB1FBD1                 mov     [ebp+bmi.bmiHeader.biCompression], ebx
            .text:5CB1FBD7                 call    ?CalcBitmapSize@                         ; 如果为非OS/2且未压缩的win扩展DIB位图重新计算大小
                     
                                                    
            .text:5CB1FBF4                 cmp     esi, 8                                   ; 判断biBitCount是否为1,4,8,
                                                                                            ;因为24的不需要调色板
            .text:5CB1FBF7                 mov     [ebp+bmi.bmiHeader.biXPelsPerMeter], ebx
            .text:5CB1FBFD                 mov     [ebp+bmi.bmiHeader.biYPelsPerMeter], ebx
            .text:5CB1FC03                 mov     [ebp+bmi.bmiHeader.biClrUsed], eax
            .text:5CB1FC09                 mov     [ebp+bmi.bmiHeader.biClrImportant], ebx
            .text:5CB1FC0F                 ja      loc_5CB1FC9B                             ;  biBitCount为1,4,8不跳转
            .text:5CB1FC15                 mov     edx, [ebp+arg_C]                         ; 判断参数pbmi是否指向NULL
            .text:5CB1FC18                 cmp     edx, ebx
            .text:5CB1FC1A                 jz      short loc_5CB1FC46
            .text:5CB1FC1C                 movzx   ecx, word ptr [edx+0Eh] 
            .text:5CB1FC20                 cmp     ecx, esi                                 ; 判断biBitCount是否一致 
            .text:5CB1FC22                 jnz     short loc_5CB1FC46
            .text:5CB1FC24                 mov     ecx, [edx+20h]
            .text:5CB1FC27                 cmp     ecx, ebx
            .text:5CB1FC29                 jnz     short loc_5CB1FC2D
            .text:5CB1FC2B                 mov     ecx, eax
            .text:5CB1FC2D
            .text:5CB1FC2D loc_5CB1FC2D:                                                    ; !!!!!!!!!!!!!!! 问题所在 !!!!!!!!!!!!!!!!!!
            .text:5CB1FC2D                 cmp     ecx, 100h                                ; 判断biClrUsed是否大于0x100, 因为8bit最多256调色板
            .text:5CB1FC33                 jg      loc_5CB1FCF0                             ; 注意这里就是漏洞的根本问题,有符号比较
            .text:5CB1FC39                 lea     esi, [edx+28h]                           ; 而下面是无符号的长度拷贝数值,当biClrUsed为负数,
            .text:5CB1FC3C                 lea     edi, [ebp+bmi.bmiColors]                 ; 满足小于0x100, 将拷贝很长的数据到esi指向的stack
            .text:5CB1FC42                 rep movsd                                        ; 参数的BITMAPINFO指针向的bicolors便可以构造shellcode
            .text:5CB1FC44                 jmp     short loc_5CB1FC9B                       ; biClrUsed控制shellcode长度
                    
                            ......                                                          ; 下面会进行DIB Section的创建, RGB换序, bits映射到
                                                                                            ; 内存等操作,篇幅所限先略掉了.
                                                                                            ; 逆向后的C Code中有完整给出。
    

    == 函数:  ConvertDIBSECTIONToThumbnail (shimgvw.dll) 
            
            .text:5CB20102                 mov     eax, [ebx+8]                 ; pbmi.bmiHeader.biHeight
            .text:5CB20105                 cmp     eax, ecx                     ; 判断是从顶到底,还是从底到顶来存储
            .text:5CB20107                 push    esi
            .text:5CB20108                 push    edi
            .text:5CB20109                 mov     [ebp+pbmi], ebx
            .text:5CB2010C                 mov     [ebp+fTopToBottom], ecx      ; fTopToBottom = FALSE
            .text:5CB2010F                 jge     short loc_5CB2011D
            .text:5CB20111                 neg     eax                          ; 从顶到底,则取其补码
            .text:5CB20113                 mov     [ebx+8], eax                 ; pbmi->bmiHeader.biHeight
            .text:5CB20116                 mov     [ebp+fTopToBottom], 1
            
                                    ......
            
            .text:5CB20148                 mov     eax, edi
            .text:5CB2014A                 sub     eax, [ebp+rect.top]          ; eax = top - bottom
            .text:5CB2014D                 cmp     eax, [ebx+8]                 ; pbmi->bmiHeader.biHeight
            .text:5CB20150                 jz      short loc_5CB201CA       
            
                                    .......
        
            loc_5CB201CA:                           
            .text:5CB201CA                                         
            .text:5CB201CA                 cmp     [ebp+fTopToBottom], 1
            .text:5CB201CE                 mov     esi, [ebp+pbmi]              ; esi = pbmi
            .text:5CB201D1                 jnz     short loc_5CB201D6
            .text:5CB201D3                 neg     dword ptr [esi+8]            ; pbmi->bmiHeader.biHeight
            .text:5CB201D6
            .text:5CB201D6 loc_5CB201D6:                           
            .text:5CB201D6                 xor     ecx, ecx                     ; ecx = 0
            .text:5CB201D8                 cmp     [ebp+fOrigSize], ecx
            .text:5CB201DB                 jz      short loc_5CB20229
            .text:5CB201DD                 movzx   eax, word ptr [esi+0Eh]      ; pbmi->bmiHeader.biBitCount
            .text:5CB201E1                 cmp     eax, [ebp+dwRecClrDepth]
            .text:5CB201E4                 ja      short loc_5CB20229
            .text:5CB201E6                 mov     edx, [esi+4]                 ; pbmi->bmiHeader.biWdith
            .text:5CB201E9                 mov     [ebp+bmiWidth], edx
            .text:5CB201EC                 mov     edx, [esi+8]                 ; pbmi->bmiHeader.biHeight
            .text:5CB201EF                 mov     [ebp+hMem], edx
            .text:5CB201F2                 lea     edx, [ebp+phBmpThumbnail]
            .text:5CB201F5                 push    edx                          ; int
            .text:5CB201F6                 push    ecx                          ; int
            .text:5CB201F7                 push    [ebp+phBmpThumbnail]         ; int
            .text:5CB201FA                 push    esi                          ; pbmi
            .text:5CB201FB                 push    ecx                          ; ppvBits
            .text:5CB201FC                 push    eax                          ; eax = pbmi->bmiHeader.biBitCount
            .text:5CB201FD                 lea     eax, [ebp+bmiWidth]
            .text:5CB20200                 push    eax                          ; int: pbiWidth
            .text:5CB20201                 call    _CreateSizedDIBSECTION@28    ; <----这里就是上面分析的问题函数 !!!
            .text:5CB20206                 test    eax, eax                     ; the function above cause the vul !!!!!!
            .text:5CB20208                 mov     [ebp+pBits], eax             ; fCreateDIBSECTIONResult
            .text:5CB2020B                 jz      short loc_5CB2025E
            .text:5CB2020D                 push    esi                            ; struct tagBITMAPINFO *
            .text:5CB2020E                 call    ?CalcBitmapSize@@YGKPBUtagBITMAPINFO@@@Z ; CalcBitmapSize(ta
            
    == 函数:  GetDocFileThumnail (shimgvw.dll)
            .text:5CB0635A xor     esi, esi        ; esi = 0
            .text:5CB0635C push    esi             ; hWnd
            .text:5CB0635D call    ds:__imp__GetDC@4 ; GetDC(x)
            .text:5CB06363 push    eax             ; hdc
            .text:5CB06364 mov     [ebp+hDC], eax
            .text:5CB06367 call    ds:__imp__CreateCompatibleDC@4               ; 创建设备无关内存环境句柄
            
                            ......
        
                
            .text:5CB06377 push    edi
            .text:5CB06378 xor     eax, eax                                     ; eax = 0
            .text:5CB0637A mov     [ebp+pvarResult.vt], si
            .text:5CB0637E lea     edi, [ebp+pvarResult.wReserved1]
            .text:5CB06381 stosd                                                ; 初始化结构体pvarResult, 类型PROPVARIANT
            .text:5CB06382 stosd
            .text:5CB06383 stosd
            .text:5CB06384 stosw
            .text:5CB06386 mov     eax, [ebp+pPropStg]
            .text:5CB06389 mov     edx, [eax]
            .text:5CB0638B lea     edi, [ebp+pvarResult]                        ; edi = &pvarResult
            .text:5CB0638E push    edi
            .text:5CB0638F xor     ecx, ecx
            .text:5CB06391 inc     ecx                                          ; ecx = 1
            .text:5CB06392 lea     edi, [ebp+propSpec]
            .text:5CB06395 push    edi
            .text:5CB06396 push    ecx                                          ; ecx = 1: PRSPEC_PROPID
            .text:5CB06397 push    eax                                          ; eax = pPropStg: be added auto
            .text:5CB06398 mov     [ebp+ho], esi
            .text:5CB0639B mov     [ebp+propSpec], ecx
            .text:5CB0639E mov     [ebp+propSpec_propidORlpwstr], 11h
            .text:5CB063A5 call    dword ptr [edx+0Ch]                          ; 参考 IPropertyStorage C的定义得知为ReadMultiple
            .text:5CB063A5                                                      ; pPropStg->ReadMultiple(x, x, x);
            .text:5CB063A8 cmp     eax, esi
            .text:5CB063AA mov     [ebp+pPropStg], eax                          ; here pPropStg is the ReadMultiple return value for optimization
            .text:5CB063AD jl      loc_5CB06565
              
            .text:5CB063B3 cmp     [ebp+pvarResult.vt], 47h                     ; VT_CF
            .text:5CB063B8 mov     [ebp+pPropStg], 80004005h                    ; Error Message: E_FAIL
            .text:5CB063BF jnz     loc_5CB065AD
            
            .text:5CB063C5 mov     ecx, dword ptr [ebp+pvarResult.anonymous_0] ; = pvarREsult.pclipdata(since vt = VT_CF)
            .text:5CB063C8 cmp     dword ptr [ecx+4], -1                       ; pvarResult.pclipdata->ulClipFmt:
            .text:5CB063C8                                                     ; -1 : A DWORD that contains a built-in Windows clipboard format value.
            .text:5CB063CC jnz     loc_5CB0
            
            .text:5CB063D2 mov     eax, [ecx+8]                                 ; pvarResult.pclipdata->pClipData: (BYTE *)
            .text:5CB063D5 lea     edi, [eax+4]                                 ; eax + 4 = ecx + 12 = pclipdata->pClipData + 4, skip 1st DWORD
            .text:5CB063D8 mov     eax, [eax]                                   ; if the value of the ulClipFmt member is -1, the data is
            .text:5CB063D8                                                      ;  in the form of a built-in Windows format. In this case,
            .text:5CB063D8                                                      ; the first DWORD of the buffer pointed to by pClipData is
            .text:5CB063D8                                                      ;  the clipboard format identifier
            .text:5CB063DA cmp     eax, 3                                       ; 3 = CF_METAFILEPICT: metafile
            .text:5CB063DD mov     [ebp+pbmi], edi                              ; pbmi = (pvarResult.pclipdata->pClipData + sizeof(DWORD))
            .text:5CB063E0 jnz     loc_5CB0656F                                 ; goto ConvertDIBSECTIONToThumbnail
                
           .text:5CB0656F
           .text:5CB0656F loc_5CB0656F:                                         ; CF_DIB
           .text:5CB0656F cmp     eax, 8
           .text:5CB06572 mov     [ebp+pPropStg], 8004006Ah
           .text:5CB06579 jnz     short loc_5CB0655B
            
           .text:5CB0657B cmp     dword ptr [edi], 28h                          ; check if it is OS/2 DIB, or windows ext DIB
           .text:5CB0657E jnz     short loc_5CB0655B
        
           .text:5CB06580 push    dword ptr [ecx]                               ; ecx = pvarResult.pclipdata->cbsize
           .text:5CB06582 push    edi                                           ; struct tagBITMAPINFO *
           .text:5CB06583 call    _CalcBitsOffsetInDIB@8                        ; CalcBitsOffsetInDIB(x,x)
           .text:5CB06588 cmp     eax, esi
           .text:5CB0658A jz      short loc_5CB0655B
            
           .text:5CB0658C push    [ebp+fOrigSize] ; fOrigSize
           .text:5CB0658F push    0Fh             ; uiSharpPct
           .text:5CB06591 push    [ebp+hPalette]  ; hPalette
           .text:5CB06594 push    [ebp+dwClrDepth] ; dwRecClrDepth
           .text:5CB06597 push    [ebp+prgSize]   ; prgSize
           .text:5CB0659A push    [ebp+phBmpThumbnail] ; phBmpThumbnail
           .text:5CB0659D push    eax             ; pBits
           .text:5CB0659E push    edi             ; pbmi
           .text:5CB0659F call    _ConvertDIBSECTIONToThumbnail@32              ; <----这里就是了
           .text:5CB065A4 test    eax, eax
           .text:5CB065A6 jz      short loc_5CB0655B
            
                        ......                                                  ; 后面就不继续分析了
           
 0x05 补丁分析
       补丁相关文件:shimgvw.dll, shell32.dll
       下面主要分析shimgvw.dll中对doc/mic问题的修补,其中改了几处,本文自分析了在DIB转Thumnail前的主要的检测函数
        
        BOOL IsValidClipData(CLIPDATA * pClipdata)
        其中的静态反汇编分析和对应的C描述,由于篇幅问题,写在了文章的(下)
http://bbs.pediy.com/showthread.php?t=131300

上传的附件 微软MS11-006 Windows Shell图形处理漏洞原理及补丁分析 .pdf

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功