CVE-2010-2553 Microsoft Cinepak Codec CVDecompress 堆溢出漏洞

其实这个文章当时2017-03-20的时候就写了文章的题目准备学习调试,由于比赛,论文等原因等到现在5月23号才开始学习,其实主要都是懒,学习的激情不足

结果分析了下来,只能懂一点点,也不会利用

漏洞描述

在微软提供的Cinepak视屏编码器(iccvid.dll),其CVDecompress函数在解压缩媒体文件时,由于未对数据长度进行检测,导致堆溢出,利用漏洞可导致程序崩溃或执行任意代码

说些废话

这是Windows Media Player的溢出漏洞版本是10.00.00.00.4063

我看了一下,我的是11.XXX的,试了一下,不行。

于是发现吾爱破解里面的虚拟机的版本比作者的还要低,所以应该可以

一打开,马上崩溃,那就可以开始实验咯

image.png

开始分析

那个py文件是用来生成poc的,不过作者已经帮我们生成好了,windbg附加,打开页堆

0:011> !gflag +hpa
New NtGlobalFlag contents: 0x02000000
    hpa - Place heap allocations at ends of pages

打开poc,崩溃

(34c.a8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00006000 ebx=0268e9b8 ecx=000003fc edx=0290fd38 esi=0013d000 edi=0013f000
eip=73b722cc esp=0290fd04 ebp=0290fd30 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
iccvid!CVDecompress+0x11e:
73b722cc f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
0:013> kb
ChildEBP RetAddr  Args to Child              
0290fd30 73b7cbf3 00000004 00000000 00000068 iccvid!CVDecompress+0x11e
0290fd60 73b766c8 0012a740 00000000 00137048 iccvid!Decompress+0x11d
0290fdac 73b41938 0012a740 00000001 0000400d iccvid!DriverProc+0x1bf
0290fdd0 7cf8faaa 73b5b500 0000400d 0290fde8 MSVFW32!ICSendMessage+0x2b
0290fe00 7cf8f9f5 73b5b500 00000000 00137048 quartz!CVFWDynLink::ICDecompress+0x3e
0290fec0 7cf90a65 00e12ee8 00e10cc8 00000000 quartz!CAVIDec::Transform+0x282
0290feec 7cf90949 00e12ee8 00000000 00e03f48 quartz!CVideoTransformFilter::Receive+0x110
0290ff00 7cf8e68a 00e2584c 00e12ee8 0290ff40 quartz!CTransformInputPin::Receive+0x33
0290ff10 7cf90cb0 00e12ee8 00040103 00e03f48 quartz!CBaseOutputPin::Deliver+0x22
0290ff40 7cf90e2c 0290ff70 0290ff6c 00000000 quartz!CBaseMSRWorker::TryDeliverSample+0x102
0290ff84 7cf8ce40 00000000 00e03f48 00e03f48 quartz!CBaseMSRWorker::PushLoop+0x15e
0290ff9c 7cf8dbf6 00000000 7cf8a131 00000000 quartz!CBaseMSRWorker::DoRunLoop+0x4a
0290ffa4 7cf8a131 00000000 00090178 0290ffec quartz!CBaseMSRWorker::ThreadProc+0x39
0290ffb4 7c80b713 00e03f48 00000000 00090178 quartz!CAMThread::InitialThreadProc+0x15
0290ffec 00000000 7cf8a11c 00e03f48 00000000 kernel32!BaseThreadStart+0x37

因为我这有符号,作者那个还没有,所以有点不一样,

我们在上面已经看到了iccvid!CVDecompress这个函数了 

看看它的上层函数,u就是反汇编(Unassemble),b应该是before

0:013> ub iccvid!Decompress+0x11d
iccvid!Decompress+0x102:
73b7cbd8 ffb698000000    push    dword ptr [esi+98h]
73b7cbde 57              push    edi
73b7cbdf ff7528          push    dword ptr [ebp+28h]
73b7cbe2 ff752c          push    dword ptr [ebp+2Ch]
73b7cbe5 ff7530          push    dword ptr [ebp+30h]
73b7cbe8 ff7514          push    dword ptr [ebp+14h]
73b7cbeb ff765c          push    dword ptr [esi+5Ch]
73b7cbee e8bb55ffff      call    iccvid!CVDecompress (73b721ae)

可以看到调用CVDecompress前传了很多参数

这里学到了一个知识,因为iccvid.dll要打开pic.avi才会加载,我们不能直接对73b7cbee下断

我们可以使用下面的命令在首次加载dll的时候下断

sxe ld:ModuleName

0:011> !gflag +hpa
New NtGlobalFlag contents: 0x02000000
    hpa - Place heap allocations at ends of pages
0:011> sxe ld:iccvid
0:011> g
(88.4dc): Unknown exception - code 000006ba (first chance)
ModLoad: 73b70000 73b87000   C:\WINDOWS\system32\iccvid.dll
eax=00000001 ebx=00000000 ecx=00000044 edx=00092ee0 esi=00000000 edi=00000000
eip=7c92e4f4 esp=0250e298 ebp=0250e38c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCallRet:
7c92e4f4 c3              ret
0:009> lmm iccvid
start    end        module name
73b70000 73b87000   iccvid     (deferred)

我们看到第一次断下来,iccvid已经加载了,基址是73b70000

那么我们这时候就可以下断了

0:009> bp 73b7cbee 
0:009> bl
 0 e 73b7cbee     0001 (0001)  0:**** iccvid!Decompress+0x118
0:009> g
Breakpoint 0 hit
eax=00000001 ebx=01b4fd88 ecx=0005e2c0 edx=fffffee0 esi=0012b968 edi=027c0050
eip=73b7cbee esp=01b4fd38 ebp=01b4fd60 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
iccvid!Decompress+0x118:
73b7cbee e8bb55ffff      call    iccvid!CVDecompress (73b721ae)

看了下栈上的值,下面这个有可能是复制的数据来源

0:014> dd esp
01b4fd38  0014dd58 00e1e8f8 00000068 027c0050
01b4fd48  0005e800 027c0050 00000540 00000001
01b4fd58  0012b968 0012b968 01b4fdac 73b766c8
01b4fd68  0012b968 00000000 00137dc8 00e1e8f8
01b4fd78  00000000 00000000 ffffffff ffffffff
01b4fd88  0005e800 027c0050 00000068 00000000
01b4fd98  ffffffff ffffffff 01b4fde8 73b5b500
01b4fda8  00e150d0 01b4fdd0 73b41938 0012b968
0:014> dc 00e1e8f8 
00e1e8f8  68000000 20016001 00101000 00001000  ...h.`. ........
00e1e908  60000000 00206001 00110000 41411000  ...`.` .......AA
00e1e918  41414141 41414141 00114141 41411000  AAAAAAAAAA....AA
00e1e928  41414141 41414141 00114141 41411000  AAAAAAAAAA....AA
00e1e938  41414141 41414141 00114141 00411000  AAAAAAAAAA....A.
00e1e948  31786469 00000010 63643030 00000010  idx1....00dc....
00e1e958  00000004 00000068 00000000 00000000  ....h...........
00e1e968  33797430 00000000 00002288 00002728  0ty3....."..('..

接下来的代码判断CVID的数据长度是否大于0x20,这样才能往下执行

0:014> p
eax=00000000 ebx=0014dd58 ecx=0005e2c0 edx=fffffee0 esi=00000000 edi=00000000
eip=73b721e3 esp=01b4fd04 ebp=01b4fd30 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
iccvid!CVDecompress+0x35:
73b721e3 837d1020        cmp     dword ptr [ebp+10h],20h ss:0023:01b4fd40=00000068

这两个合起来就是Frame Header

image.png

含义如下

flag \x00
CIVD数据长度 \x00\x00\x68
编码帧宽度 \x01\x60
编码帧高度 \x01\x20
编码条数量 \x00\x10

后面那个就懒得写了,看看就好

第一次复制

0:014> g
Breakpoint 1 hit
eax=00002000 ebx=0014dd58 ecx=00000800 edx=01b4fd38 esi=0014dda0 edi=0014fda0
eip=73b722cc esp=01b4fd04 ebp=01b4fd30 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
iccvid!CVDecompress+0x11e:
73b722cc f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

第二次不粘贴了,第三次,是这一次的复制触发的异常

0:014> g
Breakpoint 1 hit
eax=00006000 ebx=0014dd58 ecx=00000800 edx=01b4fd38 esi=00151da0 edi=00153da0
eip=73b722cc esp=01b4fd04 ebp=01b4fd30 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
iccvid!CVDecompress+0x11e:
73b722cc f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

我们来看看关键的变量,这是循环次数,0x10次

0:014> p
eax=00000000 ebx=0014dd58 ecx=0000005e edx=01b4fd20 esi=00e1e902 edi=00000000
eip=73b72232 esp=01b4fd04 ebp=01b4fd30 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
iccvid!CVDecompress+0x84:
73b72232 8a46ff          mov     al,byte ptr [esi-1]        ds:0023:00e1e901=10
0:014> p
eax=00000010 ebx=0014dd58 ecx=0000005e edx=01b4fd20 esi=00e1e902 edi=00000000
eip=73b72235 esp=01b4fd04 ebp=01b4fd30 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
iccvid!CVDecompress+0x87:
73b72235 3bc7            cmp     eax,edi

第一次复制的大小ecx为0x800,复制第二次就到了0x2800位置为起始位置,复制到了0x3600

第三次,复制起点为0x5600,复制0x400个就差不过溢出了,看下面的话是复制了0x800-0x368个

感觉作者说得有点问题,因为根据上面结果,很可能是错的

0:014> g
(88.76c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00006000 ebx=0014dd58 ecx=00000368 edx=01b4fd38 esi=00153000 edi=00155000
eip=73b722cc esp=01b4fd04 ebp=01b4fd30 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
iccvid!CVDecompress+0x11e:
73b722cc f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

异常时因为那个目的地址已经了private的了

0:014> !address 00155000
                              
Failed to map Heaps (error 80004005)
Usage:                  <unclassified>
Allocation Base:        00090000
Base Address:           00155000
End Address:            00190000
Region Size:            0003b000
Type:                   00020000MEM_PRIVATE
State:                  00002000MEM_RESERVE
Protect:                00000000

修复

将获取到的编码条的数量,假如大于3的强制改为3,

其实第一次循环是不进入copy的,所以总共才copy两次,所以不会堆溢出

应该是作者说的有问题

打赏
微信
支付宝
微信二维码图片

微信扫描二维码打赏

支付宝二维码图片

支付宝扫描二维码打赏

CVE-2010-2553 Microsoft Cinepak Codec CVDecompress 堆溢出漏洞》上有2条评论

  1. 666

    终于又更新了,博客再不更新就准备从浏览器收藏夹删了···~( ̄▽ ̄~)(~ ̄▽ ̄)~···

    回复

giantbranch 发表评论 取消回复