我正在对ChessBase存档(.cbv)进行反向工程。

我发现了文件的一般结构,已经可以解压缩一些文件了。

但是,一些较大的.cbv文件似乎使用了第二种压缩算法。

我通过调试ChessBase找到了第一种压缩算法。 Reader 2013软件,但是我无法理解第二种压缩算法。

我尝试了诸如signsrch之类的工具来找出使用了哪种算法而没有运气:这似乎是自定义算法。 />
这是我可以用我的工具进行部分解压缩的文件(当我的工具检测到使用了未知的压缩算法时,我的工具将打印What to do?)。

如果没有,您是否可以通过查看压缩文件找到它?

我能够创建存档,所以我可以有文件既压缩又不压缩:我想知道在这种情况下是否有任何方法可以找到压缩模式。

#1 楼

在下载ChessBase Reader并使用ProcMon进行一些查找以找到读取存档并写入数据文件的功能之后,我将整个内容加载到IDA中进行分析。数据是霍夫曼编码的。

每个数据块具有以下结构。请注意,霍夫曼压缩仅适用于位,而不适用于字节,因此下表中的每个大小也以位为单位。例如,块长度为16位或2个字节。

+----------------------------------------------+
|                                              |
|16 bits - uncompressed block length (len)     |
|                                              |
+-----------+----------------------------------+
|           |                                  |
|Repeat     |  4 bits - length of entry (n)    |
|256        |                                  |
|times      +----------------------------------+
|           |                                  |
|one entry  |  n bits - tree left/right        |
|per byte   |  information for this byte       |
|(0-255)    |                                  |
|           |                                  |
+-----------+----------------------------------+
|                                              |
| Huffman encoded bit sequences. The number of |
| bits isn't stored anywhere, but the number   |
| of sequences, which is equal to the number   |
| of output bytes, is the block length (len)   |
|                                              |
+----------------------------------------------+


假设在此方案中将单词“ foobar”编码,则可能导致组成字符的位值):

+----------------+
|Huffman code for|
|character   is  |
+--------+-------+
|        |       |
| o      |   0   |
| f      |   100 |
| b      |   101 |
| a      |   110 |
| r      |   111 |
|        |       |
+--------+-------+


这将导致单词foobar被编码为
100 0 0 101 110 111。长度为6个字节,即16位0000 0000 0000 0110

格式化为上表的foobar的位数组将读取为
该实现从代码表构建一个二叉树。当它读取数据时,它从树的根开始。每一位根据下一位的值在树上向左或向右移动。当到达叶子时,正在输出相应的字节。一直重复直到达到输出流的长度为止。

二进制文件中的相关函数如下:读取16位的长度;然后在解码器类中将编码表读入偏移量为BECAA0(位)和080A(位长)的两个数组中。此后,调用0E10解码数据字节。在函数的结尾,偏移量为BEC930的单词具有这些位。BEBF30:调用1014来构建树,然后从输入流中读取剩余的位。每走一棵树;找到叶子时发出一个字节。最后,调用BEBAD0销毁树。

080A:通过删除左右子节点(节点本身)来递归删除节点。

我不这样做如果您想读取文件,则认为调试编写器会更容易;压缩具有大量的逻辑和数据结构,并且知道“一种方式”的工作方式并不一定会对另一种方式有所帮助。幸运的是,在这种情况下,它是一种众所周知的算法,但是如果该算法未知,则仅知道如何解压缩就很难有效地进行压缩。

评论


数据库加密当然是一种选择。请参阅chesscentral.com/basic_chess_database_a/300.htm,因此您可能正在寻找它。

–百老汇
15年3月30日在16:28

@broadway感谢您指出这一点。然而,与此同时,我对IDA进行了更多的按摩。我很确定这是一种霍夫曼解压缩算法,尽管我还没有解决所有问题。

–贡特拉姆·布洛姆(Guntram Blohm)
15年3月30日在17:02

查看最后几千字节,您会看到“普通文本”片段散布着二进制代码。绝对是霍夫曼的变种。

–杂件
15年3月30日在17:48

感谢您的回答:我会看看。 @Jongware:我已经知道当我们看到普通的文本片段时使用的压缩算法(请参阅我在github上的工具)。我的问题是没有文本片段。顺便说一句,通过调试创建此类归档文件的应用程序(ChessBase)找出算法会更容易吗?

– antoyo
2015年3月30日19:38