【发布时间】:2013-12-09 12:34:10
【问题描述】:
我现在正在我的系统编程课上做一个处理缓冲区溢出的练习。由于我无法正确格式化问题陈述,我将对其进行解释。我们有一个大小为 512 个字符的缓冲区。调用名为 getbufn 的函数分配此缓冲区,然后调用 Gets() 函数来接收输入。输入以十六进制值的形式出现在由空格分隔的文本文档中,该文本文档通过另一个提供的程序运行以产生输入。一旦通过gets将输入输入到缓冲区中,getbufn设置eax = 1并返回一个测试函数来检查堆栈是否已损坏。
现在我已经让这个工作了。在最后一个问题中,缓冲区大小为 32,并且设置了堆栈。现在堆栈可以移动了。调用 getbufn 的代码首先在堆栈上分配一个随机数量的存储空间,因此如果您在两次连续执行 getbufn 期间对 %ebp 的值进行采样,您会发现它们的差异高达 ±240。所以我们需要使用 NOP sled 来让我们的代码工作。
首先,这里是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 sled 中间的地址。
所以现在我拥有的是 ~500 NOP OPS,然后是缓冲区末尾的代码 - 这使得总大小为 512 以填充数组。然后我有 12 个字节的十六进制与缓冲区溢出之前这些地址的堆栈中最初的内容相匹配。然后,当返回指令在 getbufn 结束时执行时,我还有 4 个字节指向 NOP 雪橇中间的地址。由于某种原因,这不起作用。如果我在我的数组和返回地址之间放置 5 个字节的垃圾,我就会发现堆栈已损坏。如果我在我的数组和返回值之间放置 6 个字节的垃圾,我会遇到分段错误。在我的计算中,我认为我需要 12 个字节才能从数组到返回地址,所以我在这里做错了什么?
【问题讨论】:
-
提供您的 C 代码示例。 (假设您正在生成 C 作为 post 标记它。)问题可能会更明显。