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

我正在研究缓冲区溢出(在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

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

解决方法:

编译器决定同时为局部变量和传递给堆栈上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在程序调用之间是不同的,尤其是取决于参数的数量. 0xbffff040或0xbffff070.

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

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

上一篇:如何确定Java进程是否在调试器中启动?


下一篇:PHP和shell_exec