在下面显示的代码中,我使用了所有记录的方法来检测异常并生成诊断.它使用C++ try/catch关键字,使用__try/__catch
扩展关键字捕获SEH异常,使用Windows的AddVectoredExceptionHandler()和SetUnhandledExceptionFilter()winapi函数来安装VEH/SEH过滤器.
使用Visual C++ 2003运行:
/GS:输出"hello,world!" 并以退出代码0终止
./ GS-:输出"hello,world!" 并以退出代码0终止.
使用Visual C++ 2013运行:
/GS:无输出,以退出代码-1073740791
/GS- 终止:输出"hello,world!" 并以0退出终止.
如何在/ GS生成的VS2013编译程序中生成诊断?
#include "stdafx.h"
#include <Windows.h>
#define CALL_FIRST 1
#define CALL_LAST 0
LONG WINAPI MyVectoredHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
UNREFERENCED_PARAMETER(ExceptionInfo);
printf("MyVectoredHandler\n");
return EXCEPTION_CONTINUE_SEARCH;
}
LONG WINAPI MyUnhandledExceptionFilter(_In_ struct _EXCEPTION_POINTERS *ExceptionInfo)
{
printf("SetUnhandledExceptionFilter\n");
return EXCEPTION_CONTINUE_SEARCH;
}
void f()
{
__try
{
char p[20] = "hello,world!";
p[24] = '!';
printf("%s\n", p);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("f() exception\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
AddVectoredExceptionHandler(CALL_FIRST, MyVectoredHandler);
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
try{
f();
}
catch (...){
printf("catched f exception\n");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
处理堆栈缓冲区溢出检测的 CRT 函数假定__report_gsfailure()
堆栈帧损坏是由恶意软件攻击引起的。此类恶意软件传统上会扰乱 fs:[0] SEH 异常过滤器(存储在堆栈帧上),以获取异常处理程序来触发恶意软件负载。将数据转化为可执行代码的方法之一。
因此 CRT 函数不能假设抛出异常是安全的。VS2013 附带的 CRT 中不再这样做,可以追溯到 ~VS2005。如果操作系统支持,它将快速失败;如果不支持,则确保注册的 VEH/SEH 异常处理程序也看不到异常。Kaboom,崩溃到桌面且没有任何诊断,除非您连接了调试器。
/SAFESEH 选项可以抵御此类恶意软件攻击,因此它不像以前那么严重。如果您仍处于代码遭受堆栈损坏错误的阶段,并且您的应用程序还不够流行,不足以成为恶意软件的目标,那么您可以考虑替换 CRT 函数。
请与您的主管讨论此事,考虑到您的客户承担的巨大责任,您永远不想为此承担个人责任。历史上很少有这样的故事:某个程序员的代码导致整个公司停业一个月。但肯定不是什么漂亮的东西。
将此代码粘贴到靠近 main() 函数的位置:
__declspec(noreturn) extern "C"
void __cdecl __report_gsfailure() {
RaiseException(STATUS_STACK_BUFFER_OVERRUN, EXCEPTION_NONCONTINUABLE, 0, nullptr);
}
Run Code Online (Sandbox Code Playgroud)
并计划很快再次将其删除。
归档时间: |
|
查看次数: |
2288 次 |
最近记录: |