简介
- 漏洞编号:cve-2016-7193
- 漏洞类型:堆溢出
- 软件名称:Office
- 模块名称:wwlib
- 历史漏洞:较多
- 影响的版本
- 攻击利用:APT 攻击利器-Word 漏洞 CVE-2016-7193 原理揭秘
操作环境
- 系统:Win10 1607
- 软件版本:Office2016 16.0.4266.1003
- poc:cve-2016-7193.rtf
- 工具:Process Monitor、windbg、IDA
分析
- 文件格式分析:样本经过博主进行简化,经过控制字运行分开运行之后发现 \dfrxst9(具有长度字节的 Unicode 字符数组)和 *\shpinst(RTF 用于绘图对象)控制字是触发漏洞的原因之一
原因分析
崩溃点分析
- 开启堆调试载入文档后引发异常,可见 eax 指向了未知地址导致了异常
- 从 IDA 分析崩溃点可以看出 mov ecx, [eax] 是取出了对象的虚表,并且调用了虚表 +1C 位置的函数
逆向分析(基地址:0x66730000)
- 经过逆向分析之后,得出 wwlib 在解析包含数字的 dfrxst 控制字时会在 wwlib!PTLS7::FsUpdateFinitePage+0x6d181(66a16efc) 地址上调用 sub_66a16c81 函数对数字进行处理。例如 langfe1024 控制字的数字为 1024,ASCII 为 0x31 0x30 0x32 0x34,在此基础上减去 0x30 得出 1 0 2 4,然后经过 ((((1) * a) * a + 2) * a + 4) 公式计算得出为 0x400,暂时称这个值为 “dfrxst 控制字后数字运算值”
- 在 wwlib!PTLS7::FsUpdateFinitePage+0x7a9c0(66A2473B) 地址上将 “dfrxst 控制字后数字运算值” 循环写入 v126 + v13 + 0x8FA0 这个地址,暂时将这个地址中的数据结构称为 “dfrxst 控制字后数字运算值数组”
- 在 wwlib!PTLS7::FsUpdateFinitePage+0x74113(66a1de8e) 地址中将 v257[0x8FC4] 传入 sub_669e393f 函数,v257 变量中的值实际上指向上面的 v126 + v13 计算后得出的地址
- 在 wwlib!PTLS7::FsUpdateFinitePage+0x39dc0(669E3B3B) 地址中会将之前 v257[0x8FC4] 往后的数据写入到 TLS(0x1e) 中指定的地址,方便后面取出
- 在 wwlib!PTLS7::FsDestroySubpageBreakRecord+0x10920(669477DD) 地址中会取出上面 TLS(0x1e) 的地址
- 在 wwlib!PTLS7::FsDestroySubpageBreakRecord+0xbfdd(66942E9A) 地址上会取出 “dfrxst 控制字后数字运算值数组” +0x24 偏移的数据,调试时值为 0x09c00c0c
- 然后调用 MSO_557 函数取出 0x09c00c0c + 0x48 地址的值,因为没有堆喷射,所以值为 0x00000000,最后在调用 mov ecx, [eax] 指令从 0x00000000 地址取值时崩溃
根本原因
- 由于 wwlib!PTLS7::FsUpdateFinitePage+0x7a9c0(66A2473B) 地址上循环调用 swtich case 138 分支将 “dfrxst 控制字后数字运算值” 写入 v126 + v13 + 0x8FA0 地址时并没有控制循环的次数,导致只要存在足够多的带数字的控制字,就会造成堆中的数据溢出
- 以下为写入前的 “dfrxst 控制字后数字运算值数组” 结构,可以看到 +0x24 的地方是一个数据结构,值为 0x56f30f90
56bc1450 00000009 00000000 00000000 00000000
56bc1460 00000000 00000000 00000000 00000000
56bc1470 00000001 56f30f90 00000000 00000000
56bc1480 00000000 00000000 00000000 00000000
56bc1490 00000000 00000000 00000000 00000000
56bc14a0 00000000 00000000 00000000 00000000
56bc14b0 00000000 00000000 00000000 00000000
56bc14c0 56f30f90 00000000 00000000 00000001
- 在持续写入之后会造成溢出,可以看出 0x56f30f90 变成了 0x09c00c0c。至于为什么 +0x20 的地方没有变化,因为这是一个 int 变量,用于统计写入的字节大小,并且在写入之后进行更新
56bc1450 0c0cc009 0c09c00c 0c09c00c 0c09c00d
56bc1460 0bc0090c 15172018 09c00c0c 200c09c0
56bc1470 00000028 09c00c0c 00000000 00000000
56bc1480 00000000 00000000 00000000 00000000
56bc1490 00000000 00000000 00000000 00000000
56bc14a0 00000000 00000000 00000000 00000000
56bc14b0 00000000 00000000 00000000 00000000
56bc14c0 56f30f90 00000000 00000000 00000001
构建与利用
构建流程
- 只要存在足够多的 dfrxst[数字] 控制字就会造成堆中数据溢出
利用姿势
- 使用堆喷射技术将载荷喷射到 0x09c00c0c + 0x48 地址左右就可以进行利用,也可以手动修改 0x09c00c0c 地址
缓解
- 补丁:https://learn.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-121
参考
- https://paper.seebug.org/288/
- https://bbs.kanxue.com/thread-221792.htm