现在的位置: 首页 > 综合 > 正文

关于SEH的一些总结

2011年06月17日 ⁄ 综合 ⁄ 共 1366字 ⁄ 字号 评论关闭
1.以前的一个误解
在ring3时候,fs段指向的是TEB。
以前一直有个误解,fs:[0]和fs:[1]记录着EXCEPTION_REGISTRATION
其实不然,而是fs:[0]记录着EXCEPTION_REGISTRATION的指针。

2.数据结构,它可以形成一个链表,这个链表的首地址记录在fs:[0],其中handle是异常处理函数。

_EXCEPTION_REGISTRATION struc
     prev    dd      ?
     handler dd      ?
 _EXCEPTION_REGISTRATION ends

3.异常处理函数会执行两遍。
第一次用来系统通过上述链表,找到确切这个异常的处理函数。
第二次是unwind,用来做一些回收相关的操作。例如,C++的destructor,执行_finally块。
执行完后,系统将恢复到当初出现错误的状态,删除没用的EXCEPTION_REGISTRATION链。

4._try _except嵌套块只使用一个EXCEPTION_REGISTRATION,而没有使用多个

5.vc的编译器将EXCEPTION_REGISTRATION数据结构扩展,使得可以支持_try _excetp
 ;struct _EXCEPTION_REGISTRATION{
 ;     struct _EXCEPTION_REGISTRATION *prev;
 ;     void (*handler)(PEXCEPTION_RECORD,
 ;                     PEXCEPTION_REGISTRATION,
 ;                     PCONTEXT,
 ;                     PEXCEPTION_RECORD);
 ;     struct scopetable_entry *scopetable;
 ;     int trylevel;
 ;     int _ebp;
 ;     PEXCEPTION_POINTERS xpointers;
 ;};

6.
有_try块的函数的堆栈情况

 EBP-00 _ebp
 EBP-04 trylevel
 EBP-08 scopetable pointer
 EBP-0C handler function address
 EBP-10 previous EXCEPTION_REGISTRATION
 EBP-14 GetExceptionPointers
 EBP-18 Standard ESP in frame
这里解释一下Standard ESP in frame的作用。
保存旧的EBP后,然后把ESP=>EBP,这样就可以用EBP访问堆栈中的局部变量。
函数一般用ADD ESP ,(负数)来开辟堆栈中的局部变量。
这时候如果再push 或者pop则是在stack的上方。这个时候的ESP需要被记住,如果出现异常的时候需要恢复这个值。它被记在EBP-18的位置。

例如:
#include <stdio.h>
#include <windows.h>
int main(int argc, char *argv[])
{
    _try
    {
        *((PUCHAR)NULL)=0;

    }_except(1)//这里需要恢复esp的数值
    {
       
    }
    return 0;
}

抱歉!评论已关闭.