首页
社区
课程
招聘
[原创]简单认识下注册表的HIVE文件格式
发表于: 2008-4-30 09:12 25969

[原创]简单认识下注册表的HIVE文件格式

2008-4-30 09:12
25969

---------------------------------------------
标 题: 【原创】简单认识下注册表的HIVE文件格式
作 者:  Sysnap
---------------------------------------------
目录
1 用windbg简单认识下HIVE文件
2 用ZwSaveKey生成一个HIVE文件
3 ring3来简单解释这个HIVE文件

1 用windbg简单认识下HIVE文件
物理上的HIVE文件
1 注册表是由许多个HIVE文件组成的
2 一个HIVE文件由许多个BIN组成,一般一个HIVE文件的开头会有一个文件头,用与描述这个HIVE文件的一些全局信息
3 一个BIN由许多个CELL组成
而CELL有好几种类型
比如 key cell(cm_key_node) value cell(CM_KEY_VALUE) subbkey-list cell,value-

list cell等

一个HIVE文件的结构
-------------         |
_HBASE_BLOCK |
_BIN0        |
_BIN1        |
_BIN2        |
:                |
:                |
_BINx        |
------------- |
一般自己映射HIVE文件,得到映射的基地址,这个基地址加上1页的大小就来到第一个BIN了
,BIN也是一个数据结构,里面也包含了一些描述这个BIN的信息,我们称之为BIN头,一个BIN
头的大小一般是0X20,所以一个BIN后的0X20开始就是我们的第一个CELL了,怎样把一个键及其下面的子键保存为HIVE文件,微软提供了API RegSaveKey,[LEFT][/LEFT]建议学习的时候用这个API来生成一个简单的HIVE文件,然后用WINHEX之类的工具查看该HIVE文件的内部,知道个大概

注册表相关的函数

用户态的regxxx
内核的NT和CM系列(关于CM系列的,一般都是没有导出的,如果想使用可以靠导出的获取没

导出的方法)

实验:
0 用winHex打开一个HIVE文件,看看其里面的内容

1了解与注册表有关的几个结构
用命令 dt nt!*cm*
这样就会列出一大堆数据结构出来,关于每个数据结构是怎样的,自己再dt看
比较重要的有
(HBASE_BLOCK)
NT!_CMHIVE
NT!_CMHIVE
NT!_CM_KEY_HASH
NT!_CM_KEY_BODY
NT!_CM_KEY_NODE
NT!_CM_KEY_VALUE
NT!_CM_KEY_SECURITY
NT!_CM_KEY_CONTROL_BLOCK

2一个简单的实验
lkd> !reg dumppool
...略,这里会列出许多的HIVE

dumping hive at e1022b60 (NONAME)
Stable Length = 1000
1/1 pages present
Volatile Length = 1000
can't read HMAP_ENTRY at e1b16000
0/1 pages present
Total pages present = 4311 / 14680

用!reg baseblock查看这个HIVE的基块

lkd> !reg baseblock e1022b60
FileName : NONAME
Signature: HBASE_BLOCK_SIGNATURE
Sequence1: 1
Sequence2: 1
TimeStamp: 0 0
Major    : 1
Minor    : 3
Type     : HFILE_TYPE_PRIMARY
Format   : HBASE_FORMAT_MEMORY
RootCell : 20
Length   : 0
Cluster : 1
CheckSum : 0

用!reg openkeys列出HIVE文件所有打开的键

lkd> !reg openkeys e1022b60

Index 48: 1cbf04a8 kcb=e1035a70 cell=00000188 f=00200004 \REGISTRY\USER
Index 1b8: dc72ea09 kcb=e3fefb48 cell=80000020 f=00300008

\REGISTRY\USER\S-1-5-18
Index 595: d936a631 kcb=e1035008 cell=00000020 f=002c0000 \REGISTRY
Index 698: bd68092e kcb=e1035248 cell=00000120 f=00200004

\REGISTRY\MACHINE

用!reg cellindex查看一下打开键的CELL单元.它是一个_cm_key_node结构

kd> !reg cellindex e1022b60 0x120

Map = e1022bc0 Type = 0 Table = 0 Block = 0 Offset = 120
MapTable     = e1033000
BlockAddress = e1032000

pcell: e1032124

得到CELL的地址pcell: e1032124后,接着
lkd> dt _cm_key_node e1032124
nt!_CM_KEY_NODE
   nt!_CM_KEY_NODE
   +0x000 Signature        : 0x6b6e
   +0x002 Flags            : 0x20
   +0x004 LastWriteTime    : _LARGE_INTEGER 0x1c8a59a`913acf5a
   +0x00c Spare            : 0
   +0x010 Parent           : 0x20
   +0x014 SubKeyCounts     : [2] 5
   +0x01c SubKeyLists      : [2] 0x448
   +0x024 ValueList        : _CHILD_LIST
   +0x01c ChildHiveReference : _CM_KEY_REFERENCE
   +0x02c Security         : 0x78
   +0x030 Class            : 0xffffffff
   +0x034 MaxNameLen       : 0x10
   +0x038 MaxClassLen      : 0
   +0x03c MaxValueNameLen : 0
   +0x040 MaxValueDataLen : 0
   +0x044 WorkVar          : 0
   +0x048 NameLength       : 7
   +0x04a ClassLength      : 0
   +0x04c Name             : [1] 0x414d

我们来解读这里的信息:
1 +0x000 Signature        : 0x6b6e 0x6b6e表示NK,_cm_key_node结构的标识符
2 +0x014 SubKeyCounts     : [2] 5 表示该键有5个子键
3 +0x01c SubKeyLists      : [2] 0x448 表示子键列表单元的单元索引为0x448
4 +0x024 ValueList        : _CHILD_LIST 表示本键键值单元的索引

注册表的组织
这里我们首先了解一个概念,单元索引
单元索引:是一个CELL在HIVE文件上的偏移量
看一下_CM_KEY_NODE这个结构,我们以HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001

\Services\6to4这个键为例,你可以把它及其子键保存为HIVE文件,然后观察

lkd> dt _CM_KEY_NODE
nt!_CM_KEY_NODE
   +0x000 Signature        : Uint2B
   +0x002 Flags            : Uint2B
   +0x004 LastWriteTime    : _LARGE_INTEGER
   +0x00c Spare            : Uint4B
   +0x010 Parent           : Uint4B
   +0x014 SubKeyCounts     : [2] Uint4B
   +0x01c SubKeyLists      : [2] Uint4B
   +0x024 ValueList        : _CHILD_LIST
   +0x01c ChildHiveReference : _CM_KEY_REFERENCE
   +0x02c Security         : Uint4B
   +0x030 Class            : Uint4B
   +0x034 MaxNameLen       : Uint4B
   +0x038 MaxClassLen      : Uint4B
   +0x03c MaxValueNameLen : Uint4B
   +0x040 MaxValueDataLen : Uint4B
   +0x044 WorkVar          : Uint4B
   +0x048 NameLength       : Uint2B
   +0x04a ClassLength      : Uint2B
   +0x04c Name             : [1] Uint2B
A键值
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\6to4这个键就是一个

_CM_KEY_NODE结构,ValueList的值就是一个单元索引了,由这个"单元索引"我们可以找到

6to4这个键的"键值列表单元",有了"键值列表单元",我们就可以找到"键值单元",有了键

值单元,我们就可以找到数据了
一般就是下面这条线
----------------------------------------------------------------------------
键单元----键值列表单元单元索引---键值列表单元--键值单元--数据单元
----------------------------------------------------------------------------
B子键
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\6to4下面还有三个子键,怎么找,

请看_CM_KEY_NODE里面的俩个成员
+0x014 SubKeyCounts     : [2] Uint4B
+0x01c SubKeyLists      : [2] Uint4B

SubKeyCounts表示这个键单元有多少个子键,SubKeyLists是子键列表单元的单元索引
所以一般SubKeyCounts是用于控制遍历子键的一个变量,这里我们应该知道怎么找到一个

键单元的子键了
----------------------------------------
SubKeyLists----子键列表单元-----子键单元
----------------------------------------
一个键可能有多个子键,由SubKeyCounts标识

2 用ZwSaveKey生成一个HIVE文件
这里我们用驱动程序,不过用户程序也是可以的,很简单,就是获得ZwSaveKey所需要的句柄,这里我们用了ZwOpenKey和ZwCreateFile,我们把\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services这个键极其子键保存为一个HIVE文件.这个HIVE文件的路径是C:\my.dat

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
                                         IN PUNICODE_STRING theRegistryPath)
{
       
        HANDLE keyhandle,filehandle;
       
        IO_STATUS_BLOCK iostatus;
        OBJECT_ATTRIBUTES keyoa ,fileoa;
   
        UNICODE_STRING  keypath,filepath;
        RtlInitUnicodeString(&keypath,L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services");
    RtlInitUnicodeString(&filepath,L"\\Device\\HarddiskVolume1\\my.dat");
       
        InitializeObjectAttributes(
    &keyoa,
        &keypath,
    OBJ_CASE_INSENSITIVE,
    0,
    0
    );
        InitializeObjectAttributes(
    &fileoa,
        &filepath,
    OBJ_CASE_INSENSITIVE| OBJ_KERNEL_HANDLE,
    0,
    0
    );
       
       
        ZwOpenKey(&keyhandle,
                      KEY_ALL_ACCESS,
                          &keyoa);

       
        ZwCreateFile(
                         &filehandle,
                 FILE_ALL_ACCESS,
                 &fileoa,
                 &iostatus,
                 NULL,
                 FILE_ATTRIBUTE_NORMAL,
                 FILE_SHARE_READ|FILE_SHARE_WRITE,
                 FILE_CREATE| FILE_OPEN | FILE_OVERWRITE_IF,
                 FILE_SYNCHRONOUS_IO_NONALERT,
                 NULL,
                 NULL
                                 );

        ZwSaveKey(keyhandle,
                      filehandle );
   
        theDriverObject->DriverUnload = OnUnload;
        return STATUS_SUCCESS;

}

3 ring3来简单解释这个HIVE文件

好了,到了这一步我们已经有了一个HIVE文件,接着我们就是解释它
首先把这个HIVE文件读入内存,基地址加上一个页的大小就来到了第一个BIN,BIN头大小是0X20我们不用理,加上0X20后我们就来到了第一个CELL...即ROOTCELL...接着就是开始解释这个HIVE文件了

void ListValue( PCHAR keypath,  PCM_KEY_NODE KeyNode )
{
    char *SubKeyName=keypath;
        PCHAR val;
       
        memcpy(keypath,&KeyNode->KeyName,KeyNode->KeyName);
        keypath+=KeyNode->KeyName_len;
        printf("the key name      :%s\n",   SubKeyName);

   
}

void ListSubKeys( PCHAR keypath,  PCM_KEY_NODE KeyNode )
{
    RootBin=(PCHAR)KeyNode-0x20;
         
        PCM_KEY_FAST_INDEX dirKey = (PCM_KEY_FAST_INDEX)(RootBin+KeyNode->Subkeys_offset);
    for(ULONG index1=0;index1<dirKey->NumberOfKeys;index1++)
        {
               
        PCM_KEY_FAST_INDEX subkey = (PCM_KEY_FAST_INDEX)((&dirKey->ValueData_Offset)[index1]+RootBin);
        if(dirKey->Signature[1]=='f')
                {
            ListValue(keypath,(PCM_KEY_NODE)((&dirKey->ValueData_Offset)[index1*2]+RootBin));
                       
        }
                else
                for(ULONG index2=0;index2<subkey->NumberOfKeys;index2++)
                {
            ListValue(keypath,(PCM_KEY_NODE)((&subkey->ValueData_Offset)[index2]+RootBin));
               
        }
    }

}

后注:在dump hive时,正常是没有问题的...但如果使用了combojiang那篇隐藏注册表里面的那个驱动程序来隐藏注册表...比如它里面隐藏了Services键下的子键Beep,,,那我们在dump Services时就会失败....也不知道是什么原因,,应该是被什么干扰了吧...不过你可以自己复制原始的HIVE文件,在解释它...这个程序再改改应该可以...不过到了这里你应该对HIVE文件有个大概的理解了..


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 8
支持
分享
最新回复 (17)
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
2
好文,学习了。
2008-4-30 09:28
0
雪    币: 70
活跃值: (74)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
这个怎么没人顶啊  很好很详细!
2008-4-30 20:37
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
4
一直对HIVE搞不懂,google的资料也不多,谢谢
2008-4-30 21:45
0
雪    币: 332
活跃值: (30)
能力值: ( LV12,RANK:460 )
在线值:
发帖
回帖
粉丝
5
一会看
2008-4-30 22:21
0
雪    币: 280
活跃值: (15)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
学习了,适合我这样的菜鸟看
2008-5-1 08:08
0
雪    币: 243
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
谢谢lz,先收藏了
2008-5-1 09:05
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
非常棒 学习
2008-5-5 02:20
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
占位学习了
2008-5-7 21:40
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
ZwSaveKey是一个软件么???,是的话能提供一下吗?
还是有点不明白,谢谢楼主!!!
2009-2-11 17:21
0
雪    币: 247
活跃值: (10)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
11
好文,,,注册表有好多不懂~~~
2009-2-11 18:22
0
雪    币: 232
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
好,!!就是看不懂!
2009-2-14 17:30
0
雪    币: 52
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
我想问一下:
lkd> dt _CM_KEY_NODE
nt!_CM_KEY_NODE
   +0x000 Signature        : Uint2B
   +0x002 Flags            : Uint2B
   +0x004 LastWriteTime    : _LARGE_INTEGER
   +0x00c Spare            : Uint4B
   +0x010 Parent           : Uint4B
   +0x014 SubKeyCounts     : [2] Uint4B
   +0x01c SubKeyLists      : [2] Uint4B
   +0x024 ValueList        : _CHILD_LIST
   +0x01c ChildHiveReference : _CM_KEY_REFERENCE
   +0x02c Security         : Uint4B
   +0x030 Class            : Uint4B
   +0x034 MaxNameLen       : Uint4B
   +0x038 MaxClassLen      : Uint4B
   +0x03c MaxValueNameLen : Uint4B
   +0x040 MaxValueDataLen : Uint4B
   +0x044 WorkVar          : Uint4B
   +0x048 NameLength       : Uint2B
   +0x04a ClassLength      : Uint2B
   +0x04c Name             : [1] Uint2B

这个结构里面的Name存的是什么内容,是:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\6to4
的最后一节,也就是"6to4"吗?

还有个问题:如果往注册表中插入一个新的子键,那需要去SubKeyLists这个偏移处,子键序列的未必再添加一个子健,这个不是就老要挪动内存了吗?不懂这个添加的过程。谢谢。
2011-3-5 14:48
0
雪    币: 52
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
是从根开始加载,然后查询哪一项,就加载哪一项吗?

还有,删除操作怎么执行?会有小内存的释放吗?
2011-3-5 14:51
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
15
最近刚看到好像微软官网有个专门读写hive的dll供SDK
2011-3-5 21:51
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
有没有很详细分析hive文件结构的资料?
2011-7-13 15:30
0
雪    币: 36
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
谢谢分享
2013-6-5 12:59
0
雪    币: 986
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
拜读了您的文章,有感觉。
2015-12-28 16:09
0
游客
登录 | 注册 方可回帖
返回
//