5

这是一项任务,但我在基本理解方面遇到了问题。

易受攻击的代码:

int choc(char *arg)
{
  char buf[400];
  snprintf(buf, sizeof buf, arg);
  return 0;
}

我知道 arg 需要是一个格式字符串,它将用我要执行的代码的地址覆盖返回地址。但是我在创建格式字符串时遇到了麻烦。

所以,格式字符串需要具备的东西:

  1. 返回指令的地址,我需要覆盖
  2. %x 的列表
  3. 我将在返回地址上写的值。这将是我要执行的代码的地址。

为了得到返回地址,我只需要查看gdb中'ret'指令的地址,对吗?%x 的目的到底是什么?以及如何在格式字符串中对要执行的代码的地址进行编码?

我做了一个测试:使用gdb我发现我的buf的地址是0xbffffba0。我生成 arg 为 "\xa0\xfb\xff\xbf_%x.%x.%n"; 这不应该在地址 0xbffffba0 的缓冲区的开头写入一些值吗?但是我得到一个段错误。我究竟做错了什么?

任何帮助,将不胜感激!

4

4 回答 4

2

不应该是 buf的"\xa0\xfb\xff\xbf"地址,而是堆栈上的返回地址的位置(这是您希望覆盖的值)。您必须使用 gdb 找到该值。

然后,您需要在格式字符串中放入足够的 %x ,以便您的 %n 将从堆栈中读取该值并写入您指定的地址。您还需要使用正确的字段大小,以便 %n 实际上写入正确的值。

于 2012-04-11T20:53:03.267 回答
1

您尝试利用的漏洞称为格式字符串漏洞。为了进一步研究这个话题,我会推荐这个链接或名为“黑客:剥削的艺术”的书。

于 2012-04-11T20:07:22.910 回答
0

从调试器中读取值通常是不够的。一些平台具有地址空间随机化安全功能,这将导致特定对象的地址在程序调用之间有所不同。相反,您需要找出返回地址在堆栈上的存储位置(相对于snprintf调用)并在那里覆盖它。这是非常特定于 CPU 的。你在开发什么平台?

return使用调试器,在汇编级别单步执行该函数的代码,并在遇到命令之前检查堆栈。确保堆栈和返回地址看起来像您认为的那样。这应该会给你一个关于问题出在哪里的线索。此外,您可以尝试在 之前使用调试器手动修改堆栈,return以验证您定位的位置实际上是返回地址。

于 2012-04-11T20:13:09.680 回答
-2

答案是否定的,您不仅需要“ret”指令的地址。您实际需要的是“ret”指令加载的内存位置。看看这张图:

http://post.queensu.ca/~trd/377/tut5/stack.html

您的目标是覆盖“退货地址”。

我将继续尝试编写一个简短的程序来显示这个指针(即将到来)。

更新:我有坏消息。我也想不通。我写过:

#include <stdio.h>
#include <stdlib.h>

void bar()
{
    printf("Bar function\n");
}

void foo()
{
    void (**p)(void);
    asm volatile("movl %%ebp, %0\n\t" : "=r"(p) : : "%0");
    p += 1;
    *p = bar;
}

int main()
{
    foo();
    return 0;
}

这会导致分段错误,而不会在bar(). 我希望它能够工作......所以现在我和你一样困惑。谁能解释为什么bar()不在我的代码中执行?

于 2012-04-11T20:50:46.427 回答