HIVE结构解析_第二章阅读
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
HIVE结构解析
在认识真正的HIVE文件之前,先列举HIVE文件的几个主要特征。先入为主的将它们呈现出来将有助于我们对其文件组织和数据结构的理解。
注册表由多个HIVE文件组成。
一个HIVE文件由多个巢箱(BIN)组成
HIVE文件的首部有一个文件头(基本块、base block),用于描述这个HIVE文件的一些全局信息
一个BIN由多个巢室(CELL)组成,
CELL可以分为具体的5种(后面介绍),用于存储不同的注册表数据。
本文中,我们并不统一使用HIVE、BIN和CELL的英文单词,而是和对应的中文词汇交替出现。在中文里,它们分别对应储巢、巢箱和巢室三个名词。
一个储巢被看成是一些称为块(block)的分配单元,类似于将磁盘分为簇的形式。根据定义,每一个注册表块的大小为4096字节(4KB),当新的数据要加入到一个储巢中来时,该储巢总是按照块的粒度来增加。一个储巢的第一个块是基本块(base block),包含了有关该储巢的全局信息,包括一个特征签名“regf”,更新序列号,储巢上一次写操作发生的时间戳,储巢格式版本号、检验和,以及该储巢文件的内部文件名等等。下面的_HBASE_BLOCK就是一个基本块的数据结构还原。
typedef struct _HBASE_BLOCK
{
ULONG Signature; /* 签名ASCII-"regf" = 0x66676572 (小端序)*/
ULONG Sequence1;
ULONG Sequence2;
LARGE_INTEGER TimeStamp; /* 最后一次写操作的时间戳 */
ULONG Major; /* 主版本号 */
ULONG Minor; /* 次版本号 */
ULONG Type;
ULONG Format;
ULONG RootCell; /* 第一个键记录的偏移 */
ULONG Length; /* 数据块长度*/
ULONG Cluster;
UCHAR name[64]; /* 储巢文件名*/
ULONG Reserved1[99];
ULONG CheckSum; /* 校验和*/
ULONG Reserved2[894];
ULONG BootType;
ULONG BootRecover;
} HBASE_BLOCK, *PHBASE_BLOCK;
Windows将一个储巢所存储的注册表条目组织在一种称为巢室的容器中,当一个巢室加入到一个储巢中,而且该巢室必须经过扩展才能容纳该巢室时,系统将创建一个巢箱的分配单元。巢箱是新巢室正好扩展到下一个块的边界的大小,系统将巢室的尾部和巢箱的尾部之间的任何空间都看作是空闲空间,因而可以分配其他的巢室。
巢箱也有头部的标识,包含了一个特殊的签名“hbin”,一个记录了该巢箱在储巢文件中偏移量的域,以及该巢箱的大小。下面是巢箱的数据结构。
typedef struct _HBIN
{
ULONG Signature; /* 签名 ASCII-"hbin" = 0x6E696268 (小端序)*/
ULONG FileOffset; /* 本巢箱相对第一个巢箱起始的偏移*/
ULONG Size; /* 本巢箱的大小*/
ULONG Reserved1[2];
LARGE_INTEGER TimeStamp;
ULONG Spare;
} HBIN, *PHBIN;
一个巢室可以容纳一个键、一个值、一个安全描述符、一列子键或者一列键值,分别有对应的巢室来存储数据。在巢室数据的开始之处,有一个数据域描述了该巢室数据的类型,具体的数据结构如下:
键巢室,包含了一个注册表键(也称为键节点)的巢室,一个键巢室包含一个特征签名(对于一个键是kn,一个符号链接是kl)、该键最近一次更新的时间戳、该键父键巢室的巢室索引、代表该键的子键的子键列表巢室的索引、该键的安全描述符巢室索引、一个代表该键类名的字符串键巢室索引,以及该键的名称。
typedef struct _CM_KEY_NODE
{
USHORT Signature; /* 签名ASCII-"kn" = 0x6B6E (小端序)*/ USHORT Flags; /* 根键标识: 0x2C, 其他为0x20 */
LARGE_INTEGER LastWriteTime;
ULONG Spare;
ULONG Parent; /* 父键的偏移*/
ULONG SubKeyCounts[2]; /* SubKeyCounts[0]为子键的个数 */
union /* 偏移为0x001C 联合体 */
{
struct
{
ULONG SubKeyLists[2]; /* SubKeyLists[0]为子键列表相差本BIN的偏移*/
CHILD_LIST ValueList; /* ValueList结构体*/
};
ULONG ChildHiveReference[4];
};
ULONG Security; /* 安全描述符记录的偏移 */
ULONG Class; /* 类名的偏移 */
ULONG MaxNameLen: 16;
ULONG UserFlags: 4;
ULONG VirtControlFlags: 4;
ULONG Debug: 8;
ULONG MaxClassLen;
ULONG MaxValueNameLen;
ULONG MaxValueDataLen;
ULONG WorkVar;
USHORT NameLength; /* 键名长度 */
USHORT ClassLength; /* 类名长度*/
PBYTE Name; /* 键名称*/
}CM_KEY_NODE, *PCM_KEY_NODE;
值巢室,一个巢室,包含了关于一个键的值的信息,该巢室包含一个签名kv,该值的类型,如REG_DWORD或REG_BINARY,以及该值的名称。一个值巢室也包含了另一个值巢室的索引,后者包含了对前者的数据。
typedef struct _CM_KEY_VALUE
{
WORD Signature; /* 签名ASCII-"kv" = 0x6B76(小端序)*/
WORD NameLength; /* 名称长度 */
ULONG DataLength; /* 数据长度*/
ULONG Data; /*数据偏移或数据, 如果DataLength最高位为1,那么它就是数据,
且DataLenth&0x7FFFFFFF为数据长度;否则*/
ULONG Type; /* 值类型*/