接着我们在第三季上集中讨论的内容。
在我们最开始的两个例子中,数据的值分别为 0x48000E00 和0x304D8500。但是我们的数据长度分别为176和88。
当我们只有4个字节空间时,数据长度怎么会是176呢?
在这之前,要认真探讨下注册表hive中另一个常见的数据结构——数据节点。
数据节点是一种非常简单的数据结构,具体情况如下:
| 大小:这是一个长度为32位的无符号整数,存储起始于偏移量0x00。
| 数据:数据起始于偏移量0x04。
| 填充:确保长度是8字节的整数倍。
数据节点被简用于存储被其他高级别的记录类型所占据的数据字节数。至少有一个数据节点有一个众所周知的签名(“db”列表),这在当我们探讨注册表中使用的不同列表格式时,我们会涉及到。
在我们继续之前,我想让你们思考下:在VK记录中,数据节点的大小和数据长度之间有什么关系?
现在,既然我们已经知道数据节点的概念了,那么VK记录怎么生成一个与数据相符的数据节点呢?正如我之前所提到的那样,存储在数据中的字节是实际数据存储位置的相对偏移量。
要得到绝对偏移量,我们需要在现有的相对位移量上再加上0x1000,也就是十进制的4096。 0x0E0048 + 0x1000 == E1048,所以我们就可以在绝对偏移量0xE1048处找到我们所需要的数据节点。数据节点的信息如下图所示:
在上图所示的情况下,数据节点正好就就在我们已经找到的VK记录的后面。但实际操作中并不总会出现这样的巧合,所以只需要按照偏移量进行计算,你就会找到数据节点。
同大多数注册表的结构一样,前四个字节是数据节点的长度。在上图中,其值为0x48FFFFFF,转换成十进制即为-184。
在数据驻留的例子中,回想之前的数据长度为176个字节,如果我们从数据节点的偏移量0x04处开始,取176个字节的数据,我们就得到了下面的数据:
46 00 69 00 6E 00 64 00 20 00 6F 00 75 00 74 00 20 00 77 00 68 00 61 00 74 00 19 20 73 00 20 00 68 00 61 00 70 00 70 00 65 00 6E 00 69 00 6E 00 67 00 2C 00 20 00 72 00 69 00 67 00 68 00 74 00 20 00 6E 00 6F 00 77 00 2C 00 20 00 77 00 69 00 74 00 68 00 20 00 74 00 68 00 65 00 20 00 70 00 65 00 6F 00 70 00 6C 00 65 00 20 00 61 00 6E 00 64 00 20 00 6F 00 72 00 67 00 61 00 6E 00 69 00 7A 00 61 00 74 00 69 00 6F 00 6E 00 73 00 20 00 79 00 6F 00 75 00 20 00 63 00 61 00 72 00 65 00 20 00 61 00 62 00 6F 00 75 00 74 00 2E 00 00 00
在我们学习了有关类型Type的知识之后,我们就可以将这些字节数据进行适当的解析了。当然了,可能有些同学会想知道上面列出的数据是那种类型的数据。
现在我们可以将数据节点的格式总结出来,具体内容如下图所示:
请记住,直到目前我们仍然无法将这些数据值解析为我们所能理解的内容,我们还需要VK记录中有关类型Type的知识。
类型(Type)
类型的存储位置开始于偏移量0x10处,系统采用一个长度为32位的无符号整数来对其进行存储。以下是一些注册表中常用的标准类型:
RegNone = 0x0000:无数据类型
RegSz = 0x0001: 一个字符串值,以UTF-16LE格式存储
RegExpandSz = 0x0002: 一个“可扩展的”包含环境变量的字符串值,通常以UTF-16LE格式存储
RegBinary = 0x0003: 二进制数据
RegDword = 0x0004: 一个DWORD值,一个长度为32位的无符号整数 (小端格式)
RegDwordBigEndian = 0x0005: 一个DWORD 值,一个长度为32位的无符号整数 (大端格式)
RegLink = 0x0006: 一个符号链接
RegMultiSz = 0x0007: 一个多字符串值,通常是一组有序的非空字符串,通常以UTF-16LE格式存储,终止符为NULL字符
RegResourceList = 0x0008: 一个资源列表
RegFullResourceDescription = 0x0009: 一个资源描述符
RegResourceRequirementsList = 0x000A: 一个资源需求列表
RegQword = 0x000B: 一个QWORD值,长度为64位的整数
RegFileTime = 0x0010: FILETIME数据
在这里需要注意的是RegNone Type,它表明数据没有类型,而不是说不存在数据。
如果你之前使用过注册表编辑器来查看系统的注册表,那你肯定见过下图所示的情形:
上图中同样有一个类型是没有任何值的。
当你了解了类型Type之后,现在我们就可以将字节数据解码为一些我们能看懂的信息了。
标识符(Flag)
标识符的存储位置起始于偏移量0x14处,系统采用了一个长度为16位的无符号整数来对其进行存储。标识符是用来判断VK记录的名称是否已经采用ASCII码或者Unicode格式存储过。
在上面的第一个例子中,其标识符的十六进制数值为0x0100,转换为十进制即为1。如果这个标识符的值大于零,那么这条VK记录的名称就是以ASCII码值的形式存储的。如果这个值等于零,那么就是以Unicode格式进行存储的。
名称
名称的存储位置起始于偏移量0x18处,它表示的是VK记录的初始名称。我们已经知道,名称的长度为11个字节,即:
44 65 73 63 72 69 70 74 69 6F 6E
填充
VK记录的长度必须是8字节的整数倍。第一个例子中,vk记录的总长度是40个字节(0x28)。既然名称从偏移量0x18处开始存储,长度为11字节, 0x18 + 0x0B == 0x23 bytes(转换成十进制即为35个字节)。VK记录中剩余的5个字节(00 3C 00 4D 00)就起到了填充的作用。
总结
我们把第一个例子分解成最重要的几个部分来看,重点已经进行了特别标注:
如果用注册表浏览器来查看VK记录,具体信息如下图所示:
注册表hive基础知识介绍的第四季会介绍SK记录,第五季将会介绍列表(list)。敬请期待!
还没有评论,来说两句吧...