如何匹配特定压缩数据格式并实现字节级重压缩匹配?
问题:zlib重压缩无法匹配原始压缩字节流
我尝试用Python对一段压缩数据解压缩后重压缩,还原原始压缩输出,但用zlib做不到字节级匹配,不确定原始数据的压缩方法或参数。
所用zlib代码
import zlib original_compress = '78010dc2390a80400c05d052b4d4ce4a3c8024933fdb719259c046c1c2f32bbc696ba098cd92b23242ed66625db568498d106d5e22e0202e4b622f082c24eba0577deeb3eee34bfe20fa7df036131b0000f53a00000000' print('original_compress:', original_compress) # 解压缩数据 decompress = zlib.decompress(bytes.fromhex(original_compress)) print('decompress:', decompress.hex()) # 重压缩数据 again_compress = zlib.compress(decompress) print('again_compress:', again_compress.hex()) # 对比结果 if original_compress == again_compress.hex(): print('Matched') else: print('NotMatched')
问题现状
用zlib解压缩正常,推测是zlib兼容格式,但重压缩无法生成和原始数据完全一致的字节流。
观察结果
原始压缩数据以78 01开头,属于zlib头,解压缩后的数据有效,可确认解压缩完整。
疑问
- 怎么还原完全一致的原始压缩输出?用zlib时需要特定参数或标志吗?
- 原始数据是不是用了自定义或非标准压缩实现?如果是,怎么识别?
- 除了zlib,还有哪些工具或库能用来逆向分析所用的压缩格式?
尝试过的miniz库代码
import ctypes # 加载Windows平台编译好的miniz DLL miniz = ctypes.CDLL("C:/Users/neatbox/miniz/miniz.dll") # 定义解压缩和压缩函数的签名 miniz.mz_compress2.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_ulong), ctypes.c_void_p, ctypes.c_ulong, ctypes.c_int] miniz.mz_compress2.restype = ctypes.c_int miniz.mz_uncompress.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_ulong), ctypes.c_void_p, ctypes.c_ulong] miniz.mz_uncompress.restype = ctypes.c_int # 用miniz解压缩 def decompress_miniz(data): source = ctypes.create_string_buffer(data) source_len = len(data) dest_len = ctypes.c_ulong(source_len * 4) # 为解压缩数据分配更大空间 dest = ctypes.create_string_buffer(dest_len.value) result = miniz.mz_uncompress(dest, ctypes.byref(dest_len), source, source_len) if result != 0: raise RuntimeError("解压缩失败") return dest.raw[:dest_len.value] # 用miniz压缩,默认级别为1 def compress_miniz(data, level=1): source = ctypes.create_string_buffer(data) source_len = len(data) dest_len = ctypes.c_ulong(source_len * 2) # 为压缩数据分配更大空间 dest = ctypes.create_string_buffer(dest_len.value) result = miniz.mz_compress2(dest, ctypes.byref(dest_len), source, source_len, level) if result != 0: raise RuntimeError("压缩失败") return dest.raw[:dest_len.value] # 原始压缩数据 original_compress = bytes.fromhex( '78010dc2390a80400c05d052b4d4ce4a3c8024933fdb719259c046c1c2f32bbc696ba098cd92b23242ed66625db568498d106d5e22e0202e4b622f082c24eba0577deeb3eee34bfe20fa7df036131b0000f53a00000000' ) print(f"原始压缩数据(十六进制): {original_compress.hex()}") print(f"原始压缩数据长度: {len(original_compress)} bytes") # 步骤1:解压缩 try: decompressed = decompress_miniz(original_compress) print(f"解压缩数据(十六进制): {decompressed.hex()}") print(f"解压缩数据长度: {len(decompressed)} bytes") except RuntimeError as e: print(f"解压缩失败: {e}") exit() # 步骤2:重压缩 try: recompressed = compress_miniz(decompressed) print(f"重压缩数据(十六进制): {recompressed.hex()}") print(f"重压缩数据长度: {len(recompressed)} bytes") # 步骤3:检查重压缩数据是否匹配原始数据 if recompressed == original_compress: print("Matched") else: print("NotMatched") except RuntimeError as e: print(f"压缩失败: {e}")
解答
1. 还原原始压缩输出的方法
原始数据开头78 01对应的是zlib的无压缩级别(level 0),但zlib的compress默认使用level 6,这是导致不匹配的核心原因之一。你需要指定压缩级别为0,同时尝试调整压缩策略:
import zlib # 指定无压缩级别 again_compress = zlib.compress(decompress, level=0) # 若仍不匹配,尝试不同压缩策略 again_compress = zlib.compress(decompress, level=0, strategy=zlib.Z_HUFFMAN_ONLY) again_compress = zlib.compress(decompress, level=0, strategy=zlib.Z_FILTERED)
另外,部分实现会使用特定的窗口大小或预设字典,如果上述调整无效,可以尝试指定窗口大小参数(比如wbits=15,对应最大窗口),不过原始数据带zlib头,默认wbits参数即可。
2. 识别自定义/非标准压缩实现
- 用
infgen工具解析原始压缩的DEFLATE流,输出详细的压缩步骤,对比标准zlib压缩后的流,看是否存在特殊的块类型、霍夫曼表编码逻辑差异; - 检查原始压缩数据是否包含zlib头/尾之外的额外字节,判断是否存在自定义校验、附加头信息;
- 对比不同压缩库(如miniz、zlibng)的压缩结果,若某库输出和原始数据一致,说明原始实现基于该库的特定参数。
3. 逆向分析压缩格式的工具/库
- infgen:专门解析DEFLATE流,输出压缩细节,用于对比原始与重压缩流的差异;
- 7-Zip:自带格式检测功能,可验证是否为其他兼容压缩格式;
- binwalk:二进制分析工具,能检测压缩数据的特征签名;
- minizip:支持测试不同压缩参数、格式(zlib/gzip/raw DEFLATE);
- libarchive:兼容多种压缩格式,可用于格式验证。
内容的提问来源于stack exchange,提问作者neatsof
相关产品推荐
相关产品推荐

