緩衝區溢出原理及ShellCode編寫

緩衝區溢出屬於非常有名的漏洞之一,其大體含義為:緩衝區溢出是超出程序內存設定範圍,數據溢出後程序發生異常,黑客可以利用緩衝區溢出執行指定代碼,重寫棧中的返回地址(ret_Addr)內容來執行任意操作。

本文從棧的介紹、shellcode代碼示例、切入思路三個方面進行體系化介紹。

一、棧的介紹

棧是一種內存使用方式,採用LIFO(Last In,First Out,先進後出),像手槍的子彈夾一樣。

緩衝區溢出原理及ShellCode編寫

示例代碼

當調用func函數時,在跳轉至函數起始地址的瞬間,棧的形式如下圖:

緩衝區溢出原理及ShellCode編寫

棧的存儲形式

基地址為內存高位,從後向前(向地址遞減方向)增長, $1、$2、$3為方法變量地址,ret_addr為main函數返回目標地址。

接下來 esp/rsp逐漸遞減,為函數內部的局部變量分配內存空間,a&buff為方法內變量,存儲形式如下圖:

緩衝區溢出原理及ShellCode編寫

方法內變量存儲

這時,如果數據溢出,超過了原本分配給buff數組的內存空間,數組後面的ebp、ret_addr以及傳遞給函數的參數都會被溢出的數據覆蓋掉,如下圖:


緩衝區溢出原理及ShellCode編寫

內存溢出覆蓋內容

一旦 ebp和ret_addr被覆蓋掉,將會引發嚴重的後果,ret_addr存放的為main函數返回目標地址,也就是說,如果覆蓋ret_addr,攻擊者就可以讓程序跳轉至任意地址,如果攻擊者事前準備一段shellcode,然後讓程序跳轉至這段代碼,也就相當於成功攻擊了”可執行任意代碼的漏洞“。

二、shellcode介紹

關於shellcode方面,簡單的shellcode代碼如下:

緩衝區溢出原理及ShellCode編寫

shellcode示例代碼

該代碼功能就是啟動/bin/sh。通過該代碼,我們可以將其轉換為彙編語言,通過gdb方式對程序進行調試,gdb指令常用操作如下:

r:程序運行;

b:設置斷點,加星號可傳遞地址;

c:在斷點處中斷後,繼續運行程序;

x/[數字]i:對指定數量的指令進行反彙編;

x/[數字]x:顯示指定長度數據;

x/[數字]s:以字符串形式顯示指定長度數據;

set:向寄存器或內存寫入;

q:退出;

通過對程序進行gdb調試,我們可清晰瞭解程序運行方式,如下圖:

緩衝區溢出原理及ShellCode編寫

反彙編

上圖0X0000000000400550至558位置為execve方法的三個參數,倒序形式存放,我們在40055b位置設置斷點該位置為execve方法調用,當執行該方法時,我們通過r指令通過斷點使用x/8x指令,確認rsp內容是否包含“/bin/sh”。

瞭解系統執行原理後,可通過彙編語句形成代碼,代碼如下:

緩衝區溢出原理及ShellCode編寫

shellcode彙編代碼

具體代碼解讀如下:

xor eax,eax //清空寄存器;

push eax //入棧

push 0x68732f2f //sh

push 0x6e69622f //bin

mov al, 0x3b //0x3b表示其系統調用號的十六進制,十進制為59,本系統execve的系統調用編號為59。需要根據自身系統來確定。

將彙編轉換成16進制

執行以下語句:

nasm -f elf testshell.asm

ld -m elf_i386 -o testshell testshell.o

最終形成16進制code碼,如下圖:

緩衝區溢出原理及ShellCode編寫

彙編轉16進制

將上圖16進制代碼整合後,形成執行文件,

緩衝區溢出原理及ShellCode編寫

執行文件

當我們執行該文件時,會出現段錯誤,是因為系統有保護機制,全局數據段shellcode不能被運行,即出現段錯誤。可安裝execstack,隨後執行:execstack -s 程序名,“故意”關掉 GCC 的堆棧段不可執行保護機制,便可執行成功,如下圖:

緩衝區溢出原理及ShellCode編寫

執行shellcode成功

三、切入思路

通過第一章介紹,我們瞭解緩衝區溢出原理及如何利用該原理進行滲透。通過第二章我們實現了shellcode代碼編寫。如何利用緩衝區進行shellcode切入才是重重之重,一般我們不知道程序的返回地址,因此只能進行推測,我們可儘量在內存空間中填充NOP(0x90)指令(可通過gdb進行查看),然後將shellcode放在最後,這樣就可以提高shellcode執行的概率。


本文源自我之前在其它博客所寫文章,因之前內容不夠詳實,所以進行了再次編輯,通過本次再梳理使其內容更為豐富,具有更高的可讀性。通過以上內存溢出原理和簡單的shellcode,提供了一種代碼切入思路,在具體實施過程中難度還是非常大的。


分享到:


相關文章: