本文作者:rkvir(Ms08067實驗室合夥人&二進制小組組長)
人才招募:二進制小組尋找二進制領域志同道合的朋友
一. 實驗環境:
作業系統 | Windows XP SP3 |
---|---|
開發環境 | VC++ 6.0 |
調試器 | 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!\n\n");}else{printf("Congratulation! You have passed the verification!\n");break;}}} |
---|
三. 溢出原理
程式未對輸入的密碼進行長度檢測,接收密碼的緩沖區隻有8,而輸入的密碼最長可以輸入1024。判斷密碼是否正确的變量authenticated存儲在棧中,當輸入的密碼長度大于8時,輸入的字元串将沖破緩沖區,淹沒authenticated所處的位置。當密碼錯誤時authenticated的值是1,正确的時候authenticated的值是0.這就意味着我們可以構造一個合适的輸入字元串來改變判斷結果。
四. 實戰調試
我們的重點不是逆向工程,而是漏洞分析,故此不再詳訴諸如尋找main函數等逆向知識。
1. 在jmp mai下斷點,友善後續反複調試

2. 單步步入main函數分析程式
3. 分析main函數邏輯,可以看出主要問題出在密碼比對函數00401005
3.1 輸出引導字元串後,要求使用者輸入密碼。
3.2 通過00401005處的函數進行密碼比對
3.3 判斷比對結果是不是0,如果是0則輸出成功字元串,如果是1則輸出失敗字元串。
4. 單步執行程式,随便輸入一個密碼,然後單步步入00401005函數,分析這個函數的内容。
4.1 可以看出這個00401005是個跳轉,直接單步進入函數真實位置。
4.2 進入到函數内部後可以看到真正的密碼是1234567,如果我們是在逆向破解這個程式,那麼到了這一步,就已經算是成功了。但是我們的目的是分析漏洞,是以我們現在進一步分析這個函數。
4.2.1 可以看出,在strcmp之後,ebp-4的位置上就有了密碼比對的結果
4.2.1.1 strcmp比對密碼,将比對結果存入ebp-4的位置上
4.2.1.2 棧中的密碼比對結果
4.2.2 如果是正常的程式,這個時候就應該傳回了,但是因為是實驗代碼,是以下面還有一個strcpy的拷貝函數,将輸入的密碼字元串拷貝入一個長度為8的緩沖區中。
4.2.3 當執行完strcpy的時候我們看一下堆棧區,可以看到字元串緩沖區的位置就在密碼字元串比對結果旁邊,并且strcpy沒有對拷貝入的字元串進行長度判斷。是以我們可以判斷,我們在構造一個合适的字元串傳入的情況下,是可以覆寫密碼字元串比對結果的。這也意味着我們可以傳入一個合适的字元串來沖破密碼驗證。
5. 我們重新加載這個程式,并且傳入一個特定的字元串“qqqqqqqq”
6. 運作到密碼比對函數進行分析
6.1 可以看出strcmp函數沒有任何問題的執行成功并且傳回了1,代表密碼錯誤。并且把存儲在eax中的傳回值存儲到ebp-4的位置上。
6.1.1 函數執行
6.1.2 傳回值存儲在eax中
6.1.3 eax中的值mov到了ebp-4的位置上
6.2 下面到了引起溢出錯誤的strcpy函數,詳細分析該函數溢出的過程。
6.2.1首先記錄一下strcpy沒有執行前堆棧的情況
6.2.2 執行strcpy函數
6.2.3 可以看到,堆棧中原本儲存着密碼比對結果的位置ebp-4,由于傳入字元串超長,已經被覆寫成了0。這樣一來,原本比對失敗的結果就變成了比對成功。
7. 運作至傳回,成功輸出密碼比對成功的資訊
7.1 控制台成功資訊
8. 那麼是任何長于1234567的字元串都可以成功覆寫比對結果嗎,嘗試一下,輸入9個q,可以看到,對比結果的位置上并沒有被覆寫成00,而是71,而隻有對比結果等于0才可以成功驗證。這說明不是任意長度字元串都可以。
9. 那麼有什麼結果可以覆寫成整好是0呢,那麼答案是長度為8的字元串,長度為8的字元串實際長度為9,因為還有用來标記字元串結束的00,我們就是要使用結尾處的00來覆寫對比結果,使其數值為0。
來源:Ms08067安全實驗室