asm x86中变量声明的顺序?

Duk*_*kem 5 c stack-overflow x86 stack gcc

这段代码:

int main()
{

  char buffer[64];
  int check;
...
Run Code Online (Sandbox Code Playgroud)

如你所见,check声明为AFTER buffer,所以在堆栈中,我们必须在堆栈中有check ABOVE buffer吗?

但是,当我用gdb反汇编(x86)时,这就是我得到的:

- > check0xbffff4f8

- > buffer0xbffff4b8

我的问题:堆栈中是否存在局部变量的特定顺序?

另外,我必须告诉你,我在另一台计算机上尝试了同样的事情(x86也是,gcc编译选项相同,但gdb版本和linux发行版不同),顺序不一样......:S

谢谢 !

PS:如果你想了解更多细节,请看截图:(左边是电脑1,右边是电脑2) 在此输入图像描述

osg*_*sgx 3

gcc 中有一个-fstack-protect对堆栈变量进行重新排序的功能,在一些 Linux 操作系统版本中默认打开了近 10 年,特别是 Ubuntu、Redhat、gentoo。自gcc 4.8.3起也是默认值(“4.9 及更高版本启用 -fstack-protector-strong。”)

\n\n

关于 gcc 默认值的 Ubuntu 页面:https ://wiki.ubuntu.com/ToolChain/CompilerFlags

\n\n
\n

工具链中特定于 Ubuntu 的默认编译器标志用于帮助为 Ubuntu 提供额外的安全功能。...\n 默认标志-fstack-protector​​... 首先在 Ubuntu 6.10 中启用。

\n
\n\n

关于堆栈保护的 Ubuntu 页面https://wiki.ubuntu.com/GccSsp

\n\n
\n

gcc 4.1 现在附带了 SSP,这是一项很好的技术,可以减轻许多缓冲区溢出的可利用性。... SSP 提供了一种通过 (1)重新排序堆栈变量来阻止此类漏洞被利用的技术... RedHat 和 gentoo 多年来默认使用 SSP

\n
\n\n

这种重新排序需要对函数的所有局部变量进行多次O(n^2)遍历,这将使长函数的编译速度变慢,例如“为什么编译超过 100,000 行的 std::vector::push_back 需要很长时间?” - /sf/answers/982407541/

\n\n
\n

启用延迟分配时会强制执行-fstack-protect(有时需要对所有堆栈变量重新排序)。..cfgexpand.c

\n
\n\n
969 /* A subroutine of expand_one_var.  VAR is a variable that will be\n970    allocated to the local stack frame.  Return true if we wish to\n971    add VAR to STACK_VARS so that it will be coalesced with other\n972    variables.  Return false to allocate VAR immediately.\n973 \n974    This function is used to reduce the number of variables considered\n975    for coalescing, which reduces the size of the quadratic problem.  */\n976 \n977 static bool\n978 defer_stack_allocation (tree var, bool toplevel)\n980   /* If stack protection is enabled, *all* stack variables must be deferred,\n981      so that we can re-order the strings to the top of the frame.  */\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,gcc 将重新排序所有堆栈变量,并且字符串将位于帧的顶部。尝试-fno-stack-protector禁用选项。

\n\n

与往常一样,gcc 的作者不会-fstack-protect在公共文档https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html中记录其工作原理:

\n\n
\n

-fstack-protector\n 发出额外的代码来检查缓冲区溢出,例如堆栈粉碎攻击。这是通过向具有易受攻击对象的函数添加一个保护变量来完成的。这包括调用 的函数alloca,以及缓冲区大于 8 字节的函数。当函数进入时,这些防护被初始化,然后当函数退出时被检查。如果防护检查失败,则会打印一条错误消息并退出程序。

\n\n

-fstack-protector-all\n 类似-fstack-protector,只是所有函数都受到保护。

\n\n

-fstack-protector-strong\n 与-fstack-protector\xe2\x80\x94 类似,但包含其他受保护的函数,这些函数具有本地数组定义或对本地帧地址的引用。

\n\n

-fstack-protector-explicit\n 类似-fstack-protector,但只保护那些具有该stack_protect属性的函数。

\n
\n\n

我看到的 array-before-locals 的唯一文档是真正的、最好的文档:源代码

\n\n

https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_6-branch/gcc/cfgexpand.c?revision=175029&view=markup#l1526 -expand_used_vars()

\n\n
1533          if (has_protected_decls)\n1534            {\n1535              /* Phase 1 contains only character arrays.  */\n1536              expand_stack_vars (stack_protect_decl_phase_1);\n1537    \n1538              /* Phase 2 contains other kinds of arrays.  */\n1539              if (flag_stack_protect == 2)\n1540                expand_stack_vars (stack_protect_decl_phase_2);\n1541            }\n1542    \n1543          expand_stack_vars (NULL);\n
Run Code Online (Sandbox Code Playgroud)\n\n

第 1 阶段和第 2 阶段变量由https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_6-branch/gcc/cfgexpand.c?revision=175029&view=markup#l1235分隔stack_protect_decl_phase()

\n\n
1235    /* Return nonzero if DECL should be segregated into the "vulnerable" upper\n1236       part of the local stack frame.  Remember if we ever return nonzero for\n1237       any variable in this function.  The return value is the phase number in\n1238       which the variable should be allocated.  */\n1239    \n1240    static int\n1241    stack_protect_decl_phase (tree decl)\n ...\n1243      unsigned int bits = stack_protect_classify_type (TREE_TYPE (decl));\n ...\n1249      if (flag_stack_protect == 2)\n1250        {\n1251          if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))\n1252              && !(bits & SPCT_HAS_AGGREGATE))\n1253            ret = 1;\n1254          else if (bits & SPCT_HAS_ARRAY)\n1255            ret = 2;\n1256        }\n
Run Code Online (Sandbox Code Playgroud)\n\n

stack_protect_classify_typeHAS_ARRAY将仅返回HAS_*_CHAR_ARRAYchar 数组的位(char、unsigned char 和signed char

\n