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