函数|某办公处理软件公式编辑器漏洞复现( 二 )


文章插图
在ida中查看0043ebdf处,发现ida并没有解析出该函数,需要用ida创建函数。
?编译器的优化可能导致ida无法解析出函数,导致无法在函数列表中检索到对应的函数。
函数|某办公处理软件公式编辑器漏洞复现
文章插图
创建函数后查看伪代码。
函数|某办公处理软件公式编辑器漏洞复现
文章插图
对43ebdf中涉及的3函数分析。
sub_436c85函数只是进行值的选择:
函数|某办公处理软件公式编辑器漏洞复现
文章插图
sub_415c54中进行指针的调整:
函数|某办公处理软件公式编辑器漏洞复现
文章插图
函数|某办公处理软件公式编辑器漏洞复现
文章插图
sub_43ECFA中涉及了result,同时把读取的byte值放入栈中。
函数|某办公处理软件公式编辑器漏洞复现
文章插图
sub_43ecfa涉及的参数在栈中的分布如下图所示。当时v4足够大时,sub_43ecfa中的while循环会不停的向栈中写入数据,直到把ebp和返回地址覆盖掉。
函数|某办公处理软件公式编辑器漏洞复现
文章插图
04 漏洞触发情况当eax=00450f58和00451970,即case=2,case=5时会调用sub_43EBDF。
函数|某办公处理软件公式编辑器漏洞复现
文章插图
根据MathType 6.9 SDK:
函数|某办公处理软件公式编辑器漏洞复现
文章插图
在解析char record和matrlx record记录时会发现栈溢出漏洞。
05 利用过程在x64dbg下使用checksec查看查看eqnedit采用的保护技术。结果如下图所示,只启用了dep措施。所以尝试使用rop的方式来执行命令。
函数|某办公处理软件公式编辑器漏洞复现
文章插图
先梳理出利用winexec的rop逻辑链条,如下所示:
?刚开始组织payload的时候,没有考虑到payload的通用性。经过果哥提醒后注意到,后续组织payload时要考虑通用性。payload=buffer+ebp+&Gadgets1+&winexe()+&Gadgets2+&lpCmdLine+uCmdShow+&exit()
Gadgets1=pop;ret;
Gadgets2=pop;pop;ret;
下面开始寻找payload中各部分的地址。
1、buffer的长度
进入sub_43ebdf后ebp=0x19efd0,v[7]=ebp-ch,所以需要32byte的buffer内容来覆盖ebp。
函数|某办公处理软件公式编辑器漏洞复现
文章插图
2、&winexec()
遍历程序加载模块中的winexec()后发现,只有eqnedit和kernel32.dll中有winexec。为了通用性使用eqnedit中的winexec。
函数|某办公处理软件公式编辑器漏洞复现
文章插图
查询交叉引用后eqnedit中只有sub_42D8C0调用了winexec,所以使用eqnedit!sub_42D8C0替代kernel32!winexec。
3、&exit()
遍历程序加载模块中的exit()后发现,只有msvcrt.dll,kernelbase.dll,comctl32.dll和eqnedit.exe中有合适的exit()函数。
msvcrt.dll
地址=772D6210
类型=导出
序号=291
符号=_c_exit
msvcrt.dll
地址=772D6230
类型=导出
序号=295
符号=cexit
kernelbase.dll
地址=7656C2C0
类型=导出
序号=1864
符号=cexit
comctl32.dll
地址=65DD8805
类型=符号
符号=__cexit
4、&lpCmdLine相关
4.1、第一步确定cmdline要放rtf文件中的哪里
可以放在rop链的最后。rtf文件打开时,程序会把对应的内容加载到堆中。
?注意:从伪代码里看到,程序使用了GlobalLock来获取指针。所以不能用malloc的思路去理解globalalloc的堆分配思路。
?通用句柄HANDLE有时候是逻辑指针,大多数时候是结构体指针,特殊句柄如HMENU等是结构体指针。
4.2、第二步确定cmdline在内存中的什么位置
cmdline被放在堆中,因为程序使用了globalalloc来申请堆,这种堆只能用globallock函数来读取,所以只能从程序中找globallock函数来获取cmdline的指针。同时要注意globallock函数只是把句柄转换为了指针,不能实现类似memcpy的功能。

推荐阅读