快速业务通道

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

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

 if ( (stackUserBase <= pExcptRegHead )


 && (stackUserTop >= pStack )


 && (0 == (pExcptRegHead & 3)) )

 {


 DWORD pNewRegistHead;


 DWORD retValue;


 retValue = RtlpExecutehandlerForUnwind(pExcptRec, pExcptRegHead, &context,


 &pNewRegistHead, pExceptRegHead->handler );


 if ( retValue != DISPOSITION_CONTINUE_SEARCH )


 {


 if ( retValue != DISPOSITION_COLLIDED_UNWIND )


 {



 excptRec2.ExceptionRecord = pExcptRec;



 excptRec2.NumberParameters = 0;



 excptRec2.ExceptionCode = STATUS_INVALID_DISPOSITION;



 excptRec2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;



 RtlRaiseException( &excptRec2 );


 }


 else



 pExcptRegHead = pNewRegistHead;


 }


 PEXCEPTION_REGISTRATION pCurrExcptReg = pExcptRegHead;


 pExcptRegHead = pExcptRegHead->prev;


 RtlpUnlinkHandler( pCurrExcptReg );

 }

 else // 堆栈已经被破坏!生成一个异常

 {


 excptRec2.ExceptionRecord = pExcptRec;


 excptRec2.NumberParameters = 0;


 excptRec2.ExceptionCode = STATUS_BAD_STACK;


 excptRec2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;


 RtlRaiseException( &excptRec2 );

 }

 }

 // 如果执行到这里,说明已经到了EXCEPTION_REGISTRATION

 // 结构链表的末尾,正常情况下不应该发生这种情况。

 //(因为正常情况下异常应该被处理,这样就不会到链表末尾)

 if ( -1 == pRegistrationFrame )

 NtContinue( &context, 0 );

 else

 NtRaiseException( pExcptRec, &context, 0 );
 }

 RtlUnwind函数的伪代码到这里就结束了,以下是它调用的几个函数的伪代码:

 PEXCEPTION_REGISTRATION RtlpGetRegistrationHead( void )
 {

 return FS:[0];
 }
 RtlpUnlinkHandler( PEXCEPTION_REGISTRATION pRegistrationFrame )
 {

FS:[0] = pRegistrationFrame->prev;
 }
 void RtlpCaptureContext( CONTEXT * pContext )
 {

 pContext->Eax = 0;

 pContext->Ecx = 0;

 pContext->Edx = 0;

 pContext->Ebx = 0;

 pContext->Esi = 0;

 pContext->Edi = 0;

 pContext->SegCs = CS;

 pContext->SegDs = DS;

 pContext->SegEs = ES;

 pContext->SegFs = FS;

 pContext->SegGs = GS;

 pContext->SegSs = SS;

 pContext->EFlags = flags; // 它对应的汇编代码为__asm{ PUSHFD / pop [xxxxxxxx] }

 pContext->Eip = 此函数的调用者的调用者的返回地址  // 读者看一下这个函数的

 pContext->Ebp = 此函数的调用者的调用者的EBP    // 汇编代码就会清楚这一点

 pContext->Esp = pContext->Ebp + 8;
 }

虽然 RtlUnwind 函数的规模看起来很大,但是如果你按一定方法把它分开,其实并不难理解。它首先从FS:[4]和FS:[8]处获取当前线程堆栈的界限。它们对于后面要进行的合法性检查非常重要,以确保所有将要被展开的异常帧都在堆栈范围内。

RtlUnwind 接着在堆栈上创建了一个空的EXCEPTION_RECORD结构并把STATUS_UNWIND赋给它的ExceptionCode域,同时把 EXCEPTION_UNWINDING标志赋给它的 ExceptionFlags 域。指向这个结构的指针作为其中一个参数被传递给每个异常回调函数。然后,这个函数调用Rt

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站: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号