1

An old game I'm trying to mod has a CRC-32 check. I don't have access to the CRC checksum itself, so I must modify the file while maintaining the same checksum output.

Info I have

  • The file, if the file itself is the only input to the CRC-32 program, I can calculate what the CRC-32 checksum should be.

  • The 32-bit polynomial code.

Cool Pie
  • 13
  • 2
  • 3

3 Answers3

7

As @MrSmith42 says, provided you don't need to keep the file length constant, a "collision" (the name given for two input messages that result in the same hash) can be easily calculated.

It's fiddly, with lots of bit twiddling, but very quick.

Suppose the original file is, in hex:

1122334455667788

Then its CRC-32 checksum would be 0x9118E1C2 using the standard CRC32 polynomial. If the algorithm in use is not standard, it can be substituted. I'll stick with the standard for demonstration purposes.

First, make your file changes as necessary. Eg, I change a byte in the middle:

11223344FF667788

Step one to restore the CRC is to pad the file with 4 zero bytes:

11223344FF66778800000000

The CRC checksum is now 0x6BBE83C9.

Step two, XOR the two checksums:

0x9118E1C2 XOR 0x6BBE83C9 = 0xFAA6620B

Step three, bit reverse the result:

Bit reverse of 0xFAA6620B = 0xD046655F

Step four, and this is a bit funky so see below, perform an inverse CRC32 calculation:

0xD046655F * inverse(x32) mod crc_poly = 0xe4c7d232

Step five, bit reverse the result, byte-wise this time:

0xe4c7d232 bit reversed byte-wise = 0x27E34B4C

Step six, replace the padded bytes with the result

11223344FF66778827E34B4C

Voila, the CRC32 checksum value is now back to 0x9118E1C2.

Easiest way I know of to do the inverse CRC calc is with the BitVector package in Python:

>>> import BitVector as bv
>>> poly = bv.BitVector(intVal = 0x104C11DB7) # "standard" CRC32 polynomial
>>> inv = bv.BitVector(intVal = 0x100000000).gf_MI(poly, 32)
>>> k = 0xD046655F
>>> p = bv.BitVector(intVal = k).gf_multiply_modular(inv, poly, 32)
>>> print(p.getHexStringFromBitVector())
e4c7d232

This algorithm is by Redditor /u/supersaw7 published in this thread. I've not come across a better one, despite a simpler version being tantalisingly possible.

Heath Raftery
  • 3,643
  • 17
  • 34
  • That's awesome, it seems like it will work. I got it working up to step 6.I don't understand what should be done to bit-reverse? byte-wise. . – Cool Pie Jan 14 '18 at 11:25
  • Nvm, figured it out. You had to reverse the bits per-byte. `bytes([int('{:08b}'.format(v)[::-1], 2) for v in binascii.unhexlify(format(0xe4c7d232, 'x'))])` – Cool Pie Jan 14 '18 at 12:22
3

Use spoof. After you have modified your file, you will need to identify a set of bit locations that you would permit changing to return the CRC to the original value. You'll need to provide spoof with the exclusive-or of the original CRC that you want to return to, and the current CRC, along with the bit locations you don't care about, e.g. in character strings, along with some information about the CRC itself and the length of the file. spoof will then solve for which of those bits to flip to get the desired CRC. The documentation gives guidance on how many changeable bit positions you will need to offer.

You can leave the file the same length, or you can add bytes to the file to create positions that you consider changeable.

Mark Adler
  • 101,978
  • 13
  • 118
  • 158
1

If the size of the file does not need to be constant, you can simply modify its content as much, as you like and that add some bytes (4) to fix the checksum.

Which bytes to add can be

a) calculated, if you understand the used CRC algorithm or

b) try a brute force attempt to find suitable bytes (might take a while, but if you do not need to do it that often, it is still a feasable attemp

MrSmith42
  • 9,961
  • 6
  • 38
  • 49
  • Thanks, this game 2 directions to go in. 4294967296 permutations, thinking about rebooting the game that many times gave me a sense of despair. Since I know the code for the CRC algo, Hopefully, I can figure it out within a day or 2. Either through methodical understanding of the cascading math, or brute force checking via the algorithm. – Cool Pie Jan 14 '18 at 08:43
  • CRC calculations are linear, so you can study the effect of a single bit flip on the CRC and then combine the results by XOR. A Gaussian elimination process allows you to compute the correct combination. – Henry Jan 14 '18 at 08:55