异常的分发和处理时在线程范围内进行的,异常处理器的注册也是相对线程而言的。Windows系统中的每个用户态线程都拥有一个线程环境块(Thread Environment Block),TEB结构的具体定义。
TEB结构的起始处总有一个被称为线程信息块(Thread information Block)的结构,简称TIB.TIB的第一字段ExceptionList记录的就是用来登记结构化异常处理链表的表头地址,在x86系统中,段寄存器FS总是指向线程的TEB/TIB结构,FS:[0] 总是指向结构化异常处理链表的表头,所以将这个链表称为FS:[0]链条。可以把结构化异常处理看作是操作系统与用户代码软硬件异常的一种模型,而FS:[0]链条便是这两者间协作的接口。当有异常需要处理时,操作系统通过FS:[0]链条来寻找异常处理器,给用户代码异常情况的机会。
可以手工编写代码来登记和注销异常处理器。首先需要编写一个异常处理器函数,它应该具有标准的sehHandler原型,然后在栈上建立一个EXCEPTION_REGISTRATION_RECORD结构,并把这个结构的地址注册到FS:[0]链表中。
注册FS:[0]的代码如下所示:
#include "stdafx.h"
#include <windows.h>
// 定义一个符合sehHandler原型的异常处理函数,如果该函数检测发生的是
// 除零异常,然后将上下文结构中的ECX寄存器的值改为10,让其继续执行
// 导致异常的代码,第二次执行时由于除数不再为0所以可以顺利执行了
EXCEPTION_DISPOSITION __cdecl _raw_seh_handler( struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT * ContexRecord,
void * DispacherContext
)
{
printf("_raw_seh_handler: code-0x%x, flags-0x%x\n",
ExceptionRecord->ExceptionCode,
ExceptionRecord->ExceptionFlags);
if(ExceptionRecord->ExceptionCode == STATUS_INTEGER_DIVIDE_BY_ZERO)
{
ContexRecord->Ecx = 10;
return ExceptionContinueExecution;
}
return ExceptionContinueSearch;
}
int main(int argc, char* argv[])
{
__asm
{
// 手工方法将异常函数注册到FS:[0]链表中
push OFFSET _raw_seh_handler
push FS:[0]
mov FS:[0], ESP
// 执行除零异常
xor edx, edx
mov eax, 100
xor ecx, ecx
idiv ecx
mov eax, [ESP]
mov FS:[0], EAX
add esp, 8
}
printf("Hello World!\n");
return 0;
}
欢迎访问最专业的网吧论坛,无盘论坛,网吧经营,网咖管理,网吧专业论坛
https://bbs.txwb.com
关注天下网吧微信/下载天下网吧APP/天下网吧小程序,一起来超精彩
|
本文来源:不详 作者:佚名