office 复合文档数据结构解析“初探”

您所在的位置:网站首页 肚脐眼结构剖析图 office 复合文档数据结构解析“初探”

office 复合文档数据结构解析“初探”

2024-07-11 03:35| 来源: 网络整理| 查看: 265

一、OLE(Object Linking and Embedding) 文件二进制结构

Office 文档(如:.doc、.ppt、.xls等)很多是复合文档(OLE文件),所有文件数据都是存储在一个或多个流中。每个流都有一个相似的数据结构,用于存储元数据的数据结构。这些元数据有用户和系统的信息、文件属性、格式信息、文本内容、媒体内容。宏代码信息也是以这种方式存储在复合文档中的。为了在 Office 文档文件中提取出宏代码,以及进行其他相关安全研究,必须学会解析复合文档的二进制格式。

① 复合文档将数据分成许多流(Steams),流存储在不同的 Storages 里。

② 复合文档采用NTFS(NT File System)格式。 ③ 流又分成更小的数据扇区(sectors),数据扇区可能包含控制数据或用户数据。

④ 整个文件由一个头结构(Header) 结构以及 Sectors 组成,头结构确定了 Sectors 的大小,每个 Sector 的大小相同。  

office文件格式根据版本可以分为Office2007之前的版本和Office2007之后的版本。 Office2007之前的版本为OLE复合格式:doc,dot,xls,xlt,pot,ppt;

Office2007之后的版本为OpenXML格式:docx,docm,dotx,xlsx,xlsm,xltx,potx

二、准备

1、工具:offvis(如下) + 010editor

链接: https://pan.baidu.com/s/1ivh3VgkkIn3oUnpUP-7C8Q 提取码: e6u2

2、doc、docx 和 docm 文档

三、关于 doc、docx、docm

Office文档主要基于三种格式:ole、xml、ooxml —— ooxml 以 xml 为基础,可以理解为 zip文件。 doc、xls、ppt 三种扩展名文档属于97-2003版Office,可解析出ole格式文件。 docm、xlsm、pptm 是启用宏的Office文档,存储 Visual Basic Applications(VBA)宏代码,可解析出 xml 文件。 docx、xlsx、pptx 三种扩展名文档可解析出 xml 文件。 ppsx 是 2007 的PPT的一种格式,打开就是幻灯片播放模式。

1、 .doc 是一种普通的OLE文件(复合文件),可以包含宏代码,而.docx和.docm文件,实际上都是是压缩文件。二进制文件头数据截取如下,其中docx文件得输入一点内容,不然解析为空。

>> Office 2007 之前的版本可以看作二进制文件。其中十六进制文件头为 D0 CF 11 E0 A1 B1 1A E1,这是固定的 OLESS 文档格式文件头。

>> Office 2007 之后的样本,可以发现文件头为PK。这代表着ZIP算法的发明者 Phil Katz。Office 2007之后的文档本质上是一个压缩包。由于文档中包含 ooxml 文件,因此不能用 offvis 进行解析,按下 offvis 的 Parser 按钮确实无法解析文件,这类文档可以通过解析出 .xml 和 .rels 来获取内容和逻辑关系。

每个PK包都必须有一个[Content_Types] .xml,在包的根目录中找到。此文件包含包中所有部件的内容类型的列表,每个部分及其类型必须列在[Content_Types] .xml中。在这里插入图片描述

2、将 docx.docx 文件重命名为 docx.zip ,然后以压缩包形式打开,可以看到文档的内容被存储在不同的文件里,文件的主要内容大部分都在 Word 目录中。这里涉及到一个新名词:OPC-Open Package Convention 开放打包协定,是一种基于 zip+xml 定义的文件存储格式。

>> 这里面要理解三个概念:Part、Relationship、ContentTypes。 zip 中的每个文件都是一个 part,可以是任何格式,比如图片、xml等。Relationship 是一种特殊的 Part,它描述了各个Part之间的依赖关系,存储在_rels文件夹中,存储为rels文件。ContentTypes 在zip压缩包的根目录下,文件名为Content_Types.xml,它记录了 OPC 文件中除了他自己以外的所有文件的类型。

>> 比较重要的几个文件如下:

3、利用同样方式打开 .docm 文件,发现内容大致相同。有的文章里说 .docm 的压缩包中会比 .docx 多一个 vbaProject.bin 的复合文件,用来记录 VBA 工程信息,这也是合理的。

四、开始解析 OLE 文件数据格式

用 offvis 打开 doc 文件,可以看到清晰的文件结构。

1、Header(文件头)

固定大小 512 字节,header 中记录着文件解析必需的所有参数,每个参数都很重要,自己标注了一下

2、FAT

FAT 实际记录了该扇区 sector 指向的下一个扇区的地址,成为一个索引表。数据在硬盘上的存储是离散的,需要有一个索引表能找到这些数据,索引表中存放着数据的起始地址(即扇区的起始地址)。

一个 sector 只能存放一种类型的数据,但是复合文档怎么知道扇区中存储的是哪一种类型的数据?因而在复合文档的 FAT 数据中,除了表示扇区 ID 的数字,还有些特殊的数字 ID 表示一些特定的扇区。

一个扇区大小为512字节,一组FAT信息占据4个字节。因而一个FAT扇区中,最多能够存放128组FAT信息。可以利用 DIFAT列表把不同的FAT扇区串联起来。

3、MiniFAT 和 FAT 解析类似

4、DirectoryEntries

复合文档从字面上理解就是很多内容放在一起复合形成文档,这么多内容当然需要有个目录,而 DirectoryEntries 就是这个目录。DirectoryEntries 起始的 SectorID 需要从 Header 读取,定位的方法: 512+ 扇区大小 * 扇区ID。DirectoryEntries 中每个DirectoryEntry 固定为 128字节,其主要结构如表所示:

五、深入理解OLE

先看明白这篇再往下读:Activex、OLE、COM、OCX、DLL之间的区别(转) - 任智康 - 博客园

下面解释打开一个 OLE 文档时发生了什么?

===================== OLE 对象的初始化 ======================

>> 意思就是说当你打开一个Office文档,如果里面包含OLE对象,则将会对这个OLE对象进行初始化,那么如何来初始化一个文档中已经插入的OLE对象呢,通过 ole32.dll 中的 OleLoad() 函数来实现。其具体步骤分为 6点,如下图。

① 如果必要的话,自动执行对象的转换

② 调用 IStorage:Stat 方法从打开的存储对象中获取 CLSID

③ 调用 CoCreateInstance 方法生成一个实例的处理器,如果处理器代码不能用,将会用默认的处理器

④ 调用 IOleObject::SetClientSite 方法 with the pClientSite parameter 通知对象其客户端站点

⑤ 为 IPersistStorage 接口调用 QueryInterface 方法,如果成功的话, IPersistStorage::Load 方法会被对象调用

⑥ 查询并返回由 riid 参数标识的接口

>> 这里阐述比较重要的两点:

① 调用 CoCreateInstance 生成一个用来初始化对象的处理器

② 调用  IPersistStorate 来初始化 OLE 对象的数据

>>>>>>>>>> step 1:调用 CoCreateInstance 初始化生成一个对象的处理器

注意第一个标红的参数 CLSID ,OLE对象由 CLSID 指定,CLSID 在 rtf 和 open-xml 文档中都可以被获取,也就是说可以由攻击者自由配置,它指明了想要初始化哪一个 OLE 对象,CoCreateInstance 的作用与结果就是加载了与 CLSID 所属的 DLL 到进程(这也是此漏洞的关键所在)。那么如何去定位、去获取到这个 CLSID 呢,不同类型的文档有不同类型文档格式,CLSID 的定位方式也不一样,下面是 4 种常见的文档格式类型:

如下只举例 Open-XML 格式和 RTF 格式类型的文档的定位 CLSID 的方法:

···········① open-xml 是通过 OLESS 格式的二进制数据中读入的(用 offvis 看看)

···········② rtf 是通过 OLE对象头部的 progID 进行转化得来的-查看二进制数据可得(Objdata往下第3行8个十六进制数)

>>>>>>>>>> step 2: IPersistStorage:Load

当 OLE对象 被确定之后(找到了对应的 CLSID,加载了 CLSID 关联的DLL),OLE对象的 IPersistStorage 接口中的 Load() 被调用,用来初始化 OLE 对象的初始状态。(这个“初始化”在我理解就是将 Storage Data(OLE Native Data) 进行分片读取、处理,获取具体的字段值与意义,如下下下图)

>> 关于 Storage Data:

可以在上图中看到 HRESULT Load() 函数中的字段 IStorage *pStg 是一个指针,会指向二进制数据中 Storage Data 的具体位置(由于是 HRESULT 类型,因此无论读取成功与否都会返回一个状态码,这里不细讲),而 Storage Data 就保存在文档的二进制数据中,见下下图。 

······以上两步其实就分别读取了到了 具体的 CLSID(OLE对象标识) 和 Storage Data,Office 读取 CLSID 是为了找到并初始化对应的 OLE对象,Office 读取 Storage Data 是为了将读到的数据传递给 OLE对象,由 OLE对象 负责处理读取的 Storage Data数据。

>> 以 8570 的 exp.rtf 举例

一个 OLE文档可以包含多个对象(使劲儿往里插就得了),下面这个 rtf 文档包含了两个对象。上面是一个 Package对象,下面的是一个 链接对象。

以 Package对象为例:其中 ActiveX 就是 ActiveX控件,指的是一类控件:

Storage Data 是实现恶意功能的主要数据区域,因此多数已发现的 OLE漏洞都是利用 IPersistStorage::Load 方法。当 Storage Data 读取完毕并传递给 OLE对象去处理之后,到此为止 OLE对象的初始化算是结束,下面开始第二部分。

===================== “Verb” 动作的执行 ======================

>> 来到了 Verb 动作的执行,可以看到红框上方的两点解释,触发“Verb”动作有两种方法:

① 用户点击、双击插入的 OLE对象(图片、链接等)

② “Verb” 自动执行,比如 PPT 中某些动画事件,又比如 ppsx 文档一打开就是自动执行

Verb动作本质上是依靠调用 IOleObject::DoVerb 方法完成的,见下图,需要注意的是第一个参数 iVerb,这个参数的 MSDN 定义是:IOleObject ::EnumVerbs 返回的 OLEVERB结构中的 verb动作的编号。

六、关于 OLE漏洞的简单总结

【漏洞分析】关于 OLE 漏洞的简单总结_dajiiii的博客-CSDN博客

参考:

知识星球博主 crazyman 的系列文章《宏病毒的研究与实例分析-2》

恶意Office文档解析——1. Office文档格式解析_ShandyLZS的博客-CSDN博客_offvis

复合文档的二进制存储格式研究[ole存储结构]整理_Gondon的博客-CSDN博客

[翻译]攻击互通性-以OLE为例-二进制漏洞-看雪论坛-安全社区|安全招聘|bbs.pediy.com



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3