如何防止缓冲区溢出的密码屏蔽

时间:2013-02-25 12:41:30

标签: c buffer buffer-overflow masking

#include <conio.h>
#include <windows.h>
#include <stdio.h>

int main ()
{
char input[255];
int i = 0;
for(;;i++) /* Infinite loop, exited when RETURN is pressed */
{
    char temp;
    temp = getch (); /* Get the current character of the password */
    if (GetAsyncKeyState (VK_RETURN)) /* If the user has pressed return */
    {
        input[i]='\0';
        break;
    }
    input[i] = temp;
    printf("*"); /* Print a star */
}
//printf("%s",input);
if(strcmp(input,"kamal")==0)
{
                     printf("ACCEPTED");
                     }
                     else
                     printf("not");
_getch();
return EXIT_SUCCESS; /* Program was executed successfully */
}

这是我的代码。如何防止缓冲区溢出,如果我输入更多密码,那么我的程序崩溃了。无论如何我能解决这个问题吗?

5 个答案:

答案 0 :(得分:2)

存储在堆栈中的局部变量char输入[255]。在C中没有对数组进行边界检查。问题是当我们添加超过255个字符时,堆栈中存储的另一个变量的值可能会发生变化。这可能会导致崩溃。

一种解决方案是,如果范围(i)小于255,则读取字符并仅分配给输入数组。

#include <conio.h>
#include <windows.h>
#include <stdio.h>

int main ()
{
    char input[255];
    int i = 0;
    int flag = 0;
   for(;;i++) /* Infinite loop, exited when RETURN is pressed */
   {
       char temp;
       temp = getch (); /* Get the current character of the password */
       if (GetAsyncKeyState (VK_RETURN)) /* If the user has pressed return */
       {
           input[i]='\0';
           break;
       }
       if ( i< 255)
       {
            input[i] = temp;
       }
       else     
       {
           flag = 1;
       }

       printf("*"); /* Print a star */
 }
//printf("%s",input);
if(strcmp(input,"kamal")==0 && flag == 0)
{
      printf("ACCEPTED");
 }
 else
       printf("not");
 getch();
 return EXIT_SUCCESS; /* Program was executed successfully */
}

另一种解决方案是动态分配(realloc())输入数组的大小。

答案 1 :(得分:1)

始终检查边界。始终根据缓冲区的长度检查i的值。

答案 2 :(得分:1)

在某些情况下,扩展缓冲区是可以接受的。这很少是理想的,因为无限制的扩展可能会导致其他问题。

在其他情况下,截断输入是可以接受的。这可能是一个选项,但它也不理想。

在这种情况下,当您与不更改的字符串进行比较时,您可以跳过“将输入存储在数组中”阶段,并将输入的字节逐字节地与输入密码进行比较。这样的代码应该看起来像这样,但要小心,因为这是未经测试的:

char password[] = "kamal";
size_t position = 0;
char c = getch();
while (password[position] != '\0' || strchr("\r\n", (unsigned char) c) == NULL) {
    if (c != password[position++] || position == sizeof password) {
        // Password mismatch. Discard the rest of the password, then tell the user...
        while (strchr("\r\n", (unsigned char) c) == NULL) {
            c = getch();
        }
        position = 0;
        puts("Invalid password. Please retry.");
    }
    c = getch();
}

...如果没有缓冲区溢出,那你还担心什么?

答案 3 :(得分:0)

尝试包装类似:

if(i<255) {
    ...
}

...围绕你的角色收集过程。

- 编辑 -

#include <conio.h>
#include <windows.h>
#include <stdio.h>

int main ()
{
char input[255];
int i = 0;
for(;;i++) /* Infinite loop, exited when RETURN is pressed */
{
    if(i < 255) 
    {
        char temp;
        temp = getch (); /* Get the current character of the password */
        if (GetAsyncKeyState (VK_RETURN)) /* If the user has pressed return */
        {
            input[i]='\0';
            break;
        }
        input[i] = temp;
        printf("*"); /* Print a star */
    }
}
//printf("%s",input);
if(strcmp(input,"kamal")==0)
{
                     printf("ACCEPTED");
                     }
                     else
                     printf("not");
_getch();
return EXIT_SUCCESS; /* Program was executed successfully */
}

答案 4 :(得分:0)

如您所示,如果用户提供超过255个字符,则会编程崩溃。

所以,你应该检查已经提供的字符数量,如果达到最大值(你的缓冲区),你应该停止抓取更多的密钥(因为密码已经错了,这并不重要...... ):

#define BUFFER_MAX 255

// +1 so we can always add the 0-terminator
char input[BUFFER_MAX + 1];
do {
    char temp;
    temp = getch (); /* Get the current character of the password */
    // Check if char does fit in the buffer
    if(i < BUFFER_MAX) {
        // add to buffer
        input[i] = temp;
        i++;
    }
    printf("*"); /* Print a star */
    // Check if the user pressed return
} while(GetAsyncKeyState (VK_RETURN) == false);
input[i]='\0';

注意:我也重新安排了你的循环,因为它是'丑陋的'(在这种情况下是不好的做法和不必要的),使用无限循环并打破它们......