gowonisgood/CVE-2025-62215-POC

GitHub: gowonisgood/CVE-2025-62215-POC

CVE-2025-62215漏洞的Proof of Concept验证代码。

Stars: 10 | Forks: 1

# CVE-2025-62215 — Windows Token UAF (SepTokenSidSharingEnabled Race Condition) ## 本仓库仅供教育和研究目的使用。 ## 概述 这是一个发生在 Windows 内核 `SepTokenSidSharingEnabled` 优化路径中的 **Use-After-Free** 漏洞 PoC。 - 当 `NtDuplicateToken` 将 SID Values Block 的 RefCount 从 1 增加到 2 时, 竞争的内核线程会通过 `ExFreePoolWithTag` 释放该内存块。 - 随后,`SepDereferenceSidValuesBlock` 访问了已释放的内存块 → **UAF / Double Free**。 ``` [User] IOCTL_REPLACE_SID_BLOCK → Place an independent block (RefCount=1) at TOKEN+0x468 [User] IOCTL_TRIGGER_FREE → Spawn kernel thread (poll until RefCount==2) [User] NtDuplicateToken → Internally increments RefCount 1→2 [Kernel Thread] RefCount==2 detected → ExFreePoolWithTag(pBlock) ← UAF point ``` ## 文件结构 | 路径 | 描述 | |------|-------------| | `exploit/exploitWithDriv/exploitWithDriv.cpp` | 用户态 exploit (控制台应用) | | `tokendriv/tokendrv/tokendrv/tokendrv.cpp` | 内核驱动 (提供 IOCTL 接口) | ## 构建说明 (Visual Studio) ### 前置条件 - Visual Studio 2022 (MSVC) - Windows Driver Kit (WDK) — 构建 tokendriv 时需要 - SDK 10.0.26100.x 或更高版本 ### 1. `tokendriv.sys` — 内核驱动 1. 打开 `tokendriv/tokendrv/tokendrv.slnx` 2. 配置: **Release / x64** 3. 构建 → 生成 `tokendriv/tokendrv/x64/Release/tokendrv.sys` 4. 独立部署: 仅将 `.sys` 文件复制到 VM 即可 ### 2. `exploitWithDriv.exe` — 用户态 exploit 1. 打开 `exploit/exploitWithDriv.slnx` 2. 配置: **Release / x64** 3. 项目属性 → Linker → System → SubSystem: **Console** 4. 构建 → 生成 `exploit/x64/Release/exploitWithDriv.exe` 5. 独立部署 (无需 Visual C++ Redistributable): - C/C++ → Code Generation → **Runtime Library: Multi-threaded (/MT)** ## 在 VM 中运行 ### 前置条件 - VM 内存: **2 GB 或更少** (激活 `SepTokenSidSharingEnabled` 所需) - 测试账户: `test` / `1234` (本地账户,无需管理员权限) - Kernel Debugging 连接 (可选,分析时需要) - **管理员 cmd** ### 加载驱动 ``` sc create tokendriv type= kernel binpath= "C:\path\to\tokendrv.sys" sc start tokendriv ``` 验证驱动是否正在运行: ``` sc query tokendriv ``` 状态应为 `RUNNING`。 ### 运行 exploit ``` exploitWithDriv.exe ``` 执行流程: 1. 检查 `FullNumberOfPhysicalPages` (必须 ≤ 0x83400) 2. `LogonUser("test", ".", "1234")` → 获取 hSource 3. 按 Enter 键开始竞争循环 (100,000 次迭代) 4. 每次迭代: `REPLACE → TRIGGER → NtDuplicateToken → Sleep(1)` ## Race Condition 分析 (WinDbg KD) ### 1. 获取目标进程地址 ``` 0: kd> !process 0 0 exploitWithDriv.exe ``` 示例输出: ``` PROCESS ffffa88f5e61e080 SessionId: 1 Cid: 1234 Peb: ... ParentCid: ... Image: exploitWithDriv.exe ``` `ffffa88f5e61e080` 是 EPROCESS 地址。 ### 2. 设置断点 以下地址可能因环境而异 — 请使用实际的内核符号进行确认。 **A. SID Block RefCount 增加处 (竞争窗口开始)** ``` 0: kd> bp fffff800`725c6114 ".if (@$proc == 0xffffa88f5e61e080) { .echo A_REFCNT_INCR; dq poi(@rsi+0x468)+8 L1; gc } .else { gc }" ``` - 打印位于 `TOKEN+0x468` 处的 SID Values Block 的 RefCount (+0x8) - 值从 `1 → 2` 变化的时刻即为竞争窗口 **B. UAF 读取点** ``` 0: kd> bp fffff800`726f51fb ".if (@$proc == 0xffffa88f5e61e080) { .echo REAL_UAF_READ; r rax,rdx; gc } .else { gc }" ``` - 读取已释放内存块的位置 - 检查 `rax`, `rdx` 的值 **C. UAF 写入点** ``` 0: kd> bp fffff800`726f5208 ".if (@$proc == 0xffffa88f5e61e080) { .echo REAL_UAF_WRITE; r rcx,rdx,rax; gc } .else { gc }" ``` - 写入已释放内存块的位置 - 检查 `rcx`, `rdx`, `rax` 以确认是否损坏 ### 3. 竞争时序流程 ``` NtDuplicateToken entry └─ SeTokenCanImpersonate └─ SID Block RefCount: 1 → 2 ← bp A (A_REFCNT_INCR) ← kernel thread: ExFreePoolWithTag(pBlock) └─ SepDereferenceSidValuesBlock └─ dereference pBlock (read) ← bp B (REAL_UAF_READ) └─ dereference pBlock (write) ← bp C (REAL_UAF_WRITE) ``` ### 4. 分析提示 - 如果在打印 `A_REFCNT_INCR` 后 RefCount 立即为 `2`,则说明已成功进入竞争窗口 - 如果出现 `REAL_UAF_READ` / `REAL_UAF_WRITE`,则确认发生了实际的 UAF - 跟踪使用 pool tag `'kcoB'` 分配的内存块: `!pool ` 或 `!poolused` ## 关键偏移量 (Windows 11 24H2) | 结构体 | 偏移量 | 字段 | |-----------|--------|-------| | `_TOKEN` | `+0x468` | `SepSidValues` (SID Values Block 指针) | | SID Values Block | `+0x000` | `Length` (ULONG) | | SID Values Block | `+0x008` | `ReferenceCount` (LONGLONG) | ## 卸载驱动 ``` sc stop tokendriv sc delete tokendriv ``` # CVE-2025-62215 — Windows Token UAF (SepTokenSidSharingEnabled Race Condition) ## 概述 这是一个发生在 Windows 内核 `SepTokenSidSharingEnabled` 优化路径中的 **Use-After-Free** 漏洞 PoC。 - 当 `NtDuplicateToken` 内部将 SID Values Block 的 RefCount 从 1 增加到 2 时, 通过竞争让内核线程通过 `ExFreePoolWithTag` 释放该内存块。 - 随后,`SepDereferenceSidValuesBlock` 再次访问已释放的内存块 → **UAF / Double Free**。 ``` [User] IOCTL_REPLACE_SID_BLOCK → TOKEN+0x468 에 RefCount=1 독립 블록 배치 [User] IOCTL_TRIGGER_FREE → 커널 스레드 시작 (RefCount==2 폴링 대기) [User] NtDuplicateToken → 내부에서 RefCount 1→2 [Kernel Thread] RefCount==2 감지 → ExFreePoolWithTag(pBlock) ← UAF 지점 ``` ## 文件结构 | 路径 | 描述 | |------|------| | `exploit/exploitWithDriv/exploitWithDriv.cpp` | 用户态 exploit (控制台应用) | | `tokendriv/tokendrv/tokendrv/tokendrv.cpp` | 内核驱动 (提供 IOCTL 接口) | ## 构建说明 (Visual Studio) ### 通用前置条件 - Visual Studio 2022 (MSVC) - Windows Driver Kit (WDK) — 构建 tokendriv 时需要 - SDK 10.0.26100.x 或更高版本 ### 1. `tokendriv.sys` — 内核驱动 1. 打开 `tokendriv/tokendrv/tokendrv.slnx` 2. 配置: **Release / x64** 3. 构建 → 生成 `tokendriv/tokendrv/x64/Release/tokendrv.sys` 4. 独立部署: 只需将 `.sys` 文件复制到 VM 即可 ### 2. `exploitWithDriv.exe` — 用户态 exploit 1. 打开 `exploit/exploitWithDriv.slnx` 2. 配置: **Release / x64** 3. 项目属性 → Linker → System → SubSystem: **Console** 4. 构建 → 生成 `exploit/x64/Release/exploitWithDriv.exe` 5. 独立部署: 为确保在没有 Visual C++ Redistributable 的情况下也能运行 - 设置 C/C++ → Code Generation → **Runtime Library: Multi-threaded (/MT)** ## 在 VM 中运行 ### 前置条件 - VM 内存: **2 GB 或更少** (激活 `SepTokenSidSharingEnabled` 的条件) - 测试账户: `test` / `1234` (本地账户,无需管理员权限) - Kernel Debugging 连接 (可选,分析时需要) - **管理员 cmd** ### 加载驱动 ``` sc create tokendriv type= kernel binpath= "C:\path\to\tokendrv.sys" sc start tokendriv ``` 验证驱动加载状态: ``` sc query tokendriv ``` 如果状态为 `RUNNING` 则正常。 ### 运行 exploit ``` exploitWithDriv.exe ``` 执行流程: 1. 检查 `FullNumberOfPhysicalPages` (必须 ≤ 0x83400 才能继续) 2. `LogonUser("test", ".", "1234")` → 获取 hSource 3. 按 Enter 键开始 100,000 次竞争循环 4. 每次迭代: `REPLACE → TRIGGER → NtDuplicateToken → Sleep(1)` ## Race Condition 分析 (WinDbg KD) ### 1. 确认目标进程地址 ``` 0: kd> !process 0 0 exploitWithDriv.exe ``` 示例输出: ``` PROCESS ffffa88f5e61e080 SessionId: 1 Cid: 1234 Peb: ... ParentCid: ... Image: exploitWithDriv.exe ``` `ffffa88f5e61e080` 部分是 EPROCESS 地址。 ### 2. 设置断点 以下地址可能因环境而异,请在使用前通过实际的内核符号进行确认。 **A. SID Block RefCount 增加点 (竞争窗口开始)** ``` 0: kd> bp fffff800`725c6114 ".if (@$proc == 0xffffa88f5e61e080) { .echo A_REFCNT_INCR; dq poi(@rsi+0x468)+8 L1; gc } .else { gc }" ``` - 打印位于 `TOKEN+0x468` 的 SID Values Block 的 RefCount(+0x8) - 值从 `1 → 2` 变化的瞬间即为竞争窗口 **B. UAF 读取点** ``` 0: kd> bp fffff800`726f51fb ".if (@$proc == 0xffffa88f5e61e080) { .echo REAL_UAF_READ; r rax,rdx; gc } .else { gc }" ``` - 读取已释放内存块的位置 - 检查 `rax`, `rdx` 的值 **C. UAF 写入点** ``` 0: kd> bp fffff800`726f5208 ".if (@$proc == 0xffffa88f5e61e080) { .echo REAL_UAF_WRITE; r rcx,rdx,rax; gc } .else { gc }" ``` - 写入已释放内存块的位置 - 通过 `rcx`, `rdx`, `rax` 的值确认是否损坏 ### 3. 竞争时序流程 ``` NtDuplicateToken 진입 └─ SeTokenCanImpersonate └─ SID Block RefCount: 1 → 2 ← bp A (A_REFCNT_INCR) ← 커널 스레드: ExFreePoolWithTag(pBlock) └─ SepDereferenceSidValuesBlock └─ pBlock 역참조 (읽기) ← bp B (REAL_UAF_READ) └─ pBlock 역참조 (쓰기) ← bp C (REAL_UAF_WRITE) ``` ### 4. 分析提示 - 如果在输出 `A_REFCNT_INCR` 后立即显示 RefCount 为 `2`,则说明成功进入竞争窗口 - 如果输出 `REAL_UAF_READ` / `REAL_UAF_WRITE`,则确认发生了实际的 UAF - 跟踪使用 pool tag `'kcoB'` 分配的内存块: `!pool ` 或 `!poolused` ## 关键偏移量 (基于 Windows 11 24H2) | 结构体 | 偏移量 | 字段 | |--------|--------|------| | `_TOKEN` | `+0x468` | `SepSidValues` (SID Values Block 指针) | | SID Values Block | `+0x000` | `Length` (ULONG) | | SID Values Block | `+0x008` | `ReferenceCount` (LONGLONG) | ## 卸载驱动 ``` sc stop tokendriv sc delete tokendriv ```
标签:0day挖掘, PoC, UAF, Web报告查看器, Windows, 内核安全, 暴力破解, 漏洞利用, 网络安全监控, 驱动开发