快速业务通道

Win32结构化异常处理(SEH)探秘(下)

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29
H;

}

else if ( DISPOSITION_CONTINUE_SEARCH == retValue )

{}

else if ( DISPOSITION_NESTED_EXCEPTION == retValue )

{


pExcptRec->ExceptionFlags |= EH_EXIT_UNWIND;


if ( dispatcherContext > yetAnotherValue )


yetAnotherValue = dispatcherContext;

}

else // DISPOSITION_COLLIDED_UNWIND

{


excptRec2.ExceptionRecord = pExcptRec;


excptRec2.ExceptionNumber = STATUS_INVALID_DISPOSITION;


excptRec2.ExceptionFlags  = EH_NONCONTINUABLE;


excptRec2.NumberParameters = 0;


RtlRaiseException( &excptRec2 );

}

pRegistrationFrame = pRegistrationFrame->prev; // 转到前一个帧

}

return DISPOSITION_DISMISS;
}
_RtlpExecuteHandlerForException: // 处理异常(第一次)
MOV EDX,XXXXXXXX
JMP ExecuteHandler 
RtlpExecutehandlerForUnwind: // 处理展开(第二次)
MOV EDX,XXXXXXXX 

int ExecuteHandler( PEXCEPTION_RECORD pExcptRec,

  PEXCEPTION_REGISTRATION pExcptReg,

  CONTEXT * pContext,

  PVOID pDispatcherContext,

  FARPROC handler ) // 实际上是指向_except_handler()的指针
{

// 安装一个EXCEPTION_REGISTRATION帧,EDX指向相应的handler代码

PUSH EDX

PUSH FS:[0]

MOV FS:[0],ESP 

// 调用异常处理回调函数

EAX = handler( pExcptRec, pExcptReg, pContext, pDispatcherContext );

// 移除EXCEPTION_REGISTRATION帧

MOV ESP,DWORD PTR FS:[00000000]

POP DWORD PTR FS:[00000000]

return EAX;
}
_RtlpExecuteHandlerForException使用的异常处理程序:
{

// 如果设置了展开标志,返回DISPOSITION_CONTINUE_SEARCH

// 否则,给pDispatcherContext赋值并返回DISPOSITION_NESTED_EXCEPTION 

return pExcptRec->ExceptionFlags & EXCEPTION_UNWIND_CONTEXT ?
DISPOSITION_CONTINUE_SEARC : ( *pDispatcherContext =


 pRegistrationFrame->scopetable,


 DISPOSITION_NESTED_EXCEPTION );
}

_RtlpExecuteHandlerForUnwind使用的异常处理程序:
{

// 如果设置了展开标志,返回DISPOSITION_CONTINUE_SEARCH

// 否则,给pDispatcherContext赋值并返回DISPOSITION_COLLIDED_UNWIND 

return pExcptRec->ExceptionFlags & EXCEPTION_UNWIND_CONTEXT ?
DISPOSITION_CONTINUE_SEARCH : ( *pDispatcherContext =


 pRegistrationFrame->scopetable,


 DISPOSITION_COLLIDED_UNWIND );
}

KiUserExceptionDispatcher 的核心是对 RtlDispatchException 的调用。这拉开了搜索已注册的异常处理程序的序幕。如果某个处理程序处理这个异常并继续执行,那么对 RtlDispatchException 的调用就不会返回。如果它返回了,只有两种可能:或者调用了NtContinue以便让进程继续执行,或者产生了新的异常。如果是这样,那异常就不能再继续处理了,必须终止进程。

现在把目光对准 RtlDispatchException 函数的代码,这就是我通篇提到的遍历异常帧的代码。这个函数获取一个指向EXCEPTION_REGISTRATION 结构链表的指针,然后遍历此链表以寻找一个异常处理程序。由于堆栈可能已经被破坏了,所以这个例程非常谨慎。在调用每个EXCEPTION_REGISTRATION结构中指定的异常处理程序之前,它确保这个结构是按DWORD对齐的,并且是在线程的堆栈之中,同时在堆栈中比前一个EXCEPTION_REGISTRATION结构高。

RtlDispatchException并不直接调用EXCEPTION_REGISTRATION结构中指定的异常处理程序。相反,它调用 RtlpExecute

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号