void foo(char *data){
char name[10];
printf("%p\n%p\n%p\n%p\n");//打印当前程序栈内存
strcpy(name, data);//覆盖返回地址
}
void hack(void){
puts("another place");
}
int main(){
char buf[10];
char buf2[10];
scanf("%s", buf);
foo(buf);
return 0;
}
以上是经典的缓冲区溢出攻击,当buf中输入超过10(16)字节,将会覆盖buf2中的内容;如果写入更多字节数,可以改变寄存器中保存的地址,使得被调用函数执行完成后返回到另一个函数的入口地址。
问题:
当前保护机制下,只能覆盖buf2中内容,但是即便跳过很长的内存保护的区域依然找不到记录被调函数返回地址的位置。1.在linux下不采用任何内存保护方法编译源代码的方法?2.关于现在内存保护机制下缓冲区溢出攻击的可能形式。
Stack protector 的实现是在在栈上放一个canary随机值,在函数调用完成后,检查这个值是否原样,如果不是原样则证明栈被破坏了。
你的原代码是有问题的。如果你输入的东西溢出了缓冲区,那么它就会覆盖scanf的返回地址,那么就无法正确返回,也就不能调用foo了。
我猜你想要的是这样:
void foo(char *data){
scanf("%s", data);
printf("%pn%pn%pn%pn%pn%pn%pn%pn%pn%pn%pn%pn%pn%pn%pn%pn");
}
int main(){
char buf[10];
char buf2[10];
foo(buf);
return 0;
}
有些常识需要知道,不是你输入超出20个字符长度就一定能将返回地址覆盖。局部变量在栈上的分配,并不是紧凑的,通常情况下都会进行align,并且按16字节对齐。
所以,如果你输入很多字符(超过64?),你是能得到segment fault的。
但你没有办法改正确返回地址,一个是因为ALSR,Address space layout randomization,另一个是因为canary本身是随机值,你也无法覆盖正确,最终逃不过检查。
所以,你只能搞出segmentfault的效果,却并不能覆盖返回地址还能让代码继续正常运行。
1.在linux下不采用任何内存保护方法编译源代码的方法?
GCC有一个-fno-stack-protector参数。默认情况下stack-protector是启用的,GCC检测到函数参数类型为char *,并且没有限定长度时,它就会在函数调用前,在栈上放一个canary。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。