为什么这段代码容易出现缓冲区溢出?

Why is this code vulnerable to buffer overflow?

void cpy(char* b) {
    char values[1024];
    strcpy(b, values);
    fprint(values);
}

int main(int argc, char** argv){
    if(argc == 1 || strlen(argv[1]) > 1024) {
        fprint("Nope!\n");
        return 1;
}
    cpy(argv[1]);
    return 0;
}

为什么这段代码容易出现缓冲区溢出?我认为这与 "strcpy" 部分有关,但我不确定...

有什么想法吗?

我认为您使用的是 char 数组,因为没有运算符来标记数组的结尾。

问题是fprint,它不知道你的字符串什么时候结束。它应该以“\0”结尾。因此,如果您在数组中写入所有 1024 字节集的内容。 fprint命令会从内存中读取出来检查是否有'\0'... 会一直读取直到找到结束标记。

短篇小说:strcpy 上的论点被调换了。

长话短说:strcpy 从第二个参数复制到第一个 参数。

让我们快速分析一下。在 main 中,代码检查 argv[1] 的长度最多为 1023+1(NUL 字节)个字符。 argv[1] 然后作为第一个也是唯一的参数传递给 cpy 并在那里作为 b.

可用

cpy中,还有一个未初始化的char数组,名为values,分配为1024个字符长。

现在,strcpy 被指示从 values 复制到 b。我们知道,b是从argv[1]得到的指针,因此最多有space的1024个字符。 values 保留为 1024 个字符,但未初始化。因此,它在这 1024 个字符中可能包含也可能不包含 NUL 字节。

如果它在达到 argv[1] 的边界之前恰好包含一个 NUL 字节,那么一切都很好。如果没有,可能会发生两件事:

  • 如果 argv[1] 正好是 1023 个字符长(+ 终止 NUL 字节),越界读取(在 values 上)和写入(在 argv[1] 上)会发生的。

  • 如果argv[1]长度小于1023个字符,argv[1]会发生越界写入,推而广之,[=也可能发生越界读取18=],如果程序在越界写入后仍然存在。

取决于 fprint 是什么(我的系统上没有它的联机帮助页),代码中可能还有其他问题。