Skip to content

Instantly share code, notes, and snippets.

@DavidBuchanan314
Last active March 1, 2024 13:56
Show Gist options
  • Star 38 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save DavidBuchanan314/a15e93eeaaad977a0fec3a6232c0b8ae to your computer and use it in GitHub Desktop.
Save DavidBuchanan314/a15e93eeaaad977a0fec3a6232c0b8ae to your computer and use it in GitHub Desktop.

MD5 Collision with CRC32 Preimage

Here's the scenario: We want to craft two different messages with the same MD5 hash, and a specific CRC32 checksum, simultaneously.

In other words, we want an MD5 collision attack and a CRC32 preimage attack.

This might seem like a contrived scenario, but it's exactly the one I faced while producing my PNG hashquine (Yes OK maybe that's also a contrived scenario, cut me some slack).

On its own, a CRC32 preimage attack is trivial. You can craft a 4-byte suffix that gives any message a specific checksum, calculated using a closed-form expression (which I am too lazy to derive, not even with assistance from Z3). It's not an attack per-se, since CRC32 was never meant to be cryptograpically secure in the first place.

Similarly, an MD5 collision can be calculated near-instantly (about 1 second) using FastColl - which uses some very clever maths, but as an end-user it's point-and-shoot.

So, FastColl can give us two different messages with the same MD5 hash, but different CRCs. We can add a 4-byte suffix to each message, to correct the CRCs, right?

Wrong. Since each message started off with a different CRC, there is no single suffix that could be added to both, to give them both the same final CRC (The proof of this is left as an exercise to the reader!). If you used a different suffix for each message, you could make the CRCs match, but the MD5s would be different.

It seems like we can't have our cake and eat it.

To make things more concrete, here's an example message pair I made using UniColl (same idea as FastColl, but gives more control over the data, letting me write this funny message):

$ md5sum collision*
6aa7959465eff8eeade6d4ce15fdf1ee  collision1.bin
6aa7959465eff8eeade6d4ce15fdf1ee  collision2.bin
$ crc32sum collision*
505d9be4  collision1.bin
18dc7eba  collision2.bin
$ head -n1 collision1.bin 
Hello, it's me, Mr President. If this box is ticked, launch the nukes: ✔
$ head -n1 collision2.bin 
Hello, it's me, Mr President. If this box is ticked, launch the nukes: ✕

We have two different files, both with the same MD5, but different CRCs. We want both CRCs to be the same, and we want them to be an arbitrary value - I'm picking 0xdeadbeef.

Here's the plan. First, we're going to use FastColl to add even more (36) colliding block pairs to the messages. This will change their MD5s, but they'll still be the same as each other.

import os

prefix = bytearray(open("collision1.bin", "rb").read())
f2_a = b""
f2_b = b""

for _ in range(36):
	with open("prefix_mitm.bin", "wb") as pf:
		pf.write(prefix)
	os.system("rm -f prefix_mitm_msg*.bin && ./fastcoll -p prefix_mitm.bin")
	coll_a = open("prefix_mitm_msg1.bin", "rb").read()[-128:]
	coll_b = open("prefix_mitm_msg2.bin", "rb").read()[-128:]
	f2_a += coll_a
	f2_b += coll_b
	prefix += coll_a

with open("f2a.bin", "wb") as f:
	f.write(f2_a)
with open("f2b.bin", "wb") as f:
	f.write(f2_b)

Each collision we generate gives us a choice of two different blocks to pick from, at that position in the message.

Swapping the blocks will change the CRC32, but keep the MD5 the same. As a quick demonstration, swapping out all the blocks at once changes the CRCs like so (but not the MD5s):

$ cat collision1.bin f2a.bin | md5sum
d5ef003912d6877a6686d16a45054ce5  -
$ cat collision1.bin f2b.bin | md5sum
d5ef003912d6877a6686d16a45054ce5  -
$ cat collision2.bin f2a.bin | md5sum
d5ef003912d6877a6686d16a45054ce5  -
$ cat collision2.bin f2b.bin | md5sum
d5ef003912d6877a6686d16a45054ce5  -
$ cat collision1.bin f2a.bin | crc32sum 
17f0391b
$ cat collision1.bin f2b.bin | crc32sum 
adf1eb5b
$ cat collision2.bin f2a.bin | crc32sum 
6080b475
$ cat collision2.bin f2b.bin | crc32sum 
da816635

Since there are 36 pairs of blocks, there are 2^36 possible combinations, for each message. If we enumerate them all and check the resulting CRC, we'd have a reasonable chance of stumbling across the target CRC (0xdeadbeef) by chance - since there are only 2^32 possible CRC32 results.

This is a feasible computation, but it would be a bit slow, probably on the order of minutes - infeasible as part of the inner-loop of a larger attack (such as a PNG hashquine!). Fortunately, there's a trick we can use to speed this up.

Meet In The Middle

CRC32 is an invertible function. This means we can run it backwards as well as forwards, to "rewind" the state to an earlier point in time, so long as we know the data it was hashing.

To illustrate, here's a quick python implementation and demo:

def create_table():
	a = []
	for i in range(256):
		k = i
		for j in range(8):
			if k & 1:
				k ^= 0x1db710640
			k >>= 1
		a.append(k)
	return a

crc_table = create_table()
inv_table = [None]*256
for i, x in enumerate(crc_table):
	inv_table[x>>24] = (x << 8) ^ i

def crc32(buf, crc=0):
	crc ^= 0xffffffff
	for k in buf:
		crc = (crc >> 8) ^ crc_table[(crc & 0xff) ^ k]
	return crc ^ 0xffffffff

def inverse_crc32(buf, crc):
	crc ^= 0xffffffff
	for k in buf[::-1]:
		crc = ((crc << 8) ^ inv_table[crc >> 24] ^ k) & 0xffffffff
	return crc ^ 0xffffffff

# this prints 0x3610a686
print("crc32(hello) =", hex(crc32(b"hello")))

# this prints 0x0
print("inverse_crc32(hello, crc32(hello)) = ", hex(inverse_crc32(b"hello", 0x3610a686)))

Rather than iterate through all 2^36 combinations of our colliding blocks, we'll do this:

Take the first 18 pairs of collision blocks, and iterate through all 2^18 possible combinations. For each combination, calculate the CRC and note down the result and the combination that produced it, using a hashtable (a dict, if you speak python).

This gives us a table of approximately 2^18 CRC-to-input-block-combination mappings, which we can query efficiently.

Next, we take the last 18 pairs of collision blocks, and iterate through all 2^18 possible combinations of those - but this time running CRC32 in reverse, starting from the target value of 0xdeadbeef.

For each result we get, we look it up in our hashtable - if it's present, than we've just successfully "met in the middle", and found a CRC32 preimage! This process must be repeated for each of our messages (twice).

Because all our blocks were MD5 collisions, the final MD5s are unchanged, and we have our target CRC! And, the overall attack complexity is only 2^19, which is very feasible.

Without further ado, here's the full implementation:

prefix1 = open("collision1.bin", "rb").read()
prefix2 = open("collision2.bin", "rb").read()

blocks = []
with open("f2a.bin", "rb") as fa:
	with open("f2b.bin", "rb") as fb:
		for _ in range(36):
			blocks.append([
				fa.read(128),
				fb.read(128)
			])

forward_blocks = blocks[:18]
backward_blocks = blocks[18:][::-1]

def search_forwards(table, sum, history=[], idx=0):
	if idx >= len(forward_blocks):
		table[sum] = history
		return
	for i, child in enumerate(forward_blocks[idx]):
		search_forwards(table, crc32(child, sum), history + [i], idx+1)

def search_backwards(table, sum, history=[], idx=0):
	if idx >= len(backward_blocks):
		if sum in table:
			return table[sum] + history[::-1]
		return
	for i, child in enumerate(backward_blocks[idx]):
		res = search_backwards(table, inverse_crc32(child, sum), history + [i], idx+1)
		if res is not None:
			return res

def do_preimage(prefix, filename):
	table = {}
	search_forwards(table, crc32(prefix))
	path = search_backwards(table, 0xdeadbeef)
	reassembled = prefix + b"".join([b[i] for i, b in zip(path, blocks)])
	with open(filename, "wb") as of:
		of.write(reassembled)

do_preimage(prefix1, "out1.bin")
do_preimage(prefix2, "out2.bin")

When we run it, this gives us the final result:

$ md5sum out?.bin 
f54e7363d9c72ebf81605e2b38fa2be5  out1.bin
f54e7363d9c72ebf81605e2b38fa2be5  out2.bin
$ crc32sum out?.bin 
deadbeef  out1.bin
deadbeef  out2.bin
$ head -n1 out1.bin 
Hello, it's me, Mr President. If this box is ticked, launch the nukes: ✔
$ head -n1 out2.bin
Hello, it's me, Mr President. If this box is ticked, launch the nukes: ✕

Note that I'm using head to isolate the first line of the files, hiding all the garbage collision data. You could also use ANSI control squences embedded in the data to hide it - this is left as an exercise to the reader.

The output files are attached to this gist, base64'd, if you want to play with them.

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
ImJd4HoozcrKh3IP
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
ImJd4HoozcrKh3IP
@hellman
Copy link

hellman commented Sep 27, 2022

@hellman
Copy link

hellman commented Sep 27, 2022

You can actually forge MD5+any affine hash (e.g. any large CRC) by solving some linear system instead of MitM

@DavidBuchanan314
Copy link
Author

Neat, I didn't know there was a MD5+CRC CTF challenge!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment