如何模仿“a”;使用“crc”;2013年zlib API接口中的(黑客)1998解压缩()标记?

如何模仿“a”;使用“crc”;2013年zlib API接口中的(黑客)1998解压缩()标记?,c,gzip,zlib,compression,C,Gzip,Zlib,Compression,我正在将一个项目的代码从1998版的zlib更新到2013版的zlib。有一件事似乎发生了变化,那就是解压函数上曾经有一个“use_crc”标志,它似乎已经丢失了: int ZEXPORT uncompress (dest, destLen, source, sourceLen, use_crc) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; int use_crc;

我正在将一个项目的代码从1998版的zlib更新到2013版的zlib。有一件事似乎发生了变化,那就是解压函数上曾经有一个“use_crc”标志,它似乎已经丢失了:

int ZEXPORT uncompress (dest, destLen, source, sourceLen, use_crc)
    Bytef *dest;
    uLongf *destLen;
    const Bytef *source;
    uLong sourceLen;
    int use_crc; // <-- vanished (?)
输出为:

成功通货膨胀:123456789012345X

显示数据正在解压缩,但我们需要全部16个字节。(应该收到的文件中有一个换行符。)16+MAX_WBITS甚至不能得到这个


你知道怎么回事吗?任何设置的排列似乎都不会出错。

不,自从20多年前引入zlib接口以来,没有对其进行过不兼容的更改。从来没有
使用crc
参数来
解压缩()

您给出的示例是一个两字节的zlib头,deflate压缩数据,deflate数据的CRC-32以大端顺序排列,然后是一个四字节的长度以小端顺序排列。这是zlib和gzip包装的一个真正奇怪的混搭,和您一直提到的zip格式并没有任何关系。(你说的“zip文件中的有效负载”是什么意思?)zlib的末尾有一个以大端顺序排列的Adler-32,而gzip的末尾有一个以小端顺序排列的CRC-32,后跟一个以小端顺序排列的四字节长度。这一个混淆了这些,包括字节顺序,然后故意误导地将一个有效的zlib头放在这个东西上,这是对这个世界上一切美好和体面的东西的侮辱

我很确定提出这种格式的人当时喝醉了

要对此进行解码,您需要:

  • 丢弃流的前两个字节。(您可以检查它是否是有效的zlib头,但这在解释流的其余部分时没有意义。)

  • 使用原始放气,使用
    充气装置2(&strm,-15)初始化
    ,以解压缩数据。解压缩时,跟踪总长度并使用
    crc32()
    计算CRC-32

  • 在deflate数据完成后,读取接下来的四个字节,按大端顺序将它们组合为32位值,并将其与计算的CRC-32进行比较。如果不匹配,则流已损坏,或者不是这些格式异常的流之一。(可能再试一次,将其解码为正常的zlib流。如果它有一个好的zlib头,那么可能它实际上就是这样,而不是这些弗兰肯斯坦流中的一个。)

  • 读取接下来的四个字节,并按小的尾数顺序组装它们,然后将其和未压缩数据的长度进行比较。如果不匹配,则流已损坏,或者不是您所想的

  • 如果数据没有在这里结束,那么其他一些奇怪的事情正在发生。咨询醉汉


  • 这是什么版本的zlib?我只是在不同的标签版本中搜索了一下,没有找到任何
    use\u crc
    ref。可能这是某个第三方对官方zlib的补丁?@Joe这很可能是非官方的,很好的观点。它位于Rebol代码库中,其中有一个提取的文件:。没有关于添加的注释,但是在GitHub上查看它确实有一个不寻常的选项卡,这表明您可能是对的。我真正的目标是对二进制代码进行解码,所以我将更新这个问题。我认为最好的答案是,甚至不要尝试将该功能移植到新的zlib。将这些文件视为根本不是zlib(实际上不是,因为它们是由被黑客攻击的zlib生成的)。假设解压它们的唯一方法是使用压缩它们的相同工具。您已链接到github。使用rebol解压您的文件,以更合理的格式保存它们,并且不要重复在中使用rebol(或其zlib(或其use_crc标志))的错误future@WumpusQ.WumbleyRebol不生成此格式。这是由zip文件处理器传入的数据,正如我在问题中所说,该文件是通过zip test.zip test.txt生成的。似乎我现在应该对处理器进行更多的检查。以前不这么做的原因是我没有写过这些东西,有人让我弄明白,“它过去是有效的,现在链接到2013 zlib时就失效了”。正如我告诉MarkAdler的那样,我假设zip之前对.zip进行的工作解码表明二进制blob是一个zip负载,我会看看你们为什么说它不是。既然你们链接到rebol向我们展示了use_crc标志,我假设这就是你们实际使用的。无论如何,如果您的实际源文件是zip格式的,为什么不使用zip工具并跳过所有zlib业务呢?或者它也不符合zip格式?请,请,请,请不要修改zlib来处理这一暴行,如果你这样做,看在上帝的份上,永远不要分发这样的东西。正如我所描述的,zlib可以按原样处理这些数据。很高兴听到这个人自己的消息!(但请记住,我以前从未与zlib打过交道,还有一位志愿者通过尝试破译代码并链接新的佳能zlib来获得“消除暴行”的“好工作”。如果你想对某人大喊大叫。)但当我说“zip文件中的有效负载”时,我的意思是这就是传递给“解压”()“通过zip阅读器使用crc。听起来你是说我需要去查看提供这一信息的zip阅读器源代码,我会用这些信息去做,然后报告回来。情况和你描述的一模一样。解包.ZIP的代码就是这么编的。摆脱所有这些,只用-15就行了。谢谢你的指点和及时的帮助!
    #include <stdio.h>
    #include "zlib.h"
    
    int main(int argc, char *argv[]) {
        char compressed[] = { 0x78, 0x9C, 0x33, 0x34, 0x32, 0x36, 0x31, 0x35, 0x33,
            0xB7, 0xB0, 0x34, 0x30, 0x04, 0xB1, 0xB8, 0x00, 0x31, 0x30, 0xB1, 0x30,
            0x10, 0x00, 0x00, 0x00 }; // last 4 bytes are size (16)
    
        char uncompressed[16 + 1]; // account for null terminator
        int ret; z_stream strm;
    
        memset(uncompressed, 'X', 16);
        uncompressed[16] = '\0';
    
        strm.zalloc = strm.zfree = strm.opaque = Z_NULL;
        strm.total_out = 0;
        strm.avail_in = 25;
        strm.next_in = compressed;
    
        ret = inflateInit2(&strm, MAX_WBITS /* + 16 */); // it is Z_OK
    
        strm.avail_out = 15; // 16 gives error -3: "incorrect header check" 
        strm.next_out = uncompressed;
        ret = inflate(&strm, Z_NO_FLUSH);
    
        if (ret != /* Z_STREAM_END */ Z_OK) { // doesn't finish... 
            printf("inflate() error %d: %s\n", ret, strm.msg);
            return 2;
        }
    
        inflateEnd(&strm);
        printf("successful inflation: %s\n", uncompressed);
        return 0;
    }