【C语言】scanf和strcpy这类关键字和函数为什么不安全,使用VS编译会报错

首先先说解决方法:

在程序最顶端加入这个代码段

#define  _CRT_SECURE_NO_WARNINGS

这主要是微软的 C 运行时库实现将这些函数标记为不安全,主要原因是这些函数缺乏对输入长度的边界检查,容易导致缓冲区溢出漏洞。

会产生这样的报错:

即:

C4996 ‘strcpy’: This function or variable may be unsafe. Consider using
strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See
online help for details.

下面是关于scanfstrcpy为什么可能不安全的一些主要原因:

1.
缓冲区溢出:scanfstrcpy函数不对输入进行边界检查,导致可能发生缓冲区溢出。这意味着当输入的字符串长度超过目标缓冲区的容量时,会覆盖相邻内存空间的数据。攻击者可以利用这种漏洞来执行恶意代码或者修改程序的行为。

2.
字符串终止符\0处理问题:strcpy函数在拷贝字符串时,需要确保目标缓冲区具有足够的空间来容纳源字符串,以及在目标缓冲区的末尾添加字符串终止符\0。如果源字符串比目标缓冲区大,或者忘记添加\0,会导致缓冲区溢出或未定义的行为。

3.
无法处理特殊字符:scanf函数对于输入中的特殊字符(例如空格、制表符等)的处理不够灵活。默认情况下,scanf会将这些特殊字符视为输入结束的标志,因此可能无法正确读取包含特殊字符的字符串。

4. 难以追踪和调试:由于不安全的函数和关键字使用不依赖于输入的长度,因此很难在运行时捕获和排查相关问题。这可能导致程序的脆弱性更加难以发现和修复。

为微软官方给出的建议是,可以考虑使用更安全的替代函数和关键字,如fgetsstrncpy等,但是其实也并不见得安全,同样存在问题,需要结合适当的输入验证和边界检查来确保程序的安全性。

下面介绍一下这些替代的函数怎么用:

1. 使用 fgets 读取用户输入:

fgets 函数有三个参数,它们的含义分别是:

  1. 目标缓冲区:fgets 函数将从输入流中读取的数据存储在目标缓冲区中。这是一个指向字符数组的指针,用于接收输入的字符串数据。

  2. 缓冲区大小:这个参数指定了目标缓冲区的大小(以字节数表示)。fgets 函数将最多读取 size-1 个字符到目标缓冲区中,这是为了为字符串终止符 \0 预留空间。

  3. 输入流:这个参数指定了要从哪个输入流中读取数据。通常是标准输入流 stdin,表示从键盘读取用户输入。你也可以指定其他的输入流,如从文件中读取。

#include <stdio.h>

int main() {
    char input[100]; // 假设缓冲区大小为 100

    printf("请输入字符串: ");
    fgets(input, sizeof(input), stdin); // 从标准输入读取字符串,最多读取 sizeof(input)-1 个字符

    printf("输入的字符串是: %s\n", input);

    return 0;
}

fgets 函数读取一行输入,包括空格,将其存储在目标缓冲区 input 中(读取的最大字符数为
sizeof(input)-1)。input 的大小减去 1 是为了让函数有足够的空间在最后添加字符串终止符 ‘\0’。

2. 使用 strncpy 复制字符串到目标缓冲区:

strncpy 函数有三个参数,它们的含义分别是:

  1. 目标字符串:这是一个指向字符数组的指针,用于存储复制后的字符串。

  2. 源字符串:这是一个指向字符数组的指针,表示要复制的原始字符串。

  3. 复制的字符数:这个参数表示要复制的字符数,即将源字符串中的多少个字符复制到目标字符串中。

#include <stdio.h>
#include <string.h>

int main() {
    char source[10] = "Hello"; // 源字符串
    char destination[20]; // 目标缓冲区

    strncpy(destination, source, sizeof(destination)-1); // 复制 source 到 destination,最多复制 sizeof(destination)-1 个字符
    destination[sizeof(destination)-1] = '\0'; // 手动添加字符串终止符 '\0'

    printf("目标缓冲区中的字符串是: %s\n", destination);

    return 0;
}

strncpy 函数将源字符串 source 复制到目标缓冲区 destination 中,最多复制
sizeof(destination)-1 个字符。需要注意的是,strncpy 不会自动添加字符串终止符
‘\0’,因此需要手动在目标缓冲区末尾添加。

3.使用 memcpy 将一段内存的内容复制到另一段内存中的示例:

“Memory Copy”,即内存拷贝,memcpy 函数有三个参数,它们的含义分别是:

  1. 目标指针:这是一个指向目标内存区域的指针,用于存储复制后的数据。

  2. 源指针:这是一个指向源内存区域的指针,表示要复制的原始数据。

  3. 复制的字节数:这个参数表示要复制的字节数,即将源内存区域中的多少个字节复制到目标内存区域中。

#include <stdio.h>
#include <string.h>

int main() {
    char source[10] = "Hello"; // 源内存
    char destination[20]; // 目标内存

    memcpy(destination, source, strlen(source) + 1); // 将 source 复制到 destination

    printf("目标内存中的内容是: %s\n", destination);

    return 0;
}

在上面的示例中,memcpy 函数将源内存 source 复制到目标内存 destination 中,并且 strlen(source) + 1 是要复制的字节数,包括字符串结尾的空字符 ‘\0’。

学习计划安排


我一共划分了六个阶段,但并不是说你得学完全部才能上手工作,对于一些初级岗位,学到第三四个阶段就足矣~

这里我整合并且整理成了一份【282G】的网络安全从零基础入门到进阶资料包,需要的小伙伴可以扫描下方CSDN官方合作二维码免费领取哦,无偿分享!!!

如果你对网络安全入门感兴趣,那么你需要的话可以

点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

①网络安全学习路线
②上百份渗透测试电子书
③安全攻防357页笔记
④50份安全攻防面试指南
⑤安全红队渗透工具包
⑥HW护网行动经验总结
⑦100个漏洞实战案例
⑧安全大厂内部视频资源
⑨历年CTF夺旗赛题解析

  • 17
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值