Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/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
x86-32上C中的堆栈溢出和分段错误_C_Segmentation Fault_Stack Overflow_Callstack - Fatal编程技术网

x86-32上C中的堆栈溢出和分段错误

x86-32上C中的堆栈溢出和分段错误,c,segmentation-fault,stack-overflow,callstack,C,Segmentation Fault,Stack Overflow,Callstack,我有一个关于C中堆栈溢出的问题。 我写了一个小测试程序,所以当我以8as开始它时,我得到了我所期望的,我写在第二个buf的边界上,因此buf1是空的,因为后面的零是buf1中的第一个元素。 到目前为止还不错,如果我用16号试一下,它也可以,用17号试一下。但我想这里会有一个断层。。。segfault在24 As之后出现。为什么呢?我在x86-32 ubuntu、debian和suse上进行了测试。始终在24字节后插入故障。。。 在使用相同代码的AMD64系统上,我在32之后得到SEGFULT,正

我有一个关于C中堆栈溢出的问题。 我写了一个小测试程序,所以当我以8as开始它时,我得到了我所期望的,我写在第二个buf的边界上,因此buf1是空的,因为后面的零是buf1中的第一个元素。 到目前为止还不错,如果我用16号试一下,它也可以,用17号试一下。但我想这里会有一个断层。。。segfault在24 As之后出现。为什么呢?我在x86-32 ubuntu、debian和suse上进行了测试。始终在24字节后插入故障。。。 在使用相同代码的AMD64系统上,我在32之后得到SEGFULT,正如我所预期的。。。 但是为什么在x86-32上24秒之后呢

包括
#包括
/*
*$gcc-O0-Wall-fno堆栈保护器缓冲区.c-o缓冲区
*
*美元/缓冲区AAAAA
*buf1:测试
*buf2:测试
*buf1:
*buf2:AAAAA
*
*美元/缓冲区aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
*buf1:测试
*buf2:测试
*buf1:AAAAAAAA
*buf2:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
*分段故障(堆芯转储)
*/
静态无效漏洞利用(常量字符*输入字符串)
{
char-buf1[8];
char-buf2[8];
strcpy(buf1,“测试”);
strcpy(buf2,“测试”);
printf(“buf1:%s\n”,buf1);
printf(“buf2:%s\n”,buf2);
strcpy(buf2,输入字符串);
printf(“buf1:%s\n”,buf1);
printf(“buf2:%s\n”,buf2);
}
int main(int argc,const char*argv[]
{
如果(argc>1)
利用(argv[1]);
返回0;
} 

您试图猜测编译器生成的内存布局。编译器可以自由地以任何合适的方式布局代码。但是,堆栈帧必须包含:

  • 参数(由调用方推送)
  • 返回地址(由CPU推送)
  • 需要保留的寄存器。这取决于目标体系结构
  • 局部变量(由被调用方分配)
在您测试的x86机器上,本地变量和返回地址之间有8个字节,在x64机器上有16个字节。如果被调用方保存了寄存器,则它们将存储在此空间中:

func:
PUSH BP
MOV BP, SP
SUB SP, privateSpace
...
MOV SP, BP
POP BP
RET argSize

因此,返回地址后面的空格包含存储的帧指针BP。如果调用方不再使用基指针,则不会注意到此覆盖。函数使用其基指针返回,但如果函数通过系统调用退出(我记得主方法在这个意义上是“特殊的”,但我不能提供我的声明),则永远不会使用损坏的基指针,并且会忽略损坏)

要测试它是否是基指针,请执行以下操作:

  • 创建第三级调用(main、caller、callee)
  • 记录被调用方的返回,访问局部变量,再次记录,然后返回
  • 如果在访问局部变量时发生segfault,则很可能是基指针
其他可能的原因:

  • 发生错误时使用的一些调试信息
  • 金丝雀(堆栈保护器),从未测试过,但无论如何都分配了它。没有任何症状
  • 参数数()会破坏调用方的堆栈指针,如果调用方不进行另一次调用,则堆栈指针将不被注意。症状:如果呼叫者再次呼叫,则呼叫者出现故障
  • 指针。不应出现在普通功能中
其他尝试事项:


在损坏前后在被调用方中进行内存转储以查看布局。存储的基指针应指向堆栈空间(调用者的堆栈帧)。返回地址应指向代码空间(靠近当前IP)。char*参数是一个指针。旁边是另外两个参数(“>>>”和"我认为对这类事情感到好奇是件好事,但您正在调用未定义的行为,并且您执行或未执行的任何segfault都是实现定义的。Hm只是试图了解堆栈的行为。使用-fno stack protector编译以查看会发生什么。在覆盖buf1之后,我会直接覆盖返回地址但是正如我在三个不同的系统上所说的,不是在16字节之后,而是总是在24字节之后。我不明白在两个BUF之后堆栈上有什么。可能是sfp和ret地址…如果我对函数的返回地址要求过高,那么segmentationfault就会出现,对吗?好的,我在gdb中启动了我的程序,并对main和函数进行了反汇编.但我不确定输出结果。但它太长,无法在此处发布:(反汇编显示编译后的代码使用标准的输入例程。
leave
指令相当于上面的尾声中的
mov
pop
。内存转储指的是堆栈帧,但反汇编也很有用。我将查看代码。我不知道为什么,但在我看来字节是-0。)x8(%ebp)到-0x1(%ebp)确实没有使用。我特别喜欢编译器处理清理的方式。它不推和弹出,而是写在堆栈指针下面,根本不需要清理。所以在开始覆盖返回地址和更改返回地址之前,我确实有8个“空闲”字节?
func:
PUSH BP
MOV BP, SP
SUB SP, privateSpace
...
MOV SP, BP
POP BP
RET argSize