乙個正常的程式在記憶體中通常分為程式段,資料端和堆疊三部分。程式段裡放著程式的機器碼和唯讀資料,這個段通常是唯讀,對它的寫操作是非法的。資料段放的是程式中的靜態資料。動態資料則通過堆疊來存放。
在記憶體中,它們的位置如下:
/――――――――\
記憶體低端
程式段―――――――――
資料段―――――――――
堆疊\―――――――――
/記憶體高階
堆疊是記憶體中的乙個連續的塊。乙個叫堆疊指標的暫存器(
sp)指向堆疊的棧頂。堆疊的底部是乙個固定位址。堆疊有乙個特點就是,後進先出。也就是說,後放入的資料第乙個取出。它支援兩個操作,
push
和pop
。push
是將資料放到棧的頂端,
pop是將棧頂的資料取出。
在高階語言中,程式函式呼叫和函式中的臨時變數都用到堆疊。為什麼呢?因為在呼叫乙個函式時,我們需要對當前的操作進行保護,也為了函式執行後,程式可以正確的找到地方繼續執行,所以引數的傳遞和返回值也用到了堆疊。通常對區域性變數的引用是通過給出它們對
sp的偏移量來實現的。另外還有乙個基址指標(
fp,在
intel
晶元中是
bp),許多編譯器實際上是用它來引用本地變數和引數的。通常,引數的相對
fp的偏移是正的,區域性變數是負的。
在c語言中,靜態變數是分配在資料段中的,動態變數是分配在堆疊段的。緩衝區溢位是利用堆疊段的溢位的。
當程式中發生函式呼叫時,計算機做如下操作:首先把引數壓入堆疊;然後儲存指令暫存器
(ip)
中的內容,做為返回位址
(ret)
;第三個放入堆疊的是基址暫存器
(fp)
;然後把當前的棧指標
(sp)
拷貝到fp
,做為新的基位址;最後為本地變數留出一定空間,把
sp減去適當的數值。
比如說下面這個程式:
void function(int a, int b, int c)
void main()
假設我們在
linux
下,用gcc
對這段原始碼進行編譯,產生彙編**輸出:
$ gcc -s -o example1.s example1.c
看看輸出檔案中呼叫函式的那部分:
pushl $3
pushl $2
pushl $1
call function
這就將3
個引數推入堆疊裡了,並呼叫
function()
。指令call
會將指令指標
ip壓入堆疊。在返回時,
ret要用到這個儲存的
ip。在函式中,第一要做的事是進行一些必要的處理。每個函式都必須有這些過程(為了保護呀,不然就找不到了。):
pushl �p
movl %esp,�p
subl $20,%esp
這幾條指令將
ebp,基址指標放入堆疊。然後將當前
sp拷貝到
ebp。然後,為本地變數分配空間,並將它們的大小從
sp裡減掉。由於記憶體分配是以字為單位的,因此,這裡的
buffer1用了8
位元組(2
個字,乙個字
4位元組)。
buffer2
用了12
位元組(3
個字)。所以這裡將
esp減了
20。這樣,現在,堆疊看起來應該是這樣的。
低端記憶體
高階記憶體
buffer2 buffer1 sfp ret a b c
< ------ [ ] [ ] [ ] [ ] [ ] [ ] [ ]
棧頂棧底
那是什麼導致了溢位呢?緩衝區溢位就是在乙個緩衝區裡寫入過多的資料。要怎麼樣利用呢?看下面這個程式:
void function(char *str)
void main()
這個程式是乙個經典的緩衝區溢位編碼錯誤。函式將乙個字串不經過邊界檢查,拷貝到另一記憶體區域。當呼叫函式
function()
時,堆疊如下:
低記憶體端
高記憶體端
buffer sfp ret *str
< ------ [ ] [ ] [ ] [ ]
棧頂 棧底
很明顯,程式執行的結果是
"segmentation fault (core
dumped)"
或類似的出錯資訊。因為從
buffer
開始的256
個位元組都將被
*str
的內容'a'
覆蓋,包括
sfp,
ret,
甚至*str
。'a'
的十六進值為
0x41
,所以函式的返回位址變成了
0x41414141,
這超出了程式的位址空間,所以出現段錯誤。可見,緩衝區溢位允許我們改變乙個函式的返回位址,在這個例子中,我們可以通過修改
0x41414141
來改變程式返回後的入口位址。同樣通過這種方式,就可以改變程式的執行順序了。
存在象strcpy
這樣的問題的標準函式還有
strcat(),sprintf(),vsprintf(),gets(),scanf(),
以及在迴圈內的
getc(),fgetc(),getchar()等。
**
堆疊的緩衝區溢位
我們在做專案的過程中遇到過乙個問題 開啟底層板卡,對板卡進行讀寫的時候,板卡的控制代碼莫名奇妙改變了,而我們沒有顯式改變過它。其實這是一類問題,就是區域性變數莫名其妙被修改。這是由於堆疊的緩衝區溢位造成的,主要現象是 1.某些區域性變數莫名其妙被改 2.函式返回的時候崩潰 主要原因是 1.陣列越界 ...
堆疊式緩衝區溢位
通過這段 大家可以實驗一下,使用者的輸入真的把函式原先的返回位址給改變了,從而也就改變了程式的執行流向,而具體流向 也是完全可以控制的,而利用這類漏洞就是要將程式的執行流向重定向到一段執行使用者 這裡指攻擊者 希望的功能 例如種植特洛伊木馬 的機器碼處,這樣就能完全控制有這種漏洞的計算機了,當然,實...
簡單的緩衝區溢位
這是乙個簡單的緩衝區溢位程式,是我在oday上面學到的,嘿嘿嘿,每個人寫的shellcode不一樣所以實現的目的也不一樣。大家自由發揮吧。include include include include define password 1234567 int verify password char ...