当前位置: 首页 > news >正文

Windows SEH异常处理讨论

Windows C++程序异常的类型

在Windows C++异常的场景中,我们需要理解以下两种类型的异常:

  1. C++语言抛出的异常。
    • 这是利用C++ throw抛出的exception,利用C++ try-catch即可捕获。
    • 即便是来自于另一个DLL的C++ exception,仍然能利用C++ try-catch捕获。
  2. 访问操作系统受保护内存导致的异常。
    • 利用Windows API函数SetUnhandledExceptionFilter()可捕获。
    • 利用C++ try-catch无法捕获。

试验与分析

C++语言抛出的异常

即用C++ throw关键字抛出的C++ exception,则利用C++ try-catch即能捕获。已用如下样例代码证明:

// This is the main program, which links to DLL1
// main.cpp#include <iostream>int main()
{try{ThrowCppException();}catch (std::exception& e){std::cout << e.what() << "\n";}std::cout << "Program finished normally\n";return 0;
}
// DLL1, this is a Dynamic Link Library(DLL)
// DLLTest.h
#pragma once
#if defined(DLL1_EXPORTS)
#define DLL1_SYMBOL_EXPORT __declspec(dllexport)
#else
#define DLL1_SYMBOL_EXPORT __declspec(dllimport)
#endif DLL1_SYMBOL_EXPORT void ThrowCppException();
// DLL1, this is a Dynamic Link Library(DLL)
// DLLTest.cpp
#include "DLLTest.h"
#include <exception>void ThrowCppException()
{throw std::exception("This is an C++ exception");
}

输出如下:

This is an C++ exception
Program finished normally...\ConsoleApplication2\x64\Debug\ConsoleApplication2.exe (process 52160) exited with code 0.
Press any key to close this window . . . 

程序可以对C++异常进行处理,然后再继续正常地运行,或者正常地退出。

内存访问异常

首先,我们来证明,这类异常是无法通过C++ try-catch捕获的。已用如下样例代码证明:

// This is the main program, which links to DLL1
// main.cpp#include <iostream>int main()
{try{WriteOSProtectedMemory();}catch (std::exception& e){std::cout << e.what() << "\n";}std::cout << "Program finished normally\n";return 0;
}
// DLL1, this is a Dynamic Link Library(DLL)
// DLLTest.h
#pragma once
#if defined(DLL1_EXPORTS)
#define DLL1_SYMBOL_EXPORT __declspec(dllexport)
#else
#define DLL1_SYMBOL_EXPORT __declspec(dllimport)
#endif DLL1_SYMBOL_EXPORT void ThrowCppException();
// DLL1, this is a Dynamic Link Library(DLL)
// DLLTest.cpp
#include "DLLTest.h"
#include <exception>void ThrowCppException()
{throw std::exception("This is an C++ exception");
}

输出如下:

...\ConsoleApplication2\x64\Debug\ConsoleApplication2.exe (process 39044) exited with code -1073741819.
Press any key to close this window . . .

程序直接退出了,没有输出"Program finished normally"。另外,输出"exited with code -1073741819",意味着程序不是正常地结束。

应用层捕获DLL层的内存访问异常

应用层利用Windows API函数SetUnhandledExceptionFilter(),可对DLL层触发的内存访问异常进行捕获。已用以下样例代码证明:

#include "DLLTest.h"#include <iostream>
#include <Windows.h>// 试图在App层面捕获全部OS Exception
LONG NTAPI OSExceptionHandlerInApp(EXCEPTION_POINTERS* pExcepInfo)
{// Do something, for example save the data to local diskstd::cout << "OSExceptionHandlerInApp: SEH handler in App caught unhandled exception\n";std::cout << "Program could not finish normally\n";return EXCEPTION_EXECUTE_HANDLER;
}int main()
{SetUnhandledExceptionFilter(OSExceptionHandlerInApp);WriteOSProtectedMemory();std::cout << "Program finished normally\n";return 0;
}
// DLL1, this is a Dynamic Link Library(DLL)
// DLLTest.h
#pragma once#if defined(DLL1_EXPORTS)
#define DLL1_SYMBOL_EXPORT __declspec(dllexport)
#else
#define DLL1_SYMBOL_EXPORT __declspec(dllimport)
#endifDLL1_SYMBOL_EXPORT void WriteOSProtectedMemory();
// DLL1, this is a Dynamic Link Library(DLL)
// DLLTest.cpp
#include "DLLTest.h"void WriteOSProtectedMemory()
{char* p = (char*)0x0000000000000078;*p = 32;
}

输出如下:

OSExceptionHandlerInApp: SEH handler in App caught unhandled exception
Program could not finish normally...\ConsoleApplication2\x64\Debug\ConsoleApplication2.exe (process 38176) exited with code -1073741819.
Press any key to close this window . . . 

可以看出,应用层利用ExceptionHander捕获了DLL触发的内存异常,然后程序退出。

DLL层调用SetUnhandledExceptionFilter()导致应用层无法捕获内存异常

如果DLL层调用了SetUnhandledExceptionFilter(),则导致应用层调用SetUnhandledExceptionFilter()无效。实际上,是DLL层把应用层注册的ExceptionFilter改写了。已用以下样例代码证明:

#include "DLLTest.h"#include <iostream>
#include <Windows.h>// 试图在App层面捕获全部OS Exception
LONG NTAPI OSExceptionHandlerInApp(EXCEPTION_POINTERS* pExcepInfo)
{// Do something, for example save the data to local diskstd::cout << "OSExceptionHandlerInApp: SEH handler in App caught unhandled exception\n";std::cout << "Program could not finish normally\n";return EXCEPTION_EXECUTE_HANDLER;
}int main()
{SetUnhandledExceptionFilter(OSExceptionHandlerInApp);OverwriteOSExceptionHander();WriteOSProtectedMemory();std::cout << "Program finished normally\n";
}
// DLL1, this is a Dynamic Link Library(DLL)
// DLLTest.h
#pragma once#if defined(DLL1_EXPORTS)
#define DLL1_SYMBOL_EXPORT __declspec(dllexport)
#else
#define DLL1_SYMBOL_EXPORT __declspec(dllimport)
#endifDLL1_SYMBOL_EXPORT void WriteOSProtectedMemory();
// DLL1, this is a Dynamic Link Library(DLL)
// DLLTest.cpp
#include "DLLTest.h"
#include <iostream>
#include <Windows.h>void WriteOSProtectedMemory()
{char* p = (char*)0x0000000000000078;*p = 32;
}// 在DLL中截获OS Exception
LONG NTAPI OSExceptionHandlerInDLL(EXCEPTION_POINTERS* pExcepInfo)
{std::cout << "OSExceptionHandlerInDLL: SEH handler in DLL caught unhandled exception\n";return EXCEPTION_EXECUTE_HANDLER;
}void OverwriteOSExceptionHander()
{SetUnhandledExceptionFilter(OSExceptionHandlerInDLL);
}

输出如下:

OSExceptionHandlerInDLL: SEH handler in DLL caught unhandled exception...\ConsoleApplication2\x64\Debug\ConsoleApplication2.exe (process 20108) exited with code -1073741819.
Press any key to close this window . . .

可以看出,应用层已经无法利用ExceptionHander捕获DLL触发的内存异常,直接退出。


http://www.mrgr.cn/news/63434.html

相关文章:

  • 2008-2019年各省城镇人口数据
  • BurpSuite之FUZZ模糊测试
  • 51c~Pytorch~合集5
  • IoTDB 常见问题 QA 第三期
  • 【深度学习】数据预处理
  • Objective-C语言的软件工程
  • Tile38命令-【Keys】
  • 卡尔曼滤波-应用白话
  • 在JAVA中使用Paho MQTT客户端
  • ArkTS基础
  • Excel函数学习记录
  • Matlab中国三大自然分区
  • 智慧园区有哪些优势
  • Java解析word中的表格或者文本
  • 揭秘云计算 | 1、云从哪里来?
  • Redis(2):内存模型
  • 物联网设备如何助力实现高效远程老人监护
  • batc和mini-batch
  • Java面试题十五
  • 基于springboot的Java学习论坛平台
  • prometheus 快速入门
  • python enum用法
  • opencv - py_imgproc - py_grabcut GrabCut 算法提取前景
  • JavaScript 实战技巧:让你成为前端高手的必备知识3(进阶版)
  • 【环境问题】pycharm远程服务器文件路径问题
  • 【前端】项目中遇到的问题汇总(长期更新)