Skip to content

MD5

MD5

  • Merkle–Damgård based hash function
    • Vulnerable to Length extension attack

Collisions

Collision Information
https://blog.cloudflare.com/radius-udp-vulnerable-md5-attack Radius MD5 collision

PDF Collision

Same Prefix collision (hashclash)

Install:

git clone https://github.com/cr-marcstevens/hashclash
yay boost boost-libs
cd hashclash
./build.sh

Generate Collision:

echo -n "MD5_Collisiom" > prefix.txt
./scripts/poc_no.sh prefix.txt 
[...]
Block 1: ./data/coll1_1508279055
35 fc 8e 6f 83 0e 99 74 92 91 e0 50 ed 97 2d e2 
de 58 cf 0c 55 55 77 b0 fd 70 3c 40 0a d5 dc 62 
14 63 50 23 79 88 63 ef df 0b 5e 96 b5 5f 45 88 
aa a8 a3 a6 cb 9a cc 5b 89 0f 50 78 53 c9 f0 d0 
Block 2: ./data/coll2_1508279055
35 fc 8e 6f 83 0e 99 74 92 92 e0 50 ed 97 2d e2 
de 58 cf 0c 55 55 77 b0 fd 70 3c 40 0a d5 dc 62 
14 63 50 23 79 88 63 ef df 0b 5e 96 b5 5f 45 88 
aa a8 a3 a6 cb 9a cc 5b 89 0f 50 78 53 c9 f0 d0 
Found collision!
052e7244f730d2b9c21c9b84ec4c2c72  collision1.bin
052e7244f730d2b9c21c9b84ec4c2c72  collision2.bin
c23f1551dce93d815ae15e5fea1d7256e608f63c  collision1.bin
9a8ea244a3cfcc3882c6ec3f975ecc397559e02b  collision2.bin
4 -rw-r--r-- 1 gen0 gen0 128 Aug 16 16:01 collision1.bin
4 -rw-r--r-- 1 gen0 gen0 128 Aug 16 16:01 collision2.bin
[gen0@gen0 scripts]$ hexyl collision1.bin 
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 4d 44 35 5f 43 6f 6c 6c  69 73 69 6f 6d ce d0 79 │MD5_Coll┊isiom××y│
│00000010│ 4b 68 11 0c 98 63 80 68  d2 20 a6 6e 67 4c af 04 │Kh•_×c×h┊× ×ngLו│
│00000020│ 5a 28 b3 2b ed 7c 19 3f  db 3f a8 1f b8 58 a2 87 │Z(×+×|•?┊×?ו×X××│
│00000030│ 8b 74 25 bb d9 65 93 b8  7a 3e cc d9 5b 42 5e 84 │×t%××e××┊z>××[B^×│
│00000040│ 35 fc 8e 6f 83 0e 99 74  92 92 e0 50 ed 97 2d e2 │5××oו×t┊×××P××-×│
│00000050│ de 58 cf 0c 55 55 77 b0  fd 70 3c 40 0a d5 dc 62 │×X×_UUw×┊×p<@_××b│
│00000060│ 14 63 50 23 79 88 63 ef  df 0b 5e 96 b5 5f 45 88 │•cP#y×c×┊ו^××_E×│
│00000070│ aa a8 a3 a6 cb 9a cc 5b  89 0f 50 78 53 c9 f0 d0 │×××××××[┊וPxS×××│
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
[gen0@gen0 scripts]$ hexyl collision2.bin 
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 4d 44 35 5f 43 6f 6c 6c  69 74 69 6f 6d ce d0 79 │MD5_Coll┊itiom××y│
│00000010│ 4b 68 11 0c 98 63 80 68  d2 20 a6 6e 67 4c af 04 │Kh•_×c×h┊× ×ngLו│
│00000020│ 5a 28 b3 2b ed 7c 19 3f  db 3f a8 1f b8 58 a2 87 │Z(×+×|•?┊×?ו×X××│
│00000030│ 8b 74 25 bb d9 65 93 b8  7a 3e cc d9 5b 42 5e 84 │×t%××e××┊z>××[B^×│
│00000040│ 35 fc 8e 6f 83 0e 99 74  92 91 e0 50 ed 97 2d e2 │5××oו×t┊×××P××-×│
│00000050│ de 58 cf 0c 55 55 77 b0  fd 70 3c 40 0a d5 dc 62 │×X×_UUw×┊×p<@_××b│
│00000060│ 14 63 50 23 79 88 63 ef  df 0b 5e 96 b5 5f 45 88 │•cP#y×c×┊ו^××_E×│
│00000070│ aa a8 a3 a6 cb 9a cc 5b  89 0f 50 78 53 c9 f0 d0 │×××××××[┊וPxS×××│
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
[gen0@gen0 scripts]$ sha1sum *.bin
c23f1551dce93d815ae15e5fea1d7256e608f63c  collision1.bin
9a8ea244a3cfcc3882c6ec3f975ecc397559e02b  collision2.bin
da39a3ee5e6b4b0d3255bfef95601890afd80709  dummy.prefix.bin
[gen0@gen0 scripts]$ md5sum *.bin
052e7244f730d2b9c21c9b84ec4c2c72  collision1.bin
052e7244f730d2b9c21c9b84ec4c2c72  collision2.bin
d41d8cd98f00b204e9800998ecf8427e  dummy.prefix.bin

Same Prefix collision (fastcoll)

echo "TestInput1233" > input
docker run --rm -it -v $PWD:/work -w /work -u $UID:$GID brimstone/fastcoll --prefixfile input -o msg1.bin msg2.bin
docker run --rm -it -v $PWD:/work -w /work -u $UID:$GID brimstone/fastcoll --prefixfile input -o msg1.bin msg2.bin
Unable to find image 'brimstone/fastcoll:latest' locally
latest: Pulling from brimstone/fastcoll
b957541cc5ed: Pull complete 
Digest: sha256:cc41f32f05b11d89807a5a12ba8bf81e626b2c26c9a1206f58689ab1138a6c04
Status: Downloaded newer image for brimstone/fastcoll:latest
MD5 collision generator v1.5
by Marc Stevens (http://www.win.tue.nl/hashclash/)

Using output filenames: 'msg1.bin' and 'msg2.bin'
Using prefixfile: 'input'
Using initial value: 2c0d69035d93d6fd3bbade65a61f0dce

Generating first block: ........
Generating second block: S10...................................................
Running time: 1.37609 s

Confirmation:

[gen0@gen0 Downloads]$ md5sum msg*
d0e812912ace927043d268498e61cde8  msg1.bin
d0e812912ace927043d268498e61cde8  msg2.bin
[gen0@gen0 Downloads]$ sha1sum msg*
9933b90c028947a5139de3710270943438d6d05b  msg1.bin
c8e36abd5f77246d378634a1d245232a0304afe9  msg2.bin
[gen0@gen0 Downloads]$ hexyl msg1.bin 
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 54 65 73 74 49 6e 70 75  74 31 32 33 33 0a 00 00 │TestInpu┊t1233_00│
│00000010│ 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 │00000000┊00000000│
│*                                                                         │
│00000040│ ca 43 1a 87 32 02 6a 3f  9b 9c 75 53 3e 78 96 b5 │×C•×2•j?┊××uS>x××│
│00000050│ 3a 7a eb 8a 96 cd e3 01  31 0a 84 36 8f 2a 25 fb │:z××××ו┊1_×6×*%×│
│00000060│ 30 bb fe d9 62 86 df 87  0b 6a d9 9a e8 c9 02 35 │0×××b×××┊•j×××ו5│
│00000070│ a1 e8 32 c9 b4 39 1f 9e  63 91 4f a6 58 74 19 82 │××2××9•×┊c×O×Xt•×│
│00000080│ f3 67 2c 1c 95 a2 2f 49  8d e0 fb 55 a5 c0 57 ef │×g,•××/I┊×××U××W×│
│00000090│ af 3f 9d 4b 74 d8 f1 c8  2d b3 00 c8 37 60 88 c8 │×?×Kt×××┊-×0×7`××│
│000000a0│ d7 93 26 48 af 85 7e 14  74 3c 42 9c 5d 7c 08 08 │××&H××~•┊t<B×]|••│
│000000b0│ 5c 7b 1a cb f5 fc a7 47  1a 6d b1 ca 1f a1 08 32 \{•××××G┊•m×וו2│
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
[gen0@gen0 Downloads]$ hexyl msg2.bin 
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 54 65 73 74 49 6e 70 75  74 31 32 33 33 0a 00 00 │TestInpu┊t1233_00│
│00000010│ 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 │00000000┊00000000│
│*                                                                         │
│00000040│ ca 43 1a 87 32 02 6a 3f  9b 9c 75 53 3e 78 96 b5 │×C•×2•j?┊××uS>x××│
│00000050│ 3a 7a eb 0a 96 cd e3 01  31 0a 84 36 8f 2a 25 fb │:z×_××ו┊1_×6×*%×│
│00000060│ 30 bb fe d9 62 86 df 87  0b 6a d9 9a e8 49 03 35 │0×××b×××┊•j×××I•5│
│00000070│ a1 e8 32 c9 b4 39 1f 9e  63 91 4f 26 58 74 19 82 │××2××9•×┊c×O&Xt•×│
│00000080│ f3 67 2c 1c 95 a2 2f 49  8d e0 fb 55 a5 c0 57 ef │×g,•××/I┊×××U××W×│
│00000090│ af 3f 9d cb 74 d8 f1 c8  2d b3 00 c8 37 60 88 c8 │×?××t×××┊-×0×7`××│
│000000a0│ d7 93 26 48 af 85 7e 14  74 3c 42 9c 5d fc 07 08 │××&H××~•┊t<B×]ו•│
│000000b0│ 5c 7b 1a cb f5 fc a7 47  1a 6d b1 4a 1f a1 08 32 \{•××××G┊•m×J•×•2│
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘

Different Prefix collision ()

Setup:

[gen0@gen0 tmp]$ echo "TestString" > prefix1
[gen0@gen0 tmp]$ echo "FakeString" > prefix2
[gen0@gen0 tmp]$ ../scripts/cpc_md5.sh prefix1 prefix2
[...]
..[*] Time before backtrack: 13500 s
1 0
2 0
4 0
8 0
16 0
32 0
64 0
128 0
256 0
512 0
1024 0
2048 0
4096 0
8192 0
16384 0
30608 1
32768 1
65536 1
75435 2
97348 4
131072 4
262144 5
524288 7
546191 8
1048576 14
1121037 16
1953889 32
Block 1: workdir6/coll1_1488607500
87 44 3f 35 0e 83 c0 53 dc c7 2b ec 8a 36 92 cc 
ab e5 5b d0 26 e2 c9 e6 af 55 ea 91 65 17 8f 68 
80 7a 59 b5 3c 1a a4 16 2f b6 bd 0b 69 fe 7c de 
9f 57 b3 15 ab 0e 21 a0 ed b8 87 c0 30 86 0b 89 
Block 2: workdir6/coll2_1488607500
87 44 3f 35 0e 83 c0 53 dc c7 2b ec 8a 36 92 cc 
ab e5 5b d0 26 e2 c9 e6 af 55 ea 91 65 17 8f 68 
80 7a 59 b5 3c 1a a4 16 2f b6 bd 0b 49 fe 7c de 
9f 57 b3 15 ab 0e 21 a0 ed b8 87 c0 30 86 0b 89 
Found collision!
[*] Step 6 completed
[*] Number of backtracks until now: 1
[*] Collision generated: prefix1.coll prefix2.coll
d5260b0a6e974567447ebab992e63f09  prefix1.coll
d5260b0a6e974567447ebab992e63f09  prefix2.coll
[*] Process completed in 551 minutes (1 backtracks).
[gen0@gen0 tmp]$ md5sum prefix{1,2}.coll
d5260b0a6e974567447ebab992e63f09  prefix1.coll
d5260b0a6e974567447ebab992e63f09  prefix2.coll
[gen0@gen0 tmp]$ sha1sum prefix{1,2}.coll
2b1be5e8e427dc0860abec69e31b21d5f8b076f2  prefix1.coll
3d98e122d4902929a81d1f9bd51ab3e8c3cc073f  prefix2.coll

Python2 Script Collision

[gen0@gen0 python-md5-collision]$ ./gen_coll_python.py
[gen0@gen0 python-md5-collision]$ python2 ./out_py_evil.py 
evil
[gen0@gen0 python-md5-collision]$ python2 ./out_py_good.py 
good
[gen0@gen0 python-md5-collision]$ md5sum ./out_py_*
565badb0d0dfd01fa719f2a122ffcb06  ./out_py_evil.py
565badb0d0dfd01fa719f2a122ffcb06  ./out_py_good.py
[gen0@gen0 python-md5-collision]$ sha1sum ./out_py_*
2ed80199a3610ed75e23ed9ae5ffdc2e13be9cda  ./out_py_evil.py
2b38a6d12bccaa3c9076834cc96d8b98650bc2f1  ./out_py_good.py

Linux binary Collision

https://github.com/mxrch/evilize

[gen0@gen0 python-md5-collision]$ ./gen_coll_c.py
[gen0@gen0 python-md5-collision]$ ./out_c_good 
good
[gen0@gen0 python-md5-collision]$ ./out_c_evil 
evil
gen_coll_c.py
[gen0@gen0 python-md5-collision]$ md5sum out_c_*
cabdd76291f59fb263d2e62a7576c5ad  out_c_evil
cabdd76291f59fb263d2e62a7576c5ad  out_c_good
[gen0@gen0 python-md5-collision]$ sha1sum out_c_*
b375b565999fd971a969ca654c43c95bc9bb69ac  out_c_evil
6c4459bbe8c5f3c5cc18620843605957cb098e6d  out_c_good

Shellcode Packer with md5 collision

JPEG Collisions

>>> wget https://upload.wikimedia.org/wikipedia/commons/3/3f/JPEG_example_flower.jpg
>>> wget https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg
>>> md5sum JPEG_example_flower.jpg Example.jpg 
9457ccf4b0ecb91304a6e3eca7acf42b  JPEG_example_flower.jpg
c8e7e1fc344be6982710f54d47191ef6  Example.jpg
>>> ./jpg.py JPEG_example_flower.jpg Example.jpg 
>>> md5sum collision{1,2}.jpg
89ce2ab3b88a2dfa7df0e0a5618051c5  collision1.jpg
89ce2ab3b88a2dfa7df0e0a5618051c5  collision2.jpg
>>> sha1sum collision{1,2}.jpg
71d6fa51b30e269e01a4c828bdfe52611315743f  collision1.jpg
e19dd0d31767366f0b044993f659d034262bd353  collision2.jpg

PNG Collision ()

>>> curl https://www.fnordware.com/superpng/pnggrad8rgb.png --output pnggrad8rgb.png
>>> curl https://www.fnordware.com/superpng/pnggradHDrgba.png --output pnggradHDrgba.png
>>> ./png.py  pnggradHDrgba.png pnggrad8rgb.png
>>> md5sum collision{1,2}.png
3b87b373db2f5cbaeef4125e204f240c  collision1.png
3b87b373db2f5cbaeef4125e204f240c  collision2.png
>>> sha1sum collision{1,2}.png
a3d9baa25bb08adc4473a972a5b09ede9a01d1a8  collision1.png
d97c24c08da7224f49be70c1a1de97d35f7b4822  collision2.png

GIF Collision

https://github.com/corkami/collisions#gif

GZIP Collision

wget https://github.com/sgreben/http-file-server/archive/refs/tags/1.5.3.tar.gz
wget https://github.com/sgreben/http-file-server/archive/refs/tags/1.5.2.tar.gz
>>> md5sum 1.5.*
ad8bd7b6fd0439d0c069a13bb52b2103  1.5.2.tar.gz
f235c0ab5ac3f8079c050f6bb1538421  1.5.3.tar.gz
>>> python3 gz.py 1.5.2.tar.gz 1.5.3.tar.gz 
1.5.2.tar.gz (120833 bytes): split in 2 members
1.5.3.tar.gz (120830 bytes): split in 2 members
Success!
5138b60b5f314de82b2c19bcafdbc2e1
coll-1.gz => 1.5.2.tar.gz
coll-2.gz => 1.5.3.tar.gz
>>> md5sum coll-{1,2}.gz
5138b60b5f314de82b2c19bcafdbc2e1  coll-1.gz
5138b60b5f314de82b2c19bcafdbc2e1  coll-2.gz
>>> sha1sum coll-{1,2}.gz
f50ec39cefb107445889013deeab586a00edf4f1  coll-1.gz
5013a10fc67842551f56f7d87adcf199088f4796  coll-2.gz
````


#### EXE Collisions


```bash
>>> md5sum shimgen.exe 7z.exe 
3083884466a084d79d4da5a10c609e60  shimgen.exe
7187ae605f4dce14bb23ea2623956335  7z.exe
>>> ./pe.py shimgen.exe 7z.exe 
Success!
Common MD5: 4f50e93a10ffaaf7f0bdbd57f379fff6
>>> md5sum collision{1,2}.exe
4f50e93a10ffaaf7f0bdbd57f379fff6  collision1.exe
4f50e93a10ffaaf7f0bdbd57f379fff6  collision2.exe

Office Open XML: docx / pptx / xlsx

https://github.com/corkami/collisions/blob/master/scripts/zinsider.py

epub

https://github.com/corkami/collisions/blob/master/scripts/zinsider.py

3mf

https://github.com/corkami/collisions/blob/master/scripts/zinsider.py

Many Collisions

git clone https://github.com/grevutiu-gabriel/python-md5-collision
gen_coll_c.py

Implementation

from cryptopals_lib import *

class MD5(object):
	def __init__(self):
		self.buffers = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476]

		self.sin_constants = [asint32(int(abs(math.sin(i+1)) * 2**32)) for i in range(64)]

		self.shift_table = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
							5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
							4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
							6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]

	def _set_message(self, message):
		#Convert to bytes if not already
		byte_message = bytearray(message)

		#Get Length shifted by 8 and limit to 64bit int
		md5_input_length_data = asint64(len(byte_message) << 3)

		#Append 0x80 to the end of the message as a end of message byte
		byte_message.append(0x80)

		#Pad the data to a multable of 64 bytes when the 8 byte md5_input_length_data is added 
		while len(byte_message) % 64 != 56:
			byte_message.append(0x00)

		#Append the length data to the message
		byte_message += int_to_bytes_length(md5_input_length_data, 8, False)

		return byte_message

	def _hash_message_chunk(self, chunk):
		temp_buffers = self.buffers[:]

		for round_itteration in range(16):
			#Do Function F (x & y) | (~x & z)
			temp_value = (temp_buffers[1] & temp_buffers[2]) | (~temp_buffers[1] & temp_buffers[3])

			#Calculate index to opperate on
			chunk_index = round_itteration * 4

			#Add Varables mod 32
			temp_value = asint32(temp_value + temp_buffers[0] + self.sin_constants[round_itteration] + bytes_to_int(chunk[chunk_index:chunk_index+4], False))
			
			#Rotate based of of rotate table and add the second index in the buffer
			temp_value = asint32(temp_buffers[1] + shift_rotate_left(temp_value, self.shift_table[round_itteration]))

			#Swap values in to the new buffer
			temp_buffers = [temp_buffers[3], temp_value, temp_buffers[1], temp_buffers[2]]


		for round_itteration in range(16, 32):
			#Do Function G (x & z) | (y & ~z)
			temp_value = (temp_buffers[1] & temp_buffers[3]) | (temp_buffers[2] & ~temp_buffers[3])

			#Calculate index to opperate on
			chunk_index = (((5 * round_itteration) + 1) % 16) * 4

			#Add Varables mod 32
			temp_value = asint32(temp_value + temp_buffers[0] + self.sin_constants[round_itteration] + bytes_to_int(chunk[chunk_index:chunk_index+4], False))
			
			#Rotate based of of rotate table and add the second index in the buffer
			temp_value = asint32(temp_buffers[1] + shift_rotate_left(temp_value, self.shift_table[round_itteration]))

			#Swap values in to the new buffer
			temp_buffers = [temp_buffers[3], temp_value, temp_buffers[1], temp_buffers[2]]

		for round_itteration in range(32, 48):
			#Do Function H x ^ y ^ z
			temp_value = fixedlen_xor(fixedlen_xor(temp_buffers[1], temp_buffers[2]), temp_buffers[3])

			#Calculate index to opperate on
			chunk_index = (((3 * round_itteration) + 5) % 16) * 4

			#Add Varables mod 32
			temp_value = asint32(temp_value + temp_buffers[0] + self.sin_constants[round_itteration] + bytes_to_int(chunk[chunk_index:chunk_index+4], False))
			
			#Rotate based of of rotate table and add the second index in the buffer
			temp_value = asint32(temp_buffers[1] + shift_rotate_left(temp_value, self.shift_table[round_itteration]))

			#Swap values in to the new buffer
			temp_buffers = [temp_buffers[3], temp_value, temp_buffers[1], temp_buffers[2]]


		for round_itteration in range(48, 64):
			#Do Function I y ^ (x | ~z)
			temp_value = fixedlen_xor(temp_buffers[2], (temp_buffers[1] | ~temp_buffers[3]))

			#Calculate index to opperate on
			chunk_index = ((7 * round_itteration) % 16) * 4

			#Add Varables mod 32
			temp_value = asint32(temp_value + temp_buffers[0] + self.sin_constants[round_itteration] + bytes_to_int(chunk[chunk_index:chunk_index+4], False))
			
			#Rotate based of of rotate table and add the second index in the buffer
			temp_value = asint32(temp_buffers[1] + shift_rotate_left(temp_value, self.shift_table[round_itteration]))

			#Swap values in to the new buffer
			temp_buffers = [temp_buffers[3], temp_value, temp_buffers[1], temp_buffers[2]]

		#Chunks are done with the round
		#Update the internal buffers with the new data
		self.buffers = [asint32(self.buffers[0] + temp_buffers[0]), 
						asint32(self.buffers[1] + temp_buffers[1]),
						asint32(self.buffers[2] + temp_buffers[2]),
						asint32(self.buffers[3] + temp_buffers[3])]


	def hash(self, message):
		#Setup message with padding and length data
		byte_message = self._set_message(message)

		#Opperate on each of the 64 byte chunks
		for chunk in to_blocks(byte_message, 64):
			self._hash_message_chunk(chunk)

		#Convert Intagers to Byte string
		output = b""
		for x in self.buffers:
			output += (x).to_bytes(4, byteorder='little')

		
		return output
		
	def hash_digest(self, message):
		return self.hash(message).hex()

if __name__ == '__main__':
	testmd5 = MD5()
	print(testmd5.hash_digest(b""))
	#d41d8cd98f00b204e9800998ecf8427e

	testmd5 = MD5()
	print(testmd5.hash_digest(b"a"))
	#0cc175b9c0f1b6a831c399e269772661

	testmd5 = MD5()
	print(testmd5.hash_digest(b"c7840924e344f6d3934999be91f1f079c759cfc1d7ebb38655b49415df9a1c67b9345d01c0c0aaacd51357f74e356d75fc7e22322637d54d43331b143e268b297eee06be41abefdd2b78cdc33a7f9372e9f4df44d0c5d3a981c7084b2cc6be181b13251f2151cc03d2b0c6d001c13105dd1d5bd7e3200696545ed7ed9c1dc2662fe34f35b8caffbb0466b129736fa4b0ad18e21297836814561cdeaba49b345b6f5e3717a322485acb01ba9af6fe085052bdd158ab930b80b0c96eb2fd28570e9c81579f304443a8c3e4c4e3c0968444acc65e000730b4399719936c7e141d40b6d721f4fa97254465a9ddf51f1e70ad340ad8cc27671fd8a28bda7ec2ce475ebf1819b448f8804c2a2df277ae613974c889a7dc0bfa42698e29e663e0d5591324221267fc5d3ff101e81afdb4f9fb4a40c025bbab9c5809bd297904e6ca3b8036cc4ead33ea28639803cac1a5a67572bbc7947254d15d8befd44e7125920ba5f6f6e87cf07e75e56ea47f3817ff35de2033652a5c9a797d44b811c6482a345d0201a3064b6dd9e6b86735c16efd34120a3adb3496fc52472175056bef762f76e93bd6e7253f4c2baaddeb7d2aa1ee187909fc842276021ce38c82ad57594eb416f80fa0804437a501b21e9f8643d6120b9c0ab5d7624e1c3354c473446757dd1c722f5703055598d16d2458b77defbab48b87ca205339e4417a4486958d96db"))
	#85bdc64de404bf5ab58e313fd6aa089b