这是一项任务,但我对基本理解有疑问。
易受攻击的代码:
int choc(char *arg)
{
char buf[400];
snprintf(buf, sizeof buf, arg);
return 0;
}
我知道arg需要是一个格式字符串,它会用我想要执行的代码的地址覆盖返回地址。但是我在创建格式字符串时遇到了麻烦。
因此,格式字符串需要具有的内容:
为了获得返回地址,我只需要查看gdb中'ret'指令的地址吧? %x的目的究竟是什么?我如何用格式字符串编码我想要执行的代码的地址?
我做过的测试: 使用gdb我发现我的buf的地址是0xbffffba0。我生成了arg为“\ xa0 \ xfb \ xff \ xbf_%x。%x。%n”;这不应该在地址0xbffffba0的buff开头写一些值吗?但是我得到了一个段错误。我做错了什么?
任何帮助将不胜感激!
答案 0 :(得分:2)
"\xa0\xfb\xff\xbf"
不应该是buf的地址,而应该是堆栈上返回地址的位置(这是您要覆盖的值)。你必须使用gdb找到这个值。
然后,您需要在格式字符串中放入足够的%x,以便%n将从堆栈中读取该值并写入您指定的地址。您还需要使用正确的字段大小,以便%n实际上写入正确的值。
答案 1 :(得分:1)
您尝试利用的漏洞称为格式字符串漏洞。 有关此主题的进一步调查,我建议THIS链接或书籍“Hacking:剥削艺术”。
答案 2 :(得分:0)
从调试器中读取值通常是不够的。某些平台具有地址空间随机化安全功能,这些功能将导致特定对象的地址在程序调用之间不同。相反,您需要找出堆栈中存储返回地址的位置(相对于snprintf
调用)并在那里覆盖它。这是特定于CPU的。您正在开发什么平台?
使用调试器,在程序集级别上逐步执行该函数的代码,并在遇到return
命令之前检查堆栈。确保堆栈和返回地址看起来像您认为的那样。这应该可以为您提供问题所在的线索。此外,您可以尝试在return
之前使用调试器手动修改堆栈,以验证您定位的位置实际上是返回地址。
答案 3 :(得分:-1)
答案是否定的,你不需要“回复”的地址。指令。你真正需要的是记忆中的位置,即“回归”。指令加载。看看这个图表:
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()
在我的代码中没有执行?