首先先说解决方法:
在程序最顶端加入这个代码段
#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.
下面是关于scanf
和strcpy
为什么可能不安全的一些主要原因:
1.
缓冲区溢出:scanf
和strcpy
函数不对输入进行边界检查,导致可能发生缓冲区溢出。这意味着当输入的字符串长度超过目标缓冲区的容量时,会覆盖相邻内存空间的数据。攻击者可以利用这种漏洞来执行恶意代码或者修改程序的行为。
2.
字符串终止符\0
处理问题:strcpy
函数在拷贝字符串时,需要确保目标缓冲区具有足够的空间来容纳源字符串,以及在目标缓冲区的末尾添加字符串终止符\0
。如果源字符串比目标缓冲区大,或者忘记添加\0
,会导致缓冲区溢出或未定义的行为。
3.
无法处理特殊字符:scanf
函数对于输入中的特殊字符(例如空格、制表符等)的处理不够灵活。默认情况下,scanf
会将这些特殊字符视为输入结束的标志,因此可能无法正确读取包含特殊字符的字符串。
4. 难以追踪和调试:由于不安全的函数和关键字使用不依赖于输入的长度,因此很难在运行时捕获和排查相关问题。这可能导致程序的脆弱性更加难以发现和修复。
为微软官方给出的建议是,可以考虑使用更安全的替代函数和关键字,如fgets
、strncpy
等,但是其实也并不见得安全,同样存在问题,需要结合适当的输入验证和边界检查来确保程序的安全性。
下面介绍一下这些替代的函数怎么用:
1. 使用 fgets
读取用户输入:
fgets
函数有三个参数,它们的含义分别是:
-
目标缓冲区:
fgets
函数将从输入流中读取的数据存储在目标缓冲区中。这是一个指向字符数组的指针,用于接收输入的字符串数据。 -
缓冲区大小:这个参数指定了目标缓冲区的大小(以字节数表示)。
fgets
函数将最多读取size-1
个字符到目标缓冲区中,这是为了为字符串终止符\0
预留空间。 -
输入流:这个参数指定了要从哪个输入流中读取数据。通常是标准输入流
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
函数有三个参数,它们的含义分别是:
-
目标字符串:这是一个指向字符数组的指针,用于存储复制后的字符串。
-
源字符串:这是一个指向字符数组的指针,表示要复制的原始字符串。
-
复制的字符数:这个参数表示要复制的字符数,即将源字符串中的多少个字符复制到目标字符串中。
#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
函数有三个参数,它们的含义分别是:
-
目标指针:这是一个指向目标内存区域的指针,用于存储复制后的数据。
-
源指针:这是一个指向源内存区域的指针,表示要复制的原始数据。
-
复制的字节数:这个参数表示要复制的字节数,即将源内存区域中的多少个字节复制到目标内存区域中。
#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夺旗赛题解析
![](https://i-blog.csdnimg.cn/blog_migrate/a5804b35fe3b42b5450e95e32f119ff8.jpeg)