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

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 disk

    std::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)
#endif

DLL1_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 disk

    std::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)
#endif

DLL1_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.kler.cn/a/379996.html

相关文章:

  • 使用 SSH 蜜罐提升安全性和记录攻击活动
  • 这款Chrome 插件,帮助我们复制网页上不能复制的内容
  • Hugging Face魔塔使用
  • 微服务系列二:跨微服务请求优化,注册中心+OpenFeign
  • leetcode71:简化路径
  • 面试题:JVM(二)
  • 【软考】反规范化技术
  • 代码训练营 day55|卡码网98
  • Jenkins找不到maven构建项目
  • H7-TOOL的CAN/CANFD助手增加帧发送成功标识支持, 继续加强完善功能细节
  • 【GESP】C++一级真题练习(202303)luogu-B3835,每月天数
  • 基于 Transformer 的语言模型
  • 【BUG分析】clickhouse表final成功,但存在数据未合并
  • 十四届蓝桥杯STEMA考试Python真题试卷第二套第一题
  • 贝尔不等式的验证
  • Es 基础操作 增删改查
  • 一些常用的react hooks以及各自的作用
  • 【漏洞复现】泛微OA E-Office group_xml.php SQL注入漏洞
  • Vue项目与IE浏览器的兼容性分析(Vue|ElementUI)
  • Web大学生网页作业成品——和平精英网页设计与实现(HTML+CSS+JS)(4个页面)
  • MATLAB——矩阵操作
  • CSS基础学习篇——选择器
  • ThreeJS创建一个3D物体的基本流程
  • Github 2024-11-01 开源项目月报 Top19
  • 信息学科平台开发:Spring Boot核心技巧与实践
  • 银行金融知识竞赛活动策划方案