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