zlib解压游戏存档文件中途返回Z_DATA_ERROR问题求助
Troubleshooting Zlib Decompression Failures for Game Save Data
我之前处理过不少游戏存档的逆向问题,你的情况很典型——游戏能正常解压但自己的代码反复报错,大概率是游戏对标准zlib做了自定义修改或者对压缩数据做了预处理。结合你的描述和代码,这里有几个针对性的排查方向和修复建议:
1. 先修复解压代码的逻辑漏洞
你的代码里有几个容易被忽略的问题,先把这些修正了再排查其他可能性:
- 不合理的CHUNK_SIZE:设为1不仅效率极低,还可能导致调试时误判问题点,先改成
4096这类常规值。 - 错误的循环终止条件:你当前用
while (strm.avail_out == 0),但这只判断了缓冲区是否被填满,没考虑流是否真的结束。正确的循环应该持续到ret == Z_STREAM_END。 - Z_NEED_DICT的错误处理:当返回
Z_NEED_DICT时,你直接判定为数据错误,但这很可能是游戏用了自定义预设字典——zlib允许用预定义字典提升压缩率,游戏会把字典内置在程序里。此时strm.adler会返回字典的ADLER32校验值,你可以打印这个值,然后去游戏的资源文件或内存里查找匹配的字典数据,再用inflateSetDictionary传入。
修正后的核心循环代码示例:
static const int CHUNK_SIZE = 4096; char out[CHUNK_SIZE]; // ...(初始化代码不变) do { strm.avail_out = CHUNK_SIZE; strm.next_out = (Bytef*)(out); ret = inflate(&strm, Z_NO_FLUSH); Q_ASSERT(ret != Z_STREAM_ERROR); switch (ret) { case Z_NEED_DICT: // 打印字典校验值,去查找对应字典 qDebug() << "Need dictionary with Adler32:" << QString::number(strm.adler, 16); // 如果找到字典,调用inflateSetDictionary(&strm, dict_data, dict_len); break; case Z_DATA_ERROR: case Z_MEM_ERROR: (void)inflateEnd(&strm); return result; } int bytes_written = CHUNK_SIZE - strm.avail_out; result.append(out, bytes_written); } while (ret != Z_STREAM_END); // 确认所有输入数据都被处理 if (strm.avail_in != 0) { qDebug() << "Warning: Not all input data was processed!"; }
2. 排查数据预处理/变换
游戏经常会对压缩数据做简单的变换,绕过标准zlib的直接解压,常见的方式有:
- 位序翻转:每个字节的8位顺序被反转(比如0x12 → 0x48)。你可以写个小工具对输入数据的每个字节做位翻转,再喂给zlib试试。
- 字节XOR加密:每个字节和固定密钥(比如游戏的魔法值、版本号)异或。你可以对比你解压出的开头数据和预期的
0x000B,反向推导可能的密钥。 - 隐藏的额外数据:你说移除了尾部CRC,但有些游戏会在压缩数据前后插入额外的校验字节或长度字段,比如开头加2字节的真实数据长度,你需要把这些额外字段剔除后再解压。
3. 验证原始数据的有效性
把带0x789C头的原始数据保存成文件,用标准zlib工具(比如zlib-flate)尝试解压:
zlib-flate -uncompress < compressed.bin > output.bin
如果工具也报错,说明数据确实被游戏做了自定义处理;如果工具能正常解压,那问题就出在你的代码实现上(比如内存管理、数据传递的问题)。
4. 尝试不同的zlib初始化参数
你当前用inflateInit2(&strm, -15)表示使用原始deflate格式(不带zlib头),但有些游戏修改了zlib的窗口大小设置。可以尝试调整窗口大小参数,比如:
inflateInit2(&strm, 15):带zlib头的格式(但你已经移除了头,所以这个可能不适用)inflateInit2(&strm, -13):使用8KB窗口的原始deflate格式inflateInit(&strm):默认初始化(会自动识别zlib头,你需要把0x789C头加回去再试)
内容的提问来源于stack exchange,提问作者mrg95
相关产品推荐
相关产品推荐

