当用户异常产生后,内核函数KiDispatchException并不是像处理内核异常那样在0环直接进行处理,而是修正3环EIP为KiUserExceptionDispatcher函数后就结束了。

这样,当线程再次回到3环时,将会从KiUserExceptionDispatcher函数开始执行。

KiUserExceptionDispatcher会调用RtIDispatchException函数来查找并调用异常处理函数,查找的顺序:

  1. 先查局链表: VEH
  2. 如果VEH没找到,再查局部链表: SEH

3环fs[0]->TEB.+ 0x0 _NT_TIB
0环fs[0]->KPCR.+ 0x0 _NT_TIB
无论是3环还是0环它的第一个都是_EXCEPTION_REGISTRATION_RECORD 这个结构,这个结构最少要有两个成员,可拓展后面再说。

//最原始的 SEH链表结构
typedef struct _EXCEPTION_REGISTRATION_RECORD
{ struct _EXCEPTION_REGISTRATION_RECORD* Next;  //下一个节点,-1就是没有下一个节点了PEXCEPTION_ROUTINE Handler; //指向异常处理函数
} EXCEPTION_REGISTRATION_RECORD;

SEH与VEH不同,VEH所有线程都能用的与线程无关,SEH哪个线程想用这个异常处理函数,就必须往自己的堆栈里压入_EXCEPTION_REGISTRATION_RECORD这种结构(你压入当前进程的A线程对B线程没有影响的),然后让fs[0]指向新构建的结构体,再给Handler提供异常处理函数。

获取当前堆栈界限与起始位置,再回来

这一块代码都是检测SEH链是否处于当将线程的堆栈中。

调用处理异常函数

测试代码

//最原始的 SEH链表结构(这个结构怎么写都行)
struct _EXCEPTION
{struct _EXCEPTION* Next;DWORD Handler;
};EXCEPTION_DISPOSITION _cdecl MyEexception_handler
(struct _EXCEPTION_RECORD *ExceptionRecord, //异常结构体PVOID EstablisherFrame,                      //SEH结构体地址struct _CONTEXT *ContextRecord,               //存储异常发生时的各种寄存器的值 栈位置等PVOID DispatcherContext
)
{MessageBox(NULL,L"SEH异常处理函数执行了...",L"SEH异常",NULL);if (ExceptionRecord->ExceptionCode == 0xC0000094){ContextRecord->Eip = ContextRecord->Eip + 2;ContextRecord->Ecx = 100;return ExceptionContinueExecution;}return ExceptionContinueSearch;
}int main()
{DWORD temp;_EXCEPTION Exception;//必须在当前线程堆栈的堆栈中//fs[0]-> Exception_asm{mov eax, fs:[0]mov temp,eaxlea ecx,Exceptionmov fs:[0],ecx}//为SEH成员赋值Exception.Next = (_EXCEPTION*)temp;Exception.Handler = (DWORD)&MyEexception_handler;//创建异常int val = 0;_asm{xor edx,edxxor ecx,ecxmov eax,1idiv ecx   //edx = eax /ecxmov val,ecx}//摘除刚插入的SEH_asm{mov eax, tempmov fs:[0],eax}printf("val = %d",val);getchar();
}

总结: SEH异常的处理流程

  1. FS:[0]指向SEH链表的第一个成员
  2. SEH的异常处理函数必须在当前线程的堆栈中
  3. 只有当VEH中的异常处理函数不存在或者不处理才会到SEH链表中查找

5.SEH(结构化异常处理)相关推荐

  1. 异常处理第三讲,SEH(结构化异常处理),异常展开问题

    异常处理第三讲,SEH(结构化异常处理),异常展开问题 作者:IBinary 出处:http://www.cnblogs.com/iBinary/ 版权所有,欢迎保留原文链接进行转载:) 不知道昨天有 ...

  2. Win32 结构化异常处理(SEH)探秘【下篇】

    图十三 UnHandledExceptionFilter 函数的伪代码 UnhandledExceptionFilter( STRUCT _EXCEPTION_POINTERS *pException ...

  3. 深入解析结构化异常处理(SEH) - by Matt Pietrek

    目录 1.浅析SEH 2.移向更深处 3.编译器层面的SEH 4.扩展的异常处理帧 5.ShowSEHFrames程序 6.展开 7.未处理异常 8.进入地狱 9.结论 ​尽管以前写过一篇SEH相关的 ...

  4. Windows系统程序设计之结构化异常处理

    标 题: [原创]Windows系统程序设计之结构化异常处理 作 者: 北极星2003 时 间: 2006-09-20,20:21:28 链 接: http://bbs.pediy.com/showt ...

  5. windows核心编程学习笔记(八)结构化异常处理(Structured Exception Handling)

    首先要要知道,结构化异常处理(SEH)和C++提供的异常处理不相同. 一.Termination HandlersTermination Handlers使用很简单.在想使用SEH处理的地方使用 __ ...

  6. 深入探索Win32结构化异常处理

    原文:http://blog.csdn.net/diamont/article/details/4259590 Matt Pietrek 著 董岩 译 在Win32操作系统提供的所有功能中,使用最广泛 ...

  7. Windows异常世界历险记(五)——VC6中结构化异常处理机制的反汇编分析(下)

    在本系列的上一篇文章Windows异常世界历险记(四)--VC6中结构化异常处理机制的反汇编分析(中)中,给出了针对VC6的异常处理机制进行逆向后得到的伪码.在本文中,我们仍然以之前写的小程序为例,通 ...

  8. SEH结构体异常处理

    异常的主要结构体信息 一般当程序发生异常时,用户代码停止执行,并将CPU的控制权转交给操作系统,操作系统接到控制权后,将当前线程的寄存器环境保存到结构体CONTEXT中,然后查找针对此异常的处理函数 ...

  9. 什么是VB.NET的结构化异常处理

    深谈VB.NET结构化异常处理执行标准 对于VB.NET语言来说,在实际编程中有一个非常重要的操作值得我们去注意,那就关于异常方面的处理.今天我们就可以通过VB.NET结构化异常处理的相关介绍,来仔细 ...

  10. Windows内存管理(3)--检查内存可用性,结构化异常处理 和 ASSERT

    1.      检查内存可用性 在驱动程序开发中,对内存的操作要格外小心.如果某段内存是只读的,而驱动程序试图去写操作,会导致系统的崩溃. DDK提供了两个函数,帮助程序员在不知道某段内存是否可读写的 ...

最新文章

  1. 工业红外温度传感器 测温探头在线式4-20mA 变送器红外线非接触式
  2. 思考:王者荣耀为什么不使用微服务架构?
  3. python常用内置模块-python常见内置模块collections
  4. 查看自己电脑可以支持的最大内存量
  5. Linux生成随机字符串
  6. @MySQL的存储引擎
  7. 短信验证码倒计时代码
  8. 系统架构师学习笔记-面向对象方法
  9. 关于数据库的设计的一点思路
  10. mint java_Oracle Java 12 (JDK 12)在Ubuntu、Linux Mint或Debian(使用PPA)安装配置
  11. Linux基础命令---检查密码文件pwck
  12. spring-session(一)揭秘续篇
  13. 如何用php代码实现人脸识别,PHP实现人脸识别技术
  14. 安信可nbiot模块_安信可wifi模组特征
  15. LCD中如何描绘点阵数据
  16. 微信公众号文章爬取方法整理
  17. 视频聊天网站的技术与发展
  18. 2015年英语专升本英语阅读「Part II 阅读专区」【文章(图片)、答案、词汇记忆】
  19. 证明:对于两个正整数a和b,为什么a/b向上取整的结果等于(a+b-1)/b向下取整的结果
  20. 基于SOCK_RAW的泛洪攻击

热门文章

  1. ML之LoRBaggingRF:依次利用LoR、Bagging、RF算法对泰坦尼克号数据集 (Kaggle经典案例)获救人员进行二分类预测(最全)
  2. AI:基于计算机视觉和语音识别案例项目打包过程记录20181226-19
  3. Django 序列化三种方式 对象 列表 元组
  4. arcgis js api proxy java 版本配置
  5. 《软件工程课程总结》
  6. 将redis作为windows服务安装
  7. applicationSettings设置和appsttings
  8. struts2+kindeditor4.0.5的上传图片的实现
  9. 三十九、Android原理 不需要关闭后台运行程序
  10. Boost------ windows 库的编译安装