TL;DR编译用-z execstack
为您的可执行文件启用 Linux 的 read-implies-exec 功能。尽管有这个名字,但它适用于all页,而不仅仅是堆栈。
该程序出现故障是因为buffer
符号进入.data
该部分依次与其他部分一起进入映射为读写的 ELF 段,但是不可执行.
为了使buffer
可执行文件的最佳做法是创建一个带有 RWE 标志的新 ELF 段并为其分配一个新段,然后告诉 GCC 将buffer
在这个新部分中。
这可以做到,原则使用以下链接器脚本:
PHDRS
{
MYSEG PT_LOAD FLAGS (7);
}
SECTIONS
{
MYSECT : { *(MYSECT) } : MYSEG
}
,更改源:
#include <stdio.h>
char buffer[] __attribute__ ((section ("MYSECT"))) ={0x90,0x90,0xC3};
int main(int argc, char *argv[])
{
void (*fct)();
fct=buffer;
fct();
return 0;
}
和编译通过-T
切换到海湾合作委员会。
但是这个won't work.
GCC 使用基于命令行和-T
开关完全取代它。
可以通过以下方式获取 GCC 使用的脚本-Wl,-verbose
并更新它。
如果我们通过首先调用 GCC 来分割编译和链接-c
然后 LD,我们只会得到一个片段,因为这就是我们放入链接器脚本中的内容 - 从而破坏了我们所有的努力only buffer
唯一的可执行数据。
With -z execstack
我们实际上只告诉 GCC 使用链接器脚本来设置GNU_STACK
ELF 段 RWE。
这是一个标记段(大小和 lma 为零),加载程序使用它来设置堆栈页的正确权限。
但实际上它是用作兼容性开关- 当堆栈设置为可执行文件时,加载程序将设置all将可写页作为可执行文件。
如果你正在玩 shellcode-z execstack
会让这一切变得简单,但是它会让您的应用程序遭受大量攻击,但我想这就是您首先需要的。