利用单链表的头插入法,理解SEH的设置

作者在 2008-08-22 23:45:15 发布以下内容
在Win32汇编中,对于SEH异常处理回调函数的设置,只有3条简单的指令,但要真正理解起来,还真不容易.
指令如下:
push    offset  _Handler   ;回调函数地址入栈
push    fs:[0]             ;原先的EXCEPTION_REGISTRATION 结构地址入栈
mov     fs:[0],esp         ;把当前栈顶地址赋予fs:[0]
 
如果只看这3条指令是无法理解的,必须结合单链表的头插入法来理解它.
首先,可以把fs:[0] 当作头指针来看待;(注意:fs:[0]就是NT_TIB结构中ExceptionList 的值!)
头指针fs:[0]指向一个SEH单链表! 且指向的是链表的第一个结点:第一个EXCEPTION_REGISTRATION 结构!
当从SEH链表的头部插入一个新的结点(即新的EXCEPTION_REGISTRATION结构)的时候,要修改两个指针!
即,把第一个结点的地址放入新的EXCEPTION_REGISTRATION结构的prev 字段中,把新的EXCEPTION_REGISTRATION结构的地址赋予头指针fs:[0].
而上面的3条指令正是这么做的,但最巧妙的是:竟然把新的结点放到了栈中!!!
push    offset  _Handler 结点的数据域入栈!
push    fs:[0]  头指针值入栈!
这两条指令正好在栈中构造了一个新的结点,即新的EXCEPTION_REGISTRATION结构![esp + 4]是字段Handler;[esp]是字段prev,且prev的值就是原先第一个结点的地址!
再 mov     fs:[0],esp 把当前栈顶地址放入fs:[0],这等于把新结点的地址赋予了头指针!(特别注意:是esp赋予了头指针,而不是[esp]的值赋予了头指针!)
 
真的很巧妙啊~~~
文章评论,共0条
游客请输入验证码