2013-12-21 21 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调优等。

所以我的建议只是停止担心,除非你正在开发一个相当有限的资源案例(嵌入式,系统启动等)