浅析整数溢出

overflow!

刺猬@http://blog.csdn.net/littlehedgehog

 

 

 

 

 

在Linux 2.4内核版本中我们经常看见如下类似的判断:

 

  1. if ((offset + PAGE_ALIGN(len)) < offset)
  2. goto out;

如果是第一次看到这段代码说不定就会联想到 难道len还是个负数? 回头看看这条语句的调用函数( do_mmap.c) ,很明显的len是个无符号整型:

  1. static inline unsigned long do_mmap(struct file *file, unsigned long addr,unsigned long len, unsigned long prot,unsigned long flag, unsigned long offset)

这里事实上是意在检测offset的值是否存在溢出,本来是C语言的基础课程,不过俺实在比较菜,等学了汇编才对此有所了解。

 

 

 

上溢和下溢

 

先来看段代码:

  1. bool func(size_t cbSize) 
  2. {
  3.    if (cbSize < 1024) 
  4.    {
  5.       // we never deal with a string trailing null
  6.       char *buf = new char[cbSize-1];
  7.       memset(buf,0,cbSize-1);
  8.       // do stuff
  9.       delete [] buf;
  10.       return true;
  11.    } 
  12.     else
  13.    {
  14.       return false;
  15.    }
  16. }

代码是正确的,对吗?它验证 cbSize 不大于 1 KB,并且 new 或 malloc 应该始终正确地分配 1 KB,对吗?让我们忽略以下事实,new 或 malloc 的返回值应该在此时进行检查。同样,cbSize 不能为负数,因为它是 size_t。但是,如果 cbSize 是零,又会如何呢?查看一下分配缓冲区的代码,它从缓冲区大小请求中减去一。从零减去一会产生 size_t 变量,这是一个无符号的整数,其限制为 0xFFFFFFFF(假设为 32 位的值)或者 4 GB。您的应用程序只有结束了,或者更糟!

 

再来看一段代码:

  1. bool funcB(char *s1,unsigned short int len1,char *s2,unsigned short int len2)
  2. {
  3.  if (1 + len1 + len2 > 64)
  4.   return false;
  5.  char *buf = (char*)malloc(len1+len2+1);
  6.  if (buf) {
  7.   memcpy(buf,s1;len1);
  8.   memcpy(buf+len1,s2,len2);
  9.  }
  10.  if (buf) free(buf);
  11.  return true;
  12. }

同样,代码看起来编写得很好;它检查数据大小,验证 malloc 是否成功,并且使用 safe 字符串处理函数 StringCchCopy 和 StringCchCat但是,这段代码可能会受到整数上溢的危害。如果 len1 是 64,len2 是 0xFFFFFFFF,又会如何呢?确定缓冲区大小的代码合法地将 1、64 和 0xFFFFFFFF 加在一起,由于加操作的限制,会产生 64。接下来,代码仅分配了 64 个字节,然后代码生成了一个长度为 64 个字节的新字符串,然后将 0xFFFFFFFFF 字节与该字符串相连。同样,应用程序将会结束,在某些情况下,如果利用精心设计的大小进行攻击,代码可能会受到可用缓冲区溢出攻击。

 

 

来总结一下,如果offset 靠近0xFFFFFFFF,此时再加上一个len,可能会导致溢出,就是说0xFFFFFFFF+len>0xFFFFFFFF,这里就肯定要进位了,那么一进位,比如0x1000000EF ,offset不能装下9位数,那么它表示只能是0x000000EF,自然比原来offset小了,表示了溢出。

 

 

 

 

你可能感兴趣的:(浅析整数溢出)