在堆栈上执行代码

时间:2016-03-30 15:16:59

标签: c linux gcc compilation stack

我是gcc编译基础知识的新手。据我所知,出于安全原因,堆栈是不可执行的。那我们怎样才能在堆栈上执行代码。我在一个函数返回指向函数的指针的情况下观察到了这一点。它不返回指向代码的指针,而是指向堆栈上具有要执行的代码的位置。如何在linux中允许这样做?

已经由gcc完成了。我想知道它怎么可能?

这是c代码:

     #include<stdio.h>

    typedef int (* funcptr) ();


funcptr f ()
{

  int g ()
  {

}
return (&g);
}


main ()
{
  funcptr fp;
  fp = f();

  fp ();

 }

以下是汇编代码在堆栈中生成代码的部分:

    #Starting trampoline code. The trampoline code is a small
    #piece of code set up inside the stack!!!. This code, when
    #executed, loads ecx with the static link and calls the
    #function g
        movb    $-71, (%eax)    # This is B9, the opcode for
                                  "movl address_in_next_loc ecx"
                                  this, when executed, will
                                  load the static link in ecx

        movl    %edx, 1(%eax)   # address_in_next_loc=ebp-16
                                  the static link effectively

        movb    $-23, 5(%eax)   # This is E9. the opcode for
                                  jmp addr_nxt_ins + offset_
                                  in_nxt_loc
                                  Since the offset_in_nxt_loc 
                                  is &g - addr_nxt_ins, this
                                  results in a jump to &g

        movl    $g.1831, %ecx   # Stores &g - addr_nxt_ins
        leal    10(%eax), %edx  #
        subl    %edx, %ecx  # 
        movl    %ecx, %edx  # 
        movl    %edx, 6(%eax)   # 
    #End of trampoline code

3 个答案:

答案 0 :(得分:1)

您将从堆中分配内存而不是堆栈。但是,由于现代处理器/操作系统允许区分包含代码的内存区域和包含数据的内存区域(出于明显的安全原因),这可能无法解决问题。

答案 1 :(得分:1)

您的C代码包含嵌套函数,因此GCC会将生成的目标文件的.note.GNU-stack部分设置为x(表示需要可执行堆栈)。

调用链接器时,它会检查此部分的所有提供的目标文件。由于其中一个输入文件的.note.GNU-stack设置为x,因此链接器知道堆栈必须是可执行文件。

为了表明这一点,最终可执行文件中的ELF标题GNU_STACK添加了标记PF_X

命令:

readelf -l a.out | grep -A1 GNU_STACK

应该允许您看到RWE标志而不是RW

内核在为进程设置内存映射时专门查找此标头。

original patch

中的更多详细信息

答案 2 :(得分:0)

我想你假设堆栈本身就是代码。情况可能并非如此。 Stack只是指向代码区域的指针。

您可以详细了解堆栈的工作原理here

This SO answer表明函数指针或函数本身需要代码位置