在以下代码中:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_authentication(char *password) {
char password_buffer[16];
int auth_flag = 0;
strcpy(password_buffer, password);
if(strcmp(password_buffer, "brillig") == 0)
auth_flag = 1;
if(strcmp(password_buffer, "outgrabe") == 0)
auth_flag = 1;
return auth_flag;
}
int main (int argc, char *argv[]){
if(argc < 2){
printf("Usage: %s <password>\n", argv[0]);
exit(0);
}
if(check_authentication(argv[1])){
printf("\n-=-=-=-=-=-=-==-=-=-\n");
printf(" Access Granted\n");
printf("-=-=-=-=-=-=-==-=-=-\n");
}
else {
printf("Access Denied\n");
}
}
如果我运行诸如“AAAAAAAAAAAAAAAAAAAA”之类的东西,某些东西会溢出并导致程序在授予访问权限的情况下运行。我很困惑,因为当我运行gdb调试器时,auth_flag在内存中的password_buffer之前,它从未溢出。
编辑:我知道文本不适合缓冲区,但我正在尝试缓冲区溢出以及如何以受控方式利用它们。是的,我们可以使数组更大,但这不是这个
的重点我想知道是否有人能够告诉我为什么会发生这种情况/什么是溢出导致这种情况。
答案 0 :(得分:5)
AAAAAAAAAAAAAAAAAAAA 的大小为20.您正在使用strcpy
将其复制到大小为16的字符数组。尝试增加password_buffer大小。
为避免溢出,目标指向的数组大小 应足够长,以包含与源相同的C字符串(包括 终止空字符),并且不应该在内存中重叠 源。
答案 1 :(得分:3)
因为您正在将输入复制到太小的缓冲区(并且无缘无故)。您的方法可以实现(没有溢出),如
int check_authentication(const char *password) {
size_t len = strlen(password);
return strncmp(password, "brillig", len) == 0 ||
strncmp(password, "outgrabe", len) == 0;
}
我理解它溢出了自助餐,但为什么会导致访问权限? (auth_flag&gt; 0)
因为auth_flag
是int
之后的内存中的下一个char password_buffer[16];
。对于某些编译器(和操作系统),如果您溢出password_buffer
,则很有可能修改auth_flag
。
答案 2 :(得分:1)
存储器以连续方式存储在堆栈中, 所以有一个char [16]和一个int,表明身份验证是否成功通过。
当你传入指向缓冲区的指针并在没有边界检查本地缓冲区的情况下复制它时,你可能会溢出缓冲区并重写堆栈变量。
当你输入'A'* 20时,前16'A'进入缓冲区,剩下的4'A进入int(通常sizeof(int)是4个字节)。
所以现在,你的int不是0,它是: auth = 0x41414141 因为'A'的ASCII码是0x41。
这篇文章真的很棒 - http://insecure.org/stf/smashstack.html
它列出了堆栈溢出的基础知识,稍后会进一步提高。