## 一.實(shí)驗(yàn)環(huán)境:
```
操作系統(tǒng) Windows XP SP3
開發(fā)環(huán)境 VC++ 6.0
調(diào)試器 Ollydbg
```
## 二.實(shí)驗(yàn)代碼:
```
#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)行長(zhǎng)度檢測(cè),,接收密碼的緩沖區(qū)只有8,,而輸入的密碼最長(zhǎng)可以輸入1024。判斷密碼是否正確的變量authenticated存儲(chǔ)在棧中,,當(dāng)輸入的密碼長(zhǎng)度大于8時(shí),,輸入的字符串將沖破緩沖區(qū),,淹沒(méi)authenticated所處的位置,。當(dāng)密碼錯(cuò)誤時(shí)authenticated的值是1,正確的時(shí)候authenticated的值是0.這就意味著我們可以構(gòu)造一個(gè)合適的輸入字符串來(lái)改變判斷結(jié)果,。
## 四.實(shí)戰(zhàn)調(diào)試
我們的重點(diǎn)不是逆向工程,,而是漏洞分析,故此不再詳訴諸如尋找main函數(shù)等逆向知識(shí),。
1.在jmp mai下斷點(diǎn),,方便后續(xù)反復(fù)調(diào)試

2.單步步入main函數(shù)分析程序

3.分析main函數(shù)邏輯,可以看出主要問(wèn)題出在密碼比對(duì)函數(shù)00401005
3.1輸出引導(dǎo)字符串后,,要求用戶輸入密碼,。

3.2通過(guò)00401005處的函數(shù)進(jìn)行密碼比對(duì)

3.3判斷比對(duì)結(jié)果是不是0,,如果是0則輸出成功字符串,,如果是1則輸出失敗字符串。

4.單步執(zhí)行程序,,隨便輸入一個(gè)密碼,,然后單步步入00401005函數(shù),分析這個(gè)函數(shù)的內(nèi)容,。

4.1可以看出這個(gè)00401005是個(gè)跳轉(zhuǎn),,直接單步進(jìn)入函數(shù)真實(shí)位置。

4.2進(jìn)入到函數(shù)內(nèi)部后可以看到真正的密碼是1234567,,如果我們是在逆向破解這個(gè)程序,,那么到了這一步,就已經(jīng)算是成功了,。但是我們的目的是分析漏洞,,所以我們現(xiàn)在進(jìn)一步分析這個(gè)函數(shù)。

4.2.1可以看出,,在strcmp之后,,ebp-4的位置上就有了密碼比對(duì)的結(jié)果
4.2.1.1strcmp比對(duì)密碼,將比對(duì)結(jié)果存入ebp-4的位置上

4.2.1.2棧中的密碼比對(duì)結(jié)果

4.2.2如果是正常的程序,,這個(gè)時(shí)候就應(yīng)該返回了,,但是因?yàn)槭菍?shí)驗(yàn)代碼,所以下面還有一個(gè)strcpy的拷貝函數(shù),,將輸入的密碼字符串拷貝入一個(gè)長(zhǎng)度為8的緩沖區(qū)中,。

4.2.3當(dāng)執(zhí)行完strcpy的時(shí)候我們看一下堆棧區(qū),可以看到字符串緩沖區(qū)的位置就在密碼字符串比對(duì)結(jié)果旁邊,,并且strcpy沒(méi)有對(duì)拷貝入的字符串進(jìn)行長(zhǎng)度判斷,。因此我們可以判斷,,我們?cè)跇?gòu)造一個(gè)合適的字符串傳入的情況下,是可以覆蓋密碼字符串比對(duì)結(jié)果的,。這也意味著我們可以傳入一個(gè)合適的字符串來(lái)沖破密碼驗(yàn)證,。

5.我們重新加載這個(gè)程序,并且傳入一個(gè)特定的字符串“qqqqqqqq”

6.運(yùn)行到密碼比對(duì)函數(shù)進(jìn)行分析
6.1可以看出strcmp函數(shù)沒(méi)有任何問(wèn)題的執(zhí)行成功并且返回了1,,代表密碼錯(cuò)誤,。并且把存儲(chǔ)在eax中的返回值存儲(chǔ)到ebp-4的位置上。
6.1.1函數(shù)執(zhí)行

6.1.2返回值存儲(chǔ)在eax中

6.1.3 eax中的值mov到了ebp-4的位置上

6.2下面到了引起溢出錯(cuò)誤的strcpy函數(shù),,詳細(xì)分析該函數(shù)溢出的過(guò)程,。
6.2.1首先記錄一下strcpy沒(méi)有執(zhí)行前堆棧的情況

6.2.2 執(zhí)行strcpy函數(shù)

6.2.3 可以看到,堆棧中原本保存著密碼比對(duì)結(jié)果的位置ebp-4,,由于傳入字符串超長(zhǎng),,已經(jīng)被覆蓋成了0。這樣一來(lái),,原本比對(duì)失敗的結(jié)果就變成了比對(duì)成功,。

7.運(yùn)行至返回,成功輸出密碼比對(duì)成功的信息

7.1控制臺(tái)成功信息

8.那么是任何長(zhǎng)于1234567的字符串都可以成功覆蓋比對(duì)結(jié)果嗎,,嘗試一下,,輸入9個(gè)q,可以看到,,對(duì)比結(jié)果的位置上并沒(méi)有被覆蓋成00,,而是71,而只有對(duì)比結(jié)果等于0才可以成功驗(yàn)證,。這說(shuō)明不是任意長(zhǎng)度字符串都可以,。

9.那么有什么結(jié)果可以覆蓋成整好是0呢,那么答案是長(zhǎng)度為8的字符串,,長(zhǎng)度為8的字符串實(shí)際長(zhǎng)度為9,,因?yàn)檫€有用來(lái)標(biāo)記字符串結(jié)束的00,我們就是要使用結(jié)尾處的00來(lái)覆蓋對(duì)比結(jié)果,,使其數(shù)值為0,。

參考材料:《0day安全:軟件漏洞分析技術(shù)》