Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.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
C 我在腐蚀哪个回信地址?_C_Stack Overflow - Fatal编程技术网

C 我在腐蚀哪个回信地址?

C 我在腐蚀哪个回信地址?,c,stack-overflow,C,Stack Overflow,我有一个非常简单的学习堆栈溢出的程序 #include <stdio.h> #include <string.h> int main(int argc, char **argv) { char buf[128]; if(argc < 2) return 1; strcpy(buf, argv[1]); printf("Hello\n"); return 0; } #包括 #包括 int main(int argc,字符**argv)

我有一个非常简单的学习堆栈溢出的程序

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {

  char buf[128];

  if(argc < 2) return 1;

  strcpy(buf, argv[1]);

  printf("Hello\n");

  return 0;
}
#包括
#包括
int main(int argc,字符**argv){
char-buf[128];
如果(argc<2)返回1;
strcpy(buf,argv[1]);
printf(“Hello\n”);
返回0;
}
策略是在argv[1]中提供大字符串以溢出buf并覆盖返回地址。但是哪一个回信地址?我想这是我输入strcpy之前保存的地址,所以当我们从strcpy正常返回时,我们将执行printf

但是,在我使用外壳代码有效负载溢出缓冲区后,我将此返回地址更改为我的外壳代码。我看到printf仍在执行。即使我再添加几个printf,它们都将被执行。显然,我更改的返回地址只影响主函数的返回,否则我甚至不应该看到正在执行的printfs


为什么会发生这种情况?当我溢出缓冲区以更改外壳代码的返回地址时,主程序是否会直接跳转到外壳代码而不执行下一个printf?

buf
是函数的一个变量,因此它存在于堆栈上。缓冲区溢出将损坏堆栈

当程序执行进入
main
时,
main
的返回地址位于堆栈上。接下来,为
buf
分配128个字节。
strcpy
调用的第二个参数长度超过128字节,它在为
buf
分配的空间之外涂鸦,可能会损坏返回地址

接下来,将
printf
的参数和返回地址(指向
printf
之后的语句)推送到堆栈上,执行跳转到
printf
函数。执行请求的打印后,返回地址从堆栈中弹出,并使用下一条语句继续执行

最后,
返回0语句。分配给堆栈上局部变量的空间被恢复,并且(损坏的)返回地址从堆栈弹出,执行“返回”到由用于损坏内存的字符串字节给定的损坏地址

简而言之,缓冲区溢出只能在堆栈上已经写入的信息(过去)上涂鸦。它不能在尚未写入堆栈(未来)的信息上涂鸦。这就是为什么损坏后的
printf
调用仍然正确执行的原因;损坏的数据尚未使用

堆栈,在strcpy调用:

xxxx
xxxx
return address from strcpy
&buf    (arg to strcpy)
argv[1] (arg to strcpy)
buf[0]
...
buf[127]
return address from main
argc     (arg to main)
argv[0]  (arg to main)
argv[1]  (arg to main)
...
损坏发生在
buf[127]
之后。
strcpy
的返回未损坏


注意:堆栈上也可能没有“返回自strcpy
”;编译器可能已内联函数调用。

在典型的PC上,堆栈向下增长。这意味着调用strcpy时堆栈的内存布局如下所示:

/^^^^更高的地址^^^
[材料]
[主要客户的回信地址]
[buf[127]]
[buf[126]]
...
[buf[1]]
[buf[0]]
[参数2(指向argv[1]的指针]]
[参数1(指向buf的指针)]
[strcpy的返回地址(指向main)]
[strcpy中的局部变量]
//下位地址

通过溢出
buf
(写入
buf[128]
buf[129]
,等等),您可以写入
main
的调用帧(最重要的是,
main
的返回地址)。你不能影响strcpy的调用帧,因为它在
buf
之前存在于内存中。

printf的地址从来都不在堆栈上,所以你怎么能覆盖它呢?@melpomene,我的意思是在调用strcpy之前,我保存返回地址。然后strcpy会破坏返回地址,因为我给出了一个大字符串。当strcpy返回时,它跳转到我的外壳代码,并且不应该执行printf。如果堆栈向下增长,你不能弄乱strcpy的堆栈帧,因为它在内存中的
buf
之前。@melpomene,我明白你的意思了。巴夫住在梅因。如果你把它写下来作为答案,我会接受的。这是缓冲区溢出,不是堆栈溢出。这回答了与这个问题相关的问题吗?我的意思是,询问者显然知道堆栈将被损坏,这是一个关于损坏的特定问题。