前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Windows内核漏洞CVE-2016-0143分析

Windows内核漏洞CVE-2016-0143分析

作者头像
FB客服
发布2018-02-08 10:37:09
9090
发布2018-02-08 10:37:09
举报
文章被收录于专栏:FreeBuf

0x00 背景

4月20日,Nils Sommer在exploitdb上爆出了一枚新的Windows内核漏洞PoC。该漏洞影响所有版本的Windows操作系统,攻击者利用成功后可获得权限提升,微软在4月补丁日修复了该漏洞。

0x01 漏洞分析

NilsSommer并没有说明该漏洞为何种类型的漏洞,咋看崩溃场景会认为是NULL Pointerdereference或者UAF漏洞,粗略分析后,觉得是整数溢出漏洞,但是最后还是将其定义为特殊的NULL Pointerdereference漏洞。下面对漏洞成因进行简单分析。

In xxxRealDrawMenuItem

崩溃的地方是在win32k!xxxRealDrawMenuItem函数内,在windbg中查看崩溃时的内存状态:

崩溃上下文代码的IDA截图,将其命名为过程A(最后说明时会用到):

在crash之前,eax会和[ebp+arg_8]做有符号乘法,并将结果和ebx做比较,来确定是否执行crash的指令。

此时的eax为PoC中r.bottom和r.top运算后的结果,具体操作在win32k!xxxDrawMenuBarTemp内,算法为:eax= r.bottom-r.top-1;

[ebp+arg_8]为PoC中的info.bmiHeader.biSize;

PoC给的值会让”imul eax,[ebp+arg_8]”产生溢出,走向crash流程。这里看起来是由于整数溢出造成的漏洞,其实正常流程都会走这个流程的,这并不是漏洞成因所在。

所操作的ecx从[ebp+var_28]获取,原始值为1,[ebp+var_28]本应该为DIBObject的地址,但是在为其分配内存的函数win32k!SURFMEM::bCreateDIB中,并没有为其分配内存空间,漏洞的关键在这里。

下面分析创建DIBObject失败的原因。

In SURFMEM::bCreateDIB

SURFMEM::bCreateDIB的函数调用栈:

xxxDrawMenuBarTemp à GreCreateDIBitmapReal àSURFMEM::bCreateDIB

在SURFMEM::bCreateDIB函数内有这样一段代码,将其命名为过程B:

此时eax等于xxxRealDrawMenuItem函数中的edi,[ebp+arg_0]为PoC中的info.bmiHeader.biSize*4,按照PoC中设定的值,两者分别为0x7fffff69和0x274。

当两者进行乘法运算后,同样发生了溢出,但由于是无符号运算,所以edx!=0。调用函数ULongLongAdd后,[ebp+AllocationSize+4]=edx=139h!=0,因此便走向了失败的流程,不会为DIBObject分配内存,也导致GreCreateDIBitmapReal函数的返回值为0。

如果未发生溢出,并且两者的乘积(+0x154)小于7FFFFFFFh, SURFMEM::bCreateDIB函数就会根据这个乘积(+0x154)为DIBObject分配一块内存。分配内存的代码在IDA中的截图:

分配成功后,会将AllocateObject的返回值作为GreCreateDIBitmapReal函数返回值,并且赋值给xxxRealDrawMenuItem 函数中的[ebp+var_28]。

0x02 补丁对比

来看看微软是怎么来补这个漏洞的,补丁后的部分xxxRealDrawMenuItem函数代码在IDA中的截图:

可以看到,补丁后,xxxRealDrawMenuItem函数在调用GreCreateDIBitmapReal函数后,对返回值做了检查:如果返回值等于0,表示创建DIBObject失败,则不会再进入到操作DIBObject的流程,也就是过程A中了。

0x03 可能的利用

目前还没有人公开自己的利用代码,下面对该漏洞存在的可能利用方式做一个说明。

crash处是一个对ecx进行循环操作的代码段,循环次数为”imul eax,[ebp+arg_8]”的乘积。正常情况下是对申请的DIBObject进行操作。

这个循环操作中,存在一个可控的写入操作指令,在IDA中的截图:

红框中的指令就是所说的写入操作指令,edx虽然经历多条指令操作后才得到,但是参与操作的都是ecx相关内存值,因为ecx也就是零页地址的内容可控,所以edx也是可控的。

那么理论情况下,在win8之前的系统中,是可以将这条指令操作转变为:

mov[HalDispatchTable+4],shellcodeAddress

之后用户层再触发一下就完成了提权。

0x04 其他

经过深入分析后,要触发漏洞,r.bottom、r.top和info.bmiHeader.biWidth满足一定的约束就行了,不一定需要和作者给出PoC的数值完全相同。r.bottom、r.top和info.bmiHeader.biWidth的值能满足下面两个条件就可以导致crash:

1.过程B分配DIBObject失败。 2.过程A走向crash流程。

过程B和过程A要满足这两个条件,具体情况如下。

过程B

1. 过程B未发生溢出,并且乘积后的值 < 0x7FFFFFFF,造成AllocateObject调用失败。 2.过程B未发生溢出,并且乘积后的值 > 0x7FFFFFFF,不走调用AllocateObject的流程。 3.过程B发生溢出,不走调用AllocateObject的流程。

过程A

1.未溢出。 2.溢出后的结果为负数,并且改变sf位为1(有符号数比较)。

根据上面分析给出的过程A和过程B会导致crash的情况,这里给出两种具体的组合,有兴趣的可以修改原PoC中对应的值尝试一下,都会crash的。

组合1

过程B情况1+过程A的情况1,两个地方都没有溢出,但是还是crash了,也说明了不是整数溢出漏洞。

组合2

过程B情况3+过程A情况2:

* 本文作者:卫士通攻防实验室龙猫,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 漏洞分析
    • In xxxRealDrawMenuItem
      • In SURFMEM::bCreateDIB
      • 0x02 补丁对比
      • 0x03 可能的利用
      • 0x04 其他
        • 过程B
          • 过程A
            • 组合1
              • 组合2
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档