2011-02-16 218 views
3

我研究缓冲区溢出(上IA32架构),我想澄清一个特别的事情这个示例程序:堆栈溢出 - 缓冲区的内存位置

int main(int argc, char **argv) { 
    char array[512]; 
    if(argc > 1) 
    strcpy(array, argv[1]); 
} 

我跟着EBP,ESP寄存器变化 转储的汇编代码功能主要:汇编代码的执行期间

0x080483c4 <+0>:  push ebp 
    0x080483c5 <+1>:  mov ebp,esp 
    0x080483c7 <+3>:  sub esp,0x208 
    0x080483cd <+9>:  cmp DWORD PTR [ebp+0x8],0x1 
    0x080483d1 <+13>: jle 0x80483ed <main+41> 
    0x080483d3 <+15>: mov eax,DWORD PTR [ebp+0xc] 
    0x080483d6 <+18>: add eax,0x4 
    0x080483d9 <+21>: mov eax,DWORD PTR [eax] 
    0x080483db <+23>: mov DWORD PTR [esp+0x4],eax 
    0x080483df <+27>: lea eax,[ebp-0x200] 
    0x080483e5 <+33>: mov DWORD PTR [esp],eax 
    0x080483e8 <+36>: call 0x80482f4 <[email protected]> 
    0x080483ed <+41>: leave 
    0x080483ee <+42>: ret 

在ESP,EBP寄存器值分别为:

program start 
    esp: 0xbffff24c 
    ebp: 0xbffff2c8 

push ebp 
    esp: 0xbffff248 
    ebp: 0xbffff2c8 

mov ebp,esp 
    esp: 0xbffff248 
    ebp: 0xbffff248 

sub esp,0x208 
    esp: 0xbffff040 
    ebp: 0xbffff248 

strcpy call (ebp is overwritten) 
    esp: 0xbffff250 
    ebp: 0x41414141 

当我输入520个字符'a'时,导致EBP,EIP被溢出。而内存是这样的:

Lower Memory Addresses 
0xbffff070:  0xbffff078  0xbffff492  0xaaaaaaaa  0xaaaaaaaa 
0xbffff080:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
0xbffff090:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
0xbffff0a0:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
0xbffff0b0:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
... 
0xbffff270:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
Higher Memory Addresses 

我感兴趣的事情是:为什么缓冲的起始地址是0xbffff078,如果ESP指着地址0xbffff040(当局部变量的地方 - 缓冲 - 上保留堆栈)。缓冲区应该保存在0xbffff040地址。有人可以解释为什么它不是?

+0

你的''a'`字符是如何变成'0xaaaaaaaa`的?你是否向我们展示了整个项目? – 2011-02-16 22:19:24

+0

你确定`array`的地址是0xbffff078,而不是0xbffff048?也许后面的`strcpy`试图做一些堆栈的东西,它覆盖了0xbffff070的8个字节? – aschepler 2011-02-16 22:20:14

回答

5

编译器决定为本地变量分配空间,同时将参数传递给堆栈中的strcpy()

sub esp,0x208    # 0x200 for array, 8 for 2 pointers 
... 
mov DWORD PTR [esp+0x4],eax # argv[1], not push 
mov DWORD PTR [esp],eax  # array 

所以阵列实际上是在esp+8(或ebp-0x200,因为编译器是指它)。

编辑:
esp是该程序的调用之间不同,特别是依赖于参数的个数。 0xbffff0400xbffff070

缓冲区为0xbffff048,而不是0xbffff040。或者在0xbffff078,而不是0xbffff070。询问调试器在哪里检查。

在内存转储缓冲区有0xaa(我想这是在调用之前未初始化的内存)。在此之前,您可以看到传递给strcpy()的两个指针。