标题 简介 类型 公开时间
关联规则 关联知识 关联工具 关联文档 关联抓包
参考1(官网)
参考2
参考3
详情
[SAFE-ID: JIWO-2024-3264]   作者: 浩丶轩 发表于: [2023-02-03]

本文共 [273] 位读者顶过

该shellcode提取器的应用对象是Maldoc,通过将市面上存在的相关分析工具进行组合,形成工具链,达到自动化定位及提取shellcode的目的。

一、[出自:jiwo.org]

语言及环境

  • 语言:python + javascript

  • 环境:REMnux docker + win7 (注:不使用RTF中的动态方法,可以摒弃win7,但面对一下经混淆的RTF文件可能无法正确提取shellcode)

  • The docker image(g0mx/remnux-shellcode_extractor) created by myself for extracting shellcode from maldoc based on REMnux

  • 项目地址:https://github.com/g0mxxm/shellcode_extractor_for_maldoc

二、

实现细节

实现并不复杂,本人认为该工具的实现思路是它的闪光点。实现思路,即将分析人员手动定位并提取shellcode的步骤自动化。整体流程主要由解包、定位、提取这三个环节组成,后续的优化并不会改变整体流程。
  • 解包:针对RTF文件中OLE对象的定位和提取,本工具采用了动态和静态两种方式来解决此问题,二者也各有利弊。静态方式主要轮子取自Didier Stevens工具集,动态方式是本人基于frida hook框架编写了几个脚本来实现的,后文会进行详细阐述;针对OOXML文件的解包,主要轮子取自Didier Stevens工具集;针对OLE对象的解包,主要轮子取自Didier Stevens工具集。此外,该阶段会对文档类型及是否加密进行判断,主要轮子取自于oletools工具集,若加密则进行解密,随后进入下一环节;若未加密,则直接进入下一阶段。

  • 定位:主要轮子取自Didier Stevens工具集,其主要思想为遍历及暴力破解,首先对OLE对象进行解包,随后对其每个子stream进行暴力破解,特征匹配,以达到定位shellcode的目的。

  • 提取:主要轮子取自于Didier Stevens工具集,很简单的一步,定位后尝试对目标位置进行解码,随后dump即可得到最终的shellcode。

解包

判断文件类型

通过oleid检查maldoc的基本信息,并根据其中Container format字段的键值判断该文件的具体类型,根据类型进入不同的分支,但最终都会走入OLE对象处理分支。


检查该文档是否被加密

通过oleid检查maldoc的基本信息,根据其中的Encrypted字段的键值判断该文件是否被加密。


若该文件被加密,可以通过msoffcrypto-crack对密码进行爆破,并保存完成解密的文件。

文件类型

RTF文件

本人对RTF文件的处理主要分为静态和动态两种形式,其中静态的优点在于可以不依赖于Windows环境,直接基于REMnux来完成OLE对象及其中shellcode的提取操作,但面对一些经过特殊混淆的RTF文件时,可能不能有效识别其中的OLE对象,因而本人基于frida实现了一个动态定位并获取OLE对象的工具,该工具的灵感来源于Denis O'Brien大佬的一篇文章(Reference中最后一项)。

静态方法

静态方法主要利用Didier Stevens的rtfdump工具中最新更新的“-F”选项,其在blog中说到,该选项是由“-H”和“-S”演变过来的,简单根据源码说一下本人对这两个选项功能的理解。“-H”和“-S”主要由HexDecode这个函数来实现,其功能是对字节流进行处理,并将其转换为十六进制的形式,其中包含判读奇偶和补零操作(“-S”)。虽然一个正常的hex流其肯定应该是偶数位的,这样才有正确解析的可能,但由于一些RTF解析器会对hex流为奇数位(有些maldoc构造者为了逃避检测会在hex流最后的位置额外添加一个十六进制字符)的问题进行处理,以完成解析,因此该函数中的判断奇偶和补零操作,应该就是为了正确解析进行了这种混淆操作的字节流;同样其也可以对抗在hex流中添加了大量空白字符这种混淆手法。本人对RTF的混淆方式了解还不是很全面,难免会有纰漏,欢迎指正和补充。具体源码如下:


通过“-F”选项找到所有OLE对象后,将所有OLE对象的标识保存下来,为后续提取做准备。


将所有找到的OLE对象,根据标识定位并保存下来,传给OLE对象处理模块,进行后续处理。

动态方法

通过运行与hook相结合的方式,可以让我们不去考虑去混淆的问题,直接找到OLE对象并将其进行保存就可以,而Denis O'Brien大佬的Silver Bullet方法给我了用运行和hook解决该问题的灵感和方法论。

本人所实现的hook是基于frida的,整体实现十分简洁,准备部分是由python实现的,hook部分是用js实现的,python部分没啥可说的,很容易理解,可以看一下frida官方给出的例子,以及DarunGrim的Using Frida For Windows Reverse Engineering这篇文章,且这篇文章写的非常精彩,它为我们提供了基于frida hook对office宏指令进行有效处理的方法,值得学习。那我们来看一下hook的实现吧。

要想获取到OLE对象,OleConvertOLESTREAMToIStorage是关键API,我们来看一下Microsoft给出的详细解释,该API功能是将OLE对对象的格式从OLE1转换到OLE2,其中一定包含了我们想要的OLE对象信息。


因而我们可以hook该API,并通过该API的第一个参数lpolestream(其是指向包含OLE1格式的OLE对象的指针)找到OLE对象,再根据存储结构找到OLE对象的具体位置及OLE对象的整体长度即可,具体操作请看Silver Bullet方法,大佬写的十分清晰且详细,复现非常简单,本文也不再进行过多赘述,hook的具体实现请看本人写的js代码,主要就是进行了获取并保存OLE地址和OLE长度的工作。

js代码如下:


通过复现Silver Bullet,我也发现了一个小问题,即通过API参数获取到的OLE对象地址(0x0A6A5B28),并未直接指向OLE对象的标识头(红框中十六进制字节),若直接根据地址和长度对该块内存进行dump,所获取的文件并不能直接传入本人所写的shellcode提取器,这是由于文件头的问题,导致oledump无法对该OLE对象进行正确解析,后续的操作也就无从谈起。


通过查阅frida文档,我发现可以用frida提供的内存数据匹配来实现精确拷贝,将OLE对象头作为匹配所用的模式串即可解决该问题。

js代码如下:


OOXML文件

OOXML文件其实是个压缩包,若其中存在OLE文件也仅能存在于activeX1.bin文件中,因而我们可以通过由Didier Stevens编写的zipdump来判断目标OOXML文件中是否包含.bin文件,若包含.bin文件则直接进入处理OLE对象流程中。


OLE对象

获取stream

先通过oleid获取所有maldoc的所用stream标签,该处实现还有优化的空间,可以将一维list改为二维list来存储stream标签,这样当maldoc中存在多级stream的情况时,结构更为清晰,不优化的话也可以,结果上不会存在太多差异。


检查stream

再根据获取到的stream标签,对maldoc中的每一个子stream都进行检查,通过xorsearch输出中的Socre值来判断对应子stream中是否包含shellcode,目前只去得分最高者进行后续操作。该处可以优化为:有得分即保留,都进入到下一阶段。


定位

这次我们将目光转向xorsearch输出结果的偏移值上,将出现的所有偏移值进行保存。


再利用偏移值和scdbg进行测试,确定shellcode的具体开始位置。


提取

若scdbg可以判断出shellcode的具体位置,那我们通过cut-bytes对其进行精确切割,并将结果保存成文件。


若scdbg不能确定shellcode的具体位置,则将整个子stream保存为文件,作为最终的shellcode。


三、

动态获取RTF中OLE文件

提供word路径,样本文件路径,以及hook脚本文件即可。


shellcode提取器

提供maldoc文件或OLE文件即可,以刚刚动态获取到的OLE文件为例。


对得到的shellcode(final_shellcode_file)进行一下简单的验证。

静态:可以看到其中有LoadLibraryW和GetProcAddress,看到这俩函数可以确定,其在获取目标函数的地址,方便后续使用;又看到ExpandEnvironmentStringsW,可以确定其是将其中的“%APPDATA%”进行扩展;随后再调用URLDownloadToFileW来下载后续文件,写入指定路径中。


动态:选择scdbg进行模拟执行来获取更加准确的信息,通过shellcodedbg执行后的结果,可以更加清晰地看到,其调用了哪些函数,参数是什么,整体流程与上文通过静态分析得到的结果基本一致,但模拟执行向我们展示了准确的URL,以及从远端下载了什么。


可以看到通过两者结合我们快速且精确的得到了maldoc中的shellcode,并通过静态或模拟执行来获取到其主要行为,快速结束maldoc的前戏,将主要精力放在分析后续的主体行为上,提高效率,愉悦心情。

该工具目前只是一个雏形,逻辑较为简单,且可能存在不严谨之处,亦存在一定问题和优化空间,主要是提供一种从特例中提取特征,从而向普适化转变的思路。

Reference

  • 运行环境基于 Remnux (https://remnux.org/)docker

  • Didier Stevens (https://isc.sans.edu/handler_list.html#didier-stevens)大佬的工具集及博客

  • oletools 工具集(https://github.com/decalage2/oletools)

  • frida-python github(https://github.com/frida/frida-python)

  • frida 官方文档(https://frida.re/docs/home/)

  • Denis O'Brien 大佬的 Silver Bullet(http://malwageddon.blogspot.com/2018/11/deobfuscation-tips-rtf-files.html)

  • DarunGrim 的 Using Frida For Windows Reverse Engineering(https://darungrim.com/research/2020-06-17-using-frida-for-windows-reverse-engineering.html)

评论

暂无
发表评论
 返回顶部 
热度(273)
 关注微信