SEH 结构简介
好久都没有碰过 asm 了,今天工作需要,必须弄明白 seh 的问题。
所以,重新研究了一次,顺便记录一下,以被后用。
seh (Struct Exception Handling),详细情况清查询 msdn.
这里仅以我的一个小程序为例,展示 seh 的运作。
seh 的大致结构如下:
typedef
{
DWORD dwNextSEHAddr; // 下一个 SEH 结构地址
DWORD dwHandlerAddr; // 异常处理函数入口
}SEH;
从以上结构可以看出,一个 SEH 并不是孤立的,而是一个链表结构。
一个异常最终会传递给系统。这个链表的首部位于 fs:[0] 这个位置。
好了,我们通过一个小程序来说明这个(注:程序中是用了 stack 来存储 SEH,你也完全可以是用自己的内存空间)。
程序运行后,SEH 情况如图:
stack
+—————+
| dwHandlerAddr | HiMem
|—————| |
| dwNextSEHAddr | LoMem <——+
+—————+ |
|
|
+—————+ |
| SEH Pointer | fs:[0] = esp -+
+—————+
1. 首先通过 call 指令会自动压栈 dwHandlerAddr,
2. 然后利用 push dword ptr fs:[0] 指令,将原先的 SEH 地址存入 dwNextSEHAddr,构造 SEH 链表。
3. 这样我们就在栈中构造了我们的 SEH,最后把它插入到 SEH 链表的首部告知 windows 系统即可,这一步是用指令 mov fs:[0], esp 完成。
全部程序代码如下(注:以下代码是用 masm32 v8 编译通过):
=====================
.386
.model flat, stdcall
option casemap: none
include d:\masm32\include\windows.inc
include d:\masm32\include\kernel32.inc
include d:\masm32\include\user32.inc
includelib d:\masm32\lib\kernel32.lib
includelib d:\masm32\lib\user32.lib
.data
szEx db ‘Exception handled!’,0
szOK db ‘No Exception occurred!’,0
szInfo db ‘Info’,0
.code
start:
xor edx, edx
call handler ; push handler_function_addr = $+3
test eax, eax ; exception occurred: 0 - yes, 1 - no
jnz next
mov esp, [esp+8] ; restore stack after exception
add esp, 8
invoke MessageBox, 0, addr szEx, addr szInfo, 0
next:
invoke ExitProcess, 0
handler:
assume fs:nothing
push dword ptr fs:[edx]
mov fs:[edx], esp
xor eax, eax
; if you don’t intent to occur excption,
; comment the next line code
div eax
pop dword ptr fs:[edx] ; restore old SEH
invoke MessageBox, 0, addr szOK, addr szInfo, 0
mov eax, 1 ; no exception occurred
ret
end start
=====================
The End