c - 缓冲区溢出 - 用金丝雀防御未成功

标签 c buffer-overflow

我正在尝试使用金丝雀保护程序,但有些输入仍然无法通过我的防御。 这是代码:

#include <stdio.h>
#include <stdlib.h>

int urandom() {
    #ifdef __unix__
    int var;
    FILE *fd = fopen("/dev/urandom", "r");
    fread(&var, sizeof(int), 1, fd);
    fclose(fd);
    return var;
    #else
    return 4;
    #endif
}

#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
#include <stdbool.h> 
#include <string.h>

int main(void) {
    int begin_canary = urandom();
    char buff[15];
    int pass = 0;
    int end_canary = begin_canary;

    printf("\n Enter the password : \n");
    gets(buff);

    if(strcmp(buff, "thegeekstuff"))
    {
        printf ("\n Wrong Password \n");
    }
    else
    {
        printf ("\n Correct Password \n");
        pass = 1;
    }

    if(pass)
    {
       /* Now Give root or admin rights to user*/
        printf ("\n Root privileges given to the user \n");
    }

    if (begin_canary != end_canary) {
        printf("Alert! Buffer Overflow detected.\n");
        exit(1);
    }

    return 0;
}

对于包含随机字符的输入:“alskdjasldkjasldkjaslkdlkajsd”,检测到缓冲区溢出并发出“警报!”被打印。 但由于某种原因,对于仅包含一个字符(例如 24 o's)的输入,两个金丝雀具有相同的值,并且程序因段错误而崩溃,并且没有打印“警报!”。

我的金丝雀机制出了什么问题?

谢谢。

最佳答案

您的检查仅验证相同的金丝雀,而不是值没有更改...在您一遍又一遍地输入相同字符的情况下,发生的情况是您用相同的值,因此它们仍然匹配。

为了提高效率,您需要针对未存储在堆栈中的值进行验证,例如将其存储在全局变量中:

int check_canary;
int get_canary(void) {
    if (!check_canary) {
        checK_canary = urandom();
    }

    return check_canary;
}

/* ... */

int begin_canary = get_canary();
char buff[15];
int pass = 0;
int end_canary = get_canary();

然后对照 check_canary 进行检查:

if (begin_canary != get_canary() || end_canary != get_canary()) {
    /* fail */
}

一些值得一提的警告:

  • 上面的代码只会为所有调用选择一个金丝雀值,这可能没问题,因为每次执行程序时它都会改变。
  • 实际上并不能保证堆栈将按照您声明变量的顺序进行布局,因此此检查是否实际上有效取决于有关编译器实现的许多假设。例如,正如 chux 提到的,您可以通过将其包装在结构中来解决这个问题。

关于c - 缓冲区溢出 - 用金丝雀防御未成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29900189/

相关文章:

c - 在 Linux 内核模块中读/写文件

c - 用于接受和打印字符串的非常小的 C 程序中的段错误

c - c中的文件输入输出

c - 使用 write 在文件中写入 int 变量

c - 在 C 中使用宏删除(或有条件地附加)const 修饰符

c++ - C++中的fread和strncpy中的缓冲区溢出

ios - PC 寄存器更改提供的值

C 缓冲区溢出 - 为什么有恒定数量的字节会引发段错误? (Mac OS 10.8 64 位,clang)

c++ - 在 C/C++ 中防止缓冲区溢出

c - 缓冲区溢出 : EIP and jump correctly set but segfault