緩存區溢出攻擊實驗(2)


緩存區溢出攻擊實驗(2)

本實驗預計分 3 個小實驗來做,本文是第一個實驗。

  1. 緩存區溢出攻擊實驗(1)
  2. 緩存區溢出攻擊實驗(2)
  3. 緩存區溢出攻擊實驗(3)

本實驗感謝大神 YSunLIN 的幫助與指導 ~

簡述

背景介紹請參照實驗(1)。

本實驗是使用 Visual Studio (以下簡稱 VS)作為 IDE,重復上面的實驗(1)。本來不應該單獨作為一個實驗來講述,然而在實際操作的過程中發現了一些問題,因為 VS 是個比較強大的 IDE,因此在編譯過程中多了一些安全性的考慮,所以對緩沖區攻擊有了一定的防范,因此在這里做一些簡單的補充。

實驗環境

下面放上最終版的代碼,與實驗(1)的源代碼有一些不同:(建議看完下文再回頭看代碼)

源代碼

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

void overflow(const char* input)
{
char buf[8];
printf("Virtual address of 'buf' = Ox%p\n", buf);
strcpy(buf, input);
}

void fun()
{
printf("Function 'fun' has been called without an explicitly invocation.\n");
printf("Buffer Overflow attack succeeded!\n");
}

int main(int argc, char* argv[])
{
printf("Virtual address of 'overflow' = Ox%p\n", overflow);
printf("Virtual address of 'fun' = Ox%p\n", fun);
printf("Virtual address of 'main' = Ox%p\n", main);

char input[30] = "01234567\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc";
char add[5];
*((int*)add) = (int)fun;
add[4] = 0;
strcat(input, add);
overflow(input);
return 0;
}

實驗步驟

實驗步驟與實驗(1)類似,下面只進行簡單描述,具體不懂可參照實驗(1)。

  1. 先找到 fun 函數的入口地址 address_fun,然后找到 main 函數中在 overflow 函數執行完畢之后返回的地址 address_ret

  2. 找到 overflow 函數調用過程中,buf 所在地址 address_buf,數出 address_bufaddress_ret 之間的字節數,計算好准備寫入緩沖區 buf 的數據的大小,以使能夠讓 overflow 執行完畢之后跳到寫入的 address_fun

  3. 修改寫入緩沖區的數據,使其覆蓋棧中其它的數據,讓 address_fun 正好覆蓋 overflow 函數執行完畢之后返回的地址 address_ret。執行程序之后,程序如果調用了 fun 函數,則說明緩存區溢出攻擊成功。

然而實驗結果呵呵噠。下面將展示個人實驗過程中出現的問題與解決方式。

遇到的錯誤與解決方式

錯誤 #1

解決方案生成出錯,報錯如下:

這個好解決,只是因為使用了不安全的函數,可以通過在文件頭加入 #define _CRT_SECURE_NO_WARNINGS 來解決。

錯誤 #2

繼續運行程序,報了運行時檢查失敗,如下:

這是因為 VS 有一種運行時檢查機制(具體原理見下文“思考”部分),關閉即可。右鍵點擊項目,選擇“屬性”,將下圖所示的 基本運行時檢查 改為 默認值

錯誤 #3

繼續運行程序,報了堆棧 Cookie 檢測代碼檢測到緩沖區溢出錯誤,如下:

依然是因為 VS 有一種 安全檢查(\GS)機制(具體原理見下文“思考”部分),仍然需要我們關閉。如下所示,選擇 禁用安全檢查(\GS)即可。

錯誤 #4

繼續運行程序,報了訪問沖突錯誤,如下:

仔細檢查代碼、檢查匯編語言里的邏輯地址、檢查棧空間里的數據,我們會發現在棧空間里面,buf 與 overflow 函數執行完畢之后返回的地址之間,在我們解決上面兩個問題之前相差 16 個字節,而在解決上面兩個問題之后,它們之間只相差了 12 個字節。說明了 VS 的這兩種機制(基本運行時檢查機制 與 \GS安全檢查機制)可能在棧空間里面使用了某種手段來保證訪問不出錯。這一點我們將在下文的思考里面講述。這里略過原理。

既然知道了出錯的地方,那我們就修改一下將要寫入緩沖區的數據修改一下,讓 overflow 函數執行完畢之后跳到我們想讓它執行的函數 fun,即可。

錯誤 #5

繼續運行程序,依然報了訪問沖突錯誤。

這回又是哪個環節出現了問題?明明返回的地址對上號了,為什么依然訪問沖突。在這里我們重新 review 代碼與整個過程。很容易的我們就能發現,每次修改將要寫入緩沖區的數據之后, build&run 的程序里面 fun 函數的入口地址都不一樣:(
在大概測了十幾次之后,發現每次 fun 函數的入口都不同,而且沒有什么固定的規律(如果有人能夠發現請教我),沒有什么好的解決思路,於是就修改了 main 函數,強行將 fun 函數的入口地址添加在了將要寫入緩沖區的數據當中,於是解決了問題(雖然方法不太行)。
結果如下:

done!

思考

基本運行時檢查機制

下面這篇博客已經寫得很棒了~ 牆裂推薦~

這里對基本運行時檢查機制做一個簡單的概述:(總結自上面這篇博客)

  1. /RTCc開關

    檢查在進行類型轉換的保證沒有不希望的截斷(Truncation)發生。

  2. /RTCu開關

    這個開關的作用是打開對未初始化變量的檢查。u代表未初始化的變量檢查(uninitialized variable check)

  3. /RTCs開關

    這個開關是用來檢查和Stack相關的問題。s代表堆棧檢查(stack check)。

    1. Debug模式下把Stack上的變量初始化為0xcc,檢查未初始化的問題
    2. 檢查數組變量的Overrun
    3. 檢查ESP是否被毀壞

\GS 安全檢查機制

這里也參考了一篇文章,來自老牌的看雪安全論壇,講解十分詳細,也是十分推薦:

簡單來說,就是

/GS 參數在緩沖區和返回地址之間提供了“緩沖帶”,或者稱為cookie。如果溢出會覆蓋返回地址,那么這個溢出必須先覆蓋返回地址和緩沖區之間的cookie。

當然,參考的這篇文章遠遠不止講述了關於 \GS安全檢查機制的由來與原理,更是深入剖析了緩沖區溢出問題(包括Windows XP中系統函數內部大量的帶有“cookie”這個字符串的符號)另外,這篇文章是翻譯作品,原文作者是 VS 開發團隊的成員 Brandon Bray。

Reference


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com