
漏洞概述
Kingsoft WPS Office是中国金山软件(Kingsoft)公司的一款办公软件套件,常用组件包括:Writer(文字处理)、Spreadsheets(电子表格)和Presentation(演示文稿)等。
Kingsoft WPS Office 10.1.0.7106版本和10.2.0.5978版本中的kso.dll文件的‘WStr::assign’函数存在安全漏洞,该漏洞源于程序在执行an _copy调用之前未能验证源内存块的大小。远程攻击者可借助特制的Web界面、office文档或.rtf文件利用该漏洞造成拒绝服务
影响范围
Kingsoft WPS Office 10.1.0.7106
Kingsoft WPS Office 10.2.0.5978
复现环境
**操作系统:**Win10 64位操作系统
分析工具:IDA、OD、Windbg
漏洞分析
分析时使用的WPS版本为10.2.0.5978.
根据漏洞简介是在kso.dll文件的‘WStr::assign’函数存在安全漏洞,在wps的安装目录里搜索kso.dll放入IDA中,找到在导出表里的WStr::_copy,查看WStr::_copy函数交叉引用,有两处是在WStr::assign函数内部,经确认为WStr::assign(ushort const *,uint)函数为漏洞函数(导出表里同名函数有四个)。
此时可以看到函数地址为10114741,代码段的开始地址为10001000,两数相减偏移就是113741(偏移用于在OD里找函数位置).
运行wps,使用OD调试器调试附加主程序wps.exe,在OD的模块窗口可以看到kso.dll的代码起始地址,我的是7a011000,再加上之前算出的偏移113741,所以函数WStr::assign的地址为7a124741.如下图所示:
从汇编代码里有JNZ和JE两个跳转可以跳过WStr::_copy函数,重点关注这两个跳转,
第一个JNZ跳转:
7A124744 cmp dword ptr ss:[ebp+0x8],0x0,这条指令将栈上偏移为0x8的双字数据与0x0进行比较,并将结果存储在标志寄存器中。
jnz表示如果标志寄存器的零标志位(ZF)为0,则跳转到指定的目标地址。
这两句代码的作用是比较栈上偏移为0x8的双字数据是否为0,如果不为0,则跳转到下一条指令,
也就是只检查了dword ptr ss:[ebp+0x8]处存储的要拷贝的源地址里是否有数据,如果有就拷贝,而没有检查长度是否超过目的地址的内存长度
第二个JE跳转
7A124765 test ebx,ebx 这条指令将ebx寄存器中的值与自身进行按位与操作,并将结果存储在eax寄存器中。如果ebx寄存器的值为0,则eax寄存器的值也为0;否则,eax寄存器的值不为0。
je:这是一条跳转指令,表示如果上一条指令的结果是等于零(即eax寄存器的值为0),则跳转到指定的目标地址。
ebx里存储的是要拷贝的字符长度,整条指令的作用是检查ebx寄存器的值是否为0,如果是,则跳转到下一条指令。
也就是说只检查了长度是否为0.而不是检查长度是否和要拷贝的数据是否匹配。
后面再将这些参数传入WStr::_copy进行内存操作,如上图,这个函数也存在相同的问题。
漏洞复现
WStr::assign函数作为kso.dll导出表里的函数可以被程序员直接调用,
可以编写dll注入到wps,调用WStr::assign(ushort const *,uint)触发漏洞
WStr::assign(ushort const *,uint)函数有两个参数,第一个是要拷贝的字符串地址,第二个是字符串长度。
`void expolit()
{
__asm
{
push 0x03D2FDB8 //字符串地址
push 0x00010001 //拷贝大小
mov edx,0x7A124741 //漏洞函数地址
call edx
}
}`
以上代码就是触发漏洞的函数,传入了一个和字符串大小不匹配的参数,编写好dll后,用Cheatengine注入到WPS中,wps触发漏洞奔溃如下图:
漏洞修复
由于WStr::assign作为dll导出函数,程序员有可能在以后的开发中直接调用,所以不能在调用链上面函数做检测,
而要在WStr::assign直接检测长度和字符串是否匹配,同时不直接给出WStr::_copy的接口。
或者直接在有内存操作的危险函数WStr::_copy里进行检测。
参考链接
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)