如何获取有关混合应用程序中缓冲区溢出异常的信息

本文关键字:缓冲区 应用程序 溢出 异常 信息 混合 何获取 获取 | 更新日期: 2023-09-27 18:19:56

在我开发的所有WPF应用程序中,都有一个订阅AppDomain.CurrentDomain.UnhandledException的全局异常处理程序,它记录了它能找到的所有内容,然后显示一个对话框,告诉用户联系作者,日志文件的位置等。这非常有效,客户和我都对此非常满意,因为它可以快速解决问题。

但是,在开发混合 WPF/C#/CLI/C++ 应用程序的过程中,有时会发生应用程序崩溃,无法进入上述异常处理程序。相反,会弹出一个标准的窗口对话框,指出"XXX 已停止工作"。在细节中,它显示例如

 Problem Event Name: BEX
 Application Name:   XXX.exe
 Fault Module Name:  clr.dll
 ...

这主要发生在从非托管代码中回调托管函数以及该函数更新屏幕时。我没有花很长时间找出问题的根本原因,但只是因为我可以在我的机器上重现崩溃并挂接调试器:在所有情况下,本机线程仍然处于调用函数指针的位置,该指针指向直接调用 C#/WPF 代码的托管委托。

真正的问题是当这种情况发生在客户端计算机上时:鉴于通常客户端不是最好的错误报告,当他们只能向我提供上述详细信息时,可能需要非常非常长的时间才能弄清楚出了什么问题。

问题:我该怎么做才能获得此类崩溃的更多信息?无论如何,有没有办法获得像这样调用自定义错误处理程序的异常?还是获取进程转储?加载 msvcr100_clr0004.dll 和 clr.dll 的符号(加载到发生中断的线程上(时,调用堆栈如下所示:

msvcr100_clr0400.dll!__crt_debugger_hook()  
clr.dll!___report_gsfailure()  + 0xeb bytes 
clr.dll!_DoJITFailFast@0()  + 0x8 bytes 
clr.dll!CrawlFrame::CheckGSCookies()  + 0x2c3b72 bytes  

我可以以某种方式将一些本机C++代码挂接到 __crt_debugger_hook(((( 中(例如用于编写小型转储(吗?这让我想到了一个额外的问题:CheckGSCookies在没有安装调试器的机器上如何表现,它是否仍会调用相同的代码?

更新对代码的一些说明:本机C++调用 CLI 委托(使用GetFunctionPointerForDelegate获取本机函数指针,而 CLI 委托又调用 C# System.Action。此操作将更新字符串(绑定到 WPF 标签(并引发属性更改事件。这以某种方式在未命名线程中调用缓冲区溢出(更新速度非常快时(,该线程不是直接在我的代码中创建的。

更新查看SetUnhandledExceptionFilter,起初它没有做任何事情,我发现这篇漂亮的文章解释了如何捕获任何异常。它可以工作,并且我能够在使用该过程安装的异常筛选器中编写小型转储。转储提供的信息与挂钩调试器基本相同:真正的问题似乎是 Status 字符串被覆盖(通过从本机线程调用(,同时从 ui 线程读取。一切都很好,但它确实需要 dll 钩子,这不是我最喜欢的解决问题的方法。另一种方式仍然很好。

如何获取有关混合应用程序中缓冲区溢出异常的信息

.NET 4 版本的 CLR 具有针对缓冲区溢出攻击的保护。 基本方案是代码在数组或堆栈帧的末尾写入一个"cookie",然后稍后检查该 cookie 是否仍然具有原始值。 如果它已更改,运行时会假定恶意软件已破坏程序状态并立即中止程序。 这种中止不会通过通常的未处理异常机制,这将太容易被利用。

当然,您的程序真正受到攻击的可能性很小。 更有可能的是,您的本机代码存在指针错误,并将垃圾涂鸦到CLR结构或堆栈帧中。 调试并不容易,损坏通常在崩溃之前就已经完成。 一种方法是注释掉代码,直到崩溃消失。