异常链

一个进程中可以有多个线程,进程Id可作为线程表的外键。为了快速查询一个进程中的线程信息,可以在进程信息中加入线程表的地址。

 

线程环境块TEBThread Environment Block

线程信息块TIBThread Information Block

TEB结构起始处保存了TIBTIB的第一个字段ExceptionListSEH链表的表头地址。X86系统中,FS总是指向TEB/TIB,所以FS:[0]总是指向SEH链表的表头。

 

 

 

 

 

 

 

 

 

 

 

 

 

ExceptionList指向EXCEPTION_REGISTRATION_RECORD结构:

 

 

 

 

 

SEH处理函数的原型:

EXCEPTION_DISPOSITION __cdecl _except_handler(

    _In_ struct _EXCEPTION_RECORD* _ExceptionRecord,//要处理的异常

    _In_ void*                     _EstablisherFrame, //栈帧中的异常登记结构

    _Inout_ struct _CONTEXT*       _ContextRecord, //异常时线程上下文

    _Inout_ void*                  _DispatcherContext//额外信息

);

 

登记异常处理:

Push sehHandler ;处理函数的地址

Push FS:[0] ;前一个EXCEPTION_REGISTRATION_RECORD地址

Mov FS:[0], esp ;上两句push形成了EXCEPTION_REGISTRATION_RECORD结构,将结构地址赋值给FS:[0],即ExceptionList,以后发生异常时去FS:[0]获取sehHandler

此时栈结构:

FS:[0]

前一个结构地址

sehHandler

当前handler

 

 

 

注销异常处理:

 

Pop FS:[0] ;前一个结构地址给FS:[0],相当于还原了

Add esp, 4

 

异常展开:

从头节点(fs:[0])开始,fs:[0] -> fun1_seh -> main_seh -> startup_seh -> -1,当发生异常时,fun1_seh如果不能处理,先发送展开通知,便于异常处理执行清理工作,再卸载fun1_seh(看需要是否也卸载main_seh),最后更新下一个异常处理,例如startup_sehfs:[0]

 

try{//进入try时增加fs:[0]节点

 

}//离开try时删除fs:[0]节点

 

 

异常处理顺序:SEH -> Filter -> OS,这3步中每次都优先问调试器是否要处理,OS处理一般是直接关闭程序,关闭程序前还会问一次试器是否要处理。

Debugger -> SEH -> Debugger -> Filter -> Debugger -> OS -> Debugger

posted @ 2020-09-29 07:14  八转达人  阅读(137)  评论(0编辑  收藏  举报