整形溢出分类

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

References

Basic Integer Overflow