Windows CVE-2017-0263权限提升漏洞

可能已经在世界上最流行的桌面操作系统的漏洞是一个忙碌的月份。黑客大规模感染的想哭勒索的头条新闻,它利用一个SMB安全漏洞和eternalblue工具。不久前,在5月9日,微软的固定cve-2017-0263,这就使得攻击者在PC上运行的Windows 10,获得最大的系统权限的Windows 8.1,Windows 7,Windows Server 2008,Windows Server 2012和Windows Server 2016。

漏洞cve-2017-0263已经在钓鱼邮件已经使用。该邮件包含一个漏洞,首先进入系统利用微软Office的EPS文件错误的处理(cve-2017-0262)然后,一旦在里面,杠杆cve-2017-0263得到完全管理员权限。两年前,我们看着在Windows类似的漏洞,在这里我们将看到新的cve-2017-0263开辟“pwning”远程工作站和服务器。
总之,这是一个后使用免费漏洞(cwe-416)当上下文菜单窗口关闭,通过菜单占用的内存被释放了,在释放内存的指针不归零。作为一个结果,指针可以重复使用。

下面的讨论在处理窗口过程Win32k.sys中司机,这个过程使人们有可能利用该漏洞。

上下文菜单

每一个Windows用户熟悉的上下文菜单。这是当我们用鼠标右键单击下拉菜单。

出现此菜单和显示的方式是完全取决于每个应用程序的开发。WINAPI为开发商提供的TrackPopupMenuEx 功能,使上下文菜单出现在屏幕上指定的参数指定的位置。
快捷菜单的状态存储在变量中的内核Win32K!gmenustate,这是一个Win32K!tagmenustate结构:

   0: kd> dt win32k!tagMenuState
   +0x000 pGlobalPopupMenu  : Ptr32 tagPOPUPMENU
   +0x004 flags             : Int4B
   +0x008 ptMouseLast       : tagPOINT
   +0x010 mnFocus           : Int4B
   +0x014 cmdLast           : Int4B
   +0x018 ptiMenuStateOwner : Ptr32 tagTHREADINFO
   +0x01c dwLockCount       : Uint4B
   +0x020 pmnsPrev          : Ptr32 tagMENUSTATE
   +0x024 ptButtonDown      : tagPOINT
   +0x02c uButtonDownHitArea: Uint4B
   +0x030 uButtonDownIndex  : Uint4B
   +0x034 vkButtonDown      : Int4B
   +0x038 uDraggingHitArea  : Uint4B
   +0x03c uDraggingIndex    : Uint4B
   +0x040 uDraggingFlags    : Uint4B
   +0x044 hdcWndAni         : Ptr32 HDC__
   +0x048 dwAniStartTime    : Uint4B
   +0x04c ixAni             : Int4B
   +0x050 iyAni             : Int4B
   +0x054 cxAni             : Int4B
   +0x058 cyAni             : Int4B
   +0x05c hbmAni            : Ptr32 HBITMAP__
   +0x060 hdcAni            : Ptr32 HDC__

请注意,所有的调用堆栈和这里介绍的结构是从Windows 7 x86。32位操作系统的版本是用来方便:大多数函数的参数存储在堆栈中,没有WOW64层,它在系统调用切换到64位堆栈而32位堆栈帧丢失时,调用堆栈打印。一个充满脆弱的操作系统列表了微软网站

这个Win32K!tagmenustate例如结构存储,信息:点击区域的屏幕,最新的菜单命令的数量,和指针,单击或选择拖放窗口。上下文菜单窗口列表存储在第一场,pglobalpopupmenu,这是类型Win32K!tagpopupmenu:

   0: kd> dt win32k!tagPopupMenu
   +0x000 flags            : Int4B
   +0x004 spwndNotify      : Ptr32 tagWND
   +0x008 spwndPopupMenu   : Ptr32 tagWND
   +0x00c spwndNextPopup   : Ptr32 tagWND
   +0x010 spwndPrevPopup   : Ptr32 tagWND
   +0x014 spmenu           : Ptr32 tagMENU
   +0x018 spmenuAlternate  : Ptr32 tagMENU
   +0x01c spwndActivePopup : Ptr32 tagWND
   +0x020 ppopupmenuRoot   : Ptr32 tagPOPUPMENU
   +0x024 ppmDelayedFree   : Ptr32 tagPOPUPMENU
   +0x028 posSelectedItem  : Uint4B
   +0x02c posDropped       : Uint4B
   +0x030 ppmlockFree      : Ptr32 tagPOPUPMENU

在这两种结构中我们强调感兴趣的领域,它将使用下面描述的开发过程。

变量Win32K!gmenustate初始化时,上下文菜单的创建,在前面提到的TrackPopupMenuEx功能。初始化时发生Win32K!xxxmnallocmenustate被称为:

 1: kd> k
 # ChildEBP RetAddr  
00 95f29b38 81fe3ca6 win32k!xxxMNAllocMenuState+0x7c
01 95f29ba0 81fe410f win32k!xxxTrackPopupMenuEx+0x27f
02 95f29c14 82892db6 win32k!NtUserTrackPopupMenuEx+0xc3
03 95f29c14 77666c74 nt!KiSystemServicePostCall
04 0131fd58 7758480e ntdll!KiFastSystemCallRet
05 0131fd5c 100015b3 user32!NtUserTrackPopupMenuEx+0xc
06 0131fd84 7756c4b7 q_Main_Window_Class_wndproc (call TrackPopupMenuEx)

当上下文菜单不再需要,例如,用户选择一个菜单项或点击菜单的功能外Win32K!xxxmnendmenustate为释放菜单的状态:

 1: kd> k
 # ChildEBP RetAddr  
 00 a0fb7ab0 82014f68 win32k!xxxMNEndMenuState
 01 a0fb7b20 81fe39f5 win32k!xxxRealMenuWindowProc+0xd46
 02 a0fb7b54 81f5c134 win32k!xxxMenuWindowProc+0xfd
 03 a0fb7b94 81f1bb74 win32k!xxxSendMessageTimeout+0x1ac
 04 a0fb7bbc 81f289c8 win32k!xxxWrapSendMessage+0x1c
 05 a0fb7bd8 81f5e149 win32k!NtUserfnNCDESTROY+0x27
 06 a0fb7c10 82892db6 win32k!NtUserMessageCall+0xcf
 07 a0fb7c10 77666c74 nt!KiSystemServicePostCall
 08 013cfd90 77564f21 ntdll!KiFastSystemCallRet
 09 013cfd94 77560908 user32!NtUserMessageCall+0xc
 0a 013cfdd0 77565552 user32!SendMessageWorker+0x546
 0b 013cfdf0 100014e4 user32!SendMessageW+0x7c
 0c 013cfe08 775630bc q_win_event_hook (call SendMessageW(MN_DODRAGDROP))

重要的是这里的gmenustate.pglobalpopupmenu场仅在初始化在更新xxxmnallocmenustate功能不清零时,结构被破坏。
xxxmnendmenustate功能
这个功能是我们故事的明星。它把线港口的脆弱性。

xxxmnendmenustate从deinitialization和在上下文菜单中相关信息公开。这个mnfreepopup功能,我们将在下面的部分收益称为。主要任务mnfreepopup是递减的特定上下文菜单相关窗口的参考计数器。当引用计数降为零,这将可以使窗口被销毁。

然后xxxmnendmenustate功能检查fmenuwindowref旗的pglobalpopupmenu现场是否保持引用的上下文菜单,主窗口。这个标志被清除后,包含在窗口的破坏spwndpopupmenu该上下文菜单的领域:

 3: kd> k
 # ChildEBP RetAddr  
 00 95fffa5c 81f287da win32k!xxxFreeWindow+0x847
 01 95fffab0 81f71252 win32k!xxxDestroyWindow+0x532
 02 95fffabc 81f7122c win32k!HMDestroyUnlockedObject+0x1b
 03 95fffac8 81f70c4a win32k!HMUnlockObjectInternal+0x30
 04 95fffad4 81f6e1fc win32k!HMUnlockObject+0x13
 05 95fffadc 81fea664 win32k!HMAssignmentUnlock+0xf
 06 95fffaec 81fea885 win32k!MNFreePopup+0x7d
 07 95fffb14 8202c3d6 win32k!xxxMNEndMenuState+0x40

 xxxFreeWindow+83f disasm:
 .text:BF89082E loc_BF89082E:
 .text:BF89082E    and     ecx, 7FFFFFFFh  ; ~fMenuWindowRef
 .text:BF890834    mov     [eax+tagPOPUPMENU.flags], ecx

如上所述,国旗被丢弃,因此占用的内存pglobalpopupmenu场释放出来,但指针本身不清零。这造成了一种悬垂指针,在某些情况下可以重复使用。

上下文菜单的内存被释放后立即执行流程删除存储在上下文菜单结构状态与点击窗口的引用(ubuttondownhitarea场)当菜单被激活或被选定为拖放(udragginghitarea场)。

开发方法
内核中的一个窗口对象的描述tagwnd结构。我们描述了内核回调函数的概念,这将需要在这里就好了。主动参考窗口数存储在tagwnd结构clockobj场。

删除引用的一个窗口,如在上一节所示,可以使窗口本身被摧毁。在窗口被销毁,一wm_ncdestroy改变窗口状态消息发送到窗口。

这意味着当xxxmnendmenustate运行时,控制可以转移到用户应用程序的编码,到窗口的窗口过程破坏。发生这种情况时,没有保持引用到一个窗口的指针存储在gmenustate.ubuttondownhitarea场。

 2: kd> k
 # ChildEBP RetAddr
0138fc34 7756c4b7 q_new_SysShadow_window_proc
0138fc60 77565f6f USER32!InternalCallWinProc+0x23
0138fcd8 77564ede USER32!UserCallWinProcCheckWow+0xe0
0138fd34 7755b28f USER32!DispatchClientMessage+0xcf
0138fd64 77666bae USER32!__fnNCDESTROY+0x26
0138fd90 77564f21 ntdll!KiUserCallbackDispatcher+0x2e 
95fe38f8 81f56d86 nt!KeUserModeCallback
95fe3940 81f5c157 win32k!xxxSendMessageToClient+0x175
95fe398c 81f5c206 win32k!xxxSendMessageTimeout+0x1cf
95fe39b4 81f2839c win32k!xxxSendMessage+0x28
95fe3a10 81f2fb00 win32k!xxxDestroyWindow+0xf4
95fe3a24 81f302ee win32k!xxxRemoveShadow+0x3e
95fe3a64 81f287da win32k!xxxFreeWindow+0x2ff
95fe3ab8 81f71252 win32k!xxxDestroyWindow+0x532
95fe3ac4 81f7122c win32k!HMDestroyUnlockedObject+0x1b
95fe3ad0 81f70c4a win32k!HMUnlockObjectInternal+0x30
95fe3adc 81f6e1fc win32k!HMUnlockObject+0x13
95fe3ae4 81fe4162 win32k!HMAssignmentUnlock+0xf
95fe3aec 81fea8c3 win32k!UnlockMFMWFPWindow+0x18
95fe3b14 8202c3d6 win32k!xxxMNEndMenuState+0x7e

例如,在上面的调用堆栈的wm_ncdestroy消息处理程序的窗口sysshadow窗口类。这类窗口的设计是为了提供遮蔽,通常破坏随Windows一起所遮蔽。
现在我们看到的最有趣的部分是这个窗口的消息处理,在形式上是从一个恶意软件样本发现.docx钓鱼附件:

当攻击者控制,第一件事就是要占用内存,现在只是被gmenustate.pglobalpopupmenu,为了利用这个指针之后。尝试分配指定的内存块,利用执行大量的setclasslongw调用,从而建立专门成立一个菜单名为窗口类,已专门为此目的而设立的:

2: kd> k
 # ChildEBP RetAddr  
00 9f74bafc 81f240d2 win32k!memcpy+0x33
01 9f74bb3c 81edadb1 win32k!AllocateUnicodeString+0x6b
02 9f74bb9c 81edb146 win32k!xxxSetClassData+0x1d1
03 9f74bbb8 81edb088 win32k!xxxSetClassLong+0x39
04 9f74bc1c 82892db6 win32k!NtUserSetClassLong+0xc8
05 9f74bc1c 77666c74 nt!KiSystemServicePostCall
06 0136fac0 7755658b ntdll!KiFastSystemCallRet
07 0136fac4 775565bf user32!NtUserSetClassLong+0xc
08 0136fafc 10001a52 user32!SetClassLongW+0x5e
09 0136fc34 7756c4b7 q_new_SysShadow_window_proc (call SetClassLongW)

在占用内存,下一阶段的开始。利用访问ntusermndragleave系统程序,它执行一个嵌套调用的xxxmnendmenustate功能。结算的gmenustate结构的重新开始:

 2: kd> k
 # ChildEBP RetAddr  
00 9f74bbf0 8202c3d6 win32k!xxxMNEndMenuState
01 9f74bc04 8202c40e win32k!xxxUnlockMenuStateInternal+0x2e
02 9f74bc14 82015672 win32k!xxxUnlockAndEndMenuState+0xf
03 9f74bc24 82001728 win32k!xxxMNDragLeave+0x45
04 9f74bc2c 82892db6 win32k!NtUserMNDragLeave+0xd
05 9f74bc2c 100010a9 nt!KiSystemServicePostCall
06 0136fafc 10001a84 q_exec_int2e (int 2Eh)
07 0136fc34 7756c4b7 q_new_SysShadow_window_proc (call q_exec_int2e)

如前文所述,程序开始的deinitializingpglobalpopupmenu场;这个过程是由mnfreepopup打电话,这使参考计数器的Windows中包含的各个领域tagpopupmenu。前一步后,这个结构的内容现在被攻击者控制。所以当行为链进行描述,攻击者获取减量原始任意内核地址。

在这个漏洞,地址是插在tagpopupmenu.spwndprevpopup场和原始是用来减少为一个窗户的旗帜,使窗口标有标志bserversideproc,这意味着它的窗口程序是运行在内核。
为代码显示,后立即返回ntusermndragleave,一个消息被发送到窗口发送消息电话,使任意内核代码的执行。在这个阶段,攻击者通常抢断系统进程令牌来获得系统权限。事实上,这是在攻击发生在这里。

结论

该漏洞的要点是什么?在漏洞的最常见原因Win32k.sys中图书馆是访问用户空间的回调当任何内核的结构是在一个中间阶段,当一个事务正在改变他们。设置bserversideproc一个窗口的国旗也是内核代码执行的常用方法。此外,利用特权升级内核代码执行的最方便的方法是复制一个参考系统令牌。

在这个意义上,利用看起来很平凡。在许多细微之处都被简化或故意省略讨论的同时。

例如,我们没有停留在上下文菜单或菜单相关的行动造成的旗帜和领域的必要状态的具体外观Win32K!gmenustate执行过程中的变量xxxmnendmenustate程序。左未提及的事实是,在菜单的名称setclasslong称,一方面,是一个Unicode字符串没有空字符,但另一方面,是一个合法的tagpopupmenu结构。这也意味着,在内核中窗口的地址(其中减量字段将)必须不包含任何wchar_t空字符。这些只是几个例子,从一个相当长的名单。

至于更新修复漏洞,快速浏览显示缓冲处理的gmenustate.pglobalpopupmenu领域现在释放接近结束了xxxmnendmenustate多功能,后mnfreepopup和unlockmfmwpwindow电话,并伴随着归零的指针。因此,补丁地址两个原因同时存在的脆弱性导致其发生。


文章转载来源:http://blog.ptsecurity.com/2017/05/a-closer-look-at-cve-2017-0263.html