0x00 漏洞简介

CVE-2014-6332是微软2014年11月11日(数字很吉利)公布的一个IE浏览器漏洞(同时公布的还有CVE-2014-6352),影响IE版本为IE3-IE11。根据漏洞利用方法,官方定义为远程代码执行漏洞。

究其原因是因为vbs引擎在执行Redim array(nNum)时,即重定义数组时,会调用OLEAUT32.dll模块里面SafeArrayRedim函数,该函数内部处理逻辑不严谨,使用了错误的条件跳转指令,而且当传入的nNum足够大时,函数内部的数组空间申请会失败、SafeArrayRedim函数不做任何处理直接返回,导致返回时已经将nNum写入数组结构,后续对该数组便可以随意“越界”访问。

0x01漏洞分析

1.1讲点基础

1.1.1Vbscript中的VARIANT结构

VARIANT结构是脚本语言中常用的一种结构,用于封装对象结构。参见官方说明:

https://docs.microsoft.com/zh-cn/windows/desktop/api/oaidl/ns-oaidl-tagvariant

简化一下该结构,这是一个0x10大小的结构:

typedef struct _myVARIANT {                VARTYPE vt;//变量类型,占2字节                      WORD    wReserved1;                  WORD    wReserved2;                  WORD    wReserved3;//保留位,共6字节            DWORD   pHighData;//指向变量数据的指针。一般用于基本数据类型            DWORD   pLowData; //指向变量数据的指针。一般用于复合数据类型

VARTYPE结构参考:

https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/scripting-articles/3kfz157h(v=vs.84)

列出常用的几种类型如下表所示:

接下来看一下Vbscript中的数组结构,参见:

https://docs.microsoft.com/zh-cn/windows/desktop/api/oaidl/ns-oaidl-tagsafearray

VARTYPE结构参考:

我们测试一下这些结构在内存中的存储情况。

在实际调试中发现,数组元素的类型是可以不一致的;使用redim重定义数组时,数组实际的元素个数为传入的nNum+1。

1.1.2 Vbs中将函数指针赋值给变量

Vbs中将函数指针赋值给变量时,先将函数类型的VARIANT结构压入求值栈,然后将求值栈中结构再传递给变量,但当检测到求值栈中的数据类型为0x400C(即函数类型)时,并不会传递此类型,引发相关异常。如果当前代码流设置了On Error Resume Next,则会忽略当前异常,执行下面的代码。

1.1.3 SafeMode

SafeMode是Windows操作系统中针对安全的一种特殊模式,即安全模式。在Vbs引擎中同样存在这样一个安全属性值,正常情况下该属性值为0xE。默认情况下Vbscript脚本执行权限是非常低的,正是因为safemode安全属性的限制,如若我们能通过一定方法修改掉此属性值(改为0),即可绕过安全权限检查,为所欲为,即进入上帝模式。而且,经过调试我们发现在COleScript对象偏移0x174位置正是Safe Mode标志。

所以我们对该漏洞利用的核心就是找到safemode标志的位置并修改它。

1.2漏洞分析

我们选用附件中一个弹计算器的Exp进行分析(stage2.html)。

分享一片帖子上的调试方法(博客链接见文末):由于Vbscript脚本由Vbs引擎解释执行,如果我们盲目跟踪解析流程非比较低效,我们调试的目的是为了复现漏洞位置的代码bug,所以定位到漏洞模块的解析位置是关键,跟踪关键数据的解析过程即可。

前面我们为了查看测试变量的内存结构手动加入了IsEmPty()函数的调用,在WinDbg中模糊搜索该函数,可找到其符号为Vbscript.dll!VbsIsEmpty,我们将想查看的对象作为参数传给VbsIsEmpty()函数,即可断在该函数进行对象结构的查看。此为为了方便我们判断脚本执行的流程,可以将自定义的日志信息字符串传给VbsIsEmpty()函数,然后下条件断点:

bp vbscript!VbsIsEmpty "r $t1=poi(@esp+c);r $t2=poi($t1)&0xF;

上述指令的意思是:下断VbsIsEmpty函数,如传入参数为字符串(即我们自定义的日志信息)则打印字符串,然后继续执行;否则就断下来(此时我们就可以查看特定的变量结构了)。

我们重点跟踪一下redim操作,在redim Preserve arrX(ofnumele)之前跟进redim流程。搜索vbscript.dll中redim相关符号,定位到一个可疑的函数Vbscript.dll!RedimPreserveArray,下断该函数并结合IDA进行动态跟踪验证,程序成功断下。我们发现在RedimPreserveArray内部会调用SafeArrayRedim函数,传入的两个参数(下图中为psa、&psaboundNew)分别为原数组对象指针和新的SAFEARRAYBOUND结构指针。

注意到SafeArrayRedim函数位于OLEAUT32.dll模块内。此后将通过SafeArrayRedim函数的返回值(注意图中的v4是一个有符号数)判断是否redim成功,若小于零则抛出异常结束RedimPreserveArray函数。

继续跟进OLEAUT32.dll中的SafeArrayRedim函数。

我们直接反编译SafeArrayRedim函数,该模块自带符号,简单分析一下该函数的伪代码,即可快速定位该函数中的逻辑bug(如下图所示),结合动态验证也正是如此。

总结一下该漏洞成因主要有两点:


A、SAFEARRAYBOUND结构中的cElements字段(即数组元素个数)是一个ULONG类型,即无符号长整形。但是在SafeArrayRedim函数里面处理新旧数组操作(此处说的处理是指上两图中对于变动的数组空间进行开辟新的缓冲区进行保存备份操作)时,条件跳转判断选择了jge有符号跳转指令(源代码中应该是定义错了数据类型)。

这样就存在一种可能:如果psaboundNew-> cElements  -  psa-> rgsabound.cElements>=0x08000000,即数组元素个数增加的值大于或等于0x08000000,其变动的大小就会大于等于0x80000000,该数值就会占用有符号数的符号位、使得图中的v5恒小于0,随后便会产生错误的跳转。

B、SafeArrayRedim函数里面的处理流程是先将psaboundNew结构赋给psa-> rgsabound,随后按照数组空间变动的大小去申请缓冲区,如果申请失败则会返回0x8007000退出,然后外层的Vbscript.dll!RedimPreserveArray函数将会抛出异常退出。这里的处理存在一个非常严重的问题:RedimPreserveArray函数redim失败之后却并未还原psa-> rgsabound.cElements。这让后续的psa数组“越界”合法化。

至此漏洞成因已分析完毕。

0x02 Exploit分析

接下来,我们分析一下附件中的漏洞利用文件stage2.html,学习一下该Exp的编写技巧及思路。前面的分析中提到该漏洞的常规利用方法是修改vbs引擎中的SafeMode标志开启上帝模式,而且我们知道COleScript对象偏移0x174位置正是Safe Mode标志。所以我们分析的重点是如何找到Safe Mode标志的具体位置并且合法的去修改该标志。

笔者在调试stage2.html时,简单总结了一下代码流程:

  1. 初始化数组arrX()、arrY()。(即Init()函数)。

  2. 通过循环redim尝试使得arrX和arrY空间“连续”(准确来讲使得原始数组arrX和arrY之间只间隔8字节)。(Exploit()函数)

  3. 触发漏洞修改arrX的cElements字段,使得arrX数组可“越界”访问arrY数组元素,让两个数组后续空间重叠。(Trigger()函数)

  4. 通过前面提到的将自定义函数指针赋给变量的方法获取获取CScriptEntryPoint对象地址、为获取Safe Mode标志位置做准备。(LeakFnAddr()函数)

  5. 获取COleScript对象地址,并通过数组重叠后的特性构造特定的数组空间布局以及伪造的数组结构myarray成功访问到Safe Mode并修改其属性值为0。此时已成 功开启上帝模式(EnableGodMode()函数)

  6. 执行自定义的shell。(runshell()函数)

详细调试注释见附件中的z.html文件。这里我们重点分析一下第4步和第5步。我们依然选用前面提到的通过打印日志快速定位关键代码的方法。

随后该函数arrX(olapPos)赋给LeakFnAddr返回,注意此时是将CScriptEntryPoint对象地址作为长整型赋给LeakFnAddr。

然后将调用ReadMenInt函数获取COleScript对象地址。前面我们已经知道poi(pCScriptEntryPoint+8)+0x10即可获取COleScript对象地址。

这里需要注意两个细节:

A、 通过arrY(0)=8间接地将arrX(olapPos)的类型修改为8(即v_str字符串类型)。

B、 Lenb函数的作用是获取字符串的字节总数,传入v_str类型参数该函数会按照v_str结构默认将字符串指针前四字节的DWORD值作为结果返回。这也是前 面执行arrX(olapPos)=addr+4的原因。

获取到COleScript对象地址之后,接下来要解决的问题便是如何合规的去修改COleScript+0x174位置的SafeMode标志了。

我们来分析一下这里的流程:

1、构造一个自定义的数据类型,即myarray。其数据内容为:

08800001 00000001 00000000 00000000 7fffffff  00000000

这里0x18字节的数据刚好是一个数组的结构(一个单元素字节长度为1,总共7fffffff个元素的一维数组,即byte array[0x7fffffff])。myarray是指向这个数组的自定义结构。

2、将myarray对象赋给arrX(olapPos+2)。此时arrX(olapPos+2)类型为0x4a,值为0x00676584、即myarray对象地址。

3、arrY(2)=8192+12。间接的修改arrX(olapPos+2)类型为0x200c,即vbArray|vbVariant类型(数组|变体类型)。

4、此时arrX(olapPos+2)已成功修改为数组类型,现在就可以正常的去访问该数组空间了,该数组空间从0x00000000到0x7ffffffe,即整个用户空间,SafeMode肯定位于整个空间。

5、前面已经获取ColeScript对象地址并传递给i保存,那么直接通过arrX(olapPos+2)(i+0x174)便可以访问SafeMode,将其修改为0。

至此,利用分析已完毕。

0x03 填个坑

笔者因为较少编写Vbscript文件,在分析该Exp时随手写了较多注释,然后调试就出现问题了……

上图红色方框(即Vbscript中关键字then之后的位置),若此处写注释则会连带下一行一起注释……

0x04 总结

该漏洞是一个存在于IE VBS引擎中的非常经典的数组“越界”的漏洞,对于研究IE漏洞是一个非常不错的选择。浏览器相关漏洞定位关键代码一直是重点也是难点,勤学苦练、重在积累。

非常感谢论坛上各位同仁分享的非常详细、高效的分析思路和方法。笔者分析功底有限,有任何分析不当或疏漏之处期望各位交流斧正。

参考链接:

https://blog.csdn.net/qq_32400847/article/details/77799191

- End -

看雪ID:输出全靠吼                              

https://bbs.pediy.com/user-808521.htm

本文由 输出全靠吼 原创

转载请注明来自看雪社区

热门技术文章推荐:

  • CVE-2018-15982 flash 0day漏洞分析报告

  • CVE-2014-6332 修改浏览器安全属性开启Godmode

  • CVE-2017-4901 VMware虚拟机逃逸漏洞分析【Frida Windows实例】

  • 关于LOL动态皮肤修改的逆向与实现

公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com

CVE-2014-6332学习笔记相关推荐

  1. 深度学习(二十六)Network In Network学习笔记-ICLR 2014

    Network In Network学习笔记 原文地址:http://blog.csdn.net/hjimce/article/details/50458190 作者:hjimce 一.相关理论 本篇 ...

  2. 学习笔记--2014年7月7日

    2014年7月7日晚上学习笔记 ================ 目录: 一.学习Bash笔记 二.利用Ubuntu创建无线wifi 三.在Ubuntu里禁用不用的桌面 四.安装软件时依赖冲突的万能解 ...

  3. C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)【1】

    C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)[1] 前言: 本笔记作为记录我从零开始学习C#的记录,为了unity的兴趣爱好自学一门C#,也算是寒假为自己充个电,希望这个寒假可以坚持下去 ...

  4. C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)【2】

    C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)[2] 初识类和名称空间 前言: 本笔记作为记录我从零开始学习C#的记录,为了unity的兴趣爱好自学一门C#,也算是寒假为自己充个电,希望这 ...

  5. Protocol - Exploits学习笔记

    Protocol - Exploits 注:本分类里内容并非全是协议的 bug,部分 "基于.使用" 这个协议的应用所存在的漏洞也算在其中,例如 dns 域传送漏洞,其并非 dns ...

  6. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  7. 【Stage3D学习笔记续】山寨Starling(八):核心优化(批处理)的实现

    批处理是使GPU进行高效绘制的一种技术手段,也是整个渲染流程中最核心的技术,到目前为止我们并没有使用到这种技术手段,下面我们看看我们现在的渲染机制. 先想一想我们最开始是怎么向GPU绘制一幅图像的,可 ...

  8. 一文弄懂元学习 (Meta Learing)(附代码实战)《繁凡的深度学习笔记》第 15 章 元学习详解 (上)万字中文综述

    <繁凡的深度学习笔记>第 15 章 元学习详解 (上)万字中文综述(DL笔记整理系列) 3043331995@qq.com https://fanfansann.blog.csdn.net ...

  9. java message bus_【Microsoft Azure学习之旅】消息服务Service Bus的学习笔记及Demo示例...

    今年项目组做的是Cloud产品,有幸接触到了云计算的知识,也了解并使用了当今流行的云计算平台Amazon AWS与Microsoft Azure.我们的产品最初只部署在AWS平台上,现在产品决定同时支 ...

  10. mybatis学习笔记(13)-延迟加载

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(13)-延迟加载 标签: mybatis [TOC] resultMap可以实现高级映射(使用asso ...

最新文章

  1. 微信小程序setData()方法的使用
  2. php文件上传绕过mime类型,文件上传限制绕过技巧
  3. BugkuCTF-Misc:宽带信息泄露
  4. 通过调试对WriteFile()API的钩取
  5. 手写jwt框架SSO
  6. RGB-D dataset
  7. oracle雇主联盟官网,ocm联盟线下分享会圆满结束!
  8. 接口测试--ssl证书问题
  9. pythondjango是干什么的_python django框架是什么?怎么使用?
  10. 我如何知道Bash脚本中的脚本文件名?
  11. Prometheus+Grafana监控系统部署与使用
  12. 有什么办法可以让微信群二维码永久有效?这类的二维码生成器怎么制作?
  13. IBM X3650服务器使用说明
  14. tms320vc5416c语言编程,TMS320VC5416与CAN总线的接口设计及软件编程
  15. 职场健康:大脑20个已知秘密[转]
  16. 3dsmax展UV,制作UV贴图,将物体的贴图放到一张图片上,贴图优化方式,UVW贴图制作全流程
  17. 用ADC0809实现八通道采集
  18. 新手必备pr 2021快速入门教程「一」初识premiere pro 工作界面
  19. android程序开发笔记
  20. 从产物追溯研发合成路线?自建化合物数据库溯源不再成难题

热门文章

  1. 【剑指offer】29、顺时针打印矩阵
  2. Python基础之set集合与函数
  3. 第一行代码--笔记(3)
  4. 深入理解HTTP协议(转)
  5. MySQLdb 1031 Error
  6. Linux中的7件武器详解
  7. iOS底层探索之多线程(四)—GCD的队列
  8. 通过javascritp对表格进行列拖动排序
  9. SQL Server :理解GAM和SGAM页
  10. Android开发学习笔记:数据存取之File浅析