STATUS_STACK_BUFFER_OVERRUN不一定是栈缓冲区溢出
STATUS_STACK_BUFFER_OVERRUN异常一般是指栈缓冲区溢出的溢出,代码为0xC0000409,消息提示一般为“Security check failure or stack buffer overrun”。微软给出的解释如下:系统在应用程序中检测到基于堆栈的缓冲区溢出。此溢出可能允许恶意用户获得此应用程序的控制权。/GS编译器开关允许创建堆栈“cookie”值,该值用作检测堆栈缓冲区溢出的金丝雀。如果cookie已损坏,则进程会立即终止自身,状态代码为STATUS_STACK_BUFFER_OVERRUN。
在做如上描述的时后,STATUS_STACK_BUFFER_OVERRUN是一个好名字。但是,随着时间的推移,随着我们遇到和处理问题越来越多,我们会发现其他立即终止进程的原因。其中一些与安全有关其他的没有。比如在遇到更糟糕的情况下希望在进程终止前立即停止,用fail fast这个词是用来形容这种情况的就非常好。甚至还有一个编译器内部函数来终止使用这个特殊状态代码的当前进程。
似乎人们无法就是fail fast还是fast fail达成一致,所以在实践中,你可以看到这两种变化。这意味着现在当你得到一个STATUS_STACK_BUFFER_OVERRUN时,实际上并不意味着存在堆栈缓冲区溢出。这只意味着应用程序决定以极快的速度自行终止。
如果你查看winnt.h文件,您将看到各种快速失败代码的列表。这些代码指示发生了哪种类型的快速故障。
#define FAST_FAIL_LEGACY_GS_VIOLATION 0 #define FAST_FAIL_VTGUARD_CHECK_FAILURE 1 #define FAST_FAIL_STACK_COOKIE_CHECK_FAILURE 2 #define FAST_FAIL_CORRUPT_LIST_ENTRY 3 #define FAST_FAIL_INCORRECT_STACK 4 #define FAST_FAIL_INVALID_ARG 5 #define FAST_FAIL_GS_COOKIE_INIT 6 #define FAST_FAIL_FATAL_APP_EXIT 7
从上面的列表中,有点意思的是FAST_FAIL_FATAL_APP_退出代码。此代码在调用C运行时函数abort()时使用。 std::terminate()调用abort()。对于从noexcept函数中抛出异常或抛出的异常未经处理的情况,将自动调用std::terminate()。当一个内部断言失败时,或者当一个错误发生并且程序只是想放弃而不是试图恢复时,它也被一些模块使用。这些不一定是安全问题。只是程序说,“嗯,我有麻烦了。我想我就在这里停一下。”
这样的情况,我最近就遇到一次,具体表现时进程退出时崩溃了,报的错误就是STATUS_STACK_BUFFER_OVERRUN。
0:000> .exr -1
ExceptionAddress: 528a7666 (msvcr120!abort+0x00000028)
ExceptionCode: c0000409 (Security check failure or stack buffer overrun)
ExceptionFlags: 00000001
NumberParameters: 1
Parameter[0]: 00000007
Subcode: 0x7 FAST_FAIL_FATAL_APP_EXIT
具体参考《记一次在父类析构里调用纯虚函数而引发的异常 》
ExceptionAddress: 528a7666 (msvcr120!abort+0x00000028)
ExceptionCode: c0000409 (Security check failure or stack buffer overrun)
ExceptionFlags: 00000001
NumberParameters: 1
Parameter[0]: 00000007
Subcode: 0x7 FAST_FAIL_FATAL_APP_EXIT
具体参考《记一次在父类析构里调用纯虚函数而引发的异常 》
为虫子生,为虫子死,为虫子奋斗一辈子