棧溢出實(shí)驗(yàn)
利用淹沒返回值控制程序執(zhí)行流程
操作系統(tǒng):Windows XP SP3
開發(fā)環(huán)境:VC++ 6.0
調(diào)試器:Ollydbg
#include <stdio.h>
#include<string.h>
#define PASSWORD "1234567"
int verify_password (char *password)
{
int authenticated;
char buffer[8];
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password);
return authenticated;
}
main()
{
int valid_flag=0;
char password[1024];
while(1)
{
printf("please input password: ");
scanf("%s",password);
valid_flag = verify_password(password);
if(valid_flag)
{
printf("incorrect password!nn");
}
else
{
printf("Congratulation! You have passed the verification!n");
break;
}
}
}
程序未對(duì)輸入的密碼進(jìn)行長度檢測(cè),接收密碼的緩沖區(qū)只有8,而輸入的密碼最長可以輸入1024。判斷密碼是否正確的變量authenticated存儲(chǔ)在棧中,當(dāng)輸入的密碼長度大于8時(shí),輸入的字符串將沖破緩沖區(qū),淹沒authenticated所處的位置。當(dāng)密碼錯(cuò)誤時(shí)authenticated的值是1,正確的時(shí)候authenticated的值是0.這就意味著我們可以構(gòu)造一個(gè)合適的輸入字符串來改變判斷結(jié)果。
本次的程序與上一節(jié)的程序的區(qū)別為由控制臺(tái)輸入改為讀取文件。這是因?yàn)楹芏嘧址麩o法由控制臺(tái)直接輸入。
本次的程序與上一節(jié)只有讀取文件和控制臺(tái)輸入的區(qū)別,故此不再詳細(xì)分析。著重分析如何通過覆蓋返回值來控制程序執(zhí)行流程。
1. 首先我們隨便在password.txt中隨便輸入一個(gè)字符串保存,然后調(diào)試程序,進(jìn)入main函數(shù)開始分析。
2. 因?yàn)檫@次的目的是淹沒返回值控制程序流程,所以在進(jìn)入密碼比對(duì)函數(shù)之前,先記錄下函數(shù)位置。
3. 單步進(jìn)入密碼比對(duì)函數(shù),在剛剛進(jìn)入函數(shù)的時(shí)候可以看到ESP的位置就是函數(shù)的返回地址。
4. 在經(jīng)過strcpy函數(shù)之后,可以看到password.txt內(nèi)的字符串成功的覆蓋了函數(shù)比對(duì)結(jié)果變量,那么我們可以看到在附近還存儲(chǔ)著函數(shù)返回地址,那么我們是否可以通過加長password.txt內(nèi)的文本內(nèi)容,覆蓋掉返回地址。我們可以看到距離返回地址我們需要12個(gè)長度的文本,你那么這次我們將password.txt的內(nèi)容修改為123456781234567812345678,再次調(diào)試程序。
5. 再次調(diào)試可以看到堆棧內(nèi)的函數(shù)返回地址已經(jīng)被成功覆蓋了,但是執(zhí)行后會(huì)報(bào)錯(cuò),因?yàn)?8373635的位置上并沒有執(zhí)行,是一片非法內(nèi)存。
6. 那么我們可以看到在0012FB20的位置上的字符串是1234,根據(jù)上下文,我們可以看出是第三個(gè)1234,那么我們就把它覆蓋成我們想要地址。比如輸出比對(duì)成功字符串的位置。
7. 那么我們把password.txt中第三個(gè)1234改成輸出字符串的地址,但是需要注意兩點(diǎn)。第一,我們要按照小端序倒著輸入返回地址,第二需要修改的是HEX而不是字符串。因此我們需要使用十六進(jìn)制編輯器010editer進(jìn)行如下編輯。
8. 然后我們?cè)俅握{(diào)試程序??梢钥吹蕉褩V蟹祷氐刂芬呀?jīng)被我們成功覆蓋了。
9. 運(yùn)行一下,可以看到成功的運(yùn)行到了我們想要的位置,雖然隨后就因?yàn)槎褩2黄胶鈱?dǎo)致程序崩潰,但是這是后續(xù)需要解決的問題,這一節(jié)的目的我們已經(jīng)成功達(dá)到了。