我也要学C语言-第二十二章:给自己的代码找漏洞,然后自己攻击自己(365天编程极限学习-第2天上午)

万能密码

前两天的时候,我一直在思考写电话薄的事情,很多程序,都是需要登录,而且需要密码才才能进入程序。所以我也写了个验证密码的小程序,我们来看看这个小程序:
#include "stdio.h" #include void main() { char szPawd[16] = "dodolook"; char szIn[16]; int i = 3; while(i--) { scanf("%s", szIn); if (strcmp(szIn, szPawd) == 0) { printf("登录成功!你是合法用户\r\n"); break; } else { printf("登录失败!请再尝试\r\n"); } } }
这个本意是检查用户输入的密码和设定的密码,一致的话就登录成功,不一致的话呢就登录失败!但是这个程序纯在万能密码,如果你输入1111111111111111任意密码 然后再输入你刚才输入的任意密码,就可以成功登录!我们来看看登录成功的图:
我也要学C语言-第二十二章:给自己的代码找漏洞,然后自己攻击自己(365天编程极限学习-第2天上午)
这个原因其实因为先定义的变量在前面,后定义的变量在后面,而且是挨着的,然后用户输入密码撑爆了szIn变量,一般来说,撑爆了程序崩溃,但是如果通过静心构造后不但可以避免崩溃,而且还能影响到程序的执行流程,甚至可以让程序执行缓冲区里的代码,这样的话,就太危险了!
我们来看看内存:
我也要学C语言-第二十二章:给自己的代码找漏洞,然后自己攻击自己(365天编程极限学习-第2天上午)
那么该如何避免这样的情况发生了!我们可以这样做:
我们可以针对scanf做1个限制。不能让它撑破了变量。我们把scanf那行代码用下面的替换:
for(int n = 0; n < sizeof(szPwd)/sizeof(char) - 1; n++) { szIn[n] = getchar();
if(szIn[n] == '\n')
{
break;
} } szIn = \0";
这样的话就会自动切断啦!不会撑破啦!
但是仔细一想,也不行的啊,因为虽然不会撑爆,但是当程序一运行,原始密码肯定也在内存里的啊。是不是这样的呢,我们打开可执行文件看看。
我们首先运行我们的程序,然后用WinHex打开运行的程序,然后你随便输入1个密码,然后再在WinHex中查找你刚才输入的密码,如下图:
我也要学C语言-第二十二章:给自己的代码找漏洞,然后自己攻击自己(365天编程极限学习-第2天上午)
我晕啊!就在我们随便输入的密码下面就是真正的密码,差不多就在隔壁呢!这样的话,我们很轻松就得到了真正的密码,而且还可以把真正的密码给改啦!
看来啊!写这样的密码验证根本没有任何意义,但是我通过学习这个更加清楚的知道了内存的排列,和数组越界访问的弊端和其利用价值。我相信随便以后的学习,我会知道如何去写程序,不会这么轻松让人给攻破密码。同时以后也会学习如何利用一些漏洞在别人的程序里跑自己的代码!加油O!!!
关于通过漏洞控制程序的流程,以及在别人的程序里跑自己的代码,我会在自己学习了以后再写笔记!这个问题暂时就到这里啦!哈哈!真有意思!
Tags: 

延伸阅读

最新评论

发表评论