Visual Studio 2013如何检测缓冲区溢出 [英] How does Visual Studio 2013 detect buffer overrun

查看:2191
本文介绍了Visual Studio 2013如何检测缓冲区溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Visual Studio 2013 C ++项目具有 / GS 切换,可在运行时启用缓冲区安全检查验证。我们在升级到VS 2013后遇到更多STATUS_STACK_BUFFER_OVERRUN错误,并怀疑它与新编译器中缓冲区溢出的改进检查有关。我一直在试图验证这一点,并更好地了解如何检测缓冲区溢出。我感到困惑的事实,缓冲区溢出报告,即使内存更新的语句只更改在同一范围内的堆栈上的另一个局部变量的内容!因此,它必须检查不仅是更改不会损坏内存不是由一个局部变量拥有,而是该变化不影响任何局部变量,而不是分配给由单个更新语句引用的。这个怎么用?

Visual Studio 2013 C++ projects have a /GS switch to enable buffer security check validation at runtime. We are encountering many more STATUS_STACK_BUFFER_OVERRUN errors since upgrading to VS 2013, and suspect it has something to do with improved checking of buffer overrun in the new compiler. I've been trying to verify this and better understand how buffer overrun is detected. I'm befuddled by the fact that buffer overrun is reported even when the memory updated by a statement only changes the contents of another local variable on the stack in the same scope! So it must be checking not only that the change doesn't corrupt memory not "owned" by a local variable, but that the change doesn't affect any local variable other than that allocated to the one referenced by the individual update statement. How does this work? Has it changed since VS 2010?

编辑:
这里是一个例子,说明Mysticial的解释不包括: / p>

Here's an example illustrating a case that Mysticial's explanation doesn't cover:

void TestFunc1();

int _tmain(int argc, _TCHAR* argv[])
{
   TestFunc1();
   return 0;
}

void TestFunc1()
{
   char buffer1[4] = ("123");
   char buffer2[4] = ("456");
   int diff = buffer1 - buffer2;
   printf("%d\n", diff);
   getchar();
   buffer2[4] = '\0';
}

输出 4 表示要被覆盖的内存在 buffer1 (紧接在 buffer2 之后)的范围内,程序以缓冲区溢出终止。技术上,它应该被认为是一个缓冲区溢出,但我不知道如何被检测,因为它仍然在局部变量的存储,而不是真正破坏任何外部局部变量。

The output is 4 indicating that the memory about to be overwritten is within the bounds of buffer1 (immediately after buffer2), but then the program terminates with a buffer overrun. Technically it should be considered a buffer overrun, but I don't know how it's being detected since it's still within the local variables' storage and not really corrupting anything outside local variables.

这个屏幕截图与内存布局证明了它。步进一行后,程序由于缓冲区溢出错误而中止。

This screenshot with memory layout proves it. After stepping one line the program aborted with the buffer overrun error.

我在VS 2010中尝试过相同的代码,虽然调试模式捕获了缓冲区溢出缓冲区偏移为12),在释放模式下,它捕获它(缓冲区偏移为8)。所以我认为VS 2013收紧了 / GS 开关的行为。

I just tried the same code in VS 2010, and although debug mode caught the buffer overrun (with a buffer offset of 12), in release mode it did not catch it (with a buffer offset of 8). So I think VS 2013 tightened the behavior of the /GS switch.

编辑2: strong>
我设法通过这个代码偷偷过去甚至VS 2013范围检查。它仍然没有检测到尝试更新一个局部变量实际上更新了另一个:

Edit 2: I managed to sneak past even VS 2013 range checking with this code. It still did not detect that an attempt to update one local variable actually updated another:

void TestFunc()
{
   char buffer1[4] = "123";
   char buffer2[4] = "456";
   int diff;
   if (buffer1 < buffer2)
   {
      puts("Sequence 1,2");
      diff = buffer2 - buffer1;
   }
   else
   {
      puts("Sequence 2,1");
      diff = buffer1 - buffer2;
   }

   printf("Offset: %d\n", diff);
   switch (getchar())
   {
   case '1':
      puts("Updating buffer 1");
      buffer1[diff] = '!';
      break;
   case '2':
      puts("Updating buffer 2");
      buffer2[diff] = '!';
      break;
   }
   getchar(); // Eat enter keypress
   printf("%s,%s\n", buffer1, buffer2);
}


推荐答案

/ GS机制,首先添加到VS2012。最初/ GS可以检测缓冲区溢出,但仍然有一个漏洞,攻击代码可以闯入堆栈,但绕过cookie。大致如下:

You are seeing an improvement to the /GS mechanism, first added to VS2012. Originally /GS could detect buffer overflows but there's still a loop-hole where attacking code can stomp the stack but bypass the cookie. Roughly like this:

void foo(int index, char value) {
   char buf[256];
   buf[index] = value;
}

如果攻击者可以操纵那么cookie没有帮助。此代码现在重写为:

If the attacker can manipulate the value of index then the cookie doesn't help. This code is now rewritten to:

void foo(int index, char value) {
   char buf[256];
   buf[index] = value;
   if (index >= 256) __report_rangefailure();
}

只是简单的索引检查。其中,触发后,如果没有连接调试器,则使用__fastfail()立即终止应用程序。背景这里

Just plain index checking. Which, when triggered, instantly terminates the app with __fastfail() if no debugger is attached. Backgrounder is here.

这篇关于Visual Studio 2013如何检测缓冲区溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆