缓冲区溢出从上个世纪开始,已经成了一个系统安全的恶梦了。从最早简单的栈溢出,到后来的堆溢出,格式化字符串的溢出,内存块数据结构的破坏,各种方法都出现了,phrack60的一篇文章Basic Integer Overflows介绍的是整数溢出,这里做个笔记:
widthness overflow的例子:
int main(int argc, char *argv[]){
unsigned short s;
int i;
char buf[80];
if(argc < 3){
return -1;
}
i = atoi(argv[1]); // 如果argv[1]是个超过short表示范围的很大的正数呢?(比如65536+10)
s = i; // 那么在这里s被截断,得到了一个看上去合理的正数 (比如10)
if(s >= 80){ // 这里的检查,显然没有阻止这种情况
printf("Oh no you don't!");
return -1;
}
memcpy(buf, argv[2], i); // 溢出发生了!被拷贝的长度可以是一个非常大的数(65536+10)
return 0;
}
arithmetic overflow的例子:
int myfunction(int *array, int len) {
int *myarray, i;
// 这里如果len是一个很大的正数,那么乘法的结果发生溢出,
// 所以分配的内存长度会比较小(len * sizeof(int) % 0x100000000)
myarray = malloc(len * sizeof(int));
if(myarray == NULL){
return -1;
}
// 溢出发生了!
for(i = 0; i < len; i++){
myarray[i] = array[i];
}
return myarray;
}
int copy_something(char *buf, int len){
char kbuf[800];
// 如果len为负数,那么这个长度检查显然没有作用了。
if(len > sizeof(kbuf)){
return -1;
}
// 那么memcpy会把len隐式的转换成正数,呵呵,溢出啊!
return memcpy(kbuf, buf, len);
}
这种由于整数长度和符号导致的溢出,是一个非常难于发现的bug,而且相对来说,也不是非常容易被利用的,因为只有在攻击者可以同时指定长度和字符串的时候,才会发生,与传统的只需要指定字符串就可以导致溢出相比,是困难了一点。而且相对来说写shellcode的难度也比较大,不过,如果有源代码,这种bug还是比较容易被火眼金睛的攻击者发现的。而且就算不能得到一个好的shell,就是把系统搞得不稳定也是有很大危害性的啊。
这一期的phrack还有一篇文章,是将如何针对整数溢出对代码进行保护的。不过保护的有限。呵呵。有兴趣可以去翻翻http://www.phrack.org/phrack/60/p60-0x09.txt
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/30283179/viewspace-1695175/ ,如需转载,请注明出处,否则将追究法律责任。