首先,我正在使用这个编译标志:
gcc -fno-stack-protector -z execstack -m 32
好的,请看下面的代码
int main(int argc, char *argv[]){
char pass[8];
char logged = 'n';
strcpy( pass, argv[1] );
if( logged == 'y' ){
printf("Hello \n");
} else {
printf("Run hacker :(\n");
}
return 0;
}
和第二个代码
int main(int argc, char *argv[]){
char logged = 'n';
char pass[8];
strcpy( pass, argv[1] );
if( logged == 'y' ){
printf("Hello \n");
} else {
printf("Run hacker :(\n");
}
return 0;
}
这些代码容易受到堆栈溢出攻击。 (通过'yyyyyyyyy'作为arg将通过测试)
但为什么?第二个代码中的局部变量的顺序与第一个代码中的不同。所以在堆栈上推送局部变量的队列也应该是另一个,但它不是吗?
答案 0 :(得分:0)
首先,堆栈溢出漏洞与堆栈损坏不完全相同。
此代码正在编写一个在堆栈上(在您的框架中)分配的自动变量。编译器在堆栈上为传递字符串保留了8个字节。如果写入超过8个字节,则会破坏pass []数组旁边的堆栈上的其他内容。真的不重要;它将被破坏,这就是堆栈损坏的含义。
通过一些技巧,可以生成一个输入(argv [1])字符串(实际上是指令字节流),它将与main的返回指令对齐,从而可以强制执行代码。这就是漏洞。
您似乎明白堆栈中变量的顺序只决定了什么以及如何被破坏,如果您使用-fno-stack-protector关闭堆栈保护,您应该看到您的预期,加上减去编译器强加的确切堆栈布局。在保护的情况下,两种情况都应该倾倒堆栈粉碎回溯和诊断。
请注意,不同的linux distrubution将no-stack-protector默认设置为不同的值,但只要您在命令行上显式控制它就可以设置。 -z execstack选项是一种处理是否允许在堆栈上执行的机制;在这里它是无关紧要的,因为你的代码只是破坏了堆栈。