逆向工程压缩字节数组

逆向工程 文件格式
2021-06-16 23:07:28

我们正在尝试从专有的声纳日志文件格式中提取声纳数据,我们在大多数情况下都能很好地工作。数据以二进制形式存储,带有包含深度、地理位置等信息的可变长度标头,以及原始声纳返回的字节数组。我们拥有的大多数这种格式的示例都有一个简单的字节数组,其中每个字节都是一个原始声纳返回级别。使用这些值和单色 8 位调色板创建位图将为您提供声纳的视觉描述,就像您在回声测深仪屏幕上看到的那样。最近,我们收到了一些旧文件,它们不会以相同的方式存储声纳 ping 数据。这些文件显然是在“低质量”设置下录制的,并且已经应用​​了某种压缩。标题和以前一样可读。

我们知道我们无法读取的文件具有 1600 字节的“块长度”(这可以在设备上配置)。块长度是指ping数组+头部的大小。在这种情况下,标头长度为 28 个字节 - 但到下一行的间隙仅为 372 个字节。这表明压缩是固定的,并且每个文件编码字节产生 4 个最终字节。

这是此压缩字节数组的一个块的示例。该示例的前两个字节不是字节数组的一部分,但可能很重要。在此文件的未压缩版本中,此数字为 -1。在压缩版本上,它有一个数字,每个 ping 都会不同。

任何如何进行的建议或指示都会受到热烈欢迎。以防万一它有帮助,它非常典型的 ping 在开始时包含一组非零值(来自表面的噪声),然后是很多零或非常低的值,然后是一些来自返回的更重要的值底部信号。

67 7F 42 46 3D 35 3C 53 3B 40 80 40 36 41 3A
53 3F 3F 40 40 80 40 40 81 40 47 40 40 40 3D 51
3E 40 40 40 40 40 40 81 40 89 40 3B 43 3F 40 40
40 40 40 80 3E 46 3F 41 3E 41 40 40 40 40 80 40
40 40 40 40 80 40 81 40 80 40 95 3F 42 40 40 40
40 40 40 40 40 40 40 40 40 40 40 40 40 40 3F 46
40 40 40 41 40 40 40 40 40 40 40 40 40 40 40 40
40 40 40 40 40 40 80 40 40 40 40 40 40 40 40 84
40 90 40 9F 40 3F 40 40 40 40 40 40 40 40 40 40
40 40 40 40 40 40 81 40 40 40 40 40 40 40 80 40
40 40 40 81 40 81 40 80 40 44 40 40 40 40 80 40
40 40 80 40 40 80 40 80 40 40 40 81 40 40 40 82
40 40 40 80 40 81 40 83 40 80 40 40 83 40 80 40
40 80 40 80 40 80 40 40 80 40 88 40 84 40 E6 40
40 40 40 40 40 40 83 40 80 40 40 80 40 40 40 40
80 40 40 40 82 40 40 40 40 40 40 80 40 40 40 80
40 40 85 40 81 40 40 81 40 81 40 82 40 88 40 40
80 40 80 40 40 40 42 83 40 40 40 81 40 80 40 80
40 40 80 40 40 80 40 80 40 40 80 40 80 40 40 80
40 80 40 80 40 40 40 84 40 40 40 40 86 40 40 40
AC 40 93 40 FF E9 40 40 40 40 40 80 40 40 40 40
80 40 40 82 40 87 40 82 40 83 40 40 80 40 80 40
8B 40 40 8B 40 82 40 86 40 8D 40 91 40 93 40 81
40 86 40 88 40 42 00 

编辑添加:“压缩”可能不是正确的术语(上面的文件片段肯定看起来没有用所有这些相似的值压缩)。我想它可能只是某种类型的编码,并且可能是有损的——这就是为什么该选项被称为“低质量”的原因。也有可能这里每个字节只需要两个字节——我们不是 100% 确定。不过,这并不像啃咬那么明显。此外,这会实时记录在没有大量处理能力的旧硬件单元上。所以我怀疑它有什么花哨的东西。

编辑以添加更多信息和说明

只是为了澄清一些困惑(我的错)并回答 sukminders 问题:

  • 我的不好 - 我没有从原始示例中删除尾随的 34 个字节 - 我现在已经这样做了,这 34 个字节是下一个标头和下一个 ping 的前 6 个字节。我已经更新了原始字节。

关于文件格式的更多信息:

  • 文件以8个字节开始,不重复,包含在这个头中的是一个short,表示文件的行长。

  • 每行的标题长度可变 - 有一个位掩码作为标题中的第一个字段之一,指示要读取的字段。在这个特定文件中,标题是 28 个字节 - 但实际上可以随着数据的包含而改变行。

  • ping 数据大小(以文件字节为单位)是文件级行大小减去标头长度。

  • 我们知道我们已经对标头进行了排序,因为我们获得了合法的纬度、经度、时间(毫秒偏移量)和深度信息。我们可以使用此文件中的数据绘制轨迹。

  • 我将收回我们认为这些字节扩展到 1600 字节的想法 - 我们还不够确定,这可能是一个红鲱鱼。我们确实“知道”观察到的 ping 大于 372 字节,并且该文件是以“低质量”记录的。

  • 我们可以访问显示此文件的查看应用程序,但只能作为屏幕上的图像。我们无法获得用于比较的原始字节输出。上面示例中的 ping 非常典型 - 中间的 0x40 和 0x80 值的大集群可能为零或接近零值。

  • 显示此编码的文件在 8 字节文件头中具有值 1024(十进制),其中未显示此编码的文件为零。

我认为某种游程编码听起来很可能 - 但没有什么明显足以让我解决!很高兴向任何感兴趣的人提供文件和查看器应用程序(免费软件 - 不是我们的)。

1个回答

不是答案,但这作为评论变得混乱。

从你写的我解释它是:

67 7F                                            < Last two bytes of header
                                                 +---
42 46 3D 35 3C 53 3B 40 80 40 36 41 3A 53 3F 3F  |
40 40 80 40 40 81 40 47 40 40 40 3D 51 3E 40 40  |
...                                              : 372 ping bytes
8B 40 82 40 86 40 8D 40 91 40 93 40 81 40 86 40  |
88 40 42 00                                      |
                                                 +---
                                                 +---
01 2C CB C9 97 41 B9 1E 55 41 05 EA CC 3F 0D 8E  |
53 41 73 00 00 00 ED 20 00 00 67 7F 42 46 3D 35  | What is this then? (34 bytes)
3C 53                                            |
                                                 +---

乍一看,我还注意到样本数据在数据的顶部和末尾重复了以下序列:

67 7F 42 46 3D 35 3C 53
  • 你怎么知道头是28个字节?大小是否硬编码在标题中?
  • 整个文件中的深度和位置数据是否正常?你在其他地方有大约这些值吗?

在我看来,在尝试做任何其他事情之前,应该确保正确解码标题。从标题中了解深度,您应该能够在深度变化时从底部识别 ping 数据中的散点。

由于在较低的0x40's 和0x80's 中大量使用字节,它可能表示较高的位,例如 3,是某种重复计数。如果是这样,00372 中的最后一个可能表示某种类型的数据结束指示符。00不在其他地方,而是在下一个字节块中 - 最后的 34)。

如前所述,当我不确定如何映射数据时有点困难——而且只有一个样本......


如果您使用重要信息回复此评论,最好更新问题而不是在此下方发表评论。(我也可能会删除它,如果我离它很远或没有多看它......)