Reference

首先感谢原作者
本文翻译自https://sploitfun.wordpress.com/2015/06/23/integer-overflow/
并没有严格的把原文翻过来,加了些自己的理解在里面。

0x00 综述

当我们试图存储一个超过了数据类型允许的最大值的数据时,就会发生整数溢出。整数溢出不会像栈溢出或者堆溢出那样导致任意代码执行,但是整数溢出可能会导致栈溢出或者堆溢出。

对于64位机,常用的数据类型范围如下

Data Type Size Unsigned Range Signed Range
char 1 0 ~ 255 -128 ~ 127
short 2 0 ~ 65535 -32768 ~ 32767
int 4 0 ~ 4294967296 -2147483648 ~ 2147483647

在计算机中,我们对于数据溢出的处理一般是舍弃溢出后的最高位,更直观的表述是,我以上限溢出为例,比如

上面代码的前两句代码执行后,a超过了char类型的上限值127,舍去补码的溢出位再转换为原码后其值为-128。此时a处在正确的数据范围内,它依然可以正确的进行数据运算,同样的,如果此时再执行第三句,a的值会小于char类型的下限值,舍去补码的溢出位再转换为原码后其值为127。因此你可以简单的理解为,不论是上溢还是下溢,数据遵循循环队列那样的规则变化。
这里涉及到补码的相关知识,不赘述。

0x10 示例

代码

编译命令

上面的代码在注释[1]那行存在整数溢出漏洞。程序用unsigned char类型来存储strlen()的返回值。我们之前提到,strlen()返回值如果大于255,就会发生整数溢出。所以当password的长度为261时,passwd_len当中保存的值将为5。因此我们能够绕过[2]处的检查,从而进一步制造栈溢出

0x20 分析

在直接给出攻击代码之前,我们先看看这里的堆栈布局

反汇编

堆栈布局

iov00

为了测试这个漏洞是否能被利用起来,我们向这个程序发送一连串的'A'。

1.返回地址可以被覆写吗?

可以看到写入成功。

2.写入地址到目标缓冲区的偏移量是多少?

通过前面的反汇编结果和堆栈布局,我们能够得出偏移量是 0xb + 0x1 + 0x4 + 0x4 + 0x4 = 0x18
其中

  • 0xb = ‘passwd_buf’ size
  • 0x1 = ‘passwd_len’ size
  • 0x4 = 对齐占用空间
  • 0x4 = edi
  • 0x4 = caller’s EBP

下面用'A' * 24 + 'B' * 4 + 'C' * 233来跑一下,不出意外,我们会把BBBB写进返回地址的区域。

可以看到运行结果和预期的一样,综合以上信息我们可以写出攻击代码。

0x30 攻击代码

运行结果