反向计算CRC32

18
我正在寻找一种反转CRC32校验和的方法。虽然有一些解决方案,但它们要么写得很糟糕,要么极其技术性和/或使用汇编语言。目前我还不会汇编语言,所以我希望有人能够用更高级别的语言来实现。Ruby是理想的选择,但我也可以解析PHP、Python、C、Java等语言。

有人愿意吗?


7
“reverse” 的确切含义是什么? - Frank Bollack
1
刚刚将一个C实现移植到Python:https://github.com/jellever/Pwnage/blob/master/reversecrc.py - Jelle Vergeer
@JelleVergeer 你能指出你的代码需要哪个表格吗?我应该在这里添加什么: #自定义CRC表,用你自己的替换 table = [] - Vishnu Narang
12年后,这个问题仍然引起了一些关注,所以我想补充一下,现在已经失效的链接曾经指向了类似于我下面答案中修正某些数据的CRC的代码,我记得是通过使用反向CRC算法或蛮力来实现的,并不是通过神秘方式从CRC值中创建数据。我认为这种关于CRC是否可以被“反转”或“反转CRC”意味着什么的语言律师讨论是低效和不必要的。 - Fozi
4个回答

29

CRC32只有在原字符串长度为4字节或更短时才可逆。


2
如果您查看实现,对于4个字节,它将执行3个8位移位,并且仅使用XOR操作,因此是可逆的:http://www.sanity-free.org/12/crc32_implementation_in_csharp.html - Cade Roux
2
如果CRC基于原始多项式通常意味着它将为每一个2^32个输入返回唯一的密钥。 - Luka Rahne
1
错失了重点:尽管CRC32并不总是可逆的,但是考虑到某个CRC32值是一个真实字符串的CRC,它必然是可逆的。 - Pavel Radzivilovsky
1
问题是什么意思“reverse,确实”。 - Pavel Radzivilovsky
4
不仅能够构造出任何32位值的四个字节序列,以生成相应的CRC32,而且对于任何长度大于等于四个字节的序列,如果选择其中任意32位(集中在四个字节内或分散在整个序列中),这32位的每种组合都将生成不同的CRC32。确定为了产生所需CRC32而使用哪些位的组合并不困难。 - supercat
显示剩余8条评论

9

请阅读《反向CRC理论与实践》文档。

以下是C#代码:

public class Crc32
{
    public const uint poly = 0xedb88320;
    public const uint startxor = 0xffffffff;

    static uint[] table = null;
    static uint[] revtable = null;

    public void FixChecksum(byte[] bytes, int length, int fixpos, uint wantcrc)
    {
        if (fixpos + 4 > length) return;

        uint crc = startxor;
        for (int i = 0; i < fixpos; i++) {
            crc = (crc >> 8) ^ table[(crc ^ bytes[i]) & 0xff];
        }

        Array.Copy(BitConverter.GetBytes(crc), 0, bytes, fixpos, 4);

        crc = wantcrc ^ startxor;
        for (int i = length - 1; i >= fixpos; i--) {
            crc = (crc << 8) ^ revtable[crc >> (3 * 8)] ^ bytes[i];
        }

        Array.Copy(BitConverter.GetBytes(crc), 0, bytes, fixpos, 4);
    }

    public Crc32()
    {
        if (Crc32.table == null) {
            uint[] table = new uint[256];
            uint[] revtable = new uint[256];

            uint fwd, rev;
            for (int i = 0; i < table.Length; i++) {
                fwd = (uint)i;
                rev = (uint)(i) << (3 * 8);
                for (int j = 8; j > 0; j--) {
                    if ((fwd & 1) == 1) {
                        fwd = (uint)((fwd >> 1) ^ poly);
                    } else {
                        fwd >>= 1;
                    }

                    if ((rev & 0x80000000) != 0) {
                        rev = ((rev ^ poly) << 1) | 1;
                    } else {
                        rev <<= 1;
                    }
                }
                table[i] = fwd;
                revtable[i] = rev;
            }

            Crc32.table = table;
            Crc32.revtable = revtable;
        }
    }
}

感谢您发布这个!在这里可以找到一个Julia的实现:https://github.com/JuliaIO/AdjustCRC.jl - SGJ

2

卡德·鲁克斯(Cade Roux)关于反转CRC32是正确的。

您提到的链接提供了一种解决方案,通过改变原始字节流来修复成为无效的CRC。这个修复是通过更改一些(不重要的)字节来重新创建原始的CRC值实现的。


2
或者黑客攻击流,使得CRC保持不变,而重要数据(如反盗版代码)被更改。 - Cade Roux

2
如果您知道生成它的多项式,可以通过回退位来反转它以生成原始的32位。但是,如果您想要从给定文件反转CRC32并在文件末尾附加一系列字节以匹配我发布的原始CRC,则我在此线程中用PHP发布了代码:
我花了一些时间研究它,希望它能帮助那些正在解决更棘手问题的人: Reversing CRC32 干杯!

1
逆序附加的缺点是可以通过简单的长度检查来破解。更方便的方法是通过允许在文件内特定边界内修改数据来进行反向匹配 crc。 - Nyerguds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接