网络安全之内核提权漏洞深入分析

背景知识本节内容描述了创建窗口时需要用到的结构体及函数:

  1. 用户态的窗口数据结构体:WNDCLASSEXW 。
  2. 窗口数据保存在内核态时使用:tagWND和tagWNDK结构体 。
  3. 用户态调用SetWindowLong可以设置窗口扩展内存数据,逆向分析SetWindowLong如何设置窗口扩展内存数据 。
窗口类拥有如下属性结构,此处仅列出比较重要的结构:
typedef struct tagWNDCLASSEXW {UINTcbSize;//结构体的大小…UINTstyle;//窗口的风格WNDPROClpfnWndProc;//处理窗口消息的回调函数地址intcbClsExtra;//属于此类窗口所有实例共同占用的内存大小intcbWndExtra;//窗口实例扩展内存大小LPCWSTRlpszClassName;//类名…} WNDCLASSEXW在用户态创建窗口时,需要调用RegisterClass注册窗口类,每个窗口类有自己的名字,调用CreateWindow创建窗口时传入类的名字,即可创建对应的窗口实例 。
当cbWndExtra不为0时,系统会申请一段对应大小的空间,如果回调到用户态申请空间时,可能会触发漏洞 。
内核中使用两个结构体来保存窗口数据tagWND和tagWNDK:
ptagWND//内核中调用ValidateHwnd传入用户态窗口句柄可返回此数据指针0x18 unknown0x80 kernel desktop heap base//内核桌面堆基址0x28 ptagWNDk// 需要重点关注这个结构体,结构体在下方:0xA8 spMenutagWNDK结构体,需要重点关注此结构体:
struct tagWNDK{ULONG64 hWnd;//+0x00ULONG64 OffsetToDesktopHeap;//+0x08 tagWNDK相对桌面堆基址偏移ULONG64 state;//+0x10Dword dwExStyle;//+0x18DWORD dwStyle;//+0x1CBYTE gap[0x38];DWORD rectBar_Left;//0x58DWORD rectBar_Top;//0x5CBYTE gap1[0x68];ULONG64 cbWndExtra;//+0xC8 窗口扩展内存的大小BYTE gap2[0x18];DWORD dwExtraFlag;//+0xE8决定SetWindowLong寻址模式BYTE gap3[0x10];//+0xECDWORD cbWndServerExtra;//+0xFCBYTE gap5[0x28];ULONG64 pExtraBytes;//+0x128 模式1:内核偏移量 模式2:用户态指针};当WNDCLASSEXW 中的cbWndExtra值不为0时,创建窗口时内核会回调到用户态函数USER32!
_xxxClientAllocWindowClassExtraBytes申请一块cbWndExtra大小的内存区域,并且将返回地址保存在tagWNDK结构体的pExtraBytes变量中 。
【一>所有资源关注我,私信回复“资料”获取<一】
1、很多已经买不到的绝版电子书
2、安全大厂内部的培训资料
3、全套工具包
4、100份src源码技术文档
5、网络安全基础入门、linux、web安全、攻防方面的视频
6、应急响应笔记 7、 网络安全学习路线
8、ctf夺旗赛解析
9、WEB安全入门笔记
使用函数SetWindowLong和GetWindowLong,可对窗口扩展内存进行读写,进入内核后调用栈如下:
win32kfull!xxxSetWindowLongwin32kfull!NtUserSetWindowLong+0xc7win32k!NtUserSetWindowLong+0x16nt!KiSystemServiceCopyEnd+0x25win32u!NtUserSetWindowLong+0x14USER32!_SetWindowLong+0x6eCVE_2022_21882!wmain+0x25dSetWindowLong函数形式如下:
网络安全之内核提权漏洞深入分析

文章插图
 
第二个参数为index,含义为设置扩展内存偏移index处的内容 。
在win32kfull!xxxSetWindowLong函数中,会对第二个参数index进行判断,防止越界:
网络安全之内核提权漏洞深入分析

文章插图
 
137行代码判断index+4如果大于cbWndServerExtra+ cbWndExtra,表明越界,一般情况下cbWndServerExtra为0,如果越界,会跳转到117行LABEL_34,设置v18为1413,跳转到LABEL_55,调用UserSetLastError设置错误值,我们可以在cmd下查看此错误值的含义:
网络安全之内核提权漏洞深入分析

文章插图
 
如果没有越界的话,接下来会根据不同的模式来使用pExtraBytes,如下:
网络安全之内核提权漏洞深入分析

文章插图
 
在xxxSetWindowLong函数中:
正常情况下cbWndServerExtra为0,157行如果index+4< cbWndServerExtra,那么修改的是窗口的保留属性,例如GWL_WNDPROC对应-4,含义为设置窗口的回调函数地址 。我们需要设置的是窗口扩展内存,所以进入165行的代码区域 。
在167行会判断dwExtraFlag属性是否包含0x800,如果包含,那么168行代码destAddress=pExtraBytes+index+内核桌面堆基址,此处pExtraBytes作为相对内核桌面堆基址的相对偏移量,


    推荐阅读