目錄
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,建議學習的時候用這個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"http://REGISTRY//MACHINE//SYSTEM//ControlSet001//Services");
RtlInitUnicodeString(&filepath,L"http://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文件有個大概的理解了..
新聞熱點
疑難解答