1.原理 每种数据类型都有各自的大小范围 add 0x7fff, 1 == 0x8000,这种上界溢出对无符号整型就没有影响,但是在有符号短整型中,0x7fff 表示的是 32767,但是 0x8000 表示的是 -32768,用数学表达式来表示就是在有符号短整型中 32767+1 == -32768 比如上面的有符号型加法的汇编代码是 add eax, 1,因为 eax=0xffff,所以 add eax, 1 == 0x10000,但是无符号的汇编代码是对内存进行加法运算 add word ptr [rbp - 0x1a], 1 == 0x0000。 再从数字层面看看这种溢出的结果,在有符号短整型中,0xffff==-1,-1 + 1 == 0,从有符号看这种计算没问题。 但是在无符号短整型中,0xffff == 65535, 65535 + 1 == 0。 2.例子#include
int main(void)
{
int len;
int data_len;
int header_len;
char *buf;
header_len = 0x10;
scanf("%uld", &data_len);
len = data_len+header_len
buf = malloc(len);
read(0, buf, data_len);
return 0;
}
整数溢出
只申请 0x20 大小(0xf+0x10+0x1)的堆(实测0x21,可能是对齐之类的原因),但是却能输入 0xffffffff 长度的数据,从整型溢出到堆溢出
整数溢出
$ cat test3.c
int main(void)
{
int len, l;
char buf[11];
scanf("%d", &len);
if (len < 10) {
l = read(0, buf, len);
*(buf+l) = 0;
puts(buf);
} else
printf("Please len < 10");
}
$ gcc test3.c
$ ./a.out
-1
aaaaaaaaaaaa
aaaaaaaaaaaa
从表面上看,我们对变量 len 进行了限制,但是仔细思考可以发现,len 是有符号整型,所以 len 的长度可以为负数,但是在 read 函数中,第三个参数的类型是 size_t,该类型相当于 unsigned long int,属于无符号长整型
|