异常


未处理异常

在之前学习windows异常处理机制时,windows通过VEH和SEH来处理0环和3环的异常,但如果一个程序没有异常抛出或者,没有处理异常的函数那会怎么样呢?

测试代码

#include<iostream>

int main() {
	int i = 5;
	return 0;
}

查看反汇编代码

在这里插入图片描述

我们可以看下调用堆栈,可以发现我们的main函数并不是一开始就执行的,而是由其他函数来调用的

ntdll.dll!7797d2fb() // 定位到这个位置的调用

看下这里面的第一个CALl做了什么

`

可以很明显的看到有修改堆栈中FS:[0]位置的代码(挂异常练链表)

在这里插入图片描述

看到这里就明白了,即使我们不去创建异常处理函数,在调用时编译器也会为我们创建一个

同理:在主函数中会为我们创建一个SEH,在线程当中也会为我们创建一个SEH,所以无论是进程也好,线程也好,都会有一个默认的SEH

只有程序被调试时,才会存在未处理异常

UnhandledExceptionFilter的执行流程:

  1. 通过NtQueryInformationProcess查询当前进程是否正在被调试,如果是,返回EXCEPTION_CONTINUE_SEARCH,此时会进入第二轮分发
  2. 如果没有被调式:
    • 查询是否通过SetUnhandledExceptionFilter注册处理函数,如果有就调用
    • 如果没有通过SetUnhandledExceptionFilter注册处理函数,弹出窗口让用户选择终止程序还是启动即时调试器
    • 如果用户没有启用即时调试器,那么该函数返回EXCEPTION_EXCUTE_HANDLER

代码测试

#include<iostream>
#include<windows.h>

LONG __stdcall callBack(EXCEPTION_POINTERS* pExp) {
	pExp->ContextRecord->Ecx = 1;
	return EXCEPTION_CONTINUE_EXECUTION; // 从出错的地方继续执行
}

int main() {
	SetUnhandledExceptionFilter(callBack);

	_asm {
		xor edx,edx
		xor ecx,ecx
		mov eax,0x10
		idiv ecx		// 除0异常
	}

	printf("程序正常执行\n");
	system("pause");
	return 0;
}

直接运行exe程序

在这里插入图片描述
在Visual Studio调试模式下启动

在这里插入图片描述

  • 当程序没有处于调式状态下时,我们SetUnhandledExceptionFilter注册的函数就有机会执行并修改Ecx的值,程序正常执行
  • 当程序处于调式状态下时,SetUnhandledExceptionFilter注册的函数将不会执行,程序发生错误终止进程

KiUserExceptionDispatcher函数分析

  1. 调用RtlDispatchException查找并执行异常处理函数
  2. 如果RtlDispatchException返回真,调用ZwContinue再次进入0环,但线程再次返回3环时,会从修正后的位置开始执行
  3. 如果RtlDispatchException返回假,调用ZwRaiseException进行第二轮异常分发
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐