一、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

office 复合文档数据结构解析“初探”相关推荐

  1. 微软OFFice复合文档

    劳拉"-神秘的微软办公软件文件格式 在复合文档中,可以有很多目录,每个目录下面可以有子目录,目录和子目录中包含了"存储",一个存储就相当于磁盘上的一个文件,整个复合文档就 ...

  2. 宏病毒的研究与实例分析02——复合文档格式分析

    文章目录 复合文档二进制解析 复合文档数据结构解析 准备工作 基础知识 Header FAT Directory 补充 宏代码数据结构解析 说明 目前主流杀软在处理宏病毒时,都是直接删除含有宏病毒的文 ...

  3. 恶意Office文档解析——1. Office文档格式解析

    写在前面:这是我最近在做的一个小课题,按照研究进度不定期更新.主要是学习前人的研究思路,自己开发的内容会比较少. 复合文档的概念 复合文档不仅包含文本,而且包括图形.电子数据表格.声音.视频等其他信息 ...

  4. 复合文档的二进制存储格式研究(word,xls,ppt...)

    本文是研究DOC文件格式的第一部分.office中的doc等文件在外层都遵循复合文档格式,而真正的doc内容主要是(也有其它流和仓库)作为复合文档的一系列流而存在.下面为转载的文章正文,讲解复合文档格 ...

  5. java中sax的使用_java使用sax对xml文档的解析

    随着互联网技术的发展,XML技术变得越来越重要,从而出现了很多 与XML的整合应用方面的技术,SAX就是其中之一.在这里,我就简要 谈谈java怎样使用sax对xml文档的解析. 首先,让我们来谈谈S ...

  6. 微软复合文档二进制格式实例分析

    复合文档二进制格式(compound File binary Format:CFBF)基本上以扇区(sector)为单位,sector大小由文件头中的信息决定,文件头是固定大小为512的扇区: CFB ...

  7. 手工重建复合文档(.doc;xls,ppt)文件头,修复文件全过程

    最近学习了复合文档的格式,在修复复合文档头方面做了不少实践,有了一些心得,经过梳理,做了个例子,把思路和过程介绍给大家,希望能解决你的不时之需! 例子中用的文件如下图:名为"实验文档&quo ...

  8. 使用ABAP编程实现对微软Office Word文档的操作

    SAP ABAP里提供了一个标准的类CL_DOCX_DOCUMENT,提供了本地以".docx"结尾的微软Office word文档的读和写操作. 本文介绍了ABAP类CL_DOC ...

  9. java openoffice 打印_java调用openoffice将office系列文档转换为PDF的示例方法

    前导: 发过程中经常会使用java将office系列文档转换为PDF, 一般都使用微软提供的openoffice+jodconverter 实现转换文档. openoffice既有windows版本也 ...

  10. python读取word指定内容_python解析html提取数据,并生成word文档实例解析

    简介 今天试着用ptyhon做了一个抓取网页内容,并生成word文档的功能,功能很简单,做一下记录以备以后用到. 生成word用到了第三方组件python-docx,所以先进行第三方组件的安装.由于w ...

最新文章

  1. Google 排名第一的语言,引数十万人关注:搞定它,技术大牛都甘拜下风
  2. form参数化 jq_[转载]Jquery Form插件表单参数
  3. c语言数据结构系统化,C语言数据结构+数据库+操作系统
  4. 云熙板式家具参数化拆单软件免锁版_数控开料机拆单软件如何选择?
  5. CentOS 7.5基于Docker部署4.2 版本的zabbix监控平台
  6. python适合自学编程吗-对没有编程基础的人来说,直接学Python入门IT合适吗?
  7. IoTP2PGate 两台物联网设备点对点通信快速实现方案
  8. 文献检索是利用计算机对文献,计算机文献检索方向论文选题 计算机文献检索论文标题怎么定...
  9. hive sql中常用技巧
  10. c语言五行星型图案,五行图非五方星形图
  11. matlab logspace 虚数,《MATLAB智能算法超级学习手册》一一1.2 矩阵的表示
  12. 手机点餐系统概述_廖师兄 微信点餐系统 springcloud学习笔记
  13. 关于dvb 基本知识
  14. 新生课题研究---人工智能
  15. DMZ主机的使用设置
  16. pgsql创建用户并赋予权限
  17. 旅行家算法(贪心算法)
  18. Java使用JAVE获取MP4播放时长
  19. 如何下载学习通mooc上的课件,不需要任何工具
  20. liunx系统安装docker

热门文章

  1. 安装老版本flash - 解决”正尝试安装的adobe flash player不是最新版本“的办法
  2. tar 压缩文件夹到指定的目录
  3. 手机测试陨石软件,鉴定陨石真伪的简单测试方法
  4. 查看nvidia gpu共享内存大小
  5. html圆形头像的制作
  6. windows10流媒体服务器文件查看,win10的流媒体怎样启用?Win10启用流媒体的方法
  7. welearn考试切屏会有显示吗_welearn班级测试答案
  8. QTextEdit添加输入提示语
  9. 【Arch】Android 7 Nougat源码目录结构分析
  10. 串行口终端乱码的解决.