日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows栈溢出原理

發(fā)布時間:2025/4/16 windows 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows栈溢出原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.棧是什么?

棧是一種運算受限的線性表

其限制是僅允許在表的一端進行插入和刪除運算

這一端稱為棧頂(TOP),相對的另一端稱為棧底(BASE)

向一個棧插入新元素,稱作進棧、入棧或壓棧(PUSH)

它是把新元素放到棧頂元素的上邊,使之成為新的棧頂元素;

從一個棧刪除元素,又稱出棧或退棧(POP)

它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素

進程使用的內(nèi)存可以分成4個部分

代碼區(qū):存儲二進制機器碼,存儲器在這里取指令

數(shù)據(jù)區(qū):用于存儲全局變量

堆區(qū):動態(tài)分配和全局變量

棧區(qū):動態(tài)存儲函數(shù)間的調(diào)用關(guān)系,保證被調(diào)用函數(shù)返回時恢復(fù)到母函數(shù)中繼續(xù)運行

寄存器與函數(shù)棧幀

ESP:棧頂指針寄存器,永遠指向系統(tǒng)棧頂

EBP:基址指針寄存器,永遠指向系統(tǒng)棧最上邊一個棧的棧底

ESP和EBP之間的內(nèi)存空間為當前棧幀

2.棧的溢出

棧溢出是由于C語言系列沒有內(nèi)置檢查機制來確保復(fù)制到緩沖區(qū)的數(shù)據(jù)不得大于緩沖區(qū)的大小

因此當這個數(shù)據(jù)足夠大的時候,將會溢出緩沖區(qū)的范圍

?

3.如何利用

通過程序的緩沖區(qū)寫超出其長度的內(nèi)容,造成緩沖區(qū)的溢出,

從而破壞程序的堆棧,使程序轉(zhuǎn)而執(zhí)行其它指令,以達到攻擊的目的

造成緩沖區(qū)溢出的原因是 程序中沒有仔細檢查用戶輸入的參數(shù)

覆蓋鄰接變量

例如buffer大小是8字節(jié)

輸入8個字符,加上字符串截斷字符NULL字符,即可覆蓋相鄰變量,改變程序運行流程

修改函數(shù)返回地址

上述覆蓋相鄰變量的方法雖然很管用,但是漏洞利用對代碼環(huán)境很苛刻

更通用的攻擊緩沖區(qū)的方法是,瞄準棧幀最下方EBP和函數(shù)返回地址等棧幀的狀態(tài)值

如果繼續(xù)增加輸入字符,超出buffer[8]字符邊界

將依次淹沒 相鄰變量、前棧幀EBP、返回地址

4.實例

1)創(chuàng)建一個password.txt文件,內(nèi)容為1234

2)C語言實例代碼

#include <stdio.h>
#include <windows.h>
#define PASSWORD "1234567"
int verify_password (char *password) //密碼驗證函數(shù)
{
? ?int authenticated;
? ?char buffer[44];//緩沖區(qū)大小
? ?authenticated=strcmp(password,PASSWORD);
? ?strcpy(buffer,password);//over flowed here! ? ?
? ?return authenticated;
}
main()
{
int valid_flag=0;
char password[1024];
FILE *fp;
LoadLibrary("user32.dll"); //準備?messagebox
if(!(fp=fopen("password.txt","rw+")))
{
exit(0);
}
fscanf(fp,"%s",password);
valid_flag = verify_password(password);
if(valid_flag)
{
printf("incorrect password!\n");
}
else
{
printf("Good password is OK,You Win!\n");
}
system("pause");
fclose(fp);
}

代碼環(huán)境

操作系統(tǒng)Widows XP SP2
編譯器Visual C++ 6.0
編譯選項默認編譯選項
build版本debug版本

運行測試一下,更改密碼文件對比結(jié)果

根據(jù)函數(shù)棧溢出原理,實現(xiàn)棧溢出需要以下過程

(1) 分析并調(diào)試程序,獲得淹沒返回地址的偏移

(2) 獲得buffer的起始地址,根據(jù)獲得的偏移將其覆蓋返回地址,使得函數(shù)返回時執(zhí)行buffer起始地址保存的代碼

(3) 提取彈框操作的機器碼并保存于buffer的起始地址處,在函數(shù)返回時得到執(zhí)行

為什么會覆蓋?

如果在password.txt中寫入恰好44個字符,那么第45個隱藏的截斷符 null 將沖刷

變量authenticated低字節(jié)中的 1,從而突破密碼驗證的限制

出于字節(jié)對齊、容易辨認的目的,我們把"4321"作為一個輸入單元

buffer[44]共需要11個這樣的單元

第12個輸入單元將authenticated覆蓋;

第13個單元將前棧幀EBP的值覆蓋;

第14個單元將返回地址覆蓋;

調(diào)試棧的布局

通過動態(tài)調(diào)試,可以得到以下信息

(1) buffer數(shù)組的起始地址為:0x0012FAF0

(2) password.txt 文件中第53~56個字符的ASCII碼值,將寫入棧幀中的返回地址,成為函數(shù)返回后執(zhí)行的指令地址

也就是說,在buffer的起始地址寫入password.txt文件中的第53~56個字節(jié)

在 verify_password 函數(shù)返回時,會跳到我們輸入的字符串開始取指執(zhí)行

(3) 給password.txt中植入機器碼,彈出消息框

MessageBoxA是動態(tài)鏈接庫user32.dll的導(dǎo)出函數(shù),本實驗中未默認加載

在匯編語言中調(diào)用這個函數(shù)需要獲得這個函數(shù)的入口地址。

獲取彈窗函數(shù)入口參數(shù)信息

MessageBoxA的入口參數(shù)可以通過user32.dll 在系統(tǒng)中加載的基址和MessageBoxA在庫中的偏移得到。

用VC6.0自帶的小工具"Dependency Walker"可以獲得這些信息(可在Tools目錄下找到)

隨便把一個有GUI界面的程序扔進去,結(jié)果如圖所示

user32.dll的基址為:0x77D10000

MessageBoxA 的偏移地址為:0x000407EA

基址+偏移地址=MessageBoxA內(nèi)存中的入口地址:0x77D507EA

我們要彈窗的字符設(shè)成"wintry",用python轉(zhuǎn)換成16進制的ASCII

然后借助OD寫匯編代碼,獲得機器碼

將上邊的機器碼,以十六進制形式逐字寫入到 password.txt

第53~56字節(jié)填入buffer的起址:0x0012FAF0 ,其余字節(jié)用 90(nop) 填充

上邊的機器碼可能是字符沒對齊的原因,會彈出內(nèi)存讀取錯誤,把字符串改為"wintry00"

成功彈出窗口

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/wintrysec/p/10616793.html

總結(jié)

以上是生活随笔為你收集整理的Windows栈溢出原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。