首先來看看C語言溢位小程式
這個程式看著好像是沒有任何問題,執行是這樣的:
我們主要關注這個check函式,首先定義了一個int型別的陣列且其中個數為8個,下一行將fun函式地址存入arr[9]中,其實這裡我們可以看到定義陣列的時候個數也就是8,實際到達的下標是7,所以我們最多能取陣列的值為arr[7],連8都不到,這裡我們獲取fun函式地址的時候卻存到了下標為9的地址,跳了一個下標。首先來了解下陣列的儲存方式
高地址 低地址
這是我簡單畫的陣列儲存的堆疊圖,陣列是使用連續的記憶體空間來儲存的,說白了和區域性變數的儲存差異不大,我們現在開始分析程式碼:
現在我們記住ebp和esp的值
現在我們來把這個堆疊圖畫一下
這裡按F11進入函式體中,call進函式會將它下一行地址壓入棧中,然後調到函式體,這時再來看看堆疊的變化:
接著往下走,我們看看函式體中的程式碼:
進入函式後將ebp壓入棧中,然後將esp中的值移動到ebp中,之後esp-60h(60h/4h=18h=24)提升棧空間,再來看看此時的堆疊:
接下來將ebx,esi,edi依次推入棧中,下面的程式碼到rep指令是將緩衝區填充為CCCCCCCCCh,再來看看堆疊的變化:
接著往下走
這裡是將陣列存到緩衝區中,從低地址向高地址儲存,20h/4h=8h=8從esp的位置向上數八格就是儲存1的位置,依次儲存下來,再來看看棧中的變化:
這裡是取fun的地址出來並轉換為int型別,然後存入陣列下標為9的地方,我們看看ebp+4這個地址執行前後的變化
執行前
經過這個對比之後,ebp+4剛好是這個儲存返回地址的地方,我們繼續往下走
異或eax之後,依次取出edi,esi,ebx,然後將ebp的值移動到esp中,隨後取出ebp,再來看看堆疊變化:
上面的操作是使堆疊平衡,接著來看
接著執行了一個ret,ret的操作相當於push eip,F11一下,看看eip
就這樣進入了fun函式
本次分析就是分析緩衝區都溢位了為何還能執行fun函式,到這裡我們可以知道溢位之後覆蓋掉了程式的返回地址,所以導致程式進入了fun函式中。溢位並不可怕,可怕的是不會除錯啊!