栈溢出漏洞的细节点

程序1

#include <stdio.h>
#include <string.h>
void input(char *s)
{
gets(s);
}
int main()
{
char s[10];
input(s);
return 0;
}

从源代码可以看出,这个程序明显存在栈溢出漏洞,那么我想问利用这个漏洞可以覆盖input()的和main()的返回地址吗?

答案是利用这里的漏洞只能覆盖main()的返回地址不能覆盖input()的返回地址

原因很简单,因为变量s是在main函数里创建的,当gets()读取字符串存入s的地址时,由于s的地址位于main函数的栈空间,并且因为栈是由高地址向低地址增长的,而写入数据是从低地址向高地址存储的,所以无论怎么栈溢出,都不可能覆盖到input()的返回地址的

如图所示: 输入的字符串存在地址0x7fffffffdfc0处,在input()的返回地址(main()+35)下方(地址更高处),所以无论输入多少个字符也无法覆盖input()的返回地址。

image-20211102214631158

程序1

#include <stdio.h>
#include <string.h>
void input(char *s)
{
char dest[4];
scanf("%s",s);
strcpy(dest,s);
}
int main()
{
char s[100];
input(s);
return 0;
}

从源代码可以看出,这个程序明显存在栈溢出漏洞,那么我想问利用这个漏洞可以覆盖input()的和main()的返回地址吗?

答案是利用这里的漏洞不仅覆盖main()的返回地址而且还能覆盖input()的返回地址

原因很简单,因为变量dest是在input函数里创建的,当strcpy()复制字符串s存入dest的地址时,造成栈溢出时,可以覆盖到input()的返回地址

如图所示:0x7fffffffdfc0里储存着变量s保存的字符串,0x7fffffffdfa0里储存着变量dest保存的字符串,所以当dest溢出时可以造成比它位于更高地址的返回地址的覆盖

image-20211102220117668

总结

从以上两个例子可以看出,栈溢出漏洞可以覆盖哪些返回地址取决于变量定义的位置位于哪个函数之内。例如:定义在a函数的变量s,对于变量s发生的栈溢出漏洞至多能覆盖a函数以前所有函数的返回地址,但是不能覆盖a函数的子函数b的返回地址。出现这样情况的原因是因为栈是由高地址向低地址增长的,而写入数据是从低地址向高地址存储的