Windows异常学习笔记(五)—— 未处理异常
Windows异常学习笔记(五)—— 未处理异常
- 要点回顾
- 最后一道防线
- 实验一:理解最后一道防线
- 实验二:新线程的最后一道防线
- 总结
- UnhandledExceptionFilter
- 实验三:理解UnhandledExceptionFilter
- 未处理异常
要点回顾
windows异常处理流程:
CPU检测到异常
↓
查IDT表执行中断处理函数
↓
CommonDispatchException //存储异常相关信息
↓
KiDispatchException //异常分发处理函数,查找由哪一个处理程序处理这个异常//判断0环异常还是3环异常//若为3环,修正EIP,指向KiUserExceptionDispatcher(ntdll.dll)
↓
KiUserExceptionDispatcher //通过RtlDispatchException查找异常处理函数位置,VEH/SEH
↓
RtlDispatchException //先查找VEH,若找不到,查找SEH(从FS:[0]开始遍历)
↓
VEH
↓
SEH
思考:会不会存在一种情况,SEH中也没有程序能处理当前异常
答案:一般来说,不存在
最后一道防线
描述:当我们程序刚开始执行时,编译器已经替我们注册了一个异常处理程序,因此叫做最后一道防线
实验一:理解最后一道防线
1)编译并运行以下代码(在return处设置断点)
#include <stdio.h>
#include <windows.h>int main()
{int x = 1;return 0;
}
2)查看堆栈调用情况
可以发现,程序并不是从main函数开始运行的,而是从kernel32.dll的某个位置开始运行的
3)查看kernel32中的代码
4)查看7181704b位置调用的函数的具体代码
7C81704B call 7C8024D6 //在堆栈中注册了一个异常处理程序
↓
7C8024D6 push 7C839AC0h
7C8024DB mov eax,fs:[00000000] //读取了FS:[0]
7C8024E1 push eax
7C8024E2 mov eax,dword ptr [esp+10h]
7C8024E6 mov dword ptr [esp+10h],ebp
7C8024EA lea ebp,[esp+10h]
7C8024EE sub esp,eax
7C8024F0 push ebx
7C8024F1 push esi
7C8024F2 push edi
7C8024F3 mov eax,dword ptr [ebp-8]
7C8024F6 mov dword ptr [ebp-18h],esp
7C8024F9 push eax
7C8024FA mov eax,dword ptr [ebp-4]
7C8024FD mov dword ptr [ebp-4],0FFFFFFFFh
7C802504 mov dword ptr [ebp-8],eax
7C802507 lea eax,[ebp-10h]
7C80250A mov fs:[00000000],eax //修改了FS:[0]
7C802510 ret
5)使用IDA进行查看(BaseProcessStart)
6)总结:当我们程序刚开始执行时,编译器已经替我们注册了一个异常处理程序,因此在主线程中,找不到SEH的情况基本是不会发生的
思考:如果新起一个线程,会出现找不到SEH的情况吗?
答案:不会,参考实验二
实验二:新线程的最后一道防线
1)编译并运行以下代码(在新线程中设置断点)
#include <stdio.h>
#include <windows.h>DWORD WINAPI ThreadProc(LPVOID lpParam)
{int x = 1;return 0;
}int main()
{CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);getchar();return 0;
}
2)当中断在新线程中时,查看新线程堆栈调用情况
可以发现,线程也不是从我们提供的线程函数开始运行的,仍然是从kernel32.dll的某个位置开始运行的
3)查看kernel32中的代码
在地址7C80B6E3处也调用了地址7C8024D6的代码(__SEH_prolog),注册了异常处理函数
总结
- 无论是主线程,还是新创建的线程,都存在最后一道防线,即编译器为我们注册的异常处理程序的结构
- 这个异常处理程序相当于以下代码
__try {} __except(UnhandledExceptionFilter(GetExceptionInformation()) {//终止线程//终止进程 }
UnhandledExceptionFilter
描述:
- 最后一道防线调用的异常处理程序的过滤函数
- 只有当它的返回值为EXCEPTION_CONTINUE_SEARCH(0)时,当前线程不存在对应的SEH
- 只有在当前程序处于调试状态时,才会发生上述情况
执行流程:
- 通过NtQueryInformationProcess查询当前进程是否正在被调试,如果是,返回EXCEPTION_CONTINUE_SEARCH,此时会进入第二轮分发
- 如果没有被调试:
1)查询是否通过SetUnhandledExceptionFilter注册处理函数 如果有就调用
2)如果没有通过SetUnhandledExceptionFilter注册处理函数,弹出窗口,让用户选择终止程序还是启动即时调试器
3)如果用户没有启用即时调试器,那么该函数返回EXCEPTION_EXECUTE_HANDLER,此时会执行except中的代码
实验三:理解UnhandledExceptionFilter
1)编译并运行以下代码
#include <stdio.h>
#include <windows.h>long __stdcall callback(_EXCEPTION_POINTERS *excp)
{excp->ContextRecord->Ecx = 1;return EXCEPTION_CONTINUE_EXECUTION;
}int main()
{SetUnhandledExceptionFilter(callback);__asm{xor edx, edxxor ecx, ecxmov eax, 0x10idiv ecx}printf("程序正常执行\n");getchar();return 0;
}
2)执行结果
3)双击exe执行,执行结果
4)总结
- 当程序处于调试状态时,UnhandledExceptionFilter返回EXCEPTION_CONTINUE_SEARCH,此时该异常没有SEH能够进行处理,程序无法向下运行
- 当程序不处于调试状态时,UnhandledExceptionFilter返回EXCEPTION_EXECUTE_HANDLER,异常由注册的callback函数进行处理
思考:遇到这种情况如何进行调试
答案:HOOK NtQueryInformationProcess
未处理异常
执行流程:
KiUserExceptionDispatcher
↓
RtlDispatchException //查找并执行异常处理函数//如果返回真,调用ZwContinue再次进入0环//但线程再次返回3环时,会从修正后的位置开始执行//如果返回假,调用ZwRaiseException进行第二轮异常分发//(参见KiUserExceptionDispatcher代码)
Windows异常学习笔记(五)—— 未处理异常相关推荐
- Windows异常学习笔记(四)—— 编译器扩展SEH
Windows异常学习笔记(四)-- 编译器扩展SEH 要点回顾 编译器支持的SEH 过滤表达式 实验一:理解_try_except 实验二:_try_except 嵌套 拓展SEH结构体 scope ...
- Windows异常学习笔记(一)—— CPU异常记录模拟异常记录
Windows异常学习笔记(一)-- CPU异常记录 基础知识 异常的分类 CPU异常 分析中断处理函数 _KiTrap00 分析 CommonDispatchException 总结 软件模拟异常 ...
- Windows异常学习笔记(二)—— 内核异常处理流程用户异常的分发
Windows异常学习笔记(二)-- 内核异常处理流程&用户异常分发 用户层与内核层异常 内核异常 分析 KiDispatchException 分析 RtlDispatchException ...
- 软件调试学习笔记(四)—— 异常的处理流程
软件调试学习笔记(四)-- 异常的处理流程 要点回顾 异常的处理流程 实验1:理解调试器与异常的关系 未处理异常:最后一道防线 实验2:理解UnhandledExceptionFilter执行流程 实 ...
- Windows APC学习笔记(二)—— 挂入过程执行过程
Windows APC学习笔记(二)-- 挂入过程&执行过程 基础知识 挂入过程 KeInitializeApc ApcStateIndex KiInsertQueueApc Alertabl ...
- Windows系统调用学习笔记(三)—— 保存现场
Windows系统调用学习笔记(三)-- 保存现场 要点回顾 基本概念 Trap Frame 结构 线程相关的结构体 ETHREAD KTHREAD CPU相关的结构体 KPCR _NT_TIB KP ...
- Windows APC学习笔记(一)—— APC的本质备用APC队列
Windows APC学习笔记(一)-- APC的本质&备用APC队列 基础知识 APC的本质 APC队列 APC结构 分析 KiServiceExit 总结 备用APC队列 挂靠环境下Apc ...
- 【AngularJs学习笔记五】AngularJS从构建项目开始
为什么80%的码农都做不了架构师?>>> #0 系列目录# AngularJs学习笔记 [AngularJs学习笔记一]Bower解决js的依赖管理 [AngularJs学习笔 ...
- Windows系统调用学习笔记(四)—— 系统服务表SSDT
Windows系统调用学习笔记(四)-- 系统服务表&SSDT 要点回顾 系统服务表 实验:分析 KiSystemService 与 KiFastCallEntry 共同代码 SSDT 实验: ...
最新文章
- OSPF-网络类型(ip ospf network ?)
- pip3 install numpy
- 二.Python的基础语法知识
- java增加 删除 修改表格_Java实现单链表的创建、添加、修改、删除
- 【数据挖掘】基于密度的聚类方法 - OPTICS 方法 ( 核心距离 | 可达距离 | 族序 )
- python摄像头跟随人脸_opencv-python 学习笔记2:实现目光跟随(又叫人脸跟随)
- c++11 function
- 流媒体管理服务器显示不可用,部署国标流媒体服务器成功后无法播放视频问题步骤排查...
- 如何利用python监控主机存活并邮件、短信通知
- Redis 雪崩和击穿
- excel两列数据对比找不同_快速找出Excel表格中两列数据不同内容的3种方法!
- 研究调查脉搏血氧饱和度仪使用Masimo RRp(R)读取儿科患者呼吸率的精度
- html编辑器有哪些
- NOIP 2015 D1 T2 信息传递
- C++ 线程里面延时1秒的技巧
- LIMS实验室系统建设如何提高检验效率?
- threejs加载3D模型
- 小旋风360推送工具
- linux 2g内存 64系统怎么样,电脑2g内存能装64位系统吗|2g内存装64位系统好不好
- ubantu-20.04.3安装OTRS
热门文章
- AI:2020年6月23日北京智源大会演讲分享之智能信息检索与挖掘专题论坛——09:55-10:40刘兵教授《Open-World AI and Continual Learning》
- Postman:Postman(HTTP的测试工具)使用方法详细攻略
- 成功解决Exception unhandled OSError cannot open resource File: F:\Program Files\Python\Python36\Lib\si
- Py之smtplib:smtplib(aiosmtplib)的简介、安装、使用方法之详细攻略
- Java:Java编程实现导出二维码
- sql 获取本周周一和周日
- ionic 完美仿微信摇一摇
- Silverlight中服务通信方式的选择(WCF、Data Service、Ria Service)
- 一些.net持久化框架的例子
- STM32F103之FLASH组织