Visual Studio2013为啥调试的时候总显示缓冲区溢出,不能运行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Visual Studio2013为啥调试的时候总显示缓冲区溢出,不能运行相关的知识,希望对你有一定的参考价值。

程序如下:
#include<stdio.h>;
#include<iostream>;
using namespace std;
int main()

int a[7][7] = 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;

int c = 1;
int hang = 0,lie=0;
int hz = 0;
int hy = 6;
int ls = 0;
int lx = 6;
while (a[4][4] == 0)


for (lie = hz; lie < hy + 1; lie++)

a[hang][lie] = c;
c++;
ls++;

if (a[4][4] != 0)break;
for (hang = ls; hang<lx + 1; hang++)

a[hang][lie] = c;
c++;
hy--;

if (a[4][4] != 0)break;
for (lie = hy; lie >= hz; lie--)

a[hang][lie] = c;
c++;
lx--;

if (a[4][4] != 0)break;
for (hang = lx; hang >= ls; hang--)

a[hang][lie] = c;
c++;
hz++;


;
return 1;

参考技术A 很多搞IT都听说过缓冲区溢出,但是怎么利用缓冲区溢出的Bug来运行你自己的代码呢?这里我只介绍怎么利用静态缓冲区溢出来运行黑客程序。因为动态的,我还不会用。:)

第一节 堆栈的形式
在程序运行的时候,每次程序调用一个函数的时候,程序就要在内存里面分配一个空间来保存这个函数要使用到的本地变量,还有参数啊什么什么的。下面用一个程序片断来演示一下堆栈的形式
void TestCaller()

TestMethod(1);
int i = 0;


void TestMethod(int p)

int l1 = 0;
char l2 = '3';


上面的程序很简单,就是定义了两个函数,函数TestCaller调用了函数TestMethod,而TestMethod定义了两个局部变量。在计算机的内存里面堆栈的形式如下(大概的模型啊,不是很精确的):

|----------------------|
| .... | <------ TestCaller的堆栈
|----------------------|
| 1 | <------ TestCaller传给TestMethod的参数p的值
|----------------------|
| TestCaller的ebp的值 | <------ TestCaller的堆栈的起始位置
|----------------------|
| 函数返回地址 | <------- TestMethod调用完成以后的返回地址,就是TestCaller函数中,调用
|----------------------| TestMethod语句的下一行语句,本例中是int i = 0;
| 0 | <------- TestMethod的第一个本地变量 l1的值
|----------------------|
| '3' | <------- TestMethod的第二个变量l2的值
|----------------------|

第二节 一个写的很差的程序

我们来看一个写的很差的程序:

void BadFunc(char *input)

if ( input == NULL ) return; // 嗯,有错误验证

char local[20];

strcpy(local, input); // 将input指向的内存里面的数据拷贝到local中去


很多人都知道为什么这个程序写的很差,是啊,加入input指向的字符串的长度不只20个呢,那会怎么样?

我们先在调试器上试一下,BadFunc("12345678901234567890AAAAAAAAAAAAAAAAAAA"),运行一下程序,恩,VS弹出一个错误对话框(对不起,我这里没有C++ Builder,所有的程序都是在VS 2005调试通过的,VS 6.0和VS 2003可能稍微修改一些输入字符串的长度)。对话框的内容是:
Unhandled exception at 0x41414141 in bufferoverflow.exe: 0xC0000005: Access violation reading location 0x41414141.

注:字符'A'的ASCII玛就是41。在调试器跟踪一下,你就会发现这个错误对话框刚好是在BadFunc执行完成以后出现的。错误信息是Access violation reading location,说明你的程序在执行完BadFunc之后,CPU试图从0x41414141这个位置读取一些数据。打开内存窗口(VS 2005:Debug -- Windows -- Memory -- Memory 1),在Location那个文本框输入ebp<回车>。单击右键,选择4字节显示,你就会发现内存窗口的左上角(MSN空间不能插图,真的是很郁闷)有一溜的0x41414141。右边的ASCII显示也是一长串的AAAA.在内存窗口在往后面走一下,你就会发现刚才BadFunc的参数12345678901234567890AAAAAAAAAAAAAAAAAAA就在ebp的附近。记得我在开始说过的,ebp过去一些,就是你的函数返回地址。VS弹出的错误对话框说明了函数返回地址已经被你的垃圾数据(多出来的AAAAAAAAA)覆盖了,当BadFunc返回的时候,CPU照常读取保存在ebp后面的函数返回地址,然后试图跳到返回地址所指向的位置继续执行。当BadFunc返回的时候,因为返回地址已经是0x41414141(AAAA)了,CPU试图读取内存地址为0x41414141的指令,继续执行程序,但是0x41414141是无效的内存地址(里面保存了什么东西只有天知道),于是一个Access violation(AV)就扔出来了。

这样我们就有机会改变程序原来的执行路径了,只要我们把BadFunc的返回地址改成我们想要的地址,而这个地址刚好有我们事先设计好的指令就可以了。现在来一个比较简单的:

#include <stdio.h>
#include <string.h>

void foo(const char *input)

char buf[10];
strcpy(buf, input);


void bar(void)

printf("Augh! I've been hacked!/n");


int main(int argc, char *argv[])

printf("Address of main = %p/n", main);
printf("Address of foo = %p/n", foo);
printf("Address of bar = %p/n", bar); // 0x00411131
foo("1234567890123456/xa0/x12/x41");

return 0;

上面的例子里面,你要将最后的/xa0/x12/x41转换成你自己机器上bar函数的地址。最后你会看到,虽然在main函数中没有调用bar函数,但是bar函数还是被调用了。
上面的例子只是调用程序本身已有的函数,你还是没有办法调用你自己编写的函数。例如,你还不能把你写的dll导入到你要黑的程序里面去,所以你要让BadFunc执行你自己的函数,你还是有一些事情要做的。追问

但是我的代码没什么问题,为什么调试的时候说缓冲区溢出呢

参考技术B 上面这位大牛说的东西,你现在还不用涉及。
你的问题是while循环里判定条件在循环中没有控制,导致程序死在里面了,
两个变量一直在加,导致了栈溢出,而为啥变量值太大就会栈溢出,参考上面大牛说的话,以及数组的使用就会明白。
使用数组时要谨慎小心。使用循环时要小心。

visual studio 2008 在编写C程序语言时,为啥调试窗口自动瞬间关闭?

因为程序在运行到main函数结束了之后就等于整个程序结束了,自然会自动关闭了,所以如果想要留住窗口的话,需要让程序保持运行状态,比如在最后scanf随便什么东西,或者用system("pause");可以将程序暂停,来观察你要的结果。
使用system似乎需要包括头文件stdlib.h
参考技术A 你说的是调试执行的时候,屏幕出现了黑框框,但是一会儿就没有了,如果是的话,你可以在调试的时候,单击菜单栏上的调试,选择不启动调试吧,忘记名字了,或者直接按快捷键ctrl+f5运行程序, 参考技术B 应该是你的VS2008没装好,重装或者换个安装包装试试。 参考技术C #include <stdlib.h>

加上这个头文件追问

在哪个地方加这个头文件

以上是关于Visual Studio2013为啥调试的时候总显示缓冲区溢出,不能运行的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Visual Studio 不调试我的 VB.NET 应用程序?

visual studio 2008 在编写C程序语言时,为啥调试窗口自动瞬间关闭?

Visual Studio 2013 如何在停止调试Web程序后阻止IIS Express关闭

Visual Studio 2013仅在调试菜单中显示附件

为啥我调试时 Visual Studio 会启动多个 WebDev?

为啥我在 Visual Studio 2008 的工具下没有调试选项?