首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Nebula漏洞利用包CVE-2016-0189漏洞利用分析

Nebula漏洞利用包CVE-2016-0189漏洞利用分析

作者头像
FB客服
发布2018-02-24 11:42:52
1.4K0
发布2018-02-24 11:42:52
举报
文章被收录于专栏:FreeBufFreeBuf

1. 引言

在最近的一年里, 漏洞利用工具包(EK/Exploit Kit)市场风云变幻。2016年六月初,曾经极为猖獗的Angler EK 销声匿迹,Neutrino EK 迅速填补了空白。随后短短不到3个月时间,Neutrino EK 又转为地下,RIG EK继而成为最流行的漏洞利用工具包。今年3月初,RIG又淡出视线,而迎来了新的Nebula EK。

Nebula EK包中对CVE-2016-0189的漏洞利用,比其它漏洞利用包的漏洞利用方有了一定改进,这里进行一下深入分析。

所用工具:

IE11(调试Javascript)

windbg

Nebula EK 的首页,如下图所示。

不难看出,页面里包含了混淆过的Javascript代码。进一步分析,这些代码是否有种似曾相识的感觉?对了,代码的混淆方法跟落日漏洞利用工具包(Sundown EK)极为相似。

页面中共有2段Javascript代码, 混淆方法相同。第一段Javascript代码,去掉混淆后,代码如下, 不难看出,这段代码就是CVE-2016-0189的漏洞利用。

关于CVE-2016-0189,网上已有一些分析报告,比如Theori的分析[1]。 然而这些分析报告,并未提供在内存层面的技术细节,使得读者总有种知其然,不知其所以然的感觉。本文试图利用windbg来分析漏洞利用时的内存布局,使得读者对该漏洞利用有更深刻的理解。

2. CVE-2016-0189的关键知识点

CVE-2016-0189是个关于VBScript的漏洞。VBScript 脚本引擎代码在vbscript.dll 中。

2.1. VBScript的变量

VBScript 的内存变量占用0×10个字节, 前两个字节定了变量类型VARTYPE。常见类型定义如下表所示[2]。

我们可以在VBScript代码中插入IsEmpty()函数,然后在windbg的vbscript!IsEmpty() 函数上设置断点来观察内存[3]。

图1 调试用VBScript代码

这里,0a560198就是str对象,这里 0008两个字节表示的是VARTYPE,根据表可知,值恰好为vbString(VT_BSTR = 8) 而偏移0×8处存放的就是字符串地址,

这里还可以看出,字符串是Unicode存放的。

2.2. VBScript的数组

VBScript 的数组的定义如下

当访问数组元素时,VBScript引擎会调用 AccessArray 函数来计算元素的存放地址。

试着用windbg 调试如下代码, 在vbscript!AccessArray处下断点:

堆栈中0ab04380即为数组A地址

数组元素存放在 pvData (0x7dfd130) 起始的地方

在 vbscript!AccessArray+0x9d: 指令处停下 (不同版本这个偏移值可能会有出入)

这条指令非常关键,它计算元素A(1,2) 的地址。 这里esi 就是SAFEARRAY的地址,而esi+0c是pvData的地址。eax值就是元素相对于pvData的偏移。查看eax值

为什么A(1,2)的偏移会是0×50呢。 VBScript的数组内存布局和C语言有些不太一样。A数组的内存布局为 A(0,0) A(1,0) A(0, 1), A(1,1), A(0, 2), A(1,2), 而每个元素大小为0×10字节(cbElements)。因此 A(1,2) 的偏移为0×50。

2.3. CVE-2016-0189 漏洞原理初探

CVE-2016-0189 的漏洞在AccessArray 函数代码中。我们看一下这个函数的逻辑:

这个函数在根据索引计算偏移时,如果索引是VT_I2 或者VT_I4时,直接使用它的值。而如果是其它类型时候,将会调用rtVariantChangeTypeEx 函数来计算索引值。如果索引是JavaScript对象的话,将会调用索引对象的valueOf函数来获取索引的值。

这似乎并没有太大问题,然而我们看一下漏洞利用脚本的valueOf函数

除了返回值”1”因为, 它调用了SumggleFag函数

查看该函数的代码可以发现:它调用了ZeroineL函数,而该函数将数组重新定义成了Cod(1,1) (k1=1)

到这里,我们明白了该漏洞的原理了,在AccessArray中计算索引值的时候,索引如果是个JavaScript对象,可以通过函数valueof来重新修改该数组的大小! 当数组的大小变小时,将会导致访问越界。

3. CVE-2016-0189 漏洞利用深入分析

Nebula EK的漏洞利用在越界访问的基础上实现了:

1.泄漏VBScript对象的地址

2.读取任意地址

3.写入任意地址(受限)

这3种手段在实现原理上都是类似的。通过将数组定义 Cod从(1,2000), 缩小到(1,1),从而在AccessArray 函数中实现了越界访问。同时,立即使用大量y(i) 对释放掉的内存重新进行占位。由于y(i)是可控的,如果越界访问到y(i)的内存区,即可控制对内存的访问。

下面我们利用windbg对内存进行观察,分析1.泄露VBScript对象地址的情形。

需要注意的是,由于脚本中有大量数组操作,如果我们在AccessArray函数上下断点,可能会断下很多次。这里介绍一个小技巧:先将断点用bd命令禁掉,在想断下的VBScript 脚本前加入MsgBox函数,当MsgBox弹出后,我们再把断点用be命令恢复。这样就可以确保断在我们想断的地方。

为清晰起见,我们将在脚本中将aw.Cod(0,0)设成0×11223344。

利用该技巧,我们在vbscript!AccessArray+0x9d断在

aw.Cod(arg1, 2) = s // arg1.valueOf() == 1 , s 是我们试图泄露的对象地址

这行越界访问(写入)处。

断下时,

0x2a659d0 就是 aw.Cod数组的pvData 地址,03 00 两个字节是vbLong (VT_I4), 而 44 33 22 11恰好为我们赋的值。

前面已经分析过aw.Cod(arg1,2), 即 aw.Cod(1,2), 该元素相对pvData的偏移就是0×50, 由于aw.Cod现在被重新设定为(1,1),所以 大小为2*2*0×10=0×40, 也就是说 awCod(arg1,2) 越界了0×10个字节。

aw.Cod(1,2) 的地址为 2a659d0 + 0×50 = 0x2a65a20。而从地址0x2a65a1c起(标为绿色的部分)是某个成功占位y(i) 的值。内存布局如下图所示:

由上图可知,Aw.cod(1,2) 正好与y(i)的第四个字节开始的部分重叠。

了解了这点。上面这段代码就不难理解了–遍历 y的所有元素,找到与Aw.cod(1,2) 重叠的那个y(i). 由于s 被写入了Aw.cod(1,2), 即 yi(i) 的第四个字节开始的部分。那么Mid(y(i), 3, 1)

正好是第四个字节开始的2个字节(注意Mid函数下表是从 1 开始的),它存放的是对象的类型的值。 4个字节之后,则是对象的地址。这样,只须读取y(i)的内容,就可以获取对象的地址了。

概括起来,Aw.cod 和 某个y(i) 重叠,我们可以通过Aw.cod的越界操作来将数据写入可控的y(i)里。

下面讨论情形2 读取任意地址

这次我们在占位的内存中,成功构造如下数据:

Aw.cod(1,2) 将越界访问到 我们构造的占位内存 地址0x2f72878。

08 00 为vbString类型VT_BSTR, 而48 c2 1b 01 四个字节则为试图读取的地址。

当执行 o = aw.Cod(arg1,2)时, VBScript引擎将会把地址0x2f72878作为一个vbString对象来处理。而48 c2 1b 01 四个字节则作为字符串内容的地址来处理。

读取该字符串的内容则获取了 48 c2 1b 01 地址里存放的内容。

最后我们看一下写入任意地址(受限)的情形。

写入与读取原理大致一样。这里只是将CSng(0) 赋值给了 aw.Cod(1,2),从而导致 CSng 的类型值 4(VT_R4) 被写入了指定地址。这里脚本并未实现任意值的写入,然而并不影响漏洞的利用。

最后我们看一下,整个漏洞利用是如何工作的:

1)首先,创建一个 对象,通过上述的方法(1) 泄露该对象的地址;

2) 在该对象偏移为8的地方,利用方法(2)读取内存获取CSession对象指针;

3)然后在CSession对象偏移为4的地方,获取COleScript 对象;

4)而COleScript 对象0×174的地方则存放了SafetyOption,也就是所谓的上帝模式(GodMode)标记。利用上述方法(3)将其值修改为4,从而成功开启上帝模式。

4. 一个有趣的DLL劫持技巧

分析本来到这里可以结束了,然而我们在Nebula的漏洞利用包里发现了一个有趣的DLL劫持技巧。尽管在前面,上帝模式已经成功开启了,当IE的保护模式开启时(默认是开启的),Vista以后的版本在执行Shell.Applicaion对象的ShellExecute 函数时, 会弹出一个如下的对话框(除非被加载的程序在ElevationPolicy中定义了静默加载,比如notepad.exe),向用户询问是否允许。正是由于这个原因,一些漏洞利用包选择了仅在XP系统上对CVE-2016-0189 进行利用。

Nebula EK采用了一个BlackHat 2014[2]上 公布的技巧来规避这个问题。IE浏览器在创建Shell.Application 对象时,会加载%systemroot%\system32\shell32.dll。通常情况下%systemroot%为c:\windows目录。然而,攻击者可以通过如下方式进行DLL劫持攻击。

1)在%temp%\ 目录下创建system32目录

2)在上面创建的目录下生成一个假的shell32.dll文件,用来加载需要加载的程序。Nebula EK 在VBScript脚本中会生成一个3K左右的文件。

3)在脚本创建Shell.Application对象之前,利用WScript.Shell 来 修改 %system32%环境变量,指向1)创建的目录

4)创建Shell.Application 对象,从而自动加载 假的shell32.dll文件,达到执行文件的目的。

相应的代码片段如下。

需要指出的是,通过这种方式加载的进程是低完整性(Low Integrity)的。通常被加载的程序还需要通过本地漏洞来进一步提权。

5. 总结

Nebula EK 通过CVE-2016-0189的一个漏洞,实现了对任意内存的读写,从而开启了上帝模式。并且配合一个DLL劫持技巧,达到了绕过IE保护模式,静默执行任何文件的目的。

参考文献

[1] PATCH ANALYSIS OF CVE-2016-0189. http://theori.io/research/cve-2016-0189

[2] https://msdn.microsoft.com/en-us/library/aa263402(v=vs.60).aspx

[3] 启明星辰CVE-2014-6332分析报告。http://www.venustech.com.cn/UserFiles/20141210_%E6%97%A0%E9%9C%80%E6%8B%85%E5%BF%83%E6%BD%9C%E8%97%8F%E4%BA%8618%E5%B9%B4%E7%9A%84%E5%BE%AE%E8%BD%AF%E6%B5%8F%E8%A7%88%E5%99%A8%E8%BF%9C%E7%A8%8B%E4%BB%A3%20%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E.pdf

[4] Write Once, Pwn Anywhere.

https://www.blackhat.com/docs/us-14/materials/us-14-Yu-Write-Once-Pwn-Anywhere.pdf

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-04-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 引言
  • 2. CVE-2016-0189的关键知识点
    • 2.1. VBScript的变量
      • 2.2. VBScript的数组
        • 2.3. CVE-2016-0189 漏洞原理初探
        • 3. CVE-2016-0189 漏洞利用深入分析
        • 4. 一个有趣的DLL劫持技巧
        • 5. 总结
        • 参考文献
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档