sti*_*ijn 5 c# c++ wpf c++-cli buffer-overflow
在我开发的所有WPF应用程序中,都有一个订阅的全局异常处理程序AppDomain.CurrentDomain.UnhandledException
记录它可以找到的所有内容,然后显示一个对话框,告诉用户联系作者,日志文件在哪里等.这非常有效,客户和我对它非常满意,因为它可以快速解决问题.
但是,在开发混合的WPF/C#/ CLI/C++应用程序期间,有时应用程序崩溃无法进入上述异常处理程序.而是弹出一个标准的Windows对话框,说"XXX已停止工作".在细节中它显示了例如
Problem Event Name: BEX
Application Name: XXX.exe
Fault Module Name: clr.dll
...
Run Code Online (Sandbox Code Playgroud)
这主要发生在从非托管代码中回调托管函数时,以及该函数更新屏幕时.我没有花很长时间来找出问题的根本原因,但只是因为我可以在我的机器上重现崩溃并连接调试器:在所有情况下,本机线程仍然在调用函数指针的时候直接调用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
Run Code Online (Sandbox Code Playgroud)
我可以以某种方式将一些本机C++代码挂钩到__crt_debugger_hook()(例如,用于编写minidump)吗?这引出了一个额外的问题:如何CheckGSCookies
在没有安装调试器的机器上运行,它是否仍会调用相同的代码?
更新一些关于代码的说明:本机C++调用CLI委托(获取本机函数指针,使用GetFunctionPointerForDelegate
该委托调用C#System.Action.此Action更新字符串(绑定到WPF标签)并引发propertychanged事件这在某个未在我的代码中直接创建的未命名线程中以某种方式调用缓冲区溢出(在更新时非常快).
更新调查SetUnhandledExceptionFilter
,一开始没有做任何事情,我发现这篇漂亮的文章解释了如何捕获任何异常.它工作正常,我能够在使用该过程安装的异常过滤器中编写一个minidump.转储提供与挂钩调试器基本相同的信息:真正的问题似乎是在从ui线程读取的同时覆盖了Status字符串(通过从本机线程调用).所有这些都很好,但它确实需要dll挂钩,这不是我最喜欢的解决方法.另一种方式仍然很好.
.NET 4 版本的 CLR 可以防止缓冲区溢出攻击。基本方案是代码在数组或堆栈帧的末尾写入一个“cookie”,然后稍后检查该 cookie 是否仍然具有原始值。如果它发生了变化,运行时会假设恶意软件破坏了程序状态并立即中止程序。这种中止不经过通常的未处理异常机制,那太容易被利用了。
当然,您的程序真正受到攻击的可能性很小。更有可能的是,您的本机代码存在指针错误,并且将垃圾乱写到 CLR 结构或堆栈帧中。调试并不容易,损坏通常在崩溃之前完成。一种方法是注释掉代码,直到崩溃消失。