Windows异常学习笔记(三)—— VEHSEH
Windows异常学习笔记(三)—— VEH&SEH
- 要点回顾
- 分析 KiUserExceptionDispatcher
- 分析 _RtlDispatchException
- _RtlCallVectoredExceptionHandlers
- VEH(向量化异常处理)
- 实验:自定义VEH
- 总结:VEH异常处理流程
- SEH(结构化异常处理)
- 分析 RtlDispatchException
- 实验:构造自定义SEH
- 总结:SEH异常处理流程
要点回顾
- 当用户异常产生后,内核函数KiDispatchException并不是像处理内核异常那样在0环直接进行处理 ,而是修正3环EIP为KiUserExceptionDispatcher函数后就结束了
- 当线程再次回到3环时,将会从KiUserExceptionDispatcher函数开始执行
分析 KiUserExceptionDispatcher
位置:ntdll.dll
分析 _RtlDispatchException
3环调用了RtlCallVectoredExceptionHandlers
0环中没有调用
_RtlCallVectoredExceptionHandlers
作用:
- 查找VEH链表(全局链表),如果有则调用
- 查找SEH链表(局部链表,在堆栈中),如果有则调用
VEH(向量化异常处理)
全称:Vectored Exception Handler
描述:全局异常链表,不同的线程共用一个
实验:自定义VEH
编译并运行以下代码
#include <stdio.h>
#include <windows.h>typedef PVOID (NTAPI *FnAddVectoredExceptionHandler)(ULONG, _EXCEPTION_POINTERS *);
FnAddVectoredExceptionHandler MyAddVectoredExceptionHandler;// VEH异常处理只能返回2个值
// EXCEPTION_CONTINUE_EXECUTION 已处理
// EXCEPTION_CONTINUE_SEARCH 未处理LONG NTAPI VectExcepHandler( PEXCEPTION_POINTERS pExcepInfo)
{// pExcepInfo->ContextRecord 保存进入异常处理前的线程信息// pExcepInfo->ExceptionRecord 保存异常信息if( pExcepInfo->ExceptionRecord->ExceptionCode == 0xC0000094 ){::MessageBoxA(NULL, "VEH除0异常触发了", "VEH异常", MB_OK);//修改完EIP之后并不是异常处理结束后直接返回,而是通过ZwContinue进行修正pExcepInfo->ContextRecord->Eip = pExcepInfo->ContextRecord->Eip+2;//pExcepInfo->ContextRecord->Ecx = 1;return EXCEPTION_CONTINUE_EXECUTION;}return EXCEPTION_CONTINUE_SEARCH;
}int main()
{//1. 动态获取AddVectoredExceptionHandler函数地址HMODULE hMyModule = GetModuleHandle("kernel32.dll");MyAddVectoredExceptionHandler = (FnAddVectoredExceptionHandler)GetProcAddress(hMyModule, "AddVectoredExceptionHandler");//2. 参数1表示插入到VEH头部,0表示插入到VEH尾部MyAddVectoredExceptionHandler(0, (_EXCEPTION_POINTERS *)&VectExcepHandler);//3. 构造除0异常__asm{xor edx, edxxor ecx, ecxmov eax, 0x10idiv ecx //EDX:EAX 除以 ECX}//4. 产生异常,从这里继续printf("代码从这里继续执行\n");return 0;
}
执行结果:
总结:VEH异常处理流程
- CPU捕获异常信息
- 通过KiDispatchException进行分发(EIP=KiUserExceptionDispatcher)
- KiUserExceptionDispatcher调用RtlDispatchException
- RtlDispatchException查找VEH处理函数链表 并调用相关处理函数
- 代码返回到KiUserExceptionDispatcher
- 调用ZwContinue再次进入0环(ZwContinue调用NtContinue,主要作用就是恢复TRAP_FRAME 然后通过KiServiceExit返回到3环)
- 线程再次返回3环后,从修正后的位置开始执行
SEH(结构化异常处理)
全称:Structured Exception Handling
描述:局部异常链表,线程相关,位于当前线程的堆栈当中,不同线程不同堆栈
注意:
- 在0环时,FS指向KPCR,在3环时,FS指向TEB,这两个结构体的第一个成员都指向NT_TIB,NT_TIB第一个成员为ExceptionList,即异常处理链表
- 在加入VEH时,只需调用系统提供的API即可,但想要构造SEH的话,必须手动在当前线程当中加入这样一个结构,在A线程中加入的SEH不会对B线程产生影响
思考:当将SEH放入堆栈当中之后,什么时候会进行调用?
答案:需要分析RtlDispatchException
分析 RtlDispatchException
EXCEPTION_DISPOSITION __cdecl MyExceptionHandler(struct _EXCEPTION_RECORD *ExceptionRecord, //存储异常信息:类型、产生位置void * EstablisherFrame, //MyException结构体地址struct _CONTEXT *ContextRecord, //结构体,异常发生时各种寄存器的值,堆栈位置等void * Dispatchercontext)
实验:构造自定义SEH
编译并运行以下代码:
#include <stdio.h>
#include <windows.h>/*
//0环异常处理时讲过这个结构体
typedef struct _EXCEPTION_REGISTRATION_RECORD
{struct _EXCEPTION_REGISTRATION_RECORD *Next;PEXCEPtiON_ROUTINE Handler;
}
*///定义时结构体名字可以不同,但必须遵守这个格式
struct MyException
{struct MyException *prev;DWORD handler;
};EXCEPTION_DISPOSITION __cdecl MyExceptionHandler(struct _EXCEPTION_RECORD *ExceptionRecord, //存储异常信息:类型、产生位置void * EstablisherFrame, //MyException结构体地址struct _CONTEXT *ContextRecord, //结构体,异常发生时各种寄存器的值,堆栈位置等void * Dispatchercontext)
{if( ExceptionRecord->ExceptionCode == 0xC0000094 ){MessageBoxA(NULL, "SEH除0异常触发了", "SEH异常", MB_OK);ContextRecord->Eip = ContextRecord->Eip+2;//pExcepInfo->ContextRecord->Ecx = 1;return ExceptionContinueExecution;}return ExceptionContinueSearch;
}void TestException()
{DWORD temp;//插入异常,必须在当前线程的堆栈当中//若定义成全局变量则无效MyException myException;__asm{mov eax, FS:[0]mov temp, eaxlea ecx, myExceptionmov FS:[0], ecx}//原来的异常链表中也许有值,因此需要挂上myException.prev = (MyException*)temp;myException.handler = (DWORD)&MyExceptionHandler;//构造除0异常__asm{xor edx, edxxor ecx, ecxmov eax, 0x10idiv ecx //EDX:EAX 除以 ECX}//处理完成,摘掉异常__asm{mov eax, tempmov FS:[0], eax}printf("函数执行完毕\n");
}int main()
{TestException(); return 0;
}
运行结果:
总结:SEH异常处理流程
- FS:[0]指向SEH链表的第一个成员
- SEH的目标结构体必须在当前线程的堆栈中
- 只有当VEH中的异常处理函数不存在或者不处理才会到SEH链表中查找
Windows异常学习笔记(三)—— VEHSEH相关推荐
- Windows异常学习笔记(五)—— 未处理异常
Windows异常学习笔记(五)-- 未处理异常 要点回顾 最后一道防线 实验一:理解最后一道防线 实验二:新线程的最后一道防线 总结 UnhandledExceptionFilter 实验三:理解U ...
- Windows异常学习笔记(四)—— 编译器扩展SEH
Windows异常学习笔记(四)-- 编译器扩展SEH 要点回顾 编译器支持的SEH 过滤表达式 实验一:理解_try_except 实验二:_try_except 嵌套 拓展SEH结构体 scope ...
- Windows异常学习笔记(一)—— CPU异常记录模拟异常记录
Windows异常学习笔记(一)-- CPU异常记录 基础知识 异常的分类 CPU异常 分析中断处理函数 _KiTrap00 分析 CommonDispatchException 总结 软件模拟异常 ...
- Windows异常学习笔记(二)—— 内核异常处理流程用户异常的分发
Windows异常学习笔记(二)-- 内核异常处理流程&用户异常分发 用户层与内核层异常 内核异常 分析 KiDispatchException 分析 RtlDispatchException ...
- Windows系统调用学习笔记(三)—— 保存现场
Windows系统调用学习笔记(三)-- 保存现场 要点回顾 基本概念 Trap Frame 结构 线程相关的结构体 ETHREAD KTHREAD CPU相关的结构体 KPCR _NT_TIB KP ...
- Windows APC学习笔记(二)—— 挂入过程执行过程
Windows APC学习笔记(二)-- 挂入过程&执行过程 基础知识 挂入过程 KeInitializeApc ApcStateIndex KiInsertQueueApc Alertabl ...
- python3常用模块_Python学习笔记三(常用模块)
Python 学习笔记三 (常用模块) 1.os模块 os模块包装了不同操作系统的通用接口,使用户在不同操作系统下,可以使用相同的函数接口,返回相同结构的结果. os.name:返回当前操作系统名称( ...
- K8S 学习笔记三 核心技术 Helm nfs prometheus grafana 高可用集群部署 容器部署流程
K8S 学习笔记三 核心技术 2.13 Helm 2.13.1 Helm 引入 2.13.2 使用 Helm 可以解决哪些问题 2.13.3 Helm 概述 2.13.4 Helm 的 3 个重要概念 ...
- Windows APC学习笔记(一)—— APC的本质备用APC队列
Windows APC学习笔记(一)-- APC的本质&备用APC队列 基础知识 APC的本质 APC队列 APC结构 分析 KiServiceExit 总结 备用APC队列 挂靠环境下Apc ...
- Windows系统调用学习笔记(四)—— 系统服务表SSDT
Windows系统调用学习笔记(四)-- 系统服务表&SSDT 要点回顾 系统服务表 实验:分析 KiSystemService 与 KiFastCallEntry 共同代码 SSDT 实验: ...
最新文章
- jQuery面试题-区别mouseover和mouseenter的不同之处(看了也许对你有好处)
- 腾讯在线人数统计_PHP + REDIS 实践:统计在线人数的几种方案分析
- 天勤数据结构:树与二叉树(图解二叉树的三种遍历方式执行流程,超详细)
- python里的shell是什么_Python与shell的3种交互方式介绍
- 浅谈编程-----非计算机专业以及非培训班的一些感悟
- python复制文件shutil_Python常用模块——文件复制模块shutil
- WIN7下怎么安装iis教程
- 卷帘快门和全局快门的区别
- 酒店如何实现上网认证的呢
- 谷歌浏览器chrome翻译插件完美解决开发者模式插件问题
- 分水岭算法 c语言实现,分水岭算法的应用
- iOS 第三方框架-Masonry的使用
- lil9341_使用Python评估Lil John的“拒绝接受什么”
- 网络上游戏制作相关学习站点的网址! 1
- OSChina 儿童节乱弹 —— 六一不能让童工加班!
- JavaScript中Date的setMonth()顺延问题及解决方法
- pandas使用goupby函数和nunique函数计算每个分组对应的多个变量的独特值的个数( unique values of each group in dataframe)
- Web小轩:第一次做淘宝主页
- 腾讯云服务器的FTP账号密码如何查看?
- 【深度学习在智能机器人中的应用】论文合集推荐丨CMU新型机器人算法可操纵所有日常家具