Windows/MASM中如何修改异常处理函数的指令指针避免无限循环?
解决汇编异常处理中的无限循环问题
你的问题根源在于:ud2触发#UD异常后,CPU会将当前指向ud2的RIP保存到异常上下文里。你的处理程序直接ret,没有修改这个RIP,导致恢复执行后再次触发ud2,形成无限循环。要解决这个问题,需要修改异常上下文里的RIP,让程序跳过出错的ud2指令继续执行。
关键修改点
- 异常处理程序需要正确接收结构化异常处理(SEH)的标准参数,尤其是包含CPU上下文的
ContextRecord。 - 修改
ContextRecord中的Rip值,使其指向ud2之后的指令(ud2是2字节指令,所以RIP加2)。 - 返回
ExceptionContinueExecution,通知系统使用修改后的上下文恢复执行。
修改后的代码示例
_TEXT segment para 'CODE' ; SEH异常处理程序标准原型: ; EXCEPTION_DISPOSITION _stdcall MyHandler( ; PEXCEPTION_RECORD ExceptionRecord, ; PVOID EstablisherFrame, ; PCONTEXT ContextRecord, ; PVOID DispatcherContext ; ) MyHandler proc _ExceptionRecord, _EstablisherFrame, _ContextRecord, _DispatcherContext push rbp mov rbp, rsp sub rsp, 32h ; 分配x86-64调用约定要求的阴影空间 call printout ; 执行自定义打印逻辑 ; 修改上下文里的RIP,跳过ud2指令(ud2占2字节) mov rax, [_ContextRecord] add [rax + CONTEXT.Rip], 2 mov rsp, rbp pop rbp mov eax, ExceptionContinueExecution ; 返回继续执行的标志 ret MyHandler endp public SyntaxTest SyntaxTest proc frame:MyHandler .endprolog ud2 ; 触发#UD异常 .beginepilog ret ; 异常处理后会跳到这里执行 SyntaxTest endp _TEXT ends
说明
- 参数处理:SEH处理程序必须接收四个标准参数,这里用MASM的参数声明方式定义,同时分配x86-64调用约定要求的32字节阴影空间。
- 修改RIP:通过
ContextRecord指针找到RIP字段,加上ud2的长度(2字节),让程序恢复执行时跳过出错指令。 - 返回标志:
ExceptionContinueExecution是系统定义的常量(值为0),告诉系统使用修改后的上下文继续执行,而非重新触发异常或终止程序。
内容的提问来源于stack exchange,提问作者Badasahog
相关产品推荐
相关产品推荐

