2013-12-21 19 views
4

我有這樣的功能:堆棧中「缺失」的空間是什麼?

int vulnerableFunc(char *input) 
{ 
    char buffer[256]; 

    memcpy(buffer, input, 1024); 
    return 1; 
} 

當我把它與2000年 「A」,並與OllyDbg的dissassemble它一個32位的Windows XP計算機上,我得到堆棧上的以下地址:

22FB6C Ret Addr    | 
22FB68 Old EBP    |  | 
          | 268 | 
          |  | 264 
22FA60 Buffer for Writing A |  | 

22FA5C ?? RETURN from ntdll.7c92755D to ntdll.7C927553      | 
22FA58 1024                 | 
22FA54 SRC - Ptr to 22FBB0 (22FBB0 = A * 2000 (Original Arg to Func))  | 16 
22FA50 DEST - Ptr to 22FA60 (Copy is Inc From 22FA60)      | 
22FA4C local var end (last local var 22FA50)  

Q1)我只分配256個字節的局部變量,但我從「緩衝區寫入時的」 264個字節,直到「老EBP」,這是爲什麼?

Q2)什麼是 「從ntdll.7c92755D到ntdll.7C927553 RETURN」,在地址22FA5C?不應該只有12個字節的參數memcpy?

enter image description here

+2

的/ GS編譯選項創建檢測棧幀的腐敗,你在這裏鍛鍊的那種棧金絲雀。/RTC還創建額外的空間來檢測錯誤。 –

+0

我認爲Q1的答案可能是因爲的char []相同的char *,這本身是一個64位系統上的8個字節+您所分配的256個字節。再說,我不知道.. – Brandon

+0

@ CantChooseUsernames的操作系統是32位的,對不起,早不說明 – user962460

回答

0

要想象你應該認識到內存的全貌目前價格便宜,相比執行時間,至少在非嵌入式環境。因此,堆棧使用上的差距可能會由於錯誤地小心填充而導致。特別是對於這種情況,我不熟悉MSVC的習慣,但下面顯然可以看出,間隙起始與16字節邊界對齊。這種邊界對於高速緩存訪​​問優化是有用的,並且對於許多ABI是必需的(例如,AMD x86-64 ABI;並且GCC現在甚至對於32位環境也這樣做)。我想這是跳過幾個字節但達到更多執行速度的第一個原因。

的第二個因素是,如果一個調用的函數如下C語言風格的約定(像__cdecl)和之後它不明確棧,堆棧指針後通過它的參數大小的函數調用移動。如果重要的是呼叫者應立即將SP移回;但似乎再次比一個額外的CPU指令更重要。我在GCC之後看到了一個沒有SP返回的函數鏈的情況下的對象代碼示例,所以它被移動了超過100個字節到它的初始位置。這也是一個折衷的問題,可能取決於優化級別,目標CPU調優等。

所以我的建議只是停止擔心,除非你正在開發一個相當有限的資源案例(嵌入式,系統啓動等)