【问题标题】:Buffer overflow weird behaviour缓冲区溢出怪异行为
【发布时间】:2013-08-29 01:55:19
【问题描述】:

我已经安装了名为 DVL(该死的易受攻击的 linux)的 linux 发行版,并且我正在使用缓冲区溢出漏洞进行锻炼。 我写了两个几乎相同的程序,它们容易受到 bof 的攻击:

//bof_n.c
#include <stdio.h>
void bof() {
  printf("BOF");
}

void foo(char* argv) {
  char buf[10];
  strcpy(buf, argv);
  prinf("foo");
}

int main(int argc, char* argv[]) {
  if (argc >= 1) {
    foo(argv[1]);
  }
  return 0;
}

//bof.c
#include <stdio.h>
void bof() {
  printf("BOF!\n");//this is the only change
}

void foo(char* argv) {
  char buf[10];
  strcpy(buf, argv);
  prinf("foo");
}

int main(int argc, char* argv[]) {
  if (argc >= 1) {
    foo(argv[1]);
  }
  return 0;
}

之后我编译了它们,并且在这两种情况下都获得了 bof() 函数地址(例如,objdump -d bof.o | grep bof)。让我们将这样一个地址 ADDR 命名为 4 字节。

我还发现,如果我在 buf 变量中写入 32 字节,则 EIP 寄存器被完全覆盖(我无法在此处复制 gdb 的输出,因为它在虚拟机上)。

现在,如果我这样做:

./bof `perl -e 'print "\x90"x28 . "ADDR"'`

我明白了:

fooBOF!
Segmentation fault

如果我尝试相同的方法但使用 bof_n,我只会收到“分段错误”消息。 因此我尝试增加重复 ADDR 值的次数,我发现如果重复至少 350 次,我会得到想要的结果。但是,我并没有准确地得到上面的输出,而是一个接一个地得到一长串“BOF”消息。我试图只获得一个“BOF”消息,但显然我做不到(我得到或为零,或一长串)。 为什么会这样?有什么想法吗?

我在 gcc 3.4.6 中使用 DVL

【问题讨论】:

  • perl -e 'print "\x90"x28 . "ADDR"' 的大小 > buf[10] 的大小。 30+ > 10.
  • perl -e 'print "\x90"x28 . "ADDR"' 的结果大小也可能大于 10。
  • @mbratch:软件所做的一切当然都是完全确定的。

标签: c buffer-overflow exploit


【解决方案1】:

你的目标是什么?

你真的应该为此使用调试器,试试GDB Debuggergdb。有了它,您可以看到系统中当前正在发生的事情的内存/寄存器/堆栈和反汇编。

我猜在第一个函数中,长度只有 3 个字符的字符串被优化为\x42\x4f\x46\x00,因此反汇编可能会略有不同。

C 源代码几乎无关紧要,您需要反汇编或 fuzz 两个二进制文件以找到适合 NOP 雪橇的大小。

【讨论】:

  • 好吧,也许我不是很精确。我实际上正在使用 GDB 和 bof_n 示例,我终于发现问题是何时必须打印消息“BOF”。 eip 被正确覆盖,执行跳转到 bof() 函数,唯一的问题是(我不知道为什么)printf 在这种情况下不起作用。也许是因为飞速,我会尝试使用 fprintf 和 STDERR。
【解决方案2】:

我找到了解决方案。问题在于消息的打印,而不是缓冲区溢出漏洞本身。 事实上,在 bof_n 示例中,寄存器 eip 也被正确覆盖,并且程序流在 bof() 函数中被正确重定向。问题是,显然,在分段错误之前没有刷新标准输出,因此没有显示任何消息。

相反,使用fprintf(stderr, "BOF");,我终于得到了“BOF”消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 2013-04-11
    相关资源
    最近更新 更多