试图弄清楚使用了哪种压缩

逆向工程 解压
2021-07-08 21:29:56

我得到了以下原始数据,它们是压缩 png 图像的前 35 个字节:

00 89 50 4e 47 0d 0a 1a 0a 00 00 00 00 0d 49 48
44 52 08 00 00 02 58 00 83 5a 08 06 80 00 83 64
31 28 fe

我也碰巧有 33 个字节,上面的 35 个字节是在压缩之前

89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52
00 00 02 58 00 00 00 5a 08 06 00 00 00 64 31 28
fe

我现在盯着这些字节好几天了,无法弄清楚我们的压缩算法......它看起来像某种 lz77 或滑动窗口压缩。

对这个问题的任何帮助将不胜感激

2个回答

它确实似乎是 LZ77 变体,其中 8 个编码/未编码标志组合成单个标志字节。

然后将压缩数据分组为 8 个数据“单元”,其中每个单元由单个未压缩字节或 2 字节字典条目表示。

一批 8 个单元的数据前面是标志字节,其中每个 8 位指示每个单元是未压缩字节还是字典条目。

这里没有足够的数据来 100% 确定字典条目的编码或任何窗口是什么,因为示例数据中只有 2 个(相同的)字典条目。然而,2 字节条目似乎很可能由 12 位偏移量和 4 位长度组成,参考先前解压缩的数据。

对于压缩数据,解压过程如下 -

compressed                  decompressed
flags         data          offset  data            
00                                                  
    0=>raw    89      ->    0000:   89              
    0=>raw    50      ->    0001:   50              
    0=>raw    4e      ->    0002:   4e              
    0=>raw    47      ->    0003:   47              
    0=>raw    0d      ->    0004:   0d              
    0=>raw    0a      ->    0005:   0a              
    0=>raw    1a      ->    0006:   1a              
    0=>raw    0a      ->    0007:   0a              
00                                                  
    0=>raw    00      ->    0008:   00              
    0=>raw    00      ->    0009:   00              
    0=>raw    00      ->    000A:   00              
    0=>raw    0d      ->    000B:   0d              
    0=>raw    49      ->    000C:   49              
    0=>raw    48      ->    000D:   48              
    0=>raw    44      ->    000E:   44              
    0=>raw    52      ->    000F:   52              
08                                                  
    0=>raw    00      ->    0010:   00              
    0=>raw    00      ->    0011:   00              
    0=>raw    02      ->    0012:   02              
    0=>raw    58      ->    0013:   58              
    1=>dict   00 83   ->    0014:   00 00 00    // copy of 3 bytes from offset 8    
    0=>raw    5A      ->    0017:   5A              
    0=>raw    08      ->    0018:   08              
    0=>raw    06      ->    0019:   06              
80                                                  
    1=>dict   00 83   ->    001A:   00 00 00    // copy of 3 bytes from offset 8        
    0=>raw    64      ->    001D:   64              
    0=>raw    31      ->    001E:   31              
    0=>raw    28      ->    001F:   28              
    0=>raw    fe      ->    0020:   fe              
    0=>raw    ...     ->    0021:   ...
    0=>raw    ...     ->    0022:   ...                 
    0=>raw    ...     ->    0023:   ...          

这看起来像是由LZRW系列算法生成的格式

那里提到的代码包含

#define FLAG_COMPRESS 0     /* Signals that compression occurred. */
#define FLAG_COPY     1     /* Signals that a copyover occurred.  */

(您的变体可能交换了这两个)和

#define ITEMMAX 16     /* Maximum number of bytes in an expanded item.  */