整形溢出分类
0x1 强制宽度转换(Widthness)
从高级语言层面来看,如果数值超过 对应类型 可容纳的范围,会导致高位丢失:
char buffer[80];
char *src = argv[1];
int len = atoi(argv[2]);
unsigned short i = len; // mov WORD PTR [ebp + i], len
if (i < 80) {
memcpy(buffer, src, len);
}
运行:
$ ./width 65536 `python -c 'print "A"*100'`
Segmentation fault (core dumped)
0x2 运算溢出
void copy_data(int *data, unsigned int len)
{
int i;
int *buffer = malloc(len * sizeof(int)); // [1] overflow here
for (i = 0; i < len; i++) {
buffer[i] = data[i]; // [2] Out of bounds copy
}
}
malloc
中的参数为 unsigned long
类型,在 x86 平台中,大小为 32 字节,则最大数值为 0xFFFFFFFF
。
如果 len
数值过大,将导致计算结果溢出,分配较小内存块:
copy_data("AA...", 0x40000008); // 0x40000008 * 4 > MAX_UINT, 最终分配 0x20 大小内存
0x3 Signed / Unsigned Confusion ,混用
当将 Signed 类型作为 Unsigned 类型使用时,可能导致问题发生:
int process_data(char *data, int len)
{
char buffer[800];
if (len > sizeof(buffer)) { // [1] bypass with negative value
return -1;
}
memcpy(buffer, data, len); // [2] overflow here
return do_real_process_data(buffer, len);
}
memcpy
函数中的拷贝大小参数,对应为 unsigned int
类型,如果此时传入的 len
为负数,将绕过大小检测,并最终拷贝 4 GB 数据:
process_data("AAA...", -1); // -1 => 0xFFFFFFFF