0391-CVE2015-0057漏洞样本构造探索

# CVE2015-0057漏洞样本构造探索

0x00 前言
=======

* * *

微软最新的补丁包修补了CVE2015-0057的提权漏洞,同一天,漏洞的发现者发表了分析文章《One-Bit To Rule Them All: Bypassing Windows’ 10 Protections using a Single Bit》,看完文章,想尝试构造一下样本,原本以为很简单,结果期间遇到了几个问题,分享出来,希望能与大家一起讨论。

0x01 分析
=======

* * *

由于分析文章里提到漏洞是由xxxEnableWndSBArrows引起的,就通过CreateWindowEx创建ScrollBar,然后调用EnableScrollBar,执行到xxxDrawScrollBar,按照分析文章里的说明,完整流程如下:

![enter image description here](http://drops.javaweb.org/uploads/images/0e55549686d161e995405dc299e15bbe04fa9622.jpg)

结果发现可以执行到xxxGetColorObjects,但是总是没法走到xxxDefWindowProc,因为(*((_WORD *)P + 0x15) & 0x3FFF) == 0x29A总是成立,最后google了一下,发现这里是判断当前窗体是不是ScrollBar。

![enter image description here](http://drops.javaweb.org/uploads/images/04f76b1ba97dfc2e7bbf4619dc1b8394dbb560e7.jpg)

*((_WORD *)P + 0x15)表示FNID,是通过NtUserSetWindowFNID在创建窗体时设置的,可以在reactos的代码中看到,windows包含了如下的FNID。

“`
+// FNID’s for NtUserSetWindowFNID
+#define FNID_BUTTON 0x02A1
+#define FNID_COMBOBOX 0x02A2
+#define FNID_COMBOLBOX 0x02A3
+#define FNID_DIALOG 0x02A4
+#define FNID_EDIT 0x02A5
+#define FNID_LISTBOX 0x02A6
+#define FNID_MDICLIENT 0x02A7
+#define FNID_STATIC 0x02A8
+#define FNID_IME 0x02A9

“`

NtUserSetWindowFNID中,可以看到这里会对(_WORD *)(v2 + 0x2A)处的值进行设置,(_WORD *)P + 0x15与等价(_WORD *)(v2 + 0x2A)。

![enter image description here](http://drops.javaweb.org/uploads/images/404c2136985b52a96bdae8c0be86a82a7d1a9486.jpg)

看来直接通过创建ScrollBar是不能执行到xxxDefWindowProc的。通过内核调试器,在此处设置断点,在屏幕上点动各种窗体,当打开任务管理器,点击显示所有用户进程时,触发了断点。查看此时的调用栈,看到了CListView!!!看来可能可以通过MFC的CListCtrl来触发xxxDefWindowProc函数的执行。

![enter image description here](http://drops.javaweb.org/uploads/images/f5a3afe66f76fb1e2d130a1836a27b30467b1461.jpg)

重载了CListCtrl,当ListCtrl显示的东西过多时,就会出现ScrollBar,这样在CListCtrl里处理一下afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)消息,就能够处理CListCtrl里的ScrollBar的消息,进而释放掉ScrollBar窗体。当点击CListCtrl里的横向ScrollBar时,就会触发CListCtrlEx::OnHScroll,这次再调用EnableScrollBar,就能执行到xxxDefWindowProc函数。

“`
void CListCtrlEx::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar )
{
hScroll = this->m_hWnd;
BOOL bEnable = ::EnableScrollBar( this->m_hWnd , SB_HORZ , ESB_DISABLE_BOTH );
CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
}

“`

![enter image description here](http://drops.javaweb.org/uploads/images/72b934a641eeb3d958e957640e6becbe99a098a5.jpg)

不过又遇到了新的问题,signed int __stdcall xxxLoadUserApiHook()函数里总是没法执行到xxxLoadHmodIndex,显然这个函数是与UserApiHook相关的,(1 << gihmodUserApiHook) &_(_DWORD *)(_((_DWORD *)gptiCurrent + 46) + 0xBC)的条件总是成立,好吧,断点设置在win32k!xxxLoadUserApiHook+0x2b处,结果程序启动的时候,加载user32.dll,调用InitUserApiHook,最终会执行几次xxxLoadHmodIndex,之后就不再调用了。 ![enter image description here](http://drops.javaweb.org/uploads/images/06e38c40f608a164fd8715d50fbde17c54a6bf1f.jpg) ![enter image description here](http://drops.javaweb.org/uploads/images/2199bb75a8ef313df961e8be30eb48fc4b52d161.jpg) 重新看了一下分析文章,核心就是在用户态回调时,释放掉窗体,因此只要找到另一条路径,在xxxEnableWndSBArrows返回前,将窗体释放就可以了。在xxxDefWindowProc里,会调用到SfnDWORD,该函数中就存在一个回调,如下图。KeUserModeCallback的第一个参数2表示的是ApiNumber,也就是说最终会通过用户态的KiUserCallbackDispatcher调用USER32!__fnDWORD函数,如果能够在调用该函数的时候,将窗体释放掉,也是能够达到触发漏洞的效果的。 ![enter image description here](http://drops.javaweb.org/uploads/images/b024e31921e91ded210b19bcf045e414d0774a94.jpg) 定义一个forFree函数,在KeUserModeCallback回调到USER32!__fnDWORD时,调用这个函数将窗体对象释放掉,第一次调用DestroyWindow( hScroll )释放窗体,第二次则对窗体是否被释放进行验证。通过在USER32!__fnDWORD处调用forFree,可以看到调用EnableScrollBar最终触发了forFree执行。注意USER32!__fnDWORD会被频繁调用,因此要进行区分。 ``` void forFree() { DestroyWindow( hScroll ); DestroyWindow( hScroll ); return ; } ``` ![enter image description here](http://drops.javaweb.org/uploads/images/faaa27a5f613076dcf733402e7506105ea1c19dd.jpg) 第一次调用DestroyWindow后,可以看到函数执行成功,返回值eax=1。再次调用DestroyWindow后,win32k!ValidateHwnd就无法根据hScroll的值来获取到对应的内核窗体结构,返回值eax=0。从xxxDefWindowProc返回之后,实际上窗体已经不再与之前传递给EnableScrollBar的句柄对应了。 ![enter image description here](http://drops.javaweb.org/uploads/images/c71aae87415e22c68f9c34085ee78acc29dfbf8c.jpg) ![enter image description here](http://drops.javaweb.org/uploads/images/2f2a6394cfa0ad8729c5417147588d48cf70d9ea.jpg) 不过我在32位win7上,并没有找到分析文章里提到的OR操作和AND操作。 ![enter image description here](http://drops.javaweb.org/uploads/images/2eb9b5b96eab8f73c82417f4504b2315a28aaef6.jpg) 0x02 结语 ======= * * * 上面就是我对CVE2015-0057漏洞样本构造过程的探索,与分析文章文章里的内容存在差异,有什么不对的地方,希望能与大家交流,我的邮箱:cssembly@gmail.com。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容