靜態緩衝區溢出問題(高手進)

我寫的一個利用靜態緩衝區溢出的程序
我的預期目標是寫個死循環,但每次執行到九千多的時候就停了
百思不得其解,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

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