Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 在c可执行文件中运行数据外壳代码_Assembly_Memory Management_X86_Reverse Engineering - Fatal编程技术网

Assembly 在c可执行文件中运行数据外壳代码

Assembly 在c可执行文件中运行数据外壳代码,assembly,memory-management,x86,reverse-engineering,Assembly,Memory Management,X86,Reverse Engineering,我正在做这个c程序。我使用gcc在64位x64 linux上编译它: #include <stdio.h> char buffer[]={0x90,0x90,0xC3}; int main(int argc, char *argv[]) { void (*fct)(); fct=buffer; fct(); return 0; } #包括 字符缓冲区[]={0x90,0x90,0xC3}; int main(int argc,char*argv[

我正在做这个c程序。我使用gcc在64位x64 linux上编译它:

#include <stdio.h>

char buffer[]={0x90,0x90,0xC3};

int main(int argc, char *argv[])
{
    void (*fct)();
    fct=buffer;
    fct();
    return 0;
}
#包括
字符缓冲区[]={0x90,0x90,0xC3};
int main(int argc,char*argv[])
{
无效(*fct)();
fct=缓冲区;
fct();
返回0;
}
0x90操作码是NOP

0xC3操作码是RET

我想知道我应该怎么做才能运行这个程序。我在运行它时遇到了一个错误


谢谢

TL;DR使用
-z execstack
编译,为您的可执行文件启用Linux的read暗示exec功能。尽管名称不同,但它适用于所有页面,而不仅仅是堆栈


程序出现故障,因为
缓冲区
符号进入
.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;
}
#包括
字符缓冲区[].\uuuu属性(节(“myspect”))={0x90,0x90,0xC3};
int main(int argc,char*argv[])
{
无效(*fct)();
fct=缓冲区;
fct();
返回0;
}
通过
-T
切换到GCC的编译

但是这个不起作用。
GCC使用基于命令行的默认链接器脚本,并使用
-T
开关将其完全替换。
可以使用
-Wl,-verbose
获取GCC使用的脚本并对其进行更新

如果我们首先使用
-c
调用GCC,然后使用LD来拆分编译和链接,那么我们只会得到一个片段,因为这是我们在链接器脚本中放入的内容,从而挫败了我们将
缓冲区
作为唯一可执行数据的所有努力


使用
-z execstack
我们实际上只告诉GCC使用一个链接器脚本来设置
GNU_堆栈
ELF段RWE。
这是一个标记段(大小和lma为零),加载程序使用该标记段为堆栈页设置正确的权限。
-当堆栈设置为可执行时,加载程序将所有可写页面设置为可执行


如果您正在使用外壳代码
-z execstack
将使它变得简单,但是它会使您的应用程序遭受大量的攻击,但我想这是您首先需要的。

部分
.data
可能不可执行。使用
const char buffer
将其放入
.rodata
部分,这是(因为它作为文本段的一部分链接)。谢谢,但它不起作用
const char buffer[]={…}在有优化或无优化的情况下对我有效:。我在我的桌面上运行了它,它退出时没有出错。您采取了哪些不同的措施使其无法工作?更新:较新的
ld
版本将
.rodata
放在不可执行页面中,可能是为了减少ROP/Spectre小工具的数据暴露。有关
-zexecstack
和Linux
READ\u的更多信息意味着它启用的“执行域”: