strcpy()函数应该是我们用的比较常用的一个函数,基本功能是将一个字符串拷贝到我指定的内存空间。但是要复制的字符串长度超过这段内存空间的话,结果可能是未知的。

比如以下的程序:

#include <stdio.h>
#include <string.h> int main(int argc, char *argv[])
{
int flag = 0;
char password[5] = {'\0'}; strcpy(password, argv[1]); if(0 == strcmp("root", password))
{
flag = 1;
} if(flag)
{
printf("密码被破解了\n");
}
else
{
printf("密码破解失败\n"); }
return 0;
}

上述程序的功能是一个简单的密码破解功能,也就是判断用户输入的密码是不是”root“,如果是,则输出密码被破解了,否则提示用户密码破解失败!字符串数组argv[1]的内容已经事先设定为”123456789“。运行结果如下:

程序输出密码被破解了,说明if(0 == strcmp("root", password)) 这个语句判断通过了,将flag设为1了。但是我们的疑问是,”root“明明和”123456789“不一样啊,为什么if判断会通过呢?我们使用VC 6.0来调试下,如下:

从调试中可以看到,在执行到” if(0 == strcmp("root",
password)) “时,flag的值已经变成57了,是不是很奇怪?

仔细看调试过程,password[0]这个字符的地址是”0x0012ff74“,password[1]这个字符的地址是”0x0012ff75“,以此类推,到了flag的地址是”0x0012ff7c“。也就是说,从password[0]开始,到flag,这是一段连续的内存区域,这段内存区域一共是0x0012ff7c
- 0x0012ff75 = 9个字节大小,password数组占去了5个字节大小,也就是从地址”0x0012ff74“到地址”0x0012ff78“存放的都是password的字符。而argv[1]有”123456789“一共9个字符,将前5个字符给了password数组后,剩余的”6789“这4个字符,就存放在地址”0x0012ff79“到”0x0012ff7c“这端内存区域中。而flag的地址是”0x0012ff7c“,所以flag就存放了字符”9“,而字符”9“的ASCII码值是57,所以flag最终的值就是57。这样的话,即使用户输入的密码不是”root“,但是程序密码也被破解了,这就是使用strcpy函数的一个陷阱,即strcpy函数不会去检查第一个参数的存储区域是否容得下第二个参数的存储容量。


========================2017年1月22日更新====================
有热心的网友指出,flag变量跟password数组在内存上连续存放,但是也有肯定不是连续存放的,这可能取决于编译器。我是在VC6上编译的,也许用GCC编译的话,就不会连续存放了,gcc编译可能flag还是0。但是不管怎么,strcpy不检查数组越界,这个始终是需要注意的。

最新文章

  1. 使用java操作MongoDB
  2. 关于NGINX的502的装逼打怪之路
  3. sql查找最后一个字符匹配
  4. Linux操作系统PS命令详细解析
  5. PHP中的文件下载
  6. poj 3258 River Hopscotch(二分+贪心)
  7. windows下svn+apache搭建svn服务器
  8. iOS 关于tableView中有多个textField,输入框被遮住的解决方法
  9. Leetcode算法刷题:第14题 Longest Common Prefix
  10. VBA基础概念
  11. [ An Ac a Day ^_^ ] [kuangbin带你飞]专题五 并查集 POJ 2236 Wireless Network
  12. CentOS7系统配置国内yum源和epel源
  13. k60详细引脚功能截图
  14. [PHP]命令执行函数的区别
  15. 树莓派与Linux系统之间文件传输
  16. Python_每日习题-0008-九九乘法表
  17. 洛谷P1357 花园(状态压缩 + 矩阵快速幂加速递推)
  18. Problem B: 专家系统 解题报告
  19. HttpWebRequest、HttpWebResponse获取网页
  20. Oracle ref cursor和sys_refcursor

热门文章

  1. 使用Netconf管理Cisco网络设备
  2. Win8Metro(C#)数字图像处理--2.3图像反色
  3. Android 命令设置获取、IP地址、网关、dns
  4. 没有安装提供程序“System.Data.SqlServerCe.3.5”的解决方法
  5. 管道通信实例(A程序作为服务器,不断从B程序接收数据,并发送到C程序中)
  6. AndroidStudio问题汇总
  7. ML:吴恩达 机器学习 课程笔记(Week5~6)
  8. 智能合约开发——以太坊 DApp 实现 购买通证token
  9. 从IntToHex()说起,栈/堆地址标准写法 good
  10. 为什么API多用C而不是C++,为什么C++程序大多不使用异常