C 为什么我的外壳代码测试程序会产生segfault?

C 为什么我的外壳代码测试程序会产生segfault?,c,x86,buffer-overflow,shellcode,C,X86,Buffer Overflow,Shellcode,我正试图编写一个简单的C程序来测试给定的外壳代码字符串是否在我的机器上工作(64位),但是每次尝试运行下面的代码都会导致分段错误。即使这个“外壳代码”只是一些nop指令和一个中断,有人能解释出哪里出了问题吗?我曾经有过类似的由其他人编写的外壳代码和外壳代码测试程序的经验,是否有一些我不知道的最近引入的缓解措施?我正在运行:5.9.0-kali1-amd64#1 SMP Debian 5.9.1-1Cali2(2020-10-29)x86_64 GNU/Linux #包括 #包括 #定义代码“\x

我正试图编写一个简单的C程序来测试给定的外壳代码字符串是否在我的机器上工作(64位),但是每次尝试运行下面的代码都会导致分段错误。即使这个“外壳代码”只是一些nop指令和一个中断,有人能解释出哪里出了问题吗?我曾经有过类似的由其他人编写的外壳代码和外壳代码测试程序的经验,是否有一些我不知道的最近引入的缓解措施?我正在运行:
5.9.0-kali1-amd64#1 SMP Debian 5.9.1-1Cali2(2020-10-29)x86_64 GNU/Linux

#包括
#包括
#定义代码“\x90\x90\x90\x90\x90\x90\x90\x90\xCC”;
int main(int argc,char const*argv[]
{
int(*func)();
func=(int(*)()代码;
(int)(*func)();
}
这是我用来编译代码的命令/标志

gcc -fno-stack-protector -z execstack -no-pie -m64 -o shell shell.c

末尾的0xCC是
INT3
或a,这将导致
跟踪/断点陷阱

如果您将0xCC更改为0xC3,它将返回而不会出错

一种可能的缓解方法是,如果编译器将常量字符串放入.rdata而不是.text中

而不是:

#define CODE #define CODE "\x90\x90\x90\x90\x90\x90\x90\xCC";
试一试


末尾的0xCC是
INT3
或a,这将导致
跟踪/断点陷阱

如果您将0xCC更改为0xC3,它将返回而不会出错

一种可能的缓解方法是,如果编译器将常量字符串放入.rdata而不是.text中

而不是:

#define CODE #define CODE "\x90\x90\x90\x90\x90\x90\x90\xCC";
试一试


谢谢我原以为把字符串常量放在main的作用域中,它会被放在堆栈上,但我想不会。@matt-你可以用很少使用的
alloca()
函数来保证堆栈的位置。@matt:这是一个字符串文本,你只在main中引用;该引用的类型为
char*
而不是
char[]
。想象一个字符串文字,比如一个匿名的
静态字符数组[]
——它总是会出现在
.rodata
中。(除非将其用作本地
char数组[]=“foo”的初始值设定项)
但它并不完全是一个字符串文字。那么
-z execstack
即使在现代Linux内核上也能工作,因为它实际上只使堆栈本身可执行,而不是每个可读页面。至少如果您使用
\u内置\uuuuuuuuuu clear\u缓存
,它在x86上只是告诉GCC存储的数据不是死的,而是用作代码。)谢谢我原以为把字符串常量放在main的作用域中,它会被放在堆栈上,但我想不会。@matt-你可以用很少使用的
alloca()
函数来保证堆栈的位置。@matt:这是一个字符串文本,你只在main中引用;该引用的类型为
char*
而不是
char[]
。想象一个字符串文字,比如一个匿名的
静态字符数组[]
——它总是会出现在
.rodata
中。(除非将其用作本地
char数组[]=“foo”的初始值设定项)
但它并不完全是一个字符串文字。那么
-z execstack
即使在现代Linux内核上也能工作,因为它实际上只使堆栈本身可执行,而不是每个可读页面。至少如果您使用
\u内置\uuuuuuuuuu clear\u缓存
,它在x86上只是告诉GCC存储的数据不是死的,而是用作代码。)