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

ele*_*nor 3 c c++ linux security debugging

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

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

我在执行汇编代码时跟踪了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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

当我输入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
Run Code Online (Sandbox Code Playgroud)

我感兴趣的是:为什么缓冲区从地址0xbffff078开始,如果ESP指向地址0xbffff040(当局部变量的位置 - 缓冲区 - 在堆栈上保留时).缓冲区应保存在0xbffff040地址.任何人都能解释为什么不是吗?

aaz*_*aaz 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
Run Code Online (Sandbox Code Playgroud)

所以数组实际上是esp+8(或者ebp-0x200,正如编译器所指的那样).

编辑:
esp程序的调用之间是不同的,特别是取决于参数的数量.0xbffff0400xbffff070.

缓冲区在0xbffff048,而不是0xbffff040.或者0xbffff078,不是0xbffff070.询问调试器检查的位置.

在缓冲区的内存转储中0xaa(我猜这是在调用之前未初始化的内存).在这之前你可以看到传递给它的两个指针strcpy().