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, 内核安全, 暴力破解, 漏洞利用, 网络安全监控, 驱动开发