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