我有一段要调查的二进制数据。我的猜测是它应该是简单的类似文件系统的索引的一部分。文件中有 2 个部分。第一部分有一个非常简单的格式:
- 第一部分的字节数
- 许多看起来像文件名的以零结尾的字符串(其中 1256 个)
自然地,我希望稍后会找到指向一些以这些字符串命名的文件的指针。但是,文件的其余部分长 0x5c47 字节,看起来它有许多记录(int32,little endian = 0x4e0),然后是一系列记录本身。然而,诀窍在于显然记录长度不是恒定的:(0x5c47 - 4) / 0x4e0 ~ 18.9254807。我在这里看到了某种模式,让我演示一下:
E0 04 00 00
正如我所说,它以记录数开始,0x4e0 = 1248。请注意,1248 条记录与我之前找到的字符串数(1256)相当接近,但并不完全匹配。然后我看到一些 14 字节长的记录:
90 00 |90 0D|90 16 02 90 22 90 2A 90 39|00
90 46 |90 0D|90 16 02 90 22 90 2A 90 39|01
90 53 |90 0D|90 16 02 90 22 90 2A 90 39|02
90 61 |90 0D|90 16 02 90 22 90 2A 90 39|03
90 6E |90 0D|90 16 02 90 22 90 2A 90 39|04
最后一个字节似乎是记录号计数器。至于其他人,到目前为止,只有第二个字节发生了变化。但是,接下来我们会看到一些 15 字节长的记录:
91 82 00|90 0D|90 16 02 90 22 90 2A 90 39|05
91 97 00|90 0D|90 16 02 90 22 90 2A 90 39|06
91 A4 00|90 0D|90 16 02 90 22 90 2A 90 39|07
...
91 14 01|90 0D|90 16 02 90 22 90 2A 90 39|0E
似乎涉及到一些可变长度的整数,即记录的第一个值以90 00,开头90 46,然后它最终溢出并变为91 82 00, 91 97 00, ...91 26 01等。但是,这不是正常的(BER,AKA VLQ,AKA Base128,等)编码我曾经使用过的可变长度整数。让我们检查一下记录的内容在变成 16 字节长的记录后如何扩展:
91 26 01|90 0D|90 16 02 90 22 90 2A 90 39|0F
91 39 01|90 0D|90 16 02 90 22 90 2A 90 39|80 10
91 4E 01|90 0D|90 16 02 90 22 90 2A 90 39|80 11
91 6C 01|90 0D|90 16 02 90 22 90 2A 90 39|80 12
91 8B 01|90 0D|90 16 02 90 22 90 2A 90 39|80 13
...
哇,它只是05, 06, 07, ... 0E, 0F(大概编码记录#0..15),然后它跳到80 10指定记录#16。第一个字段似乎继续是 3 字节整数。接下来切换到 17 字节长的记录看起来像这样:
...
91 7C 08|90 0D|90 16 02 90 22 90 2A 90 39|80 7D
91 8A 08|90 0D|90 16 02 90 22 90 2A 90 39|80 7E
91 98 08|90 0D|90 16 02 90 22 90 2A 90 39|81 7F 00
91 A6 08|90 0D|90 16 02 90 22 90 2A 90 39|81 80 00
91 B4 08|90 0D|90 16 02 90 22 90 2A 90 39|81 81 00
91 C2 08|90 0D|90 16 02 90 22 90 2A 90 39|81 82 00
...
与我们之前看到的90变成的技巧有一些模糊的相似之处91:这里80变成81可能指定从#126 = 0x7e(编码为80 7E)到#127 = 0x7f(编码为81 7F 00)的切换。
进一步在文件中,似乎有一个 18 字节长记录的主要格式切换,我猜它有点像这样排列:
...
91 5D 14|90 0D |90 16 |02|90 22|90 2A |90 39|81 5C 01
91 6A 14|90 0D |90 16 |02|90 22|90 2A |90 39|81 5D 01
91 77 14|91 86 14|91 8F 14|02|90 22|91 9B 14|90 39|00
91 AA 14|91 86 14|91 8F 14|02|90 22|91 9B 14|90 39|01
91 B5 14|91 86 14|91 8F 14|02|90 22|91 9B 14|90 39|02
91 C0 14|91 86 14|91 8F 14|02|90 22|91 9B 14|90 39|03
91 CB 14|91 86 14|91 8F 14|02|90 22|91 9B 14|90 39|04
...
此更改扩展了许多字段(实际上使其在某种程度上清除了字段边界)并将最后一个字段重置为 0。
与我们之前看到的90变成的技巧有一些模糊的相似之处91:这里80变成81可能指定从#126 = 0x7e(编码为80 7E)到#127 = 0x7f(编码为81 7F 00)的切换。文件末尾的记录长 20 个字节,如下所示:
...
91 32 34|91 86 14|91 8F 14|02|90 22|91 9B 14|90 39|81 7F 03
91 3B 34|91 86 14|91 8F 14|02|90 22|91 9B 14|90 39|81 80 03
91 44 34|91 86 14|91 8F 14|02|90 22|91 9B 14|90 39|81 81 03
我最好的选择是,许多中间值已经增加并90 xx变成91 xx yy.
总结到目前为止我学到的东西,看起来这些记录使用可变长度编码的整数,编码方案是这样的:
- 0x0 =
00=0000_0000 - 0x1 =
01=0000_0001 - ...
- 0xf =
0F=0000_1111 - 0x10 =
80 10=1000_0000|0001_0000 - 0x11 =
80 11=1000_0000|0001_0001 - ...
- 0x7e =
80 7E=1000_0000|0111_1110 - 0x7f =
81 7F 00=1000_0001|0111_1111|0000_0000 - 0x80 =
81 80 00=1000_0001|1000_0000|0000_0000 - ...
- 0x15d =
81 5D 01=1000_0001|0101_1101|0000_0001
有谁知道任何看起来像这样的标准格式/编码方案?关于如何正确解码90 xx和91 xx yy值的任何想法?