欢迎来到 嗅灵易学

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

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

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


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

上篇:http://bbs.pediy.com/showthread.php?t=131294

接着上篇下面是MS11-006补丁的分析, 如果哪里有问题或大家觉得很别扭,请大家帮忙指出

对比补丁发现,几处函数做了修改,其中原来出现问题CreateSizeDIBSECTION函数已经将之前的有符号比较改成了无符号比较,
这样biClrUsed为负数也不会有问题了. 下面提到的IsValidClipData函数中也加入了相同的判断。

另外在进行DIB转Thumbnail的时候,加入了BOOL IsValidClipData(CLIPDATA * pClipdata)函数,这个函数对BITMAPHEADER信息作
了很细致的检查,不过大小是否有超过可用值,相乘的结果是否有溢出等,相当于,不管之前函数是否有问题,先在其前面加个检查
器,如果检查出问题,则不进行后面的转换。以免出现后面函数考虑不全再出现类似的漏洞。

.text:5CB06731 push    eax             ; struct tagCLIPDATA *
.text:5CB06732 call    ?_IsValidClipData@@YGHPAUtagCLIPDATA@@@Z ; _IsValidClipData(tagCLIPDATA *)
.text:5CB06737 test    eax, eax
.text:5CB06739 jz      loc_5CB0691B
            

来判断clip中的DIB数据是否为有效且合法格式。下面对这个函数简要分析:
    
text:5CB0641F pClipdata       = dword ptr  8
.text:5CB0641F
.text:5CB0641F                 mov     edi, edi
.text:5CB06421                 push    ebp
.text:5CB06422                 mov     ebp, esp
.text:5CB06424                 push    ebx
.text:5CB06425                 push    esi
.text:5CB06426                 mov     esi, [ebp+pClipdata]
.text:5CB06429                 lea     eax, [ebp+pClipdata]
.text:5CB0642C                 push    eax             ; unsigned __int32 *
.text:5CB0642D                 push    4               ; unsigned __int32
.text:5CB0642F                 push    dword ptr [esi] ; unsigned __int32
.text:5CB06431                 xor     ebx, ebx        ; ebx = 0
.text:5CB06433                 call    ?ULongSub@@YGJKKPAK@Z ; ULongSub(ulong,ulong,ulong *)    ; 检查结构体大小参数
.text:5CB06438                 test    eax, eax
.text:5CB0643A                 jl      short Return
.text:5CB0643C                 cmp     [ebp+pClipdata], 4
.text:5CB06440                 jbe     short Return
.text:5CB06442                 mov     esi, [esi+8]                                             ; esi = pClipdata
.text:5CB06445                 mov     eax, [esi]
.text:5CB06447                 cmp     eax, 3                                                   ; CF_METAFILEPICT
.text:5CB0644A                 jz      short loc_5CB06480                                       ; 判断clip中是否为图元文件格式
.text:5CB0644C                 cmp     eax, 8                                                   ; CF_DIB
.text:5CB0644F                 jz      short loc_5CB06454                                       ; 判断clip中是否为DIB位图格式
.text:5CB06451                 inc     ebx
.text:5CB06452                 jmp     short Return
                    .....
 loc_5CB06454:                          
.text:5CB06454                 lea     eax, [ebp+pClipdata]
.text:5CB06457                 push    eax             ; unsigned __int32 *
.text:5CB06458                 push    4               ; unsigned __int32
.text:5CB0645A                 push    [ebp+pClipdata] ; unsigned __int32
.text:5CB0645D                 call    ?ULongSub@@YGJKKPAK@Z ; ULongSub(ulong,ulong,ulong *)
.text:5CB06462                 test    eax, eax
.text:5CB06464                 jl      short Return
.text:5CB06466                 cmp     [ebp+pClipdata], 28h
.text:5CB0646A                 jb      short Return
.text:5CB0646C                 lea     eax, [esi+4]                                             ; eax = pclipdata->pclipdata + sizeof(DWORD) = pbmi
.text:5CB0646F                 test    eax, eax                                                 ; 跳过文件类型标识的那个DWORD
.text:5CB06471                 jz      short Return
.text:5CB06473                 push    [ebp+pClipdata] ; unsigned __int32
.text:5CB06476                 push    eax             ; struct tagBITMAPINFO *
.text:5CB06477                 call    ?_ValidateBitmapInfoAndPixelData@@YGHPBUtagBITMAPINFO@@K@Z ; 这个函数会对DIP的BITMAPHEADER信息详细的判断
.text:5CB0647C                 mov     ebx, eax
.text:5CB0647E                 jmp     short Return
                        .....

函数 ULongSub(ULONG num1, ULONG num2, ULONG * pulSubRes)
如果 ulNum1 >= ulNum2, *pulSubResult = ulNum1 - ulNum2, return 0   ;
如果 ulNum1 < ulNum2, *pulSubResult = 0xffffffff, return 0x80070216.

?ULongSub@@YGJKKPAK@Z proc near         
.text:5CB06175                                        
.text:5CB06175
.text:5CB06175 arg_0           = dword ptr  8
.text:5CB06175 arg_4           = dword ptr  0Ch
.text:5CB06175 arg_8           = dword ptr  10h
.text:5CB06175
.text:5CB06175                 mov     edi, edi
.text:5CB06177                 push    ebp
.text:5CB06178                 mov     ebp, esp
.text:5CB0617A                 mov     edx, [ebp+arg_8]             ; edx = arg8
.text:5CB0617D                 mov     ecx, [ebp+arg_0]             ; ecx = arg0
.text:5CB06180                 or      dword ptr [edx], 0FFFFFFFFh  ; [arg8] = -1
.text:5CB06183                 cmp     ecx, [ebp+arg_4]             ; ecx = arg0, cmp arg0, arg4
.text:5CB06186                 mov     eax, 80070216h
.text:5CB0618B                 jb      short return
.text:5CB0618D                 sub     ecx, [ebp+arg_4]             ; arg0 - arg4
.text:5CB06190                 xor     eax, eax                     ; eax = 0
.text:5CB06192                 mov     [edx], ecx                   ; [arg8] = arg0 - arg4
.text:5CB06194
.text:5CB06194 return:                                 
.text:5CB06194                 pop     ebp
.text:5CB06195                 retn    0Ch

函数: ValidateBitmapInfoHeader(BITMAPINFO * pbmi, ULONG ulSize)

.text:5CB061E2 mov     esi, [ebp+pbmi]
.text:5CB061E5 mov     eax, [esi]               ; pbmi->bmiHead.biSize
.text:5CB061E7 cmp     eax, 28h                 ; 检查header中的结构体大小字段
.text:5CB061EA mov     [ebp+biSize], eax
.text:5CB061ED jb      Return_FALSE
.text:5CB061F3 cmp     eax, 1000h
.text:5CB061F8 ja      Return_FALSE
text:5CB061FE mov     eax, [esi+4]              ; pbmi->bmiHeader.biWidth
.text:5CB06201 test    eax, eax                 ; 检查DIB宽度(这里单位为像素)
.text:5CB06203 mov     [ebp+biWidth], eax
.text:5CB06206 jz      Return_FALSE

.text:5CB0620C mov     ebx, [esi+8]             ; pbmi->bmiHeader.biHeight
.text:5CB0620F test    ebx, ebx                 ; 检查DIB高度(单位也是像素)
.text:5CB06211 jz      Return_FALSE
.text:5CB06217 movzx   edi, word ptr [esi+0Eh]
.text:5CB0621B cmp     edi, 20h                 ; pbmi->bmiHeader.biBitCount
.text:5CB0621B                                  ; 检查像素的BitCount,是否超出最大的32bit
.text:5CB0621E ja      Return_FALSE
.text:5CB06224 lea     ecx, [ebp+pbmi]          ; pbmi is a mul res tmp register here, not the argument any more!!!
.text:5CB06227 push    ecx
.text:5CB06228 push    eax                        ; eax = biWidth
.text:5CB06229 push    20h                          
.text:5CB0622B call    _MultiplyCheckOverflow@12 ; 检查 0x20 * biWidth 是否overflow(应该是为了计算Row Bytes做检测, 看是否有overflow)
                                               ; 因为: row bits = bicount * biwidth 
                                               ; 其中, bitcount取值为 1, 4, 8, 16, 24, 32, 所以取32最大值
.text:5CB06230 test    eax, eax                  
.text:5CB06232 jz      Return_FALSE

.text:5CB06238 mov     eax, ebx                     ; ebx = biHeight
.text:5CB0623A cdq                                  ; check biHeight <0 or >= 0
.text:5CB0623B mov     ebx, eax
.text:5CB0623D lea     eax, [ebp+pbmi]
.text:5CB06240 push    eax                          ; arg3
.text:5CB06241 mov     eax, [ebp+pbmi]
.text:5CB06244 shr     eax, 3
.text:5CB06247 xor     ebx, edx                     ; biHeight < 0, ebx = ~ebx; else ebx = ebx
.text:5CB06249 sub     ebx, edx
.text:5CB0624B add     eax, 3
.text:5CB0624E push    ebx                          ; arg2
.text:5CB0624F and     eax, 0FFFFFFFCh
.text:5CB06252 push    eax                          ; arg1
.text:5CB06253 call    _MultiplyCheckOverflow@12    ; 检查 检查SizeImage是否有溢出
                                                  ; 因为: SizeImage = row bytes * biHeight
                                                  ; 其中: row bytes = (row bits / 8 + 3) & 0xffffffffc;
                                                  ; +3 是为了当相除有余数,即不是整好够一个4byte,来通过+3使其4byte对齐
                                                  ; 图像是4byte对齐操作
.text:5CB06258 test    eax, eax
.text:5CB0625A jz      short Return_FALSE

.text:5CB0625C mov     eax, 40000000h
.text:5CB06261 cmp     [ebp+pbmi], eax              ; 判断计算出来的图片的尺寸大小是否有超过0x40000000 bytes
.text:5CB06264 ja      short Return
.text:5CB06266 mov     ecx, [esi+14h]               ; pbmi->bmiHeader.biSizeImage
.text:5CB06269 cmp     ecx, eax                     ; 判断biSizeImage是否有超过0x40000000 bytes
.text:5CB0626B mov     [ebp+pbmi], ecx
.text:5CB0626E ja      short Return_FA
.text:5CB06270 mov     eax, [esi+20h]               ; biClrUsed
.text:5CB06273 cmp     eax, 100h
.text:5CB06278 ja      short Return_FALSE           ; 这里就是对问题函数中的再次判断,用的是ja不是jg, 问题中修补后也改成了ja
......                                              ; 找到了biClrUsed后。下面就没有再分析了

对应的C描述:

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

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

0 0 0 举报
复制成功