前言 Windows内核提权漏洞CVE-2016-7255已经受到了很多媒体的关注。在11月份的Patch Tuesday中,微软发布了针对此漏洞的修复程序,将其作为MS16-135公告的一部分。根据微软的说明,CVE-2016-7255主要用于执行有针对性的攻击,并且可以通过一些“野路子”来找到样本。 谷歌和微软已经证实俄罗斯黑客集团APT28使用了一个Flash漏洞(CVE-2016-7855)和这个内核提权漏洞执行了一次有针对性的攻击,谷歌也发布了一些针对此漏洞的讨论: https://security.googleblog.com/2016/10/disclosing-vulnerabilities-to-protect.html https://threatpost.com/microsoft-says-russian-apt-group-behind-zero-day-attacks/121722/ http://securityaffairs.co/wordpress/53242/hacking/cve-2016-7255-zero-day.html McAfee Labs的漏洞研究团队花费了大量时间来分析此漏洞。我们将在这篇文章中,简要讨论我们的一些发现。 分析 我们首先从MS16-135的补丁开始着手分析,很快我们就注意到MS16-135在目标系统上更新了win32k.sys,于是我们下一步就开始比较(通过二进制差分手段)两个win32k.sys文件(安装补丁前后)。另外一提,我们的测试系统运行的是Windows 7,版本号为6.1.7601.23584。 看看二进制差分的结果,我们注意到以下功能被修改。 图1:在win32k.sys中被更改的函数——xxxNextWindow 经过这些初步调查后我们得出结论:CVE-2016-7255的补丁程序完全应用于修复win32k.sys中的xxxNextWindow函数。 以下截图显示了补丁中对xxxNextWindow(x, x)所做更改的更高级概括: 图2:对函数xxxNextWindow进行高级差分的结果 我们可以看到在被修复函数中增添了一些新的逻辑(用红色突出显示)。放大到第一个新插入的基本块,我们可以看到新引入的代码进行了对eax + 0x23的值的比较操作: 图3:xxxNextWindow中插入的第一个基本块 然后,我们在下一个新插入的基本块中看到了类似的逻辑。 图4:xxxNextWindow中插入的第二个基本块 谷歌已经声明了该漏洞“可以通过win32k.sys系统调用NtSetWindowLongPtr()为GWL_STYLE设置为WS_CHILD的窗口句柄上的索引GWLP_ID触发。“ 事实上,NtSetWindowLongPtr()只起到了触发这个漏洞的作用,而根本原因在于xxxNextWindow。更具体地说,由NtSetWindowLongPtr()设置的不合适的参数可以触发xxxNextWindow中的“任意地址写入”场景。 现在让我们来看看未打补丁的xxxNextWindow(x, x, …)的反编译版本。 图5:未修复的xxxNextWindow的反编译版本 应用补丁后,xxxNextWindow(x, x, …)如下所示: 图6:已修复的xxxNextWindow的反编译版本 打补丁后的代码使用条件分支语句“(*(_BYTE *)(v8 + 0x23) & 0xC0) != 0x40”增强了参数验证。 在这个新语句中,变量v8(在eax中)是上一个GetNextQueueWindow调用的返回值。 (见下图) 图7:变量v8来自对GetNextQueueWindow的调用:“v8 = _GetNextQueueWindow(v7, v31, 1);” 快速查看_GetNextQueueWindow(x, x, …)的实现,它揭示了该函数实际上返回一个指向tagWND结构的指针。 下图显示了windbg中的tagWND结构: 图8:tagWND的结构 分析此代码,我们可以从中得知tagWND结构中偏移量0x78处的字段是与漏洞相关的。以下来自未修复函数的反编译代码行证实了这一点: 图9:未修复的xxxNextWindow中的问题代码 现在问题变得简单了:如果我们可以控制在v8+0x78地址处的值,就能够在内核区域中任意地址进行写入操作,并且这很可能就可以实现提权。幸运的是,一个用户态中的API(NtSetWindowLongPtr)就可用于在该位置设置任意值。 下图显示,我们传递给NtSetWindowLongPtr的值(0x41414141)被反射到了tagWND结构中,通过此漏洞可以轻松实现任意内存写入。 图10:在tagWnd结构中设置了一个任意值 为了触发此漏洞,新创建的窗口的WS_CHILD属性必须被分配,并且GWLP_ID属性必须通过API函数NtSetWindowLongPtr()来进行设置。此外,最后一个障碍是如何触发xxxNextWindow。经过一番研究,我们发现可以通过按Alt + Tab的组合键或者用keybd_event API模拟按键来触发它。 漏洞复现和进一步分析 现在,我们已经从上层了解此漏洞的根本原因,下面就让我们来尝试复现此漏洞。我们将创建一个简单的窗口,并在其tagWND结构中填充一些值。
图11:调试存在漏洞的函数xxxNextWindow 上面的截图显示了实时调试输出。这里ebx寄存器保存了指向tagWND结构的指针,并且写入违规将很快发生。正如下图所看到的,违规指令的目的地正是我们以前通过NtSetWindowLongPtr API传递的地址(加上0x14),这完美地证实了一次任意地址写入攻击。 图12:任意地址写入攻击的场景 让我们回到微软的补丁,它首先检查tagWND结构起偏移0x23后的值。 在补丁代码中,我们可以看到新引入的语句
在打补丁后的函数中,ebx指向了tagWND结构
现在这个语句变成false。 因此,程序跳过以下尝试修改内存的代码行,从而避免了程序崩溃(写入访问冲突)。
如何利用此漏洞实现提权?与允许将任意值写入任意地址相比,此漏洞只能更改一个比特位; 也就是说,地址上的值将0x04(或其倍数)进行逻辑或运算,如下所示:
最新评论
72小时资讯榜
2
英伟达联合微软发布128GB统一内存的NVIDIA
AI动态
268人已阅读
3
乐鑫重磅开源 ESP-Claw:把 Agent 塞进了 E
AI动态
283人已阅读
4
Desk Tidy Sticky: 开源免费、Windows 和 M
软件精选
276人已阅读
5
LibreTranslate - 纯本地翻译神器,支持49
软件学院
293人已阅读
6
Python逆天改命,开源Hermes首次击败OpenAI
AI动态
278人已阅读
社区热门
1
━※☆※━★===二〇二六年论坛每日签到帖=
2026-03-13
3
从上大学一直玩黑基 到现在已经37岁 感谢黑
2025-06-03
5
好久没来这里了,居然能正常登录,佩服站长
2025-05-19
6
好多年没来竟然还可以登录
2025-09-22
|