静态缓冲区溢出问题(高手进)

我写的一个利用静态缓冲区溢出的程序
我的预期目标是写个死循环,但每次执行到九千多的时候就停了
百思不得其解,0x0040100a是MAIN 的入口地址转到八进制是00,100,20,12
编译环境 vc++6.0 ,程序是debug 版本,具体地址可能和机器版本有关
#include <string.h>
#include <stdio.h>  
 
int i=0; 
void ceshi(const char * input)
{   
 char buf[10];
 strcpy(buf,input);   //溢出语句
}     
void main()
{  
 i++;
 printf("我是main函数,我执行了%d次\n",i);   
 char buffer[21]="ABCDEFGHIJKLMNOP\12\20\100\0"; 
 ceshi(buffer);    
}
我就是要input比buf大才能够利用溢出啊
程序原理是缓冲区溢出时即strcpy执行后程序会读一个非法内存地址,从而出现应用程序错误的对话框,而本程序中通过控制溢出时读的地址从而达到执行任意代码的作用
在这里我是控制读MAIN的地址达到死循环的目的
你用vc++6.0编译运行就能看到结果,高手帮我调一下

不明白可以在vc++6.0下编译运行这个程序
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

void gongji()
{
 printf("大家可以看到,攻击函数执行了\n");
 getch();
 exit(-1);   //防止程序非正常退出,所以我在这里强制结束程序了。
}

void ceshi(const char * input)
{   
 char buf[10];
 strcpy(buf,input);  //有问题的语句   
} 
 
void main()
{  
//你可以用printf("%p\n",gongji)来得到gongji函数的地址
//我得到的是0x0040100f (vc++6.0,debug版本),如果你是用release版本可能不一样
//0x0040100f 依次对应8进制的 0,100,20,17,但地址要反过来写,即\17\20\100\0  
 char buffer[21]="ABCDEFGHIJKLMNOP\17\20\100\0";  
 ceshi(buffer);  
}
=================================================================================================================
大概是ceshi函数返回的时候回错误的返回到main函数的开始的地方。因为main没有返回,那么栈应该是不停的向低地址空间增长才对。根据Windows为每个可执行程序分配4G的内存空间,那么这个不停的增长总该有个限度才是吧?应该会循环达到出错的时候的,char buffer[21]="ABCDEFGHIJKLMNOP\17\20\100\0"; //可以在这里加个打印 buffer地址的语句,看看是不是栈在扩展的ceshi(buffer);

=====================================================================================================================
同意widebright的观点,我也是这么认为的,因为你代码的实质是修改函数ceshi的ret地址为main的起始地址,而ceshi和main中都有局部变量,且ceshi和main都没有返回,所以栈指针一直都没恢复,新的对main和ceshi的调用都会增加新的局部变量,栈的大小总不会是无限的吧,所以循环到一定时候是会出错退出的。

给个简单明了的例子:

#include <stdio.h>

int i;

int main()
{
 int* ret_addr;

 printf("main: %d %x\n", ++i, &ret_addr);
 ret_addr = (int*)&ret_addr + 2;
 *ret_addr = (int)&main;

 return 0;
}

此程序和你的等效,注意每次的局部变量ret_addr地址都不同,但我在vc6上测试只循环了32次,暂时不知道为什么(windows还没理解透,汇编还没学到家)。

至于你的代码,你可以采取一些措施让main多循环几次(想要真正的死循环还是老实点儿while(1)吧,或者goto...),比如把main中的buffer设置为全局:

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

int i=0;
void ceshi(const char * input)
{
char buf[10];
strcpy(buf,input); //溢出语句
}

char buffer[21]="ABCDEFGHIJKLMNOP\12\20\100\0";

void main()
{
i++;
printf("我是main函数,我执行了%d次\n",i);
ceshi(buffer);
}

另外我自己也写了一个,用了struct和union的作为存储结构来描述栈的话要更清楚和容易理解一些(只在vc6上测试了下,其他编译器可能没效果):

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

int main();
int i = 0;

struct 
{
    int local1; // 局部变量1
    int old_ebp; // 旧的ebp值
    union
    {
        int  addr; // 返回地址
        char byte[4]; // 字节码
    }ret_addr;
}stack = {0xFFFFFFFF, 0xFFFFFFFF, (int)main};

void stack_dump(const char * input)
{
    char local1[1];
    strcpy(local1, input); //溢出语句
}

int main()
{
    printf("我是main函数,我执行了%d次\n", ++i);
    stack_dump((char*)&stack);
    
    return 0;
}
提问者评价
我该了一下程序,确实可以多循环几次,谢谢
同时也谢谢widebright

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章