我有以下用于测试缓冲区溢出的代码:
#include <stdio.h>
#include <string.h>
int PasswordOkay() {
char GoodPassword = 'F';
printf("The memory address of GoodPassword is: %p\n", (void*) &GoodPassword);
char Password[8];
printf("The memory address of password is: %p\n", (void*) &Password);
gets(Password);
if(!strcmp(Password, "SPOCKSUX"))
GoodPassword = 'T';
return (GoodPassword == 'T');
}
int main() {
puts("Enter Password:");
if(PasswordOkay())
puts("Hello, Dr. Bones");
else
puts("Access denied.");
}
在32位上,溢出正常且9T正常,因为密码使我成功登录。
在64位上,我有以下内存地址:
The memory address of GoodPassword is: 0x7fff1b452a8f
The memory address of password is: 0x7fff1b452a80
因此,为了尝试在那里的溢出,我输入了16T作为密码。登录消息再次成功出现,但同时也出现了分段错误(但不是32位)。
我的问题是:为什么会在64位上出现分段错误?应该不应该吗?由于我只覆盖GoodPassword。
附加说明:文件是使用gcc编译的,并已启用和禁用优化程序。
最佳答案
您输入了16个字符(TTTTTTTTTTTTTTTT
),但是还必须将字符串的终止空字符视为第17个字符,这意味着在GoodPassword
之后,堆栈框架中还将覆盖另一个字节。GoodPassword
和password
之间的地址差为15(0x7fff1b452a8f - 0x7fff1b452a80
),这意味着GoodPassword
是第16个字符,并且您的堆栈帧中还有一个空字节的另一个字节。
如果紧随其后的字节(堆栈GoodPassword
中的较高字节)是帧指针地址或保存的堆栈指针地址(甚至是安全金丝雀值!)的一部分,则可能存在段错误。