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