Microsoft Windows Win32k本地提权漏洞分析

一、漏洞信息

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
点击收藏 | 0 关注 | 1
登录 后跟帖