18

I'm looking for a way to reverse a CRC32 checksum. There are solutions around, but they are either badly written, extremely technical and/or in Assembly. Assembly is (currently) beyond my ken, so I'm hoping someone can piece together an implementation in a higher level language. Ruby is ideal, but I can parse PHP, Python, C, Java, etc.

Any takers?

pat
  • 16,116
  • 5
  • 40
  • 46
  • 7
    What exactly do you mean by 'reverse' – Frank Bollack Oct 03 '09 at 15:53
  • 1
    Just ported a C implementation to Python: https://github.com/jellever/Pwnage/blob/master/reversecrc.py – Jelle Vergeer May 02 '16 at 22:30
  • @JelleVergeer Can you point to the table needed for your code to work. What can I add here: #Custom CRC table, replace with your own table = [] – Vishnu Narang Feb 26 '17 at 03:37
  • 12 Years later - this question still seems to get some attention, so I'd like to add that the now dead links used to point to code that much like my answer below *fixed* the CRC of some data, IIRC by using a *reverse* CRC algorithm or brute force, and not magically create data from a CRC value. I find this language lawyer discussion on whether CRC can or can not be "reversed" or what "reversing CRC" means counterproductive and unnecessary. – Fozi Mar 19 '21 at 18:02

4 Answers4

29

A CRC32 is only reversible if the original string is 4 bytes or less.

Cade Roux
  • 88,164
  • 40
  • 182
  • 265
  • 1
    I doubt crc will generate a unique 32-bit code for every string combo 4 bytes or less ... – Goz Oct 03 '09 at 15:39
  • 2
    If you look at the implementation, for 4 bytes it will do 3 8-bit shifts with only XOR operations, so yes, it is reversible: http://www.sanity-free.org/12/crc32_implementation_in_csharp.html – Cade Roux Oct 03 '09 at 15:43
  • 1
    This is what I'd initially thought, and then had people send the links mentioned above my way... obviously, the fact it's limited to 4 bytes was glossed over. Thanks for the clarification. – pat Oct 03 '09 at 15:53
  • 2
    If CRC is based on primitive polynomial what usualy is, that mean that it will return uniqe key for every of 2^32 imputs. – Luka Rahne Oct 05 '09 at 00:38
  • 1
    Misses the point: even though CRC32 is not always reversible, given that a certain CRC32 value is a CRC of a real string, it is necessarily reversible. – Pavel Radzivilovsky Jun 20 '10 at 14:28
  • 1
    @Pavel I think you cannot construct a 4-byte string for any given 32-bit value which would generate that value as CRC32 (it probably doesn't have perfect entropy). It probably is true that you can construct some string to produce a given value as its CRC32. There are an infinity of strings which produce the same CRC32. Hence the notion of reversibility is rather limited - you can only show A string which has the CRC32, not necessarily the CORRECT string (in the sense of error correction). I took reversibility in the sense that this would need to be a bijective function, which it is not. – Cade Roux Jun 20 '10 at 14:54
  • 1
    the question is what is meant by reverse, indeed. – Pavel Radzivilovsky Jun 20 '10 at 15:51
  • 4
    @CadeRoux: Not only is it possible to construct a sequence of four bytes for any 32-bit value which will generate that CRC32, but given any sequence of four bytes or more, if one selects any 32 bits of that sequence (concentrated in four bytes, or scattered throughout the overall sequence), every combination of values for those 32 bits will generate a different CRC32; determining what combination of values to use for those bits to yield a desired CRC32 is not difficult. – supercat Jan 08 '13 at 21:28
  • -1 - If you look at my answer you will see that I wrote code that runs CRC in reverse. It is also based on a whitepaper called "Reversing CRC Theory and Practice" - So the term "reverse CRC" has at very least two meanings, one of which is not what you seem to associate with it. This is why I think this answer is a) not helpful and b) should be a comment, not an answer. – Fozi Mar 19 '21 at 18:08
  • @Fozi What is not helpful is the question, which never said what exactly _they_ meant by "reverse". – Mark Adler Dec 22 '21 at 05:22
  • @MarkAdler Really, is it? Or maybe you just did not understand what "reverse CRC" means? Look at my answer, it's production code running CRC in reverse. And I did not come up with it, I linked to the whitepaper. And even if it wasn't, do you think it deserves a `U R RONG` answer? Isn't that supposed to be a comment according to SO rules? – Fozi Dec 23 '21 at 14:56
  • No, I did not understand what it meant, because I knew that there is more than one meaning for "reversing" a CRC. That is why I didn't answer the question. I simply upvoted the very first comment on the question: _What exactly do you mean by 'reverse'_. – Mark Adler Dec 24 '21 at 07:44
  • @MarkAdler Fair enough, I "understood" the question because when I came across it I already have faced this problem in the past and had the answer ready. But I'm not saying that the question is clear, I'm saying that *this answer* is bad because it is outright wrong (because Cade misunderstood the question), it is the accepted and most up-voted answer (because timing) and this question comes up as the first hit in Google when you search for "reverse CRC". It should be a comment instead and I think Cade should either delete it or edit it to say that "It depends on what you mean with "reverse"". – Fozi Dec 25 '21 at 16:01
9

Read the document called "Reversing CRC Theory and Practice".

This is 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;
        }
    }
}
Marc.2377
  • 7,807
  • 7
  • 51
  • 95
Fozi
  • 4,973
  • 1
  • 32
  • 56
  • Thanks for posting this! A Julia implementation can be found here: https://github.com/JuliaIO/AdjustCRC.jl – SGJ Aug 16 '23 at 15:52
2

You can reverse it by backing out the bits to generate the original 32 bits if you know the poly it was created with. But if you are looking to reverse the CRC32 from a given file and append a series of bytes at the end of the file to match the original CRC I posted code on this thread in PHP:

I spent a bit of time on it so I hope it can assist someone working on tougher problems: Reversing CRC32 Cheers!

Community
  • 1
  • 1
Jeremy Adsitt
  • 414
  • 4
  • 5
  • 1
    Reversing by appending has the disadvantage it can be defeated by a simple length check. Much handier would be to reverse-match a crc by allowing data inside specific boundaries inside the file to be modified... – Nyerguds Aug 14 '18 at 13:24
2

Cade Roux Is right about reversing CRC32.

The links you mentioned provide a solution to fix a CRC that has become invalide by altering the original byte stream. This fix is achieved by changing some (unimportant) bytes and so recreate the original CRC value.

Frank Bollack
  • 24,478
  • 5
  • 49
  • 58
  • 2
    Or hacking the stream so that the CRC is unchanged while important data (like anti-piracy code) is changed. – Cade Roux Oct 03 '09 at 16:14