VMDK之动态扩展文件解析思路

版权声明:对于本博客所有原创文章,允许个人、教育和非商业目的使用,但务必保证文章的完整性且不作任何修改地以超链接形式注明原始作者、出处及本声明。

博客地址:

原始作者:季亚

请容许我发一点牢骚,本人小菜。起初,刚到公司时被公司研发部副总带到另外一个部门,说是搞数据分析的,但到那边后发现做的东西的确蛮不错的,只是害怕到那边后不让做C++相关方面的开发,所以还是对副总说对这个工作不是很喜欢,又说对于XX组比较感兴趣,才得以留下来做数据恢复工作。不知道以后还会做什么,心想不管做什么都要尽力吧。

也就是刚进公司的那天下午,经理说给我一个项目做,就是研究以动态扩展方式生成的VMDK文件,将其解析成DD文件。

于是,开始漫长的研究,起初脑袋有些大了。对于C++文件流的处理不是很熟悉,而且竟然也不是很知道seek函数与写文件时指针是动态移动的,呵呵,都说了嘛,我很菜的,不过我有一颗热爱学习的心。

现在,,功能已经基本实现,只是代码可能需要略加修改,为了方便他人以及对自己近期工作进行总结,于是把学习及解析的思想介绍一下,也算是本人即将踏入数据恢复的处女作吧(也不知道这算不算作品)。

一、 概述

关于VMDK的资料还是蛮多的,主要有VMware官方提供的技术文档(点此下载)、Google Code中的一个格式说明文档(点此下载)和相关开源源码等。

二、 工具

需要使用的工具主要有WinHex、FTK Imager、VMware 、010 Editor等,感觉现在对于WinHex使用的还不够熟悉。

三、 组成

一个磁盘可由若干个link(姑且称之为链,如图1所示)或一个VMDK Extent文件(也就是实际存储数据的文件)组成。而且,一个link可由一个或多个扩展文件(extent file)组成(如图2所示),并通过descriptor file(姑且称之为描述文件)中的CID、parentCID记录链接起来。

图1构成一个虚拟磁盘的链

图2 多个扩展文件(Extents)组成一个link

一个extent就是一片物理存储区域,通常是指一个文件,被虚拟磁盘所使用。

本文主要介绍如何将由多个扩展文件(Extents)构成的一个虚拟磁盘解析成DD文件。

三、 文件结构

每个扩展文件(extent file)的内部格式完全相同,包括Sparse Header、Descriptor Header、Metadata、和Data Blocks等部分,其结构如图3所示。其中Metadata由Grain Directories、Grain tables组成,即这两个结构主要存储偏移地址,包含解析文件时所需要的必要数据,其实在解析文件就是通过这些值来定位到真实数据的存储位置。

图3VMDK地址空间

3.1 文件头

解析文件应该少不了说文件头吧,最起码对于VMDK来说文件头中的至关重要,主要包含验证信息(魔数)、存储容量(capacity)、文件内部结构的偏移(descriptorOffset 、rgdOffset 、gdOffset、overHead)等。如图1所示即为Hosted Sparse Extents的文件头结构体,注释内容为在第一扇区中的偏移。

typedef uint64 SectorType;typedef uint8 Bool;typedef struct SparseExtentHeader{uint32magicNumber; // 0x00 – 0x03uint32version; // 0x04 – 0x07uint32flags; // 0x08 – 0x0BSectorTypecapacity; // 0x0C – 0x13SectorTypegrainSize; // 0x14 – 0x1BSectorTypedescriptorOffset; // 0x1C – 0x23SectorTypedescriptorSize; // 0x24 – 0x2Buint32numGTEsPerGT; // 0x2C – 0x2FSectorTypergdOffset; // 0x30 – 0x37SectorTypegdOffset; // 0x38 – 0x3FSectorTypeoverHead; // 0x40 – 0x47charuncleanShutdown; // 0x48charsingleEndLineChar; // 0x49 – 0x4CcharnonEndLineChar; // 0x49chardoubleEndLineChar1; // 0x4AchardoubleEndLineChar2; // 0x4Buint16compressAlgorithm; // 0x4Cuint8pad[433];} SparseExtentHeader; 由以上结构可以发现,文件头信息共占512个字节,即一个扇区。3.2 需要注意

3.3 Hosted Sparse Extent Metadata

在稀疏型扩展文件中有两层元数据,第0层元数据被称作一个grain directory或一个GD,第1层元数据被称为一个grain table或一个GT,第0层元数据中的每个记录均指向一个第1层元数据块,第1层元数据的大小是固定的(即每个GT包含512个记录),其中的每个记录均指向一块真实的存储数据单元(即grain),如图4和图5所示。

图4 扩展文件之元数据

图5 VMDK体系结构和设计

Grain Directory

Grain directory中的条目称作grain directory entry或GDE,一个grain directory条目占32位数据。

grain directories中记录数由VMDK扩展文件的大小所决定,其内存储是所对应grain table的偏移,每个grain table有512个记录,grain table中的每个记录存储的为实际数据块的偏移。2GbMaxExtentSparse文件最多有64个grain directories,可由以下算法计算得出(注意单位要统一,即均可以字节或扇区数进行计算):

number of grain directory entries = maximum data size / ( number of grain table entries * grain size );if( maximum data size % ( number of grain table entries * grain size ) > 0 ){number of grain directory entries += 1;} 由于一个VMDK扩展文件最多包含4192256个扇区,有:number of grain directory entries = 4192256 / ( 512 * 128 ) = 63,又4192256 % ( 512 * 128 ) = 63488 > 0,所以number of grain directory entries=63+1=64,即每个VMDK扩展文件最多包含64个grain directories(备注:这里我是以扇区的方式进行计算的)。

Grain Table

没有绝望的处境,只有对处境绝望的人。

VMDK之动态扩展文件解析思路

相关文章:

你感兴趣的文章:

标签云: