【问题标题】:Stack Overflow - Buffer Location in Memory堆栈溢出 - 内存中的缓冲区位置
【发布时间】:2011-06-28 17:01:39
【问题描述】:

我正在研究缓冲区溢出(在 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 地址。谁能解释为什么不是?

【问题讨论】:

  • 你的'a' 字符是如何变成0xaaaaaaaa 的?您是在向我们展示整个节目吗?
  • 你确定array的地址是0xbffff078,而不是0xbffff048?也许strcpy 的后奏曲试图做一些堆栈的事情,覆盖了 0xbffff070 的 8 个字节?
  • 内存转储是否来自与寄存器跟踪相同的程序调用?
  • 嗨,我想我解决了:aaz 你的回答帮助了我。我当然在想什么,答案是如此明显。输出不是来自程序的同一次调用:一个来自 gdb 运行,另一个直接来自 bash,所以当然不一样,因为 gdb 在堆栈上使用更多空间,所以它的地址从 bash 调用开始,局部变量较低。我会标记为:问题已解决。谢谢

标签: c++ c linux security debugging


【解决方案1】:

编译器决定在堆栈上同时为局部变量传递给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()的两个指针。

【讨论】:

  • 是的,我弄错了,它是 0xbffff048,但这仍然不能解释为什么它应该在 0xbffff078 而不是 0xbffff048,它应该在哪里(因为堆栈上的可用空间是为它保留的)。
  • 我猜想在进行内存转储之前,您在没有参数的情况下重新启动了程序。所以堆栈帧更高,缓冲区填充0xaa而不是0x41(“a”)。是这样吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-23
  • 1970-01-01
  • 2012-07-15
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
相关资源
最近更新 更多