如何使用MASM64设置异常及访问SEH异常链?
MASM64访问SEH异常链及兼容x86方式的说明
核心结论
x64环境下,线程环境块(TEB)由GS寄存器而非FS寄存器寻址,异常链的首节点存储在TEB的ExceptionList字段,对应偏移为0x18,所以需要通过gs:[0x18]访问,而非x86的fs:[0]。
关于沿用x86方式设置SEH的可行性
x64支持手动注册SEH链表(类似x86的链表式结构),但有几个关键差异必须注意:
- 结构大小变化:x64的
EXCEPTION_REGISTRATION_RECORD结构中,Next和Handler都是64位指针,而非x86的32位指针。 - 异常处理函数签名:x64的异常处理函数需遵循x64调用约定,签名为:
返回值EXCEPTION_DISPOSITION _cdecl ExceptionHandler( _Inout_ PEXCEPTION_RECORD ExceptionRecord, _In_ PVOID EstablisherFrame, _Inout_ PCONTEXT ContextRecord, _Inout_ PVOID DispatcherContext );EXCEPTION_DISPOSITION枚举值与x86一致,但所有参数均为64位指针。 - 栈对齐要求:x64代码必须保证栈始终16字节对齐,构造SEH记录时需注意栈指针的调整。
MASM64手动设置SEH的示例
.code ; 异常处理函数 ExceptionHandler proc ; 简单返回继续执行,可根据需求添加处理逻辑 mov rax, ExceptionContinueExecution ret ExceptionHandler endp Main proc ; 调整栈以满足x64的16字节对齐要求 sub rsp, 28h ; 在栈上构造EXCEPTION_REGISTRATION_RECORD push ExceptionHandler push qword ptr gs:[0x18] ; 保存原异常链首节点 mov qword ptr gs:[0x18], rsp ; 将新记录设为链首 ; 触发测试异常(除零操作) xor rcx, rcx div rcx ; 恢复原异常链 pop qword ptr gs:[0x18] add rsp, 28h ret Main endp end
注意事项
- 手动修改SEH链需要足够权限,现代Windows的SEHOP等防护机制会校验链的合法性,非法修改可能导致进程崩溃。
- 若配合C++代码使用,编译器会自动生成x64 SEH相关结构,手动修改链需避免破坏编译器生成的逻辑。
内容的提问来源于stack exchange,提问作者ginko
相关产品推荐
相关产品推荐

