1

我有一个由压缩内容和 32 字节标头组成的文件。标头包含时间戳、压缩大小和未压缩大小等信息。

该文件本身约为 490mb,标题表明未压缩大小接近 2.7gb(显然不正确,因为它还认为压缩大小为 752mb)。

我已经剥离了标头并生成了压缩的有效负载,并且可以使用 zlib 解压缩它。

问题是它只解压缩了 19kb,比 490mb 小得多(应该是最低限度,但我预计未压缩大约 700mb)。

我的代码如下:

import zlib

def consume (inputFile):
    content = inputFile.read()
    print "Attempting to process " + str(len(content)) + " bytes..."
    outfile = open('output.xml', 'w')
    inputFile = zlib.decompress(content)
    print "Attempting to write " + str(len(inputFile)) + " bytes..."
    outfile.write(inputFile)
    outfile.close()

infile = open('payload', 'rb') 

consume(infile)

infile.close()

运行时,程序输出:

正在尝试处理 489987232 字节...正在尝试写入 18602 字节...

我尝试使用zlib.decompressionobj(),尽管这会产生不正确的标题警告。zlib.decompress()工作正常并生成我期望的解压缩 XML ......只是它太少了。

非常感谢任何指针或建议!

4

2 回答 2

3

您显然有一个损坏的文件。

您将无法强制 zlib 忽略损坏——而且,如果您这样做了,您很可能会得到 700MB 的垃圾,或者一些随机数量的垃圾,或者……嗯,这取决于损坏是什么,并且在哪里。但是你能得到任何有用的东西的机会非常渺茫。

zlib的块不是随机可访问的,也不是分隔的,甚至是字节对齐的;除非您能够处理前一个块,否则很难判断您何时到达下一个块。

另外,树从一个块到另一个块生长,所以即使你可以跳到下一个块,你的树也会出错,你会解压垃圾,除非你非常非常幸运并且不需要破碎的部分那个树。更糟糕的是,任何块都可以重新启动树(甚至切换压缩器);如果你错过,即使你很幸运,你也在解压垃圾。而且这不仅仅是“跳过这个字符串,因为我不认识它”的问题,如果你不认识,你甚至不知道这个字符串有多少位,所以你不能跳过它。这让我们回到了第一点——你甚至不能跳过一个字符串,更不用说一个完整的块了。

要更好地理解这一点,请参阅RFC 1951,它描述了zlib. 尝试手动处理一些简单的示例(第一个块中只有几个字符串,第二个块中只有几个新字符串),看看以难以撤消的方式破坏它们是多么容易(除非你确切知道它们是如何已损坏)。这并非不可能(毕竟,破解加密消息并非不可能),但我不相信它可以完全自动化,而且这不是你可能会为了好玩而做的事情。

如果您有关键数据(不能只是重新下载、回滚到以前的版本、从备份恢复等),一些数据恢复服务声称能够恢复损坏的 zlib/gz/zip 文件. 我猜这需要花费一条胳膊和一条腿,但这可能是正确数据的正确答案。

当然,我认为这不是自动化的可能是错误的。那里有一堆 zip 恢复工具。据我所知,他们对损坏的 zlib 流所能做的就是跳过该文件并恢复其他文件……但也许其中一些技巧在某些情况下对损坏的流有效。

于 2013-03-29T00:12:00.960 回答
0

您需要检查zlib.error它为什么停止。为什么停止了?

于 2013-03-29T00:53:20.117 回答