缓冲区溢出问题:数组比应该更短?

时间:2013-11-24 22:32:31

标签: c stack buffer overflow

我正在我的系统编程类中进行练习,处理缓冲区溢出。由于我无法正确格式化问题陈述,我只想解释一下。我们有一个大小为512个字符的缓冲区。调用名为getbufn的函数来分配此缓冲区,然后调用Gets()函数来接收输入。输入以文本文档中的十六进制值的形式出现,由空格分隔,空格通过另一个提供的程序运行以生成输入。一旦输入通过gets输入缓冲区,getbufn设置eax = 1并返回测试函数,检查堆栈是否已损坏。

现在我已经让这个工作了。在最后一个问题中,缓冲区大小为32,并且堆栈已设置。现在堆栈可以移动。调用getbufn的代码首先在堆栈上分配一个随机存储量,这样如果你在两次连续执行getbufn期间对%ebp的值进行采样,你会发现它们相差±240。所以我们需要使用NOP底座来使我们的代码工作。

首先,这是getbufn函数:

80491e8:       55                      push   %ebp
80491e9:       89 e5                   mov    %esp,%ebp
80491eb:       81 ec 18 02 00 00       sub    $0x218,%esp
80491f1:       8d 85 f8 fd ff ff       lea    -0x208(%ebp),%eax
80491f7:       89 04 24                mov    %eax,(%esp)
80491fa:       e8 db fa ff ff          call   8048cda <Gets>
80491ff:       b8 01 00 00 00          mov    $0x1,%eax
8049204:       c9                      leave  
8049205:       c3                      ret    
8049206:       90                      nop
8049207:       90                      nop

我发现了一些事情。当在地址0x8049205处调用ret时,esp = 0x556832F4。所以我知道返回地址就在那里。在lea之后的mov指令中,ebp总是等于0x556832F0(所以我不知道我的prof通过它移动了240),而eax总是等于0x556830e8。对我来说,这意味着我的数组从0x556830e8开始,到0x556832E8结束。然后为了获得返回地址,我需要再写12个字节才能到达0x556832F4。然后最后的4个字节应该是NOP底座中间的地址。

所以现在我所拥有的是~500 NOP OPS然后我的代码在缓冲区的末尾 - 这使得总大小512填满了数组。然后我有12个字节的十六进制,在缓冲区溢出之前与这些地址上最初的堆栈相匹配。然后,当在getbufn结束时执行返回指令时,我还有4个字节指向NOP底座中间的地址。这不是出于某种原因。如果我在我的数组和返回地址之间放入5个字节的垃圾,我就知道堆栈已损坏。如果我在我的数组和返回值之间放入6个字节的垃圾,我会遇到分段错误。在我的计算中,我认为我需要12个字节才能从我的数组到返回地址,所以我在这里做错了什么?

1 个答案:

答案 0 :(得分:0)

这听起来很像来自Bryant和O'Hallaron的CS:APP缓冲区溢出实验室,它听起来也像是最后一级。

让我给你一些指示:

  1. 堆栈仍然可执行。
  2. 你知道缓冲区是~512bytes,(可能更多用于对齐,当我做这个赋值时它是540字节)
  3. 您知道$ebp的差异不会超过+/- 240个字节。
  4. 您知道将调用一个函数来验证堆栈
  5. 知道这一切你可以做到以下几点:

    1. 将shell代码放入512字节缓冲区。
    2. 一些NOPS可以让你跳到缓冲区的某个随机点(由于+/- 240 ASLR,这很重要)
    3. 在那个缓冲区中你可以有一些读取$esp的shell代码,并将{512}字节(或者是缓冲区的实际大小)添加到$esp,这样就可以获得价值被覆盖的已保存的$ebp。然后,您可以执行一些计算,并将垃圾ebp替换为您刚刚计算的正确垃圾。
    4. 回到你需要的地方。
    5. 进一步解释一些事情。为什么我们需要缓冲区中的NOP(\x90)?由于基址被随机化+/- 240字节,缓冲区大小为512字节,因此您可以进行计算并确定性地始终返回缓冲区中的某个位置。当你返回缓冲区的某个地方时,它会点击NOPS(\x90)并滑入你的shell代码。

      如果您有任何其他问题,请随时提出。