学习一下off by one 漏洞

off by one 主要是堆中的漏洞,这种漏洞一般是指单字节缓冲区溢出。

原理

这种漏洞的产生往往与边界验证不严和字符串操作有关,当然也不排除写入的 size 正好就只多了一个字节的情况。

第一种:循环界限的判断失误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int my_gets(char *ptr,int size)
{
int i;
for(i = 0; i <= size; i++)
{
ptr[i] = getchar();
}
return i;
}
int main()
{
char *chunk1,*chunk2;
chunk1 = (char *)malloc(16);
chunk2 = (char *)malloc(16);
puts("Get Input:");
my_gets(chunk1, 16);
return 0;
}

拿上面的代码作举例

这里我们看到循环的条件i<=size,那么就造成了一个字节的溢出。原因是数字i是从0开始的数组,如果包括了边界size,那么在下面的main函数中我们的循环就会有17次,多了一次,就产生了一字节的溢出。

第二种:字符串长度的判断失误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(void)
{
char buffer[40]="";
void *chunk1;
chunk1=malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
}

这里我们可以看出,chunk1是一个24字节大小的堆块,在下面我们将24字节长度的字符串buffer复制进chunk1中,看上去好像不存在什么问题,但是这里我们要注意到,由于buffer是字符串,那么在字符串的末尾始终存在终止符\x00也是要占一个字节的长度的,也就是说这里我们其实往chunk1中存放了25个字节,显然造成了溢出。

以上就是off by one最常见的两种存在形式。

那么off by one(null)一般不会单独出现 ,而是和其他漏洞一起出现。

由于溢出的一个字节可以修改下一个chunk的prv_size。长和chunk_shrink一起出现。