0x00 前言
2019年6月,ESET研究人员发现攻击者利用一个0day漏洞对东欧地区发起攻击。
攻击者滥用了Windows系统中的一个本地权限提升漏洞,更具体一点是win32k.sys
组件中对NULL指针解引用(dereference)的一个漏洞。我们在发现并分析这个漏洞利用技术后,就第一时间反馈给MSRC,MSRC及时修复了漏洞并发布了安全补丁。
该漏洞影响如下Windows版本:
Windows 7 for 32-bit Systems Service Pack 1
Windows 7 for x64-based Systems Service Pack 1
Windows Server 2008 for 32-bit Systems Service Pack 2
Windows Server 2008 for Itanium-Based Systems Service Pack 2
Windows Server 2008 for x64-based Systems Service Pack 2
Windows Server 2008 R2 for Itanium-Based Systems Service Pack 1
Windows Server 2008 R2 for x64-based Systems Service Pack 1
本文重点关注该漏洞的技术细节及利用方式。在另一篇文章中,我们将深入分析这个恶意样本及其他相关信息。
0x01 漏洞利用
这几年来研究人员公布了Windows win32k.sys
组件的几个漏洞,与这些漏洞类似,此次攻击者利用的也是弹出菜单对象。我们在2017年也分析过Sednit攻击组织利用过的本地提权漏洞,当时攻击者利用的也是菜单对象,与此次攻击方法非常类似。
漏洞利用过程中创建了两个窗口,分别用于第一及第二漏洞利用阶段。对于第一个窗口,漏洞利用程序会使用CreatePopupMenu
以及AppendMenu
函数来创建弹出菜单对象并追加菜单项。此外,利用程序还会设置WH_CALLWNDPROC
以及EVENT_SYSTEM_MENUPOPUPSTART
类型的hook。
随后利用程序会使用TrackPopupMenu
函数来显示该菜单。此时hook EVENT_SYSTEM_MENUPOPUPSTART
对应的代码会被执行。该代码会向目标菜单依次发送MN_SELECTITEM
、MN_SELECTFIRSTVALIDITEM
以及MN_OPENHIERARCHY
消息,尝试打开菜单中第一个可用项。
下一个步骤对触发漏洞来说非常重要。漏洞利用程序必须及时抓住初始菜单已创建、且子菜单即将创建的时机。为了完成该任务,利用程序专门包含某些代码,用来处理在WH_CALLWNDPROC
hook中的WM_NCCREATE
消息。当利用代码检测到系统处于该状态时,就会向第一个菜单发送MN_CANCELMENUS
(0x1E6
)消息,取消该菜单。然而,该菜单对应的子菜单依然即将会被创建。
现在如果我们在内核模式中观察这个子菜单对象,可以看到tagPOPUPMENU‑>ppopupmenuRoot
的值等于0
。该状态允许攻击者在这个内核结构中使用该元素作为NULL指针执行dereference操作。利用代码会在0x00
地址处分配一个新页,而该地址会被内核当成一个tagPOPUPMENU
对象(如图1所示)。
图1. tagPOPUPMENU
内核结构
此时攻击者会使用第二个窗口。这里漏洞利用的主要目标是翻转第二个窗口tagWND
结构中的bServerSideWindowProc
位,成功翻转后内核模式中就会执行WndProc
过程。
为了完成该任务,攻击者会调用user32.dll
库中未导出的HMValidateHandle
函数,泄露第二个窗口tagWND
结构的内核内存地址。随后利用程序会在NULL页构造一个虚假的tagPOPUPMENU
对象,向子菜单发送MN_BUTTONDOWN
消息。
完成该操作后,内核最终会执行win32k!xxxMNOpenHierarchy
函数。
图2. win32k!xxxMNOpenHierarchy
函数的反汇编代码
该函数会将NULL页面上构造的对象传递给win32k!HMAssignmentLock
,而win32k!HMAssignmentLock
函数在经过几次调用后,会调用win32k!HMDestroyUnlockedObject
函数,后者会设置bServerSideWindowProc
位。
图3. win32k!HMDestroyUnlockedObject
函数的反汇编代码
现在一切准备就绪,利用代码会向第二个窗口发送特定的消息,以便在内核模式中执行WndProc
。
在最后一个攻击步骤中,利用代码会使用系统令牌替换当前进程的令牌。
微软已发布安全补丁,在win32k!xxxMNOpenHierarchy
函数添加了针对NULL指针的检查过程。
图4. win32k.sys
打补丁前(左图)后(右图)的代码对比
0x02 总结
这个漏洞利用技术只适用于老版本的Windows系统,因为从Windows 8开始,用户进程再也不能映射NULL页面。微软将这种缓解措施一并移植到了基于x64架构的Windows 7系统中。
如果大家还在使用32位的Windows 7 Service Pack 1,可以考虑更新到最新版的操作系统。Windows 7 Service Pack 1的扩展支持将于2020年1月14日结束,这意味着后续Windows 7用户无法获得关键安全更新,因此像这样的漏洞永远不会被官方修复。
0x03 IoC
SHA-1哈希 | ESET检测特征 |
---|---|
CBC93A9DD769DEE98FFE1F43A4F5CADAF568E321 | Win32/Exploit.CVE-2019-1132.A |