1 分析环境
操作系统:Window xp sp3
软件 :Windows Media Player
2 基本信息
漏洞类型:堆溢出
影响范围: Microsoft Windows XP SP2和SP3,Windows Vista SP1和SP2,以及Windows 7中的Cinepak 编码解码器
3 漏洞分析
Poc MD5: d3f51852ae9a37f0a98508bc8e47a9fc
我们首先用Windows Media Player,然后用Windbg附加上
我们在分析堆溢出的时候开启页堆,这里简要的介绍一下页堆,在启动页堆之后,堆管理器会在堆块后面增加专门用于检测溢出的栅栏页,这样一旦用户区数据触及栅栏页便会触发异常,
然后g运行,打开样本,我们看到发生异常,我们看到是在iccvid这个模块中的,取出放到IDA详细看下
我们查看一下栈函数地址。来看一下溢出函数的返回地址为73b7cbfc
我们在IDA中找到这个地址,看到调用溢出函数的地方,我们重新断到这个地方
发现还没有加载这个模块,这个时候我们现在加载模块的时候下个断点
在加载后,我们就可以下断点了,我们先运行到溢出点,来看一下复制到edi的地址属于什么位置
我们再看看整个堆的情况
我们查看peb 发现溢出点发生在进程的默认堆
在学习整个解压缩的过程前,我们首先要对样本的数据的格式要有个了解,我们看看生成poc的python
我们从movi_tag 这个开始看
其中的dc表示压缩的视频帧
我们在来看看索引块
其中最后一个字段0x68表示数据块的大小
我们在来看看函数的伪代码,这个a3 就表示的idx1索引块的0x68,也表示这个数据块必须要大于0x20
在判断完这个数据块的大小之后,就进行解压缩这个数据块的流程中
我们来看一下这个cinepak的结构,主要参考 https://multimedia.cx/mirror/cinepak.txt
我们先来看一下整个cinepak的头结构体,对应着cinepak_codec_data1 8个字节
其中标志字节 0x00
数据块长度0x68
编码帧宽度 0x01 0x60
编码帧高度 0x01 0x20
编码条数量 0x00 0x10
我们了解完结构后,可以发现首先发现如下图所说,对两个数据块进行比较
通过后,然后取得编码条数量,并判断是否大于0
之后开始对cinepak_codec_data2的数据进行解析先取得大小,然后跟剩下的进行比较
我们继续来解析cinepak_codec_data2中的数据
编码条ID 0x10 0x00
编码条数据大小 0x00 0x10
顶部Y坐标 0x00 0x00
顶部X坐标 0x00 0x00
底部Y坐标 0x00 0x60
底部X坐标 0x01 0x60
之后开始CVID Chunk块
我们看下POC样本的CVID check块的情况
CVID check ID 0x20 0x00
Chunk 数据大小 0x00 0x00
CVID check ID 0x11 0x00
CVID 数据大小 0x00 0x10
CVID 数据 0x410x410x410x410x410x410x410x410x410x410x410x410x410x410x410x41
CVID check ID 0x11 0x00
CVID 数据大小 0x00 0x10
CVID 数据 0x410x410x410x410x410x410x410x410x410x410x410x410x410x410x410x41
CVID check ID 0x11 0x00
CVID 数据大小 0x00 0x10
CVID 数据 0x410x410x410x410x410x410x410x410x410x410x410x410x410x410x410x41
在清楚了数据格式后,我们再来分析代码
然后取得了cinepak_codec_data2中的编码条数据大小和未解码数据部分进行对比
然后取得编码条ID 和10h进行对比
我们看到第一次并不会进入到拷贝的函数
后面数据帧的长度减去前面保存的chunk的长度
并在一个变量中加上0x2000的长度,供拷贝使用
又返回到比较的这里,由于未解压缩的数据的已经减去了0x10h,这里已经变成了0x4e,这里要保证数据大于16h
之后将数据的长度保存到变量中,后面未解压缩的数据好减去这个数据
后面比较CVID check ID是否是0x11
之后开始进行拷贝,由于样本中一共有三个CVID check ,所以一共拷贝三次,由于V32每次增加0x2000,所以每次拷贝地址增加0x2000
我们看看第一次拷贝的时候edi的情况
我们可以看到整个堆空间只有6000h,在拷贝三次后,发生溢出
第二次拷贝的时候
4 漏洞总结
在拷贝的的时候,可以无限制拷贝,并且堆区只有0x6000,但是每次拷贝的数据为0x2000,可以看到还是有些限制的,比如要保证未解码的数据长度要大于0x16,要保证Chunk ID为0x1100。在利用放面现在看,并不能精确控制要拷贝的数。