【问题标题】:Mapping C function to Call Stack将 C 函数映射到调用堆栈
【发布时间】:2015-05-07 04:59:57
【问题描述】:

我一直在阅读有关调用堆栈以及操作系统如何将函数数据存储在堆栈上的内容。到目前为止,我所做的所有阅读(herehereherehere)都对函数在堆栈中的存储方式有类似的看法。但我试图将其应用于具有两个函数的示例 C 程序,只是为了看看这些数据是如何存储的,但我得到的结果与我到目前为止所阅读的所有内容不一致。我可能错误地解释了数据,所以我希望有人能做出一些澄清。

问题

我正在研究缓冲区溢出示例,以及如何利用它们

据我所知,当我调用一个函数(例如:func1(int a))时,系统所做的是为参数分配空间(在我们的示例中为整数8字节)分配空间并保存返回地址的调用函数。然后它将保存基指针(EBP),之后它将为局部变量(local v1,local v2 ....)分配空间,然后是其余数据。在我的示例中,我有两个局部变量(char buff4 和 char *ptr)。这意味着将分配 8 个字节的空间。根据我的假设,我认为要到达 RETURN 地址,我只需要在缓冲区中写入 12 个字节的数据,这将导致覆盖 RETURN 地址(我会利用它)。 12bytes = 4 个字节的数据缓冲区 + 4 个字节的 EBP 数据,然后最后 4 个字节应该是我要写入的地址来代替当前的 RETURN 地址。但是,到目前为止,我必须传递 16 字节的数据才能这样做。我不明白额外的 4 字节数据来自哪里。我用gdb(我不是很精通)来找出来,但我做不到。我是否错过了计算堆栈中添加的内容?还是局部变量是逆序添加的(*s指针先,buff后)?

代码

char *func1(int n){
    char buff[4];
    char *ptr = malloc(n+1);
    fgets(ptr,n+1,stdin);
    strncpy(buff,ptr,n+1);
    return ptr;

}

【问题讨论】:

  • 请注意,不是操作系统通过堆栈完成所有这些工作,而是您自己的程序通过您的编译器生成的机器代码。
  • 您应该知道,C 规范实际上并没有提到“堆栈”,如何调用函数以及如何存储参数和局部变量取决于实现。关键是:每个编译器可能会做的有点不同。此外,您正在做的是利用未定义的行为,并犯一个小错误,该行为将是未定义的。
  • 谢谢,我只是在学习它,所以试图以某种方式了解它是如何工作的
  • 请注意,堆栈帧可能与 16 字节边界对齐。

标签: c function stack callstack


【解决方案1】:

看起来丢失的数据是'n',它也在堆栈上。

另外,请注意编译器没有义务将 'buff' 的内存放在你的 'ptr' 之前,所以在某些情况下你可能还必须覆盖 ptr。

此外,在许多情况下,临时变量也是在堆栈上计算的,因此您的 n+1 也可能会隐式添加一些堆栈空间。我想这段代码会使用不同数量的堆栈空间,例如,如果打开/关闭优化。

一个更简单的例子(作为测试),可能是将 ptr 传递给函数,并执行以下操作:

char buf[1];
strcpy(buf, ptr);

【讨论】:

    猜你喜欢
    • 2021-08-30
    • 2011-01-22
    • 2016-08-08
    • 1970-01-01
    • 2022-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多