0x01 2013 Pwn2Own 黑客大赛

  • 在 Pwn2Own 的黑客大赛上,来自法国的 VUPEN 安全团队再一次利用 0day 漏洞攻破 Windows8 环境下的 IE10 浏览器,这一次问题出在了 VML 上(VML 是向量标记语言),在处理 VML 语言时,没有对存放 dashstyle 数组长度的整数做严格限制,导致数组的越界访问和赋值,若覆盖 vgx 当中的虚表则可执行任意代码
  • 环境:Windows7 + IE8
  • 调试分析工具:Windbg32,IDA
  • 样本:能触发漏洞的 poc(提取码:ofhv)
  • 漏洞 dll:vgx.dll

0x02 根据样本分析漏洞成因

  • 开启堆页启动多线程调试,拖入样本触发异常,可以看出可能是数组在寻址时访问越界了,由于在 memcpy 函数中,所以传入的参数一定是有问题的

  • 从堆栈也可以看出是 vgx!COALineDashStyleArray 的 get_item 函数出了问题,由于是 JavaScript 的调用,那么样本应该有调用函数,经过分析是调用了 item() 函数导致数组越界访问
	for (var i=0; i<0x400; i++) { // POC 样本
a[i].marginLeft = "a";
marginLeftAddress = vml1.dashstyle.array.item(0x2E+0x16);
if (marginLeftAddress > 0) {
try // i = 0x301 的时候进入
{
shape.dashstyle.array.item(0x2E+0x16+i) = 0x4b5f5f4b;
}
catch(e) {continue}
}
}
  • vml1.dashstyle 的数组包含 44 个元素
	for (var i=0; i<0x400; i++){ // POC 样本
a[i].rotation;
if (i == 0x300) {
vml1.dashstyle = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44"
}
}
  • 而 shape 的数组元素不过 8 个,而访问的时候却直接访问第 0x2E+0x16 个元素,转换成 10 进制也就是第 68 个元素,难怪会访问越界
	<v:oval><v:stroke id="vml1"/></v:oval> // POC 样本
<v:oval><v:stroke dashstyle="2 2 2 0 2 2 2 0" id="shape"/></v:oval>
  • 这个就是 vgx 对象数组的地址,到 2c 的时候刚好是第 44 个元素,而 0x21a85060 刚好是加上 24 个元素之后的地址

  • 知道了漏洞的原理,再来看样本中是怎么把数组中的数据给修改掉的,经过研究发现原来是将 vml1 和 shape 的长度设置为了 -1,这个可能就是整数溢出的元凶
	vml1.dashstyle.array.length      = 0 - 1
shape.dashstyle.array.length = 0 - 1
  • 利用 IDA 反汇编 vgx 模块,之后查找 COALineDashStyleArray 类,其中 put_length 就是设置 vgx 对象数组元素的函数,下断之后调试看看(建议断下 vgx 模块后在下断,避免不必要的麻烦)

  • 当点击按钮 crash!! 后成功进入了 put_length 函数,继续向下调试

  • 之后会获取传入 put_length 的第一个参数,可能是某个对象的地址,继续向下调试

  • CElement 函数传入了一个数组对象,跟进这个函数看看

  • 在 0x198ed07e 时取出数组对象,之后取出数组大小 0x2c,也就是 44 个,这与样本中的 vml1 的数组元素个数是一致的
  • 0x226d2fe8 是 ORG 类对象的地址,可见数组的大小 2c 储存在类变量中

  • CElement 函数执行完后,获取传入的第二个参数,也就是设置数组的值(0xFFFFFFFF = -1)

  • 之后判断 2c 是否大于 0xFFFFFFFF,无符号比较肯定是 2c 大啊,所以发生跳转

  • 如果不发生跳转,则调用 malloc 函数给数组分配额外的空间,这样数组就不会发生溢出了,可惜的是进行了无符号比较,溢出整数 0xFFFFFFFF 成功逃脱了跳转

  • 继续向下调试至 0x1993dba4 时将 eax 中存放的数组大小减去 0xFFFFFFFF = 2d
  • 从参数中可以看出 ORG 对象也传了进来,跟进 call 函数

  • 将设置的数组大小 -1 作为参数调用 MsoDeletePx 函数

  • 进入 MsoDeletePx 函数之后,取出 2d 和 0xFFFFFFFF 调用 MsoFREMovePx 函数,跟进这个函数

  • 在 MsoFREMovePx 函数的最后,将 ORG 对象数组大小 2c 改为 0xFFFF,之后再调用 item() 函数取出对象时就会以 0xFFFF 作为数组的大小,这样就可以访问和操作数组以外的很大一部分空间,造成数组越界访问

0x03 漏洞利用

  • 漏洞利用的方法非常经典,首先创建 0x400 个 v:shape 元素

  • 之后将两个 array 的值设置为 -1 造成溢出,最后循环遍历 v:shape 结构,利用获取 marginLest 的值造成信息泄露,计算后可以获取到 ntdll.dll 的基址,从而可以用于构造 ROP 指令,构造完 ROP 指令后覆盖 vgx:CsafePtr 虚表指针,达到执行恶意代码的目的

  • 如图所示虚表指针被覆盖

  • 参考资料:0day安全:软件漏洞分析技术 + 漏洞战争

对CVE-2013-2551 的分析到此结束,如有错误,欢迎指正(天哪终于分析完了)

最新文章

  1. JavaScript 判断一个对象的数据类型。
  2. RESTful 良好的API设计风格
  3. (转)linux文件读写的流程
  4. JMeter非GUI方式运行时动态设置线程组及传参
  5. Dreamweaver 8
  6. poj 1904 强连通分量
  7. unity 3d-Easy Touch 3教程 转
  8. C# Windows - TabControl
  9. IIS7 和IIS8.0 HTTP 错误 500.19 - Internal Server Error 问题的解决方式
  10. Java基础知识强化之集合框架笔记04:Collection集合的基本功能测试
  11. Linux 网络编程中的read和write函数正确的使用方式
  12. PostgreSQL学习笔记(一)-安装PostgreSQL
  13. WIN10下Java环境变量配置
  14. 解决C#程序只允许运行一个实例的几种方法详解
  15. [CF791D]Bear and Tree Jumps
  16. Lucene 个人领悟 (一)
  17. 创建型模式之Builder(建造者)模式
  18. 配置openfire环境
  19. 解题:CTSC 2006 歌唱王国
  20. JavaScript进阶系列06,事件委托

热门文章

  1. 简单的webRTC连接测试
  2. Python3+pygame实现的flappy bird游戏,代码完整,还有音乐
  3. Andrew BP 神经网络详细推导
  4. 02-Spring配置文件加载
  5. 【linux】Linux删除文件后磁盘依旧占用空间的问题
  6. JS逆向-抠代码的第二天【手把手学会抠代码】
  7. 【python+selenium的web自动化】- 针对上传操作的实现方案
  8. EntityFrameworkCore之工作单元的封装
  9. UML类图画法整理
  10. 认清 React 的useState逻辑