堆栈溢出 - 内存中的缓冲区位置

时间:2011-02-16 22:10:30

标签: c++ c linux security debugging

我正在研究缓冲区溢出(在IA32架构上),我想用这个示例程序澄清一个特别的事情:

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

我在执行汇编代码时跟踪了ebp,esp寄存器更改: 函数main的汇编代码转储:

   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 <strcpy@plt>
   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地址。任何人都可以解释为什么不是吗?

1 个答案:

答案 0 :(得分: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()的两个指针。