Kelvin的胡言乱语

==============> 重剑无锋,大巧不工。

黑客档案:0day漏洞之简单溢出的利用

这是我进行博客搬家所找到的第一篇文章(实际上原博客分成了三篇来写),所谓的原博客,其实就是我自己的人人网(怎么样,够不专业吧:-D)。实际上,这篇文章毫无价值可言(除了针对我自己的收藏价值外),但就是这样一篇水文,从我当时写的字里行间,以及文章后面的评论来看,我当时心里是相当做作与炫耀的。现在,回头看看,我真是觉得羞愧。整篇文章,不过就是一个栈溢出导致的安全问题。知之愈多,便觉知之愈少,反过来,真是知之愈少,反觉知之愈多啊。

以此文章警示自己,静水流深。

下面是原文(未大改,稍作了一些格式上的调整):


原文的“上”篇

废话少说,首先来看下面一段简单的C程序:

#include <stdio.h>
#include <string.h>
#define PASSWORD "1234567"    //定义密码,仅为测试,无实际意义

int check_password(char *password)  //用于判断密码是否正确
{
     int result;
     char offset[8];                          //没什么用,为溢出作准备
     result = strcmp(password,PASSWORD);
     strcpy(offset,password);          //同上
     return result;
}

int main()
{
     int not_valid;
     char temp[128];
     while(1)
     {
          printf("Input the password :");
          gets(temp);   //此处同样有漏洞,只要你有足够耐心
          not_valid = check_password(temp);
          if(!not_valid)
          {
               printf("Congratulations!");
               break;
          }
          else
               printf("Invalid password !\n");
     }
     return 0;
}

本程序用于让用户输入密码,只有输入为1234567时才会退出程序,否则会一直循环要求输入。

于是大多数人就想,那只有输入"1234567"时才会退出程序了,但是,试试输入"12345678",发现程序提示密码正确并退出了,再输入"aaaaaaaa",发现上面的事又发生了。

出了什么问题呢?难道是程序的逻辑错了?但是输入"1234"就会提示错误啊?那到底是怎么回事呢?最后来一句老话:欲知后事如何,且听下回分解。

原文的“中”篇

现在来具体分析出现问题的原因。

来看函数check_password(char *password);中的相关定义:

int result;
char offset[8];

问题就在这里。在程序编译成exe文件后, resultoffset[8] 的内存地址是连在一起的, result 将在 offset[8] 的“下面”。于是,问题就产生了,如果我们让 offset[8] 产生溢出,溢出部分将会覆盖 result 中的内容。如果溢出部分刚好将 result 中的内容覆盖成0,程序就会成功运行!而要将 result 中的内容置0,则需要将ASCII码的 NULL 写入 result ,而字符串的最后一位刚好是 NULL

似乎到这里所有的问题都已经解决了,即:写入8个字符,前8个将写入 offset[8] ,而最后默认附加的一位 NULL 将溢出到 result ,将 result 置0。

但当输入01234567,也是八个字符,按上面的分析,也是将 result 置0,但为什么程序会提示输入错误,要求重新输入呢?由此看来,并不是所有的八位字符串都行,这又是为什么呢?

又是那句老话:欲知后事如何,且听下回分解。

原文的“下”篇

接着来讨论还未解决的问题,为什么输入01234567不会提示成功。

这是因为, check_password(char *) 函数中对 result 赋值采用的是 strcmp() 函数,01234567是小于1234567的,所以 strcmp() 函数会返回-1,导致 result 中的值为-1的补码0xFFFFFFFF,输入01234567只会将 result 覆盖成0xFFFFFF00,从而 result 的值不为0,也就不会成功了。

到此,所有的疑问都已解决,下次讨论,再会。

Comments

comments powered by Disqus