如何在Windows上报告堆栈缓冲区溢出?

liu*_*ifu 8 c++ exception

在下面显示的代码中,我使用了所有记录的方法来检测异常并生成诊断.它使用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)

Han*_*ant 6

处理堆栈缓冲区溢出检测的 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)

并计划很快再次将其删除。