新的攻击向量
整数溢出正在逐渐成为一个新的安全攻击向量。
一个容易被开发者忽视的场景是在使用new[]进行内存分配的时候出现的整数溢出。
两个例子
考虑下面的代码,它可能会执行一个未经检查的隐式乘法操作。
![bc81f626e779ba8ee843375661d1ba20.png](https://i-blog.csdnimg.cn/blog_migrate/813c545f293c3b4c994f95598eb87344.jpeg)
如果你仔细研究一下上面代码生成的汇编代码的话,如下图所示:
![04b0c0c3535a8952ff1412c6a7752bde.png](https://i-blog.csdnimg.cn/blog_migrate/fc9498d8bbdb23a6b75d549f45b1bc48.jpeg)
请注意,在上面的汇编代码中,它并未检查与sizeof(int)的乘积是否溢出。别有用心者可以通过传递类似howmany = 0x40000001的值来诱导代码分配不足的内存。对于比较大型的数据结构,乘法溢出会以更快的速度发生。
下面我们再来看一个例子
![1fdf37fd8507cdf0817e3ad69a8139ee.png](https://i-blog.csdnimg.cn/blog_migrate/e18feea5785a7fbf9e72b71b69f5f062.jpeg)
该类还包含一个构造函数,因此分配它们的数组涉及两个步骤:分配内存,然后构造每个对象。 allocate_myclass函数的汇编代码如下:
![b58355a0862a06b5ee201c0dc5d8b3e3.png](https://i-blog.csdnimg.cn/blog_migrate/48c35d9b5783356e4c4868f3dbd4878b.jpeg)
此函数进行大小的未经检查的乘法操作,然后尝试分配那么多字节,然后告诉构造函数迭代器多次调用构造函数(MyClass::MyClass)。
如果有人诱导你调用allocate_myclass(0x200001),则乘法将溢出并且仅分配1024个字节。 此分配成功,然后构造函数尝试初始化这些项目的0x200001,即使实际上只有其中一个被分配。因此,代码出现了越界并开始破坏内存空间。
解决之道
这的确很糟糕。
为了防止这种情况,你可以在数组分配周围添加一个整数溢出检查,如下图所示:
![03b416f0979b6f33dc09e1f1f49a4d1b.png](https://i-blog.csdnimg.cn/blog_migrate/9f88fca2e7f927235eec40771471daa3.jpeg)
注意:如果你希望使用异常机制,则可以用一个适当的throw来替换调用”return NULL”。
现在,您可以使用此模板以安全的方式进行数组分配。
![a05df7ecdaafdbabd26fbe5761371fa6.png](https://i-blog.csdnimg.cn/blog_migrate/9fae14c49a39a0952bf629e3b0365ca8.jpeg)
生成的汇编代码如下:
![6ff0d567c37c9f7b48a33f3bbafe3bd9.png](https://i-blog.csdnimg.cn/blog_migrate/6b2057da811fb1f58565586adb8b0756.jpeg)
请注意新的代码检查可能会出现的整数乘法溢出。
但是,它怎么会出现溢出的情况呢?
最常用的方法是从文件或其他存储位置读取值。例如,如果代码正在分析一个文件的节,该节的格式为”长度后跟数据”,则有人可以有意地将一个引起溢出的值放入”长度”的字段中,然后让其他人尝试加载该文件。
如果别有用心者伪造的文件是一个通常被认为是安全无害的图片文件时(例如JPG),则这种情况会十分危险,且防不胜防。
总结
我们都知道天底下没有完美的程序,但是,当我们遵守一些久经考验的安全编码规则,则有助于减少潜在的问题,问题少了,我们就不用花那么多时间加班了,也可以和家人多一点时间待着,就算不做什么事,仅仅是待着,那也是极好的。
最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Integer overflow in the new[] operator》
![593dd110c70807a569e8f6c2bae575b2.png](https://i-blog.csdnimg.cn/blog_migrate/69d0373d71b5dcb931637672c1b4cb1b.jpeg)