CVE-2016-3308 / ZDI-16-453 Microsoft Windows内核提权漏洞原理分析与利用

二进制安全研究 G1ace 阅读(2688) 0评论

 

1、漏洞简介

漏洞公告相关链接:

ZDI-16-453  CVE-2016-3308

CloverSec Labs成员bear13oy在七月中旬也发现该内核漏洞,由于当时比较忙,本想在八月微软的补丁周过后再对其进行分析和利用,不巧的是微软八月份的补丁修复了该漏洞。再次撞洞!

附上当时精简后的poc代码截图:

 

内核崩溃后栈回溯信息截图:

2、漏洞原理

由于函数win32k!xxxInsertMenuItem在处理新增菜单插入时,获得了错误的插入偏移,导致函数在计算MenuItem内核数据长度时发生错误,进而在调用memmove移动MenuItem数据时,发生越界操作。

win32k!xxxInsertMenuItem函数在调用memmove移动MenuItem内核数据前,两次调用函数win32k!MNLookUpItem来获取相关Item数据的内存地址。在此漏洞中,第一次调用win32k!MNLookUpItem时,由于传入的wIndex不存在,函数会返回NULL,于是win32k!xxxInsertMenuItem会默认把新Item数据放到原Item数组的末尾,并把wIndex更新为新Item数据在原Item数组中的偏移。相关代码如下所示:

在调用AppendMenuA函数后,Menu中的Item数据刚好达到了8个,而由下面的代码可以看出,内核中Item数据的分配刚好是以8个Item为分配粒度的。于是如下代码中的pMenu->cItems >= pMenu->cAlloced的条件正好成立,于是win32k!MNLookUpItem会被再次调用,在新分配的Item数据中通过wIndex偏移找到需要插入的内存地址并保存在pItem中。

然而win32k!MNLookUpItem函数会在所有的Item以及子菜单的Item中递归寻找,由于之前已经有7个Item数据存在,在调用InsertMenuA函数后wIndex被改写为7,而此时由于notepad的第一个File的子菜单中的最后一个Item(Exit)的id正好是7,于是win32k!MNLookUpItem函数遍会把此Item的内核地址返回。之后在计算memmove移动长度时便会出现不可预料的情况,并在移动数据时发生访问异常。




从上面代码可以看出,win32k!xxxInsertMenuItem中触发漏洞的memmove所用到的pItem地址正好是之前win32k!MNLookUpItem函数返回的内存地址。结合内存数据和PITEM数据结构可以看出,此时的pItem地址所指向的是notepad中File的子菜单中的最后一个Item(Exit)(数据结构如上图红色所示),而pMenu->rgItems为DesktopAlloc新分配的内存地址指针,这两个地址分别属于不同的Item数组中,所以相减的值是不可预料的,精确操作内核堆分配可控制memmove长度,从而控制特定的内存区域。

3、漏洞利用

漏洞利用主要用到两个数据结构如下:

通过构造数据覆盖tagPROPLIST中的cEntries和iFirstFree便可以实现对tagPROPLIST结构之后的一段数据进行控制。

漏洞触发过程中tagPROPLIST在内存中的变化:

漏洞利用过程大概可以分为如下步骤:

4、漏洞演示

测试环境: Windows 7 SP1 x86 (更新于2016-07-16)

转载请注明:CloverSec Labs » CVE-2016-3308 / ZDI-16-453 Microsoft Windows内核提权漏洞原理分析与利用

喜欢 (5)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址