轉(zhuǎn):http://www./yunjishu/yunjisuanhexinjishu/Hadoop/20110409_294.html 1.HIVE結(jié)構(gòu) 首先,要明白的是注冊表是由多個hive文件組成. 而一個hive是由許多bin組成,一個bin是由很多cell組成. 而cell可以有好幾種類型.比如 key cell(cm_key_node) value cell(CM_KEY_VALUE) subbkey-list cell,value-list cell等 當(dāng)新的數(shù)據(jù)要擴張一個hive時,總是按照block的粒度(4kb)來增加,一個hive的第一個塊是base block.包含了有關(guān)該hive的全局信息.參考結(jié)構(gòu) _hbase_block bin也有頭部,其中包含了一個特征簽名hbin,一個記錄該bin在hive中的offset(偏移),以及該bin的大小。bin頭的大小一般為0x20。 所以一個hive的磁盤映像看起來如下圖 +===============+ + _hbase_block (4kb) + +===============+ + _bin0 + +===============+ + _bin1 + +===============+ + _bin2 + +===============+ + .........+ +===============+ + _bin N + +===============+ bin頭的結(jié)構(gòu)_hbin如下: typedef struct _HBIN { +0x000 ULONG Signature; //”hbin”字符串 +0x004 ULONG FileOffset; //本BIN相差0x1000的偏移 +0x008 ULONG Size; //本BIN的大小 +0x00c ULONG Reserved1[2]; +0x014 LARGE_INTEGER TimeStamp; +0x01c ULONG Spare; +0x020 ULONG Reserved2; +0x024 // //這里開始是cell數(shù)據(jù) // } 所以定位到第一個cell的步驟如下: 1,將磁盤上的hive文件*.dat通過CreateFile()和CreateFileMapping()映射到內(nèi)存,得到hFileMap. 2,hFileMap加上一個_base_block大小(0x1000),定位到bin頭,即RootBin=hFileMap+0x1000. 3,RootBin加上一個_hbin的大小,即可定位到第一個cell,即pKeyNode=RootBin+0x24;(假設(shè)該hive的第一個cell為_CM_KEY_NODE結(jié)構(gòu)) 2.關(guān)于cell的幾個結(jié)構(gòu) 一個cell可以容納一個鍵,一個值,一個安全描述,一列子鍵,或者一列鍵值. typedef struct _CELL_DATA { union _u //注意它是一個聯(lián)合體 { CM_KEY_NODE KeyNode; //鍵結(jié)構(gòu) CM_KEY_VALUE KeyValue;//值的結(jié)構(gòu), 包含一個鍵的值的信息. CM_KEY_SECURITY KeySecurity;//安全描述 CM_KEY_INDEX KeyIndex;//一列子鍵,又一系列的鍵cell的cellindex所構(gòu)成的cell,這些cell是一個公共parent key的所有subkey. CM_BIG_DATA ValueData; HCELL_INDEX KeyList[1];//一列鍵值, WCHAR KeyString[1]; } u; } CELL_DATA, *PCELL_DATA; lkd> DT _CM_KEY_NODE nt!_CM_KEY_NODE +0x000 Signature : Uint2B //”nk”字符串 +0x002 Flags : Uint2B +0x004 LastWriteTime : _LARGE_INTEGER +0x00c Spare : Uint4B +0x010 Parent : Uint4B +0x014 SubKeyCounts : [2] Uint4B //SubKeyCounts[0]子鍵的個數(shù) +0x01c SubKeyLists : [2] Uint4B //SubKeyLists[0]子鍵列表相差本BIN的偏移 +0x024 ValueList : _CHILD_LIST //ValueList.Count值的個數(shù) //ValueList.List值列表相差本BIN的偏移 +0x01c ChildHiveReference : _CM_KEY_REFERENCE +0x02c Security : Uint4B +0x030 Class : Uint4B +0x034 MaxNameLen : Pos 0, 16 Bits +0x034 UserFlags : Pos 16, 4 Bits +0x034 VirtControlFlags : Pos 20, 4 Bits +0x034 Debug : Pos 24, 8 Bits +0x038 MaxClassLen : Uint4B +0x03c MaxValueNameLen : Uint4B +0x040 MaxValueDataLen : Uint4B +0x044 WorkVar : Uint4B +0x048 NameLength : Uint2B //鍵名的長度 +0x04a ClassLength : Uint2B +0x04c Name : [1] Uint2B //鍵名 補充下_CHILD_LIST結(jié)構(gòu): nt!_CHILD_LIST +0x000 Count : Uint4B //ValueList.Count值的個數(shù) +0x004 List : Uint4B //ValueList.List值列表相差本BIN的偏移 通過觀察_CM_KEY_NODE結(jié)構(gòu), 我們發(fā)現(xiàn)pKeyNode+0x4c獲得鍵名,即RootKeyName=pKeyNode->Name; 通過ValueList域,可得到值列表相差本bin的偏移,可以定位該鍵的值結(jié)構(gòu).即_CM_KEY_VALUE. ValueIndex=(ULONG *)(Bin+ValueLists+0x4); value=(PCM_KEY_VALUE)(Bin+ValueIndex[i]+0x4); 而通過SubKeyLists域,可得到子鍵列表相差本bin的偏移. DWORD SubKeyLists=KeyNode->SubKeyLists[0]; KeyIndex=(PCM_KEY_INDEX)(RootBin+SubKeyLists+0x4); lkd> DT _CM_KEY_VALUE nt!_CM_KEY_VALUE +0x000 Signature : Uint2B //”vk”字符串 +0x002 NameLength : Uint2B +0x004 DataLength : Uint4B //數(shù)據(jù)長度,以字節(jié)計,包括結(jié)束符 +0x008 Data : Uint4B //注意:數(shù)據(jù)偏移或數(shù)據(jù)判斷:如果DataLenth最高位為1,那么它就是數(shù)據(jù),且DataLenth&0x7FFFFFFF為數(shù)據(jù)長度 +0x00c Type : Uint4B +0x010 Flags : Uint2B +0x012 Spare : Uint2B +0x014 Name : [1] Uint2B 通過_CM_KEY_VALUE結(jié)構(gòu),可以獲得該鍵值的類型(type),名字(Name),以及數(shù)據(jù)(Data) lkd> dt _CM_KEY_INDEX nt!_CM_KEY_INDEX +0x000 Signature : Uint2B +0x002 Count : Uint2B //這里也是表示子鍵的數(shù)量,與前面的相同 +0x004 List : [1] Uint4B //這里要注意了 如果Signature==CM_KEY_FAST_LEAF或CM_KEY_HASH_LEAF,那么從0x004偏移開始的數(shù)組元素結(jié)構(gòu)如下: struct { ULONG offset; ULONG HashKey; } 否則: ULONG offset; 對于_CM_KEY_INDEX結(jié)構(gòu),通過List域可以定位所有子鍵的_CM_KEY_NODE結(jié)構(gòu),具體實現(xiàn)如下: DWORD KeyNodeOffset=KeyIndex->List[i*2]; //(其中的i是,USHORT i=0,i<count,i++) KeyNode=(PCM_KEY_NODE)(Bin+KeyNodeOffset+0x4); 這樣定位到每個子鍵的_CM_KEY_NODE結(jié)構(gòu),就能獲得該子鍵的鍵值,以及該子鍵下面的子子鍵, 這樣重復(fù)上述的步驟就能實現(xiàn)對整個hive的解析. ps下:通過是ring3的RegSaveKey(),可以生成一個Hive文件. 具體實現(xiàn)的代碼如下:
關(guān)于上面code的一些補充說明:(by linxer) 1.對nk節(jié)點下二級索引子鍵的情況沒有處理(有ri節(jié)點情況,當(dāng)子鍵過多的時候系統(tǒng)會使用ri節(jié)點的) 2.TypeValue里對值名稱的處理有問題,問題出在這下面兩行代碼 strncpy(ValueName,&value->Name,value->NameLength); printf("Value Name: %s\n",ValueName); vk節(jié)點的值名稱未必就是ascii字符串,因此用str系列函數(shù)是不可以的,正確用法應(yīng)該是 memcpy(ValueName,&value->Name,value->NameLength);因此顯示語句也不能用printf來顯示,目前我看到的很多代碼都有這樣的問題(chntpw),還有一些使用的hive解析的工具(SnipeSword0225)也有這種問題 (責(zé)任編輯:admin) |
|