{
char bufBef[32];
char buf[8];
char bufAfter[32];
sprintf(buf,"AAAAAAA
{
char bufBef[32];
char buf[8];
char bufAfter[32];
sprintf(buf,"AAAAAAA\0");
buf[8]='\0';
printf("%s\n",buf);
}
On Windows 7, I compiled the program with Visual Studio 2008 as debug project. 3 buffers are adjacent. I find their addresses with a debugger, as followed:
在Windows 7上,我使用Visual Studio 2008作为调试项目编译了这个程序。3相邻缓冲区。我通过调试器找到了他们的地址:
bufBef 0x001afa50
buf 0x001afa40
bufAfter 0x001afa18
The statement "buf[8]='\0'" writes the address out of buf. When I run the program, Operation System reported " Debug Error: Run-Time Check Failure #2 - Stack around the variable 'buf' was corrupted."
语句“buf[8]='\0'”从buf中写入地址。当我运行程序时,操作系统报告“调试错误:运行时检查失败#2 -变量‘buf’周围的堆栈被损坏。”
Then I compiled it as a release project. It run quietly, no error report raised.
然后我将它编译为一个发布项目。它运行平稳,没有出现错误报告。
My question is how run-time detect buffer overflow?
我的问题是运行时如何检测缓冲区溢出?
10 个解决方案
#1
3
What you see if the effect of the /RTCs switch.
如果/RTCs切换的效果。
John Robbins' book Debugging Applications for Microsoft .NET and Microsoft Windows talks about this in depth.
约翰·罗宾斯(John Robbins)在《微软。net和微软Windows的调试应用程序》(debug Applications for Microsoft . net)一书中对此进行了深入探讨。
Relevant excerpt:
相关摘录:
Fortunately for us, Microsoft extended the /RTCs switch to also do overrun and underrun checking of all multibyte local variables such as arrays. It does this by adding four bytes to the front and end of those arrays and checking them at the end of the function to ensure those extra bytes are still set to 0xCC.
对我们来说幸运的是,Microsoft扩展了/RTCs开关,同时对所有多字节本地变量(如数组)进行了溢出和欠运行检查。它通过在这些数组的前面和后面添加4个字节,并在函数的末尾检查它们,以确保这些额外的字节仍然被设置为0xCC。
Note that this switch only works in an unoptimized build (debug build).
注意,此开关只在未优化的构建(调试构建)中工作。
#2
3
In general, you don't. You should write defensive code that does the proper checks to ensure that it never overruns a buffer.
一般来说,你不。您应该编写进行适当检查的防御性代码,以确保不会超过缓冲区。
The debug runtime adds a large number of checks to help find this sort of bug (and all sorts of other common memory-related bugs); these checks are often very expensive, so they are only included in debug builds or when running attached to a debugger. They also can't detect every possible error, so they aren't foolproof; they are just debugging aids.
调试运行时添加大量的检查以帮助查找此类bug(以及所有其他与内存相关的常见bug);这些检查通常是非常昂贵的,所以它们只包含在调试构建中,或者在运行时附加到调试器中。它们也不能检测到每一个可能的错误,所以它们不是万无一失的;它们只是调试工具。
#3
2
The Wikipedia article on Electric Fence explains how buffer overruns are caught, and why you should not use such mechanisms in production code.
Wikipedia关于Electric Fence的文章解释了如何捕获缓冲区溢出,以及为什么不应该在生产代码中使用这种机制。
#4
2
Typically, the run-time will detect overflows like that by allocating some extra space between the variables, and filling that space with a known bit pattern. After your code runs, it looks at the bit pattern in that space. Since it's outside any variable, it should retain the same bit pattern. If the content has changed, you wrote somewhere you shouldn't have.
通常,运行时将通过在变量之间分配一些额外的空间来检测溢出,并使用已知的位模式填充该空间。在代码运行之后,它会查看该空间中的位模式。因为它在任何变量之外,所以它应该保持相同的位模式。如果内容发生了变化,那么您应该写一些不应该写的地方。
#5
2
The three buffers are not adjacent. The difference between the start of buf and the start of bufBef (the following item on the stack) is 16 bytes, but buf is only 8 bytes long.
这三个缓冲区不相邻。buf开头和bufBef开头的区别(堆栈上的下一项)是16个字节,但是buf只有8个字节长。
The 8 bytes in between is presumably filled with an 8 byte "canary" value. When the runtime detects that the canary has been changed by your wild write, it raises the error you have seen.
中间的8个字节大概是8字节的“canary”值。当运行时检测到您的野生写操作更改了金丝雀时,它会引发您所看到的错误。
(Your write to buf[8] writes to address 0x001afa48, which is in between buf and bufBef).
(您对buf[8]的写入写到地址0x001afa48,它位于buf和bufBef之间)。
#6
2
Compiler in debug mode put additional range checks for operations.
在调试模式下的编译器对操作进行额外的范围检查。
#7
1
You need to understand the stack structure. Usually compiler places extra guard bytes with random cookie around arrays, if the value at the end of the function doesn't match, there is an overflow.
您需要理解堆栈结构。通常编译器会在数组周围放置额外的保护字节,如果函数末尾的值不匹配,就会出现溢出。
#8
1
Well 0x001afa50 - 0x001afa40 = 0x10 = 16, and 0x001afa40 - 0x001afa18 = 0x28 = 40, so there's some space between the buffers for it to leave some known dummy data. If that's changed by the time the function ends, it knows you went beyond the end of the buffer. I'm just speculating -- they may have done it another way, but that seems one possibility.
0x001afa50 - 0x001afa40 = 0x10 = 16, 0x001afa40 - 0x001afa18 = 0x28 = 40,所以在缓冲区之间有一些空间可以让它留下一些已知的假数据。如果在函数结束时改变了它,它就知道你已经超出了缓冲区的末端。我只是推测——他们可能用另一种方式做过,但这似乎是一种可能性。
#9
0
C explicitly permits you to over-run (and under-run) your buffers, at your own peril.
C显式地允许您过度运行(或不足运行)您的缓冲区,您自己承担风险。
There is no short-n-simple way to detect at run-time (in release builds) buffer overflows.
在运行时(发行版中)检测缓冲区溢出没有简单的方法。
#10
0
You're looking for a language different from C. Some languages define the behavior of ever possible program, defining specific error behavior for doing things that are "wrong". C on the other hand leaves the behavior of "wrong" code undefined, which means it's up to the programmer to ensure that he/she never uses the language in ways that result in undefined behavior. Some implementations are debugging-oriented or have debugging modes that assist you in finding errors, which you absolutely need to fix before deploying the code in release/production use.
您正在寻找一种与c语言不同的语言。有些语言定义了可能的程序的行为,定义了做“错误”事情的特定错误行为。另一方面,C让“错误”代码的行为没有定义,这意味着程序员必须确保他/她从不以导致未定义行为的方式使用该语言。有些实现是面向调试的,或者具有调试模式,可以帮助您查找错误,在发布/生产使用中部署代码之前,您绝对需要对这些错误进行修复。
");
buf[8]='
{
char bufBef[32];
char buf[8];
char bufAfter[32];
sprintf(buf,"AAAAAAA\0");
buf[8]='\0';
printf("%s\n",buf);
}
On Windows 7, I compiled the program with Visual Studio 2008 as debug project. 3 buffers are adjacent. I find their addresses with a debugger, as followed:
在Windows 7上,我使用Visual Studio 2008作为调试项目编译了这个程序。3相邻缓冲区。我通过调试器找到了他们的地址:
bufBef 0x001afa50
buf 0x001afa40
bufAfter 0x001afa18
The statement "buf[8]='\0'" writes the address out of buf. When I run the program, Operation System reported " Debug Error: Run-Time Check Failure #2 - Stack around the variable 'buf' was corrupted."
语句“buf[8]='\0'”从buf中写入地址。当我运行程序时,操作系统报告“调试错误:运行时检查失败#2 -变量‘buf’周围的堆栈被损坏。”
Then I compiled it as a release project. It run quietly, no error report raised.
然后我将它编译为一个发布项目。它运行平稳,没有出现错误报告。
My question is how run-time detect buffer overflow?
我的问题是运行时如何检测缓冲区溢出?
10 个解决方案
#1
3
What you see if the effect of the /RTCs switch.
如果/RTCs切换的效果。
John Robbins' book Debugging Applications for Microsoft .NET and Microsoft Windows talks about this in depth.
约翰·罗宾斯(John Robbins)在《微软。net和微软Windows的调试应用程序》(debug Applications for Microsoft . net)一书中对此进行了深入探讨。
Relevant excerpt:
相关摘录:
Fortunately for us, Microsoft extended the /RTCs switch to also do overrun and underrun checking of all multibyte local variables such as arrays. It does this by adding four bytes to the front and end of those arrays and checking them at the end of the function to ensure those extra bytes are still set to 0xCC.
对我们来说幸运的是,Microsoft扩展了/RTCs开关,同时对所有多字节本地变量(如数组)进行了溢出和欠运行检查。它通过在这些数组的前面和后面添加4个字节,并在函数的末尾检查它们,以确保这些额外的字节仍然被设置为0xCC。
Note that this switch only works in an unoptimized build (debug build).
注意,此开关只在未优化的构建(调试构建)中工作。
#2
3
In general, you don't. You should write defensive code that does the proper checks to ensure that it never overruns a buffer.
一般来说,你不。您应该编写进行适当检查的防御性代码,以确保不会超过缓冲区。
The debug runtime adds a large number of checks to help find this sort of bug (and all sorts of other common memory-related bugs); these checks are often very expensive, so they are only included in debug builds or when running attached to a debugger. They also can't detect every possible error, so they aren't foolproof; they are just debugging aids.
调试运行时添加大量的检查以帮助查找此类bug(以及所有其他与内存相关的常见bug);这些检查通常是非常昂贵的,所以它们只包含在调试构建中,或者在运行时附加到调试器中。它们也不能检测到每一个可能的错误,所以它们不是万无一失的;它们只是调试工具。
#3
2
The Wikipedia article on Electric Fence explains how buffer overruns are caught, and why you should not use such mechanisms in production code.
Wikipedia关于Electric Fence的文章解释了如何捕获缓冲区溢出,以及为什么不应该在生产代码中使用这种机制。
#4
2
Typically, the run-time will detect overflows like that by allocating some extra space between the variables, and filling that space with a known bit pattern. After your code runs, it looks at the bit pattern in that space. Since it's outside any variable, it should retain the same bit pattern. If the content has changed, you wrote somewhere you shouldn't have.
通常,运行时将通过在变量之间分配一些额外的空间来检测溢出,并使用已知的位模式填充该空间。在代码运行之后,它会查看该空间中的位模式。因为它在任何变量之外,所以它应该保持相同的位模式。如果内容发生了变化,那么您应该写一些不应该写的地方。
#5
2
The three buffers are not adjacent. The difference between the start of buf and the start of bufBef (the following item on the stack) is 16 bytes, but buf is only 8 bytes long.
这三个缓冲区不相邻。buf开头和bufBef开头的区别(堆栈上的下一项)是16个字节,但是buf只有8个字节长。
The 8 bytes in between is presumably filled with an 8 byte "canary" value. When the runtime detects that the canary has been changed by your wild write, it raises the error you have seen.
中间的8个字节大概是8字节的“canary”值。当运行时检测到您的野生写操作更改了金丝雀时,它会引发您所看到的错误。
(Your write to buf[8] writes to address 0x001afa48, which is in between buf and bufBef).
(您对buf[8]的写入写到地址0x001afa48,它位于buf和bufBef之间)。
#6
2
Compiler in debug mode put additional range checks for operations.
在调试模式下的编译器对操作进行额外的范围检查。
#7
1
You need to understand the stack structure. Usually compiler places extra guard bytes with random cookie around arrays, if the value at the end of the function doesn't match, there is an overflow.
您需要理解堆栈结构。通常编译器会在数组周围放置额外的保护字节,如果函数末尾的值不匹配,就会出现溢出。
#8
1
Well 0x001afa50 - 0x001afa40 = 0x10 = 16, and 0x001afa40 - 0x001afa18 = 0x28 = 40, so there's some space between the buffers for it to leave some known dummy data. If that's changed by the time the function ends, it knows you went beyond the end of the buffer. I'm just speculating -- they may have done it another way, but that seems one possibility.
0x001afa50 - 0x001afa40 = 0x10 = 16, 0x001afa40 - 0x001afa18 = 0x28 = 40,所以在缓冲区之间有一些空间可以让它留下一些已知的假数据。如果在函数结束时改变了它,它就知道你已经超出了缓冲区的末端。我只是推测——他们可能用另一种方式做过,但这似乎是一种可能性。
#9
0
C explicitly permits you to over-run (and under-run) your buffers, at your own peril.
C显式地允许您过度运行(或不足运行)您的缓冲区,您自己承担风险。
There is no short-n-simple way to detect at run-time (in release builds) buffer overflows.
在运行时(发行版中)检测缓冲区溢出没有简单的方法。
#10
0
You're looking for a language different from C. Some languages define the behavior of ever possible program, defining specific error behavior for doing things that are "wrong". C on the other hand leaves the behavior of "wrong" code undefined, which means it's up to the programmer to ensure that he/she never uses the language in ways that result in undefined behavior. Some implementations are debugging-oriented or have debugging modes that assist you in finding errors, which you absolutely need to fix before deploying the code in release/production use.
您正在寻找一种与c语言不同的语言。有些语言定义了可能的程序的行为,定义了做“错误”事情的特定错误行为。另一方面,C让“错误”代码的行为没有定义,这意味着程序员必须确保他/她从不以导致未定义行为的方式使用该语言。有些实现是面向调试的,或者具有调试模式,可以帮助您查找错误,在发布/生产使用中部署代码之前,您绝对需要对这些错误进行修复。
';
printf("%s\n",buf);
}
{
char bufBef[32];
char buf[8];
char bufAfter[3