緩沖區溢出漏洞--原理


0x00 緩沖區溢出概念
緩沖區溢出是指當計算機向緩沖區內填充數據位數時超過了緩沖區本身的容量溢出的數據覆蓋在合法數據上,

 

理想的情況是程序檢查數據長度並不允許輸入超過緩沖區長度的字符,但是絕大多數程序都會假設數據長度總是與所分配的儲存空間相匹配,這就為緩沖區溢出埋下隱患,操作系統所使用的緩沖區,又被稱為"堆棧"。在各個操作進程之間,指令會被臨時儲存在"堆棧"當中,"堆棧"也會出現緩沖區溢出。

 
0x01 緩沖區溢出原理

    程序員通過往程序的緩沖區寫超出其長度的內容,造成緩沖區的溢出,從而破壞程序的堆棧,使程序轉而執行其它指令,以達到攻擊的目的。造成緩沖區溢出的原因是程序中沒有仔細檢查用戶輸入的參數。例如下面程序:

  void function(char *str) {
 
      char buffer[16];
 
      strcpy(buffer,str);
 
      }

 上面的strcpy()將直接把str中的內容copy到buffer中。這樣只要str的長度大於16,就會造成buffer的溢出,使程序運行出錯。存在象strcpy這樣的問題的標准函數還有strcat(),sprintf(),vsprintf(),gets(),scanf()等。

    當然,隨便往緩沖區中填東西造成它溢出一般只會出現“分段錯誤”(Segmentation fault),而不能達到攻擊的目的。最常見的手段是通過制造緩沖區溢出使程序運行一個用戶shell,再通過shell執行其它命令。如果該程序屬於root且有suid(Set User ID,)權限的話,攻擊者就獲得了一個有root權限的shell,可以對系統進行任意操作了。

0x02 緩沖區溢出漏洞攻擊方式

    緩沖區溢出漏洞可以使任何一個有黑客技術的人取得機器的控制權甚至是最高權限。一般利用緩沖區溢出漏洞攻擊root程序,大都通過執行類似“exec(sh)”的執行代碼來獲得root 的shell。黑客要達到目的通常要完成兩個任務,就是在程序的地址空間里安排適當的代碼和通過適當的初始化寄存器和存儲器,讓程序跳轉到安排好的地址空間執行。

     

1)在程序的地址空間里安排適當的代碼

       在程序的地址空間里安排適當的代碼往往是相對簡單的。如果要攻擊的代碼在所攻擊程序中已經存在了,那么就簡單地對代碼傳遞一些參數,然后使程序跳轉到目標中就可以完成了。攻擊代碼要求執行“exec(‘/bin/sh’)”,而在libc庫中的代碼執行“exec(arg)”,其中的“arg”是個指向字符串的指針參數,只要把傳入的參數指針修改指向“/bin/sh”,然后再跳轉到libc庫中的響應指令序列就可以了。當然,很多時候這個可能性是很小的,那么就得用一種叫“植入法”的方式來完成了。

 

當向要攻擊的程序里輸入一個字符串時,程序就會把這個字符串放到緩沖區里,這個字符串包含的數據是可以在這個所攻擊的目標的硬件平台上運行的指令序列。緩沖區可以設在:堆棧(自動變量)、堆(動態分配的)和靜態數據區(初始化或者未初始化的數據)等的任何地方。也可以不必為達到這個目的而溢出任何緩沖區,只要找到足夠的空間來放置這些攻擊代碼就夠了。

    

2)控制程序轉移到攻擊代碼的形式

      緩沖區溢出漏洞攻擊都是在尋求改變程序的執行流程,使它跳轉到攻擊代碼,最為基本的就是溢出一個沒有檢查或者其他漏洞的緩沖區,這樣做就會擾亂程序的正常執行次序。通過溢出某緩沖區,可以改寫相近程序的空間而直接跳轉過系統對身份的驗證。原則上來講攻擊時所針對的緩沖區溢出的程序空間可為任意空間。但因不同地方的定位相異,所以也就帶出了多種轉移方式。

   (1)Function Pointers(函數指針)

       在程序中,“void (* foo) ( )”聲明了個返回值為“void” Function Pointers的變量“foo”。Function Pointers可以用來定位任意地址空間,攻擊時只需要在任意空間里的Function Pointers鄰近處找到一個能夠溢出的緩沖區,然后用溢出來改變Function Pointers。當程序通過Function Pointers調用函數,程序的流程就會實現。

   (2)Activation Records(激活記錄)

       當一個函數調用發生時,堆棧中會留駐一個Activation Records,它包含了函數結束時返回的地址。執行溢出這些自動變量,使這個返回的地址指向攻擊代碼,再通過改變程序的返回地址。當函數調用結束時,程序就會跳轉到事先所設定的地址,而不是原來的地址。這樣的溢出方式也是較常見的。

      3)植入綜合代碼和流程控制

      常見的溢出緩沖區攻擊類是在一個字符串里綜合了代碼植入和Activation Records。攻擊時定位在一個可供溢出的自動變量,然后向程序傳遞一個很大的字符串,在引發緩沖區溢出改變Activation Records的同時植入代碼(權因C在習慣上只為用戶和參數開辟很小的緩沖區)。植入代碼和緩沖區溢出不一定要一次性完成,可以在一個緩沖區內放置代碼(這個時候並不能溢出緩沖區),然后通過溢出另一個緩沖區來轉移程序的指針。這樣的方法一般是用於可供溢出的緩沖區不能放入全部代碼時的。如果想使用已經駐留的代碼不需要再外部植入的時候,通常必須先把代碼做為參數。在libc(熟悉C的朋友應該知道,現在幾乎所有的C程序連接都是利用它來連接的)中的一部分代碼段會執行“exec(something)”,當中的something就是參數,使用緩沖區溢出改變程序的參數,然后利用另一個緩沖區溢出使程序指針指向libc中的特定的代碼段。

0x03 實驗分析

 

1)  main函數在調用f函數前,首先將參入的參數壓入棧中;

2)  接着,將當前程序執行的下一個的位置EIP加入棧中,后面f函數返回時用;

 

 


3)  進入f函數,f函數首先將當前的EBP壓入棧中,接着mov esp, ebp(將EBP指向當前的棧頂),接着以EBP為基礎構建自己的函數幀結構。函數幀結構中包含當前函數的局部變量(攻擊的示例程序的buffer變量及在這里面)

4)  在f函數執行完成后,會將棧中的EBP值彈出,恢復到EBP寄存器中,還原ESP寄存器,接着彈出EIP變量,程序根據EIP變量指向的位置接着執行main函數后面的程序部分。

 

 

 

JMP ESP原理:

函數返回時執行指令:

mov esp,ebp;

pop ebp;

ret;

 

mov esp ,ebp 將esp指向函數返回地址

pop ebp  此時esp棧頂上移+4,esp為返回地址+4

ret  相當於pop EIP

JMP ESP命令地址填充在ESP位置,函數執行並返回,跳轉到ESP,然后執行ESP里的JMP ESP命令,該命令跳轉到原ESP地址+4的地方,也就是后面的shellcode

構造shellcode的思想就是使用payload = 填充偏移+ESP(也就是返回地址+4的地方,填寫JMP ESP命令地址)+shellcode

 0x04 緩沖區概念

緩沖區在系統中的表現形式是多樣的,高級語言定義的變量、數組、結構體等在運行時可以說都是保存在緩沖區內的,因此所謂緩沖區可以更抽象地理解為一段可讀寫的內存區域,緩沖區攻擊的最終目的就是希望系統能執行這塊可讀寫內存中已經被蓄意設定好的惡意代碼。按照馮·諾依曼存儲程序原理,程序代碼是作為二進制數據存儲在內存的,同樣程序的數據也在內存中,因此直接從內存的二進制形式上是無法區分哪些是數據哪些是代碼的,這也為緩沖區溢出攻擊提供了可能。

 

 圖1是進程地址空間分布的簡單表示。代碼存儲了用戶程序的所有可執行代碼,在程序正常執行的情況下,程序計數器(PC指針)只會在代碼段和操作系統地址空間(內核態)內尋址。數據段內存儲了用戶程序的全局變量,文字池等棧空間存儲了用戶程序的函數棧幀(包括參數、局部數據等),實現函數調用機制,它的數據增長方向是低地址方堆空間存儲了程序運行時動態申請的內存數據等,數據增長方向是高地址方向。除了代碼段和受操作系統保護的數據區域,其他的內存區域都可能作為緩沖區,因此緩沖區溢出的位置可能在數據段,也可能在堆、棧段。如果程序的代碼有軟件漏洞,惡意程序會“教唆”程序計數器從上述緩沖區內取指,執行惡意程序提供的數據代碼!

 


原文鏈接:https://blog.csdn.net/weixin_41644777/article/details/79953062
原文鏈接:https://blog.csdn.net/qq_17204441/article/details/90105170

     https://www.cnblogs.com/fanzhidongyzby/archive/2013/08/10/3250405.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM