Windows XP注册表文件格式简单分析.docx
- 文档编号:12345839
- 上传时间:2023-06-05
- 格式:DOCX
- 页数:16
- 大小:691.67KB
Windows XP注册表文件格式简单分析.docx
《Windows XP注册表文件格式简单分析.docx》由会员分享,可在线阅读,更多相关《Windows XP注册表文件格式简单分析.docx(16页珍藏版)》请在冰点文库上搜索。
WindowsXP注册表文件格式简单分析
WindowsXP注册表文件格式简单分析
Bybillh
大家都用过注册表编辑器(regedit)修改过注册表。
它由根键(rootkey)、子键(subkey)、值(value)、数据(data)组成。
注册表并不是一个简单的大文件,而是一组称为hive的单独文件;每个hive文件是一棵注册表树,但要清楚regedit所显示的根键与hive文件中的根键不是相互对应的。
当配置管理器加载hive文件的时候,它会在HKLM\SYSTEM\CurrentControlSet\Control\hivelist子键下的注册表值中记录下每个hive文件的路径,如果被卸载,那么它也会删除对应的值。
如我的机器:
(所有图片自己可以放大来看)
那好,我们就用WinHex工具来找子键和某个键的值,我想这样最能让人认识某种文件的格式了(至少我是这样认为)。
本来我想直接用WinHex去打开C:
\WINDOWS\system32\config\SYSTEM但提示如下错误:
无奈,只有选择其他的办法了,还好Microsoft提供了RegSaveKey函数,利用它可以轻松的把某个键保存为hive文件,但要注意:
你保存的那个键就作为根键了。
说做就做,如下:
步骤1:
为了以后表达得更清楚,我在HKEY_LOCAL_MACHINE\SYSTEM下建立了子键test_root,然后在test_root下再建立两个子键1test和2test,并且在1test下新建了五种不同的值,并填写了相应的数据(你可以直接导入test.reg文件,省去自己手动编辑)。
步骤2:
自己用RegSaveKey函数编个小程序,把test_root保存为hive文件。
注意:
那么test_root就变成你保存的hive文件的根键了。
#include
#include
voidEnableToken();
intmain()
{
LONGr;
HKEYhReg;
r=RegOpenKey(HKEY_LOCAL_MACHINE,"SYSTEM\\test_root",&hReg);//test_root为根键
if(r!
=ERROR_SUCCESS)
{
printf("RegOpenKeyError!
");
return1;
}
EnableToken();
r=RegSaveKey(hReg,"c:
\\test_root.dat",NULL);
if(r!
=ERROR_SUCCESS)
{
if(r==ERROR_ALREADY_EXISTS)
{
printf("FileExists!
");
return1;
}
RegCloseKey(hReg);
printf("RegSaveKeyError!
");
return1;
}
RegCloseKey(hReg);
printf("Success!
");
return0;
}
voidEnableToken()
{
HANDLEhToken;
TOKEN_PRIVILEGESNewToken;
NewToken.PrivilegeCount=1;
NewToken.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(NULL,SE_BACKUP_NAME,&NewToken.Privileges[0].Luid);
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
if(AdjustTokenPrivileges(hToken,FALSE,&NewToken,NULL,NULL,NULL)==0)
{
printf("EnableTokenError!
");
}
CloseHandle(hToken);
}
步骤3:
分析hive格式
用WinHex打开test_root.dat文件
我们可以看到”regf”字符串,这显然是registryfile的缩写,标志它是个注册表文件。
其实文件的开头是HBASE_BLOCK结构
lkd>dt_HBASE_BLOCK
nt!
_HBASE_BLOCK
+0x000Signature:
Uint4B//”regf”字符串
+0x004Sequence1:
Uint4B
+0x008Sequence2:
Uint4B
+0x00cTimeStamp:
_LARGE_INTEGER
+0x014Major:
Uint4B
+0x018Minor:
Uint4B
+0x01cType:
Uint4B
+0x020Format:
Uint4B
+0x024RootCell:
Uint4B
+0x028Length:
Uint4B
+0x02cCluster:
Uint4B
+0x030FileName:
[64]UChar
+0x070Reserved1:
[99]Uint4B
+0x1fcCheckSum:
Uint4B
+0x200Reserved2:
[894]Uint4B
+0xff8BootType:
Uint4B
+0xffcBootRecover:
Uint4B
加0x1000(4k)也就是一页的大小
我们来到
在0x1000开始处是个HBIN结构,其实hive文件是由HBASE_BLOCK和称为BIN的东西组成的,而BIN由称为cell的东西组成。
示意图:
HBASE_BLOCK
BIN1
BIN2
BINn
......
typedefstruct_HBIN
{
+0x000ULONGSignature;//”hbin”字符串
+0x004ULONGFileOffset;//本BIN相差0x1000的偏移
+0x008ULONGSize;//本BIN的大小
+0x00cULONGReserved1[2];
+0x014LARGE_INTEGERTimeStamp;
+0x01cULONGSpare;
+0x020ULONGReserved2;
+0x024
//
//这里开始是cell数据
//
}
注意:
cell可以是一个键、一个值、一个安全描述符、一列子键或者一列键值。
typedefstruct_CELL_DATA
{
union_u//注意它是一个联合体
{
CM_KEY_NODEKeyNode;//键结构
CM_KEY_VALUEKeyValue;
CM_KEY_SECURITYKeySecurity;
CM_KEY_INDEXKeyIndex;
CM_BIG_DATAValueData;
HCELL_INDEXKeyList[1];
WCHARKeyString[1];
}u;
}CELL_DATA,*PCELL_DATA;
在这图中0x1000+0x24=0x1024开始处是CM_KEY_NODE结构
lkd>DT_CM_KEY_NODE
nt!
_CM_KEY_NODE
+0x000Signature:
Uint2B//”nk”字符串
+0x002Flags:
Uint2B
+0x004LastWriteTime:
_LARGE_INTEGER
+0x00cSpare:
Uint4B
+0x010Parent:
Uint4B
+0x014SubKeyCounts:
[2]Uint4B//SubKeyCounts[0]子键的个数
+0x01cSubKeyLists:
[2]Uint4B//SubKeyLists[0]子键列表相差本BIN的偏移
+0x024ValueList:
_CHILD_LIST//ValueList.Count值的个数
//ValueList.List值列表相差本BIN的偏移
+0x01cChildHiveReference:
_CM_KEY_REFERENCE
+0x02cSecurity:
Uint4B
+0x030Class:
Uint4B
+0x034MaxNameLen:
Pos0,16Bits
+0x034UserFlags:
Pos16,4Bits
+0x034VirtControlFlags:
Pos20,4Bits
+0x034Debug:
Pos24,8Bits
+0x038MaxClassLen:
Uint4B
+0x03cMaxValueNameLen:
Uint4B
+0x040MaxValueDataLen:
Uint4B
+0x044WorkVar:
Uint4B
+0x048NameLength:
Uint2B//键名的长度
+0x04aClassLength:
Uint2B
+0x04cName:
[1]Uint2B//键名
在这里,我们先找键名,在0x1024+0x4c=0x1070(可以看出键名为test_root)
键名长度,在0x1024+0x48=0x106c
在这里,我们的子键个数值,在0x1024+0x14=0x1038
子键列表偏移值(相对于本BIN),在0x1024+0x1c=0x1040
所以,我们的子键列表在0x1000+0x3c0=0x13c0
从0x13c0+0x4=0x13c4开始是一个CM_KEY_INDEX结构
lkd>dt_CM_KEY_INDEX
nt!
_CM_KEY_INDEX
+0x000Signature:
Uint2B
+0x002Count:
Uint2B//这里也是表示子键的数量,与前面的相同
+0x004List:
[1]Uint4B//这里要注意了
如果Signature==CM_KEY_FAST_LEAF或CM_KEY_HASH_LEAF,那么从0x004偏移开始的数组元素结构如下:
struct
{
ULONGoffset;
ULONGHashKey;
}
否则:
ULONGoffset;
在这里Signature==CM_KEY_FAST_LEAF,所以第一个子键偏移值,在0x13c4+4=0x13c8
第二个子键偏移值,在0x13c8+0x8=0x13d0
1.查找第一个子键
第一个子键,在0x1000+0x1e0=0x11e0
在0x11e0+0x4=0x11e4开始又是一个CM_KEY_NODE结构
在0x11e4+0x48=0x122c处为键名长度0xc
在0x11e4+0x4c=0x1230处为键名1test_subkey
2.查找第二个子键
对于第二个子键,查找方式和第一个子键相同,这里不再赘述了。
3.查找第一个子键的值
由CM_KEY_NODE结构,我们知道值列表偏移值,在0x11e4+0x28=0x120c
值个数,在0x11e4+0x24=0x1208
所以,值列表,在0x1000+0x318=0x1318
在0x1318+0x4=0x131c处开始,每个ULONG为值偏移值
第一个值:
在0x1000+0x240=0x1240
在0x1240+0x4=0x1244开始是一个CM_KEY_VALUE结构
lkd>DT_CM_KEY_VALUE
nt!
_CM_KEY_VALUE
+0x000Signature:
Uint2B//”vk”字符串
+0x002NameLength:
Uint2B
+0x004DataLength:
Uint4B//数据长度,以字节计,包括结束符
+0x008Data:
Uint4B//注意:
数据偏移或数据
判断:
如果DataLenth最高位为1,那么它就是数据,且DataLenth&0x7FFFFFFF为数据长度
+0x00cType:
Uint4B
+0x010Flags:
Uint2B
+0x012Spare:
Uint2B
+0x014Name:
[1]Uint2B
值名长度,在0x1244+0x2=0x1246
值名,在0x1244+0x14=0x1258
数据类型,在0x1244+0xc=0x1250
数据长度,在0x1244+0x4=0x1248
数据偏移或数据(这里为数据偏移),在0x1244+0x8=0x124c
数据,在0x1000+0x260=0x1260,但0x1260+0x4=0x1264开始才是我们的数据,并且字符是UNICODE编码的。
第二个值:
在0x1000+0x278=0x1278
在0x1278+0x4=0x127c开始同样也是一个CM_KEY_VALUE结构
值名长度,在0x127c+0x2=0x127e
值名,在0x127c+0x14=0x1290
数据类型,在0x127c+0xc=0x1288
数据长度,在0x127c+0x4=0x1280
数据偏移或数据(这里为数据),在0x127c+0x8=0x1284
第三个值:
在0x1000+0x2b0=0x12b0
在0x12b0+0x4=0x12b4开始同样也是一个CM_KEY_VALUE结构
值名长度,在0x12b4+0x2=0x12b6
值名,在0x12b4+0x14=0x12c8
数据类型,在0x12b4+0xc=0x12c0
数据长度,在0x12b4+0x4=0x12b8
数据偏移或数据(这里为数据),在0x12b4+0x8=0x12bc
第四个值、第五个值,同样的方法,我就不再赘述了。
步骤四:
到此,已经会找子键、值、数据了!
那么自己编写个解析程序吧!
详细代码见HiveParse.c
运行效果(和我们用regedit.exe查看的相同):
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Windows XP注册表文件格式简单分析 XP 注册表 文件格式 简单 分析