【问题标题】:Understanding stack in linux了解Linux中的堆栈
【发布时间】:2012-11-25 22:37:10
【问题描述】:

我有一个小的(易受攻击的)C 示例:

#include <unistd.h>

int main(int argc, char *argv[])
{
    char buff[100];

    if(argc < 2)
    {
        printf("Syntax: %s <input string>\n", argv[0]);
        exit (0);
    }

    strcpy(buff, argv[1]);
    return 0;
}

我编译它:

gcc -o basic_overflow basic_overflow.c -fno-stack-protector -fno-builtin

当我用 gdb 打开这个程序时,反汇编是这样的:

Dump of assembler code for function main:
   0x08048424 <+0>: push   ebp
   0x08048425 <+1>: mov    ebp,esp
   0x08048427 <+3>: and    esp,0xfffffff0
   0x0804842a <+6>: add    esp,0xffffff80
...

在 main 中设置断点(在序言之后)。由于我们有一个本地缓冲区,我希望我的堆栈帧大小为 100 字节。但是当我执行 $ebp-$esp 时,我可以看到结果实际上是 136。

平台:Linux user-VirtualBox 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:50 UTC 2011 i686 i686 i386 GNU/Linux

编译器:gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 调试器:GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2 我做错了什么?

【问题讨论】:

  • 你在哪个平台上?你的编译选项是什么?哪个编译器版本?在不了解上述事实的情况下,很难回答有关低级细节的问题。
  • 反汇编显示什么?
  • gcc 不也将 argc 和 argv 放入堆栈吗?
  • 所以我们编译没有优化,想知道为什么代码不是很好。我们不应该那样做!
  • @BoPersson,有缺陷的想法; -O 实际上可能增加帧大小,因为内联合并多个帧。

标签: c linux assembly disassembly


【解决方案1】:

这不仅仅是局部变量的大小——一般来说,还有填充到平台 ABI 指定的大小、损坏的寄存器、alloca() 区域... - 检查例如 this nice picture

【讨论】:

  • 在您的情况下,例如printf 的传出参数在堆栈中预先保留(ebp-8chebp-90h),它们的值在保留槽中 moved,而不是在调用之前被 pushed(设置 -mno-accumulate-outgoing-args 禁用)。此外,在堆栈上创建带有填充的 argc (ebp-78h) 和 argv (ebp-68h) 的副本(将 -mpreferred-stack-boundary=2 设置为禁用。)一旦提供了上述两个选项,根据需要从esp 中仅减去64h
【解决方案2】:

缓冲区地址很难获得。我也有这个问题。有一篇好文章教你如何smash the stack. 但在我的电脑上,ubuntu 12.04,gcc 4.6 或 4.4.7,我测试了最新的 eggshell.c,结果是核心转储。 他将shellcode放在环境变量中。但是它必须找到环境变量地址。我也发现smash the stack有时没有效果。任何人可以帮助让它运行??

【讨论】:

  • 一些人已经为这篇文章发布了针对较新版本的 linux 的补充。这个主题的一个更现代的参考可能是 John Erickson 的“Hacking. The Art of Exploitatio”。尽管标题很吵,但它是一本非常好的书。第二版带有一个准备好的 Ubuntu 环境。nostarch.com/hacking2.htm
猜你喜欢
  • 2014-06-10
  • 2018-07-18
  • 1970-01-01
  • 1970-01-01
  • 2020-10-03
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多