CVE-2012-0003:Microsoft Windows Media Player winmm.dll MIDI 文件堆溢出漏洞调试分析
0x01 蜘蛛漏洞攻击包
- 前言:2012 年 2月,地下黑产中流行着一款国产名为蜘蛛漏洞的攻击包 —— “Zhi-Zhu Exploit Pack”,该工具包含 5 个漏洞,都是在当时比较流行的漏洞,涵盖了 Flash、IE 等产品,其中就包含 CVE-2012-0003,此国产漏洞利用包与国外有一定的差别;国外通常用于构建僵尸网络或者窃取重要的情报,而 “蜘蛛” 这款漏洞攻击包主要用于盗取游戏账号,比如 “龙之谷”,这似乎也比较复合国情
 - 微软发布该漏洞补丁之后,国外安全团队 VUPEN 在其博客上公布了该漏洞的成因和利用方法,其中对漏洞的利用构造的相当精妙,堪称艺术,可谓经典中的经典
 - 该漏洞成因主要是由于 winmm.dll 动态链接库在处理 MIDI 文件的 Note On 和 Note Off 字段没有做限制,导致可以操纵该字段访问堆块之外 1 个字节的内存空间;由于该漏洞过于特殊,所以在分析和利用的时候难度是相当大的
 
0x02 分析环境
- 虚拟机:Windows XP sp3,版本:11.0.8211(提取码:woi9)、Sublime Text3
 - 调试工具:Windbg(Windbg32,Windbg64)、OD、IDA(提取码:v0pt)、C32Asm(16进制分析文件工具,提取码:4sj8)
 - 漏洞程序:IE6 浏览器
 - 漏洞DLL:有漏洞的 winmm.dll 动态链接库文件(提取码:0n2a)
 - 漏洞样本:能够触发漏洞 POC 样本(包含 poc.html 和 toto.mid 两个文件,提取码:nd0b)
 
0x03 MIDI 文件格式
- 想要理解漏洞的成因,首先需要了解什么是 MIDI 文件格式:MIDI 全称 Musical Instrument Digital Interface,是一种乐器数字接口,说白了就是一种音频格式(通过winmm.dll 链接库解析这种格式的文件之后可以播放出音乐)
 - 总体来说 MIDI 可分为 “头块” 和若干多的 “音轨块”
 
| 块名称 | 块标记(4个字节) | 块长度(4个字节) | 块数据 | 
| 头块 | "MThd" | 00 00 00 06 | 6个字节长度 | 
| 音轨块1 | "MTrk" | 后面块数据长度 | 音轨事件数据,按时间顺序排序 | 
| 音轨块2 | "MTrk" | 后面块数据长度 | 音轨事件数据,按时间顺序排序 | 
| ... | ... | ... | ... | 
| 音轨块n | "MTrk" | 后面块数据长度 | 音轨事件数据,按时间顺序排序 | 
- 头块结构如下
 
| 偏移 | 长度 | 描述 | 数值 | 
| 0x00 | 4 | 块标记 | "MThd" | 
| 0x04 | 4 | 块长度 | 00 00 00 06 | 
| 0x08 | 2 | 格式类型 | 0 ~ 2 | 
| 0x10 | 2 | 音轨数 | 1 ~ 65535 | 
| 0x12 | 2 | 时间计数值(每拍的计数值) | 比如数值 0x60 就为八分一拍 | 
- 音轨事件如下
 
注意:这个是音轨事件,不是音轨的结构,一个音轨结构中可以包含许多的音轨事件
| 事件类型 | 格式 | 描述 | 
| 关闭音符(Note Off) | 0x8n note velocity | n 代表通道号,note 代表高音数值,velocity 代表按键速度 | 
| 打开音符(Note On) | 0x9n note velocity | n 代表通道号,note 代表高音数值,velocity 代表按键速度 | 
| 触后音符(Note Aftertouch) | 0xAn note amount | n 代表通道号,note 代表高音数值,amount 代表按压力度 | 
| 控制器(Controler) | 0xBn type value | n 代表通道号,note 代表控制项(如主音、延音等音量大小的调节),value 即为设置值 | 
| 音色切换(Program Change) | 0xCn num | n 代表通道号,num 代表音色号 | 
| 触后通道(Channel Afertouch) | 0xCn note amount | n 代表通道号,note 代表高音数值,amount 代表按压力度 | 
| 滑音(Pitch Bend) | 0xEn LSB MSB | n 代表通道号,LSB 代表低位值,MSB 代表高位值 | 
- toto.mid 样本中的十六进制数据如下图所示

 
0x04 触发漏洞,定位异常点
- 我们选择通过用 IE 加载 winmm.dll 的方式触发漏洞,为了让 IE 浏览器能够触发漏洞,所以在 poc.html 样本中嵌入了一个音频播放器,由音频播放器来调用 toto.mid 文件播放音频从而触发漏洞


 - 第一步设置堆页保护,第二部打开 IE,第三部使用 Windbg 附加进程

 - F5 运行之后将 poc.html 文件拖入 IE,并且允许运行 ActiveX 控件

 - 成功断下异常,可以看出 esi 指向的地址超出了堆空间,之后被堆页保护捕捉到
 - 有经验的可以看出是 winmm.dll 中出了问题

 - IDA 载入这个 winmm.dll,该动态库在 system32 下

 - 下图可以看出是 v25 这个指针越界访问了堆上的数据

 - v25 受 v24 和 v20 影响,通过观察可以发现 v24 受 v2、v9、v11、v13、v21影响(v2 由 wParam 控制)


 - v20 受 v1 影响(v1 也由 wParam 控制)

 
0x05 OD 调试分析
- 将 IE 载入 OD 运行,先不要将 html.poc 拖入到 IE 中,之后 shift + F4 对 v2、v9、v11、v13、v21、v23 和 v20 下条件记录断点

 - 设置 v9

 - 设置 v11

 - 设置 v13

 - 设置 v21

 - 设置 v23

 - 设置 v20,最后别忘了断下漏洞触发点断点,这个断点是真的断点

 
提醒:什么条件记录断点,当程序运行到这个断点时,程序并不会真正的断下,而是会记录表达式的值;一般断点为红色,而条件记录断点为粉色
- 将 poc.html 文件放入刚刚运行的 IE 之中,之后会在异常触发点断下,按 l 这个快捷小按钮查看日志

 - 可以看出 v11、v13、v21 相等
 - v2 不变,v20 最后才被记录,且指向的地址都在 0x07EC0000 往后的堆中
 - 从资料中可以得知最后 v23 的值,也就是 0x007DB29F 是来自漏洞样本的数据,结合MIDI 格式分析可以知道,9F 代表的就是打开音符(Note On),F 就是通道号

 - 这个就是样本中的数据,刚好是倒过来的 0x007DB29F

 - 下面就对 v21 下条件断点(shift + F2),看看读取样本数据 0x007DB29F 之后是怎么处理的

 - 重新运行后断下,注意此时 ecx = 007DB29F,之后接着往下调试

 - 首先会将 9F 和 0xF0 做按位与运算,之后将结果与 90 作比较,判断这是打开音符(Note On)还是关闭音符(Note Off);由于 9F0 | 0xF = 90,所以这个是打开音符
 
提醒:由上可知,打开音符为 0x9n,关闭音符为 0x8n

- 之后将 9F 和 0xF 做按位与操作,取出通道号 F,之后左移 7 位右移 1 位,最后等于 419
 
提醒:9F | 0xF = F

- 最后将 esi(堆基址)+ eax(偏移地址419)
 
提醒:下面会解释 esi 为什么是堆基址

- 这时已经知道通道号 F 经过计算之后值为 419,控制着指针的偏移地址,也就是 v24 的值
 - 此时只需要知道 esi,也就是 v20 的值是怎么来的,就可以完全搞清楚漏洞的成因了
 - 首先 v20 由传入的参数 wParam 控制,对 midiOutPlayNextPolyEvent 函数进行交叉引用查询,看看是哪一个函数调用的这个函数
 
提醒:上面说到 v25 受 v20 和 v24 影响

- 发现是 midiOutTimerTick函数调用了 midiOutPlayNextPolyEvent 函数,并且把 v6 当作参数传入,而 v6 = gpEmuList

 - gpEmuList 不是参数传入的,所以查询 gpEmuList 的交叉引用,看看是哪一个函数设置了 gpEmuList 这个值,发现是 mseOpen 函数中引用了这个值

 - 这个就是 mseOpen 函数,gpEmuList 由 v5 传入,v5 等于 winmmAlloc 函数分配的堆空间地址

 - 整理一下调用关系

 - 因为 v6 是堆块的基地址,且这个堆块的大小为 0x400,又因为 v20 = v6,所以 v20 也为这个 0x400 堆块的基地址
 - 这样关系就很明了了,v25 的指针由 v24 和 v20 相加得出,v20 是堆的基址,而 v24 是样本数据解析运算获得,由于没有限制通道号的大小,导致运算后的偏移地址 v24 为 419,可是堆只有 0x400大小,很显然超出了申请的堆空间,照成了非法访问,故引发了堆页保护异常
 
这里需要注意的是虽然申请的堆空间大小为 400,可是实际大小不同环境会有不一样的结果,本文测试的时候实际的大小会多出 8 个字节,为 0x408
0x06 漏洞利用
- 那么如何利用这一个字节来执行任意代码呢?国外安全团队 VUPEN 在其博客上给出了构造的方法,过程十分精彩:
 - 第一步通过 JavaScript 创建一个 html 元素 select,之后给 select 元素设置 60 个属性,并且将第一个属性设置为 String 类型(w0),其余的属性设置任意即可,拥有 60 个属性的 select 大小为 0x408

 - 第二步创建一个 cloned 对象数组大小为 50,之后循环复制 select 元素到 clone


 - 第三步每隔 6 个元素,释放回收第七个元素

 - 这样的话内存空间的分布就如下图所示,只需要等待有漏洞的堆插入到这个精心构造的堆列当中即可,在 windows XP sp3 + IE6 的环境下,成功率接近为百分之百左右

 - 当插入完成之后,漏洞指令会将 String 类型(w0)标识符 0x08 加上 1,变为 0x09 的对象
 
String 在内存中的标识符为 0x08,对象为 0x09
- 最后循环调用每个 cloned.w0 属性的 toString() 方法,调用该方法会使每个对象的头 4 个字节当作索引

 - 索引虚表会取出对象的头 4 个字节,之后进行 call 调用,从而执行任意代码

 
0x07 OD 调试分析
- 首先关闭堆页保护

 - 负责解析 Html 语言的 IE 模块 mshtml.dll 在处理 html 元素时会调用 CImplAry::clone() 函数和 ClmplAry::DeleteAll() 函数来添加和删除属性的堆空间,上面的申请属性和释放属性就靠这两个方法
 - 使用字符串查找的方法找到 clone 函数和 DeleteAll 函数

 - 这个就是 clone 函数,其中 EnsureSize 函数会给每个元素的属性分配 0x10 大小的堆空间

 - 这个是 DeleteAll 函数,负责释放属性的堆空间

 - 之后下 CImplAry 数组堆首地址、CImplAry 释放堆地址、漏洞函数分配的堆地址(VulBuffer)的条件记录断点



 - 运行之后断在了漏洞触发的汇编指令上

 - 数据窗口跟随后发现此时 esi 指向的是 0x08 这个 String 标识符

 - 查看日志分析,VulBuffer 成功的插入了刚刚释放的空间中去,且大小为 0x408

 - VulBuffer 的地址 + 0x419 刚好为 1E5721,也就是 String 的标识符 0x8
 
此处多出来的 16 字节应该是堆块头部信息

- 去除断点继续运行之后,来到了虚表索引

 - 此时 String 的标识符已经变为 0x9

 - 最后会执行 call [ecx+0x4] 的地址

 - 此时 ecx 的值就是 select.w0 对象的头4个字节 0x0c0c1c0c


 - 从而控制了程序的流程,最后通过堆喷射的方法,达到了执行任意代码的目的
 - 关于绕过防护的方法,参考下图

 - 参考资料:0day安全:软件漏洞分析技术 + 漏洞战争
 
以上就是 CVE-2012-0003 的调试分析,如有错误,欢迎指正
CVE-2012-0003:Microsoft Windows Media Player winmm.dll MIDI 文件堆溢出漏洞调试分析的更多相关文章
- CVE-2012-0003 Microsoft Windows Media Player ‘winmm.dll’ MIDI文件解析远程代码执行漏洞 分析
		
[CNNVD]Microsoft Windows Media Player ‘winmm.dll’ MIDI文件解析远程代码执行漏洞(CNNVD-201201-110) Microsoft Wi ...
 - CVE-2013-0077:Microsoft DirectShow quartz.dll m2p 文件堆溢出漏洞简单分析
		
0x01 前言 2012 年 10 月 5 日,exploit-db 漏洞公布站点上发布了 QQplayer.exe 3.7.892 m2p quartz.dll Heap Pointer OverW ...
 - CVE-2010-2553:Microsoft Cinepak Codec CVDecompress 函数堆溢出漏洞调试分析
		
0x01 前言 微软提供一个叫 Cinepak 的视频解码器,通过调用 iccvid.dll 这个动态链接库文件可以使用这个解码器:微软自带的 Windows Media Player(视频音频软件) ...
 - CVE-2018-0802:Microsoft office 公式编辑器 font name 字段二次溢出漏洞调试分析
		
\x01 前言 CVE-2018-0802 是继 CVE-2017-11882 发现的又一个关于 font name 字段的溢出漏洞,又称之为 "第二代噩梦公式",巧合的是两个漏洞 ...
 - CVE-2017-11882:Microsoft office 公式编辑器 font name 字段栈溢出通杀漏洞调试分析
		
\x01 漏洞简介 在 2017 年 11 月微软的例行系统补丁发布中,修复了一个 Office 远程代码执行漏洞(缓冲区溢出),编号为 CVE-2017-11882,又称为 "噩梦公式&q ...
 - Windows Media Player  axWindowsMediaPlayer1                                                    分类:            C#             2014-07-28 12:04    195人阅读    评论(0)    收藏
		
属性/方法名: 说明: [基本属性] URL:String; 指定媒体位置,本机或网络地址 uiMode:String; 播放器界面模式,可为Full, Mini, None, Invisible p ...
 - CVE-2012-0158:Microsoft Office MSCOMCTL.ocx 栈溢出漏洞调试分析
		
0x01 Lotus Blossom 行动 在 2015 年 6 月,国外安全厂商 Palo Alto Networks 的威胁情报团队 Unit42 发现了一起针对东南亚政府的一次间谍行为,试图获取 ...
 - win7自带windows media player 已停止工作
		
解决方法如下: 在计算机开始,菜单找到控制面板 ,然后打开程序和功能,选择打开或关闭window功能,媒体功能.再取消windows Media Center Windows MediaPlayer选 ...
 - Windows Media Player安装了却不能播放网页上的视频
		
前段时间遇到Windows Media Player安装了却不能播放网页上的视频的问题,在网上查找资料时,发现大部分资料都没能解决我这个问题.偶尔试了网上一牛人的方法,后来竟然解决了.现在再找那个网页 ...
 
随机推荐
- 盘点Excel中的那些有趣的“bug”
			
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. Excel 1.0早在1985年正式进入市场,距今已经有36年了,虽然在推出 ...
 - MYSQL的replace into
			
replace into t(id, update_time) values(1, now()); 或 replace into t(id, update_time) select 1, now(); ...
 - 测试工程师Docker进阶
			
学习整理来源 B站 狂神说Java https://space.bilibili.com/95256449/ 四.docker镜像 1.镜像是什么 镜像是一种轻量级.可执行的独立软件包,用来打包软件运 ...
 - tomcat启动错误Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/ofuns]];
			
起初遇到这个问题的时候是在实训(开发环境选择的是IDEA)的时候,检查了半天未果,上网搜索之后,说的也是各式各样,最后发现问题出在web.xml上面 在配置 filter 的 url-pattern ...
 - HTML的基础语法
			
区别于c语言这类高级语言,HTML不是编程语言,而好似一种描述型语言,用于描述网页中内容的显示方式. HTML标记以<>来进行标记.HTML中的标记按其是否成对出现,可以分为单标记和双标记 ...
 - 关于java的访问修饰符权限
			
作用域 public protected default private 同一个类 yes yes yes yes 同一个包 yes yes ...
 - python-3-2
			
一 切片 1.切片是list取值的一种方式 列子: nums = ['a','b','c','d','e','f','h','g','k','l','kk','nn','ee'] 取b和c元素出来 p ...
 - Spring工程搭建
			
创建Maven项目 1.下载Maven资源包 http://maven.apache.org/download.cgi 2.打开IDEA创建Maven项目 在新建项目窗口选择Maven项目:检查当前S ...
 - java例题_49 计算子串出现的次数
			
1 /*49 [程序 49 子串出现的个数] 2 题目:计算字符串中子串出现的次数 3 */ 4 5 /*分析 6 * 1.子串的出现是有标志的,如" ",*,#或者其他 7 * ...
 - nacos下载慢吗?来这里
			
https://gitee.com/soul_PreCoder/springcloudalibab/repository/archive/master.zip