DownUnderCTF 2023 Writeup
The crypto challenges in DownUnderCTF are very intriguing. Unfortunately I have very limited time during the contest and could only solve apbq rsa ii (26 solves), hhhhh (14 solves) and handshake (4 solves). I will be covering the latter two challenges in this writeup.
hhhhh⌗
Challenge Summary⌗
The code given in this challenge is pretty short:
#!/usr/bin/env python3
from os import getenv as hhhhhhh
from hashlib import md5 as hhhhh
def hhhhhh(hhh):
h = hhhhh()
hh = bytes([0] * 16)
for hhhh in hhh:
h.update(bytes([hhhh]))
hh = bytes([hhhhhhh ^ hhhhhhhh for hhhhhhh, hhhhhhhh in zip(hh, h.digest())])
return hh
print('hhh hhh hhhh hhh hhhhh hhhh hhhh hhhhh hhhh hh hhhhhh hhhh?')
h = bytes.fromhex(input('h: '))
if hhhhhh(h) == b'hhhhhhhhhhhhhhhh':
print('hhhh hhhh, hhhh hh hhhh hhhh:', hhhhhhh('FLAG'))
else:
print('hhhhh, hhh hhhhh!')
We are given a custom hash algorithm, namely $\mathcal{H}$ (or hhhhhh
), which is based on MD5. Let each of $x_1, x_2, …, x_n$ represent a byte. $\mathcal{H}$ is defined by
$$\mathcal{H}(x_1x_2…x_n) = \text{MD5}(x_1) \oplus \text{MD5}(x_1x_2) \oplus … \oplus \text{MD5}(x_1x_2…x_n).$$
The objective is to find a preimage $x_1x_2…x_n$ such that
$$\mathcal{H}(x_1x_2…x_n) = \texttt{hhhhhhhhhhhhhhhh}.$$
Solution⌗
Part I: Generating MD5 Multicollisions⌗
It is well-known that MD5 is vulnerable to collision attacks. We can easily generate collisions with a particular prefix using FastColl. Let $B_1, B_2, …, B_k$ be $k$ 128-byte blocks, we can generate two 128-byte blocks, $X_{k+1,1}$ and $X_{k+1,2}$, such that
$$\text{MD5}(B_1B_2…B_kX_{k+1}) = \text{MD5}(B_1B_2…B_kY_{k+1}).$$
To attack, we can generate a bunch of 128-byte blocks $X_{11}, X_{12}, X_{21}, X_{22}, …$ such that
- $\text{MD5}(X_{11}) = \text{MD5}(X_{12})$ (generated using the prefix $\varepsilon$, i.e., the empty string)
- $\text{MD5}(X_{11}X_{21}) = \text{MD5}(X_{11}X_{22})$ (generated using the prefix $X_{11}$)
- $\text{MD5}(X_{11}X_{21}X_{31}) = \text{MD5}(X_{11}X_{21}X_{32})$ (generated using the prefix $X_{11}X_{21}$)
- …
- $\text{MD5}(X_{11}X_{21}X_{31}…X_{m-1,1}X_{m1}) = \text{MD5}(X_{11}X_{21}…X_{m-1,1}X_{m2})$.
Since MD5 is an implementation of the Merkle-Damgard construction,
$$\text{MD5}(X_{1i_1}X_{2i_2}…X_{ki_k}) = \text{MD5}(X_{1j_1}X_{2j_2}…X_{kj_k})$$
holds for any $k = 1, 2, …, m$ and $i_1, j_1, i_2, j_2, …, i_m, j_m \in \{0, 1\}$. In short, we can freely swap those blocks and they have the same MD5 digests. We found a $2^m$-way collision.
Part II: From multicollisions of MD5 to preimage attack of $\mathcal{H}$⌗
For us to compute a preimage of $\mathcal{H}$, we would like to show that
$$\mathcal{H}(X_{1,i_1}…X_{k,i_k}) \oplus \mathcal{H}(X_{1,1}…X_{k,1}) = \bigoplus_{j=1}^ k \left[\mathcal{H}(X_{1,1}…X_{j-1,1}X_{j,i_j}) \oplus \mathcal{H}(X_{1,1}…X_{j-1,1}X_{j,1})\right].$$
Proof.
$$\begin{aligned} & \mathcal{H}(X_{1,i_1}X_{2,i_2}…X_{k,i_k}) \\ &= \mathcal{H}(x_{1,i_1}…x_{128,i_1}x_{129,i_2}…x_{256,i_2}…x_{128k-127,i_k}…x_{128k,i_k}) \\ &= [\text{MD5}(x_{1,i_1}) \oplus … \oplus \text{MD5}(X_{1,i_1})] \\ & \qquad \oplus [\text{MD5}(X_{1,i_1}x_{129,i_2}) \oplus … \oplus \text{MD5}(X_{1,i_1}X_{2,i_2})] \oplus … \\ & \qquad \oplus [\text{MD5}(X_{1,i_1}…X_{k-1,i_{k-1}}x_{128k-127,i_k}) \oplus … \oplus \text{MD5}(X_{1,i_1}…X_{k-1,i_{k-1}}X_{k,i_k})] \\ &= [\text{MD5}(x_{1,i_1}) \oplus … \oplus \text{MD5}(X_{1,i_1})] \\ & \qquad \oplus [\text{MD5}(X_{1,1}x_{129,i_2}) \oplus … \oplus \text{MD5}(X_{1,1}X_{2,i_2})] \oplus … \\ & \qquad \oplus [\text{MD5}(X_{1,1}…X_{k-1,1}x_{128k-127,i_k}) \oplus … \oplus \text{MD5}(X_{1,1}…X_{k-1,1}X_{k,i_k})] \\ &= \mathcal{H}(X_{1,i_1}) \oplus [\mathcal{H}(X_{1,1}) \oplus \mathcal{H}(X_{1,1}X_{2,i_2})] \oplus … \oplus [\mathcal{H}(X_{1,1}…X_{k-1,1}) \oplus \mathcal{H}(X_{1,1}…X_{k-1,1}X_{k,i_k})] \\ &= [\mathcal{H}(X_{1,i_1}) \oplus \mathcal{H}(X_{1,1})] \oplus [\mathcal{H}(X_{1,1}X_{2,i_2}) \oplus \mathcal{H}(X_{1,1}X_{2,1})] \oplus … \\ & \qquad \oplus [\mathcal{H}(X_{1,1}…X_{k-2,1}X_{k-1,i_{k-1}}) \oplus \mathcal{H}(X_{1,1}…X_{k-1,1})] \oplus \mathcal{H}(X_{1,1}…X_{k-1,1}X_{k,i_k}) \\ &= [\mathcal{H}(X_{1,i_1}) \oplus \mathcal{H}(X_{1,1})] \oplus [\mathcal{H}(X_{1,1}X_{2,i_2}) \oplus \mathcal{H}(X_{1,1}X_{2,1})] \oplus … \\ & \qquad \oplus [\mathcal{H}(X_{1,1}…X_{k-2,1}X_{k-1,i_{k-1}}) \oplus \mathcal{H}(X_{1,1}…X_{k-1,1})] \\ & \qquad \oplus [\mathcal{H}(X_{1,1}…X_{k-1,1}X_{k,i_k}) \oplus \mathcal{H}(X_{1,1}…X_{k,1})] \oplus \mathcal{H}(X_{1,1}…X_{k,1}) \\ & = \mathcal{H}(X_{1,1}…X_{k,1}) \oplus \bigoplus_{j=1}^ k \left[\mathcal{H}(X_{1,1}…X_{j-1,1}X_{j,i_j}) \oplus \mathcal{H}(X_{11}…X_{j-1,1}X_{j,1})\right] \qquad \blacksquare \end{aligned}$$
We can rewrite it the equation with $k$ variables $x_1, x_2, …, x_k$:
$$\mathcal{H}(X_{1,i_1}…X_{k,i_k}) \oplus \mathcal{H}(X_{1,1}…X_{k,1}) = \bigoplus_{j=1}^k x_j \left[\mathcal{H}(X_{1,1}…X_{j-1,1}X_{j,1}) \oplus \mathcal{H}(X_{1,1}…X_{j-1,1}X_{j,2})\right],$$
here $x_r = 0$ if $i_r = 1$ and $x_r = 1$ otherwise. Since we can compute $\mathcal{H}(X_{1,1}…X_{j-1,1}X_{j,1})$ and $\mathcal{H}(X_{1,1}…X_{j-1,1}X_{j,2})$ for $j = 1, 2, …, k$. Also, since $\mathcal{H}(X_{1,i_1}X_{2,i_2}…X_{k,i_k})$ is the target MD5 digest we want to obtain, thus it is also known.
For $j = 1, 2, …, k$, denote
$$\begin{aligned} & a_j := \mathcal{H}(X_{1,1}…X_{j-1,1}X_{j,1}) \oplus \mathcal{H}(X_{1,1}…X_{j-1,1}X_{j,2}) \\ & b := \mathcal{H}(X_{1,i_1}…X_{k,i_k}) \oplus \mathcal{H}(X_{1,1}…X_{k,1}). \end{aligned}$$
The equation is now further converted to $a_1x_1 \oplus … \oplus a_kx_k = b$, which is essentially a system of 128 linear equations and $k$ unknowns. If $k$ is large enough (say $\geq 128$), we are confident to find a set of $(x_1, x_2, …, x_k)$.
In my experiment, I used $k = 256$ and the below 32768-byte message $m$ (hex-encoded), would yield $\mathcal{H}(m) = \texttt{hhhhhhhhhhhhhhhh}$.
d39710f2fedb6eb3048ae92aae3545b165dbe4900a2086802c86370a4dbe90071404c2e7daf3cca44b2e5e5b8ea5465f1875d0d10b8ae4d38699423fc6eb9b6dba93174cc9bc5bf32b6ce54b8113e522408e515033060e1dd31a863decc7fd65bebd3e16f20d24929a2b70d7a07c652838f30994ccc8248fb2b10b30041534e4e429cd8bc7f8ce7c6424e2880dcc736c2128719fa094edfd1b5a3aa1b47b212367e506e9c2f003d16be238413f687e8c69299280feda75c367abf574bac239db9e879ad2ab918d5376d4853b1716ed44041178487ccc504cee182607cec86d9d3d17f7304f9a6c86b2800d7a8ab8753ffc70c893c2c6a306db1b98e927865de0a4d3819c80b2259f3a12319a9d241020cdcd75e591074a752e327c9aee7e419e311bc5efcea24aedeb19648340d27d54fa2c61656fd705352231525a799ac4ba07f5c0ccfc4794951565cc116cf7f69f35df0b1ede08973f76f7abdf4f4d45c172ecbc0e842a831767b967f181e58107a4065d85cba881a8a6dce62dd1a3f416667d83c606ac80f4befaffe82e58e22528fea444d34664c42fb238be4ff687afa6fbbae93cf342176bc8cbda1bf6f90a39eddf8fee719dd84d7f7041adaa0ae96320527350885a619d25058da84b95674d33d7aa785aa2ff4bb300ef1a6048a6cb9dd8479f85437cf405045b6c641ca181c24f8864078cbedc40ff951766c0bd5e22fd70147124c7273fe6a7a95dfdb952cf0879ab81d6b9178e80aa0fc28b056e01d2bb7e732d12cb2f3a5bbc33834179cba8cd2806fe770f39868ee26925c0470ce27ff1f431968d6e97fd6ffc55ada4541bc65a123f0c04f96c664e3badfd2dbf334b3d975fa8427c358a88e096bcf784aa517ac64383939b4b5ae503eda26c6d4ef2a17ebed8ad9f62e1a30c3bed825614ea558078b6314a4292487c8df065fef0d2eef30d348b6877db3a6c352824c9a6899cbc5d1cc8acc8593ca3393f981dba9cd2f8def6db3d2bdcd734938e4a8fd5b69560f8fd06c55c47cf950db0055f377f648f7ce60a54497a8de014dd09f5cc7edac3a3d597a0f959fb4224a2db3fac760c0fa1f633f2f9f572bafdf22888f05978ca399f0b5679cd73aeb0ce1223b4e7ce6adbc7eb1d54fbde936e333e8f39c2ca95c46a74966b7a57a73301e081a8afacff15a10d1f9348eb1086d6d87e4e212b661eb2d35aeecbec86fe6bc69d3ed4f28a18d28a1f704f88341aabf6d504741ebd8336141878770da18517576404368f1a160f6f4a92e287dd7dc080d8ab240a9160014e4a3a6e718c9bfe7cb205c35e23405e6f64d8233904ee2e9482b760db25b577324a4f11b558faab2aa00e53273a71b2c3e685cb2166bccad1b1e80e601812c04bb310e71a6088c6d71534089f897dfe34038a5a34ec1aabb2a58b044821e59761dee806af9b98a1c74bb1ad4bc39d1710c9cd7924bf6022f4a102419c3dd3b04926816ad23d2c8385d5fce940efefc4cf3f693a02a06e311c206ae1ac4685a65485a3b5bd54c17e93ee962fc08760ee950d2bb945db4f0e880f3a5ef52536e6d11a763dec47fee50865469bf6ccdbbd78826877d010f63055bc357c54289f72b2da3011b0ebe147b07d06d4b7a236c765f03fe1e497f9fab785429a3e8e46430076772512be9ec20b05f7e33e06f858eb294d539ebf8d1cc72d4976e2619dbb3a4920589d031346a2b96791425c76c931535bc91912a1dddfa3e26616ae163f6ed99f4b4b4ccfc120d6b80e7651739ed7a5ebb839e2f406142474a3d72f76d383cafda6c5a214058d942058601141a277e803cbab26a421e4489ddff2193e1f5b167ffaee3512f3011cf2ebec028a420f4673331262618c0fa7f774cbf766a92ea3a421c00969e0e9c06e9d2bec37f36c857527ba6f06ec41e229ece26805ea7ecb8bd75b4c67c1ec2cbde984a6aabfd8a36bd908fbf22424c4601997be10f366c03c3e94f691f4bdd8210639deedd28437604c2f3c8f9b64b6540314adf9e73816437d2836b69487e1b1c35e0df065675e7854e4515967d5e1c769037addd926373343c96e04531f05f8ec57fdaf1b2f25fad5bf8ad6b2a9251ae7686202d98bb520700760a8b7cf8b4e58a745be5b37fbcb9bebd708906ce1103d105decbcbca49e66d65959c811ca93995a3b0c8c3c03691d47cfa4d19d0565991302bc6e3caa7b05d0fa08e21dccb011c8e72b670b08d9f932eed34990a09cbf32ca66aa108a91274480ddef76d43db4c34da81f396949c851f59973d4c3ddaa16392016e17b16c1dc617d9ec99196ba69f67e619957b58f6d857486afabbbd13e7225e066e2edd64134c9aebf563d5bd260c8769e838477272515f0979f15dc849530ce46727bfa6da0b81728a9ececec415eee07bc491ade7d58a6a2b4e435671046584cc5fd5187492f2712cc43172e3d5d08367ed5d495cb46245defb461efdc007f6ccfbf5f4b2147c1e49abc09742b9cffec8eef10711cd3ee387f76db61dc1d18d4c75442d5eeaffd9b51c7929921aaee997971dc5cd0dc05f4ed73dd55dc38f4236643a6eb87c600b80b0bebd2a6f75a8b5a751b41ce4a31185cfdfc6be5663c80dfc5e7d7e6501240f0bb837ca6fd3ebc0b02169d1397bc4ed59ac589283f0c1e35a35549c821ce05077824d1b213e89e87014a8e8c2e3ef21437d57bca4322b315a7eb68e9b55cf88631f773d78b8fbeeee34ffd2e3d11f1651546b5193b701ee678d9910d0eb24eadf1e9620e0e67eb2dd3f1a8cb481b33be839ec1b2654f51356ce0ba9cbdc6aa16c948e214fb5111b9308aabe67ac247940ad05420130a8bc310c8875fa8d8cbd34a34af035e54b449507c1144e4eb6096aa923427b9711c86d72d254bac6634e49051ba7ed5c72a7f08734acc32bf0aff39072ad905c51f8e39c909b2b8e3c8c5bedbb8692fc767046113f303723da43d8daba06116c981de36d3519dc48163a62c794b91f762cd2766fdabe7f029b0a47ae620348115d93714c550195d2ecd8356e25975737393439d0feabd6b04d8356f77e78b7fe26827df93670b19444f204eb546dc57ee1a3bd07fbb9a6bc566592b063336e35efbf58309691515c69aab18e43c8dbe02eb4d403ba7d91d81cf44cb158bcf848a7e0912dbd86595dbff7d47d8431e63d05b2fb0b99b9507ab13947607549b91e0cdc300e09a5f88b7d78d3c389745fdf3bbfb817a5a64ee4644c7163bb851dfe39d391f59e70cf1cfb86c8e3bf2e6bbff937103c2ce2e6f6de2c77a87a427a6603a8a801e4db4bbdf729bcee65a8ce8aecb1bdae3148803159085e7e359154c4ed8f2fb06f264773f8e7b45ca997438134d76e9bef9f6b9044c98ae42f0f6c015d51718c5d4195da2736717d66cdba261ab6fb4cf5cd959ec20598d6dc9beabeae25c14029c952571bfd1eb6c1d2c7eb6c271adb242550185b62f382e4a712e3c298e79aa30b22ee8cb12bbd9dca92855c705e251ed91faf887945240936a958d32e525d6d4e374c98be31f17bf4a2440409882708da1e94359482a1ae221213b84fd9b475f5145c15d32ad2d84b08b3ee9ba6f39031c8547f6f5f3947607cff0c8ec6f2e104494663a68f428ad25194e94aace7651611adccaf64c3505e767bc4cce401e4e0cae2da9e1faf2f06dee926f08ee1b8ad70f429c4043575c783ee84a6718c48e694927d07d6718c5a6e2b6b3826b0036a06c74c7518d6ccb3e27fa6cf78bdb4b9dc74121febc6ef68983171b9467b99c5be90498360432b7a9c15c6951ffbc897bdf24749d5d5f581b3ff0a031154e1a5d625dc11ec579fee7655947127f31cb30b20b06d3aef67ecdfd8d0f1e7bfcfaa5584b31ff3fbd17625dfe28300a4f1553524461f924f8d397a9f278deccfede2b04bf8d2fbfa5d925532c2819a707498a45afcd57b3045252e4a68615099a8de42d9efc2026837ec8434cd09fa9da339b5a57f6b1e91db491635a14ccab63c08d75ef015cb3cea40688f9175242e99aa51f05110413c6e8416c4f6b0c4a4186f3b77e6073c2da50ed2d2928c46906594bd69a83f4472588ca045ad06e1bb9dc725bb3b3d379e9c6f1141f6c4f8c5b4b9045c1f2f0b40e86ea82165c996f911890cb0ea143beefd26734425d92243ecc51cc4df2a266bf5583af5ac0610900dc387194ba5c74a6531a5c23251a41e1ce292c89e9e309c87a65bd2f6be0564320667b32859fc4e5bea4045b31a3088c1353ddc3a87895be40ccf775d7bb485cbc966581c517176a12bb93ef6cfbafdf4b4dcd41a62cc18d86088b772b97e7509516fa3aa1f5bb31032a2299828270f56d8c4ead459b57d2a5594dcc398c8e7127e1e77ced37b01b89abe24b630283eee628bc2c7b9bc5de6e2425ac0724ea448451b3613ca89bec395594496856bc8415afd5770e66eb76d350faeb52671d491e93f679d9af4d75160d81ee84959fcb5f0ced4132d6c0aa8409949667a06bb1a947ce3c8dea0799cfa55b1d055137d85777b43d6360b4c425dda4d99b1e532c687c0473d5524d186055c1a7356e3fed69931c3e5ce406c3ce2ac7c96f643cfc0aa806505019b96206e15eaca6f82d5a4d31952c388d5a1dadea02564d303cab7342f9531357befe38e102c10bc520f0a75fa8c7cbb38234af448c5c3a06ce3b801f13d89f7229b7de5636b603170b32237faf9b1fb5d9baf09931cd1deb67990c0d5c74d613208d2c4599cb44e638d1af0f30c930bcf5e4480568d867fe44bacd91236e2260fe7ec767c4646d75a6a9373dff131146933565b4a7f285ec3f2db11cb20f24ec8e05116636e7d11a86bbecc601683e9c3ed9041000129a646db7de708628569b14843e5b7d43bbd93b2b61f8d191b0c91cf7ef0e7ed3ed2e497fd19b0ec7e7064b753d72db17461a785a56529f9aedf3f3dd4e409c4a0b6275a113b2814f868fbb25be1cf6dcdc78af963c0122e812f2cbe513699b73c1634f7126e5c823abb702643c9f31c10bb540582b60a8b7cff580549742113477fbd15a7e38ef7e1cfdf140f33f8df9789f8ca2c2191d4f1ff109252d541c7d0b5e2e53e24a2ecdc725b9e6241e354047423a36909e437f67baa4e56c22aa4a8b0272dacd5f111c3edd605d483f4cba99c3d6dfb2b2a9f13db53377a7495a87255050a0d91e40ecf150c6d5423c9bab7eede3575b51cb41ae98b1ad96857a36eb9a6b59fac5f8e86c8b1a4b70e6d82cc913aaffcd71a524f220526bdcc8d23a3cdeb88dbdeb82d2f216c1f8a5519b8c03ca3a0990fc310ab3e5c8e8cfe32b9c8b5ef1c102ca9e4d3af221ad86e3bd5dcbecfc87ee21e5e7d5e641e3e100526dc392aff397b6b9603ab3fc920cb4405dd9f715c5d8585da2b96717bb65767f115b4cb08f9f894ea62683405cd113ce50ba8fb569b41016d5ff541ee2b419928bb1bf9ea473e3de788a8d335a10e9384f403641522a9e46ca07e5fbdf62a93d636be2fa54df23f45a45847f146bdfac0cbde2b72c48f765756c4d486f6e0e499563f038111d950afdc7a50ea0645f7338adc510e0bb5f88c8d33570349f48cd14ba3d467b415cee081717f73866bf3d4b8b8e3ebbaa53b12b7b6039727e68d2210920987e6273c84695602e65716a092319fe411dd234b7245b22a6de7c2a3e7a6b3e5af3f5d5934bbd64d4cd2291beae8376df46fcb4925f0c20fdd7847fcb42886a815be385960b8e59e99401fc461d02696c66ceeb299e1930f364c499da8536264dba8dd08c7cf180691b97d4230d0c9d997346e783def94e7e9548037a9d81cc2c93cce121dd0b5f82420d53aec21c0a41b1cd331eac18da00c7008f199c6b04c63c2edad78cfe40b00793212e4c0e3f2a7574c88964cae060ef82847fe73b97e3ece1a0a52b38054d2b1bbba014d5bb15c9cc287d9e459116037d097fd28f97a5ef84b574e4ad0ce93d62181551d54f5d64c7d17e4e73c5fa97d6ff0c37b8ac35ae0e46a0229e10c2132cd259664566812ae88dbab12b0bfcef70a8f958ebbbc2342052948c9b8988bac33e95127bce454ea59719bd9ac5c6f4df5964c7c65041b5e4f6d5c638129498fa067dde0c292007d15971ad7d20b73911af7ca6864ad1798ea0f1dbf1341fb7d5c74372c91a61602df1ede420995b4dc42876c3cda229840347899a90d64fac5014b73926823c49b09db3b14f13e5d5e022fcdd4bc6e4f993f7071cb7f9a6afde723566c2a4ffc077178600e78cdce169179e9e378df995db591d153ab21c957f2ffd1cfad4eeb6ca6611004527731b00708a26f63a4d7a9e243a3f02251c2178bcd3444e53d1730fa919d70e35b6c67f6776710e785c3a83cd75299b1ea86412d88c85564282e60a50a5d57b1902e74e3f37450be2f73b2e68a0693fdaa953f56895bddb220a68cc859a0241557492fb7a0eee60620cf5fa93f393d1065f62231b9dfa84d9af4b5f1c4dc1e234c92992e6aa1628b86bd1c3a9780fa37367fdd7e2e48747e60a3c471c2a80f1517cc9553579490a48f33d7e79cd52f5ab4f962313e9e459127a5eef4e21c388cdd3ff40889be0eb093d43b33b432097a7db8181861df47b375e56b5c4fe48f096e00ba13d5800cc9b6cb0cbe51f9dd362be1d373a95ee6ec5df4b4b1d4dc1f525b92e06e773f6eb966bf159cbf4207488ea5cc31452bc3b7e4102a68a620ce62d1a40a666da837f072894f35aae687306c5a65d517d0e2c7e442a2894b7efa7a909c7dcce43104bbe5f1c01747696dceb1787133ef54fc1e1a398b206a677140b5bc413015a978a44ed45ea5d69d721927849db0c514d20099a86cd19eeec95f0bef24c37ee872635c18185fcf9ded19cd7ba53cbb3e5bb6381602bb8072b0e87c34687f4678010496ded02488032c66c5d409c3d3285263639edd237a224e303f3ecc0fe72744f0a58f2902f759dfdd1d935bdb06b89358c997ffa36a8b0b97375fca5e0d8874a3632655b25654b302e614a19c64621c95af63cec4702e6cea6c61bf44f089078285c0f80001669b14eed89f1c091ca4260b92d5006041c21d5002986887bde8a8bee2fe9e6e88176f2a2068ac781ad5f3e7a71f589b196f2c1e0d1dc446c330ffe7731e7cf7d8327146bc85f7c550f53f66070ff3d812a79d4c7baf0698212354319e423d7b22ab4e7417affb7e060cdb7f5ccd92959a2cb4e1fe22fac76d5adb1d02f80465fe2aff28ce92f12316253df75615a54d460dc5ad0f97eac9b6f2644cf2863bebe95e4b3834895c7144c2d96379549b0b0649609f5ce82226e976f264a14c2c774babc751a1f6df53d8654169be02d3af57d9027f1840bf5ca0f95935381824021e04d54c6ef601d0332c9b5f0d7166048c8cb7be253af469274b5468e9bb0430e5c3c1035a5d61c8fc6d260c12598fc4617d713ac98ab1f2d6fdb457e89013489c36e9a04f6888259fff9d13942ab15a1908ee4e0ef6875fa2a670a73fbb707765d2bb28794ea2445b529fed6bbdd7a057d52153e4bb0fff38a4da4c9c3c38277f35333ba943e7c172a762fa4474f514dc1e6d0b02a923393766cbf6bd1a8054a258e3eae0124c66e71e7fe91be5f2d6ac107a6f9a49f2d76d1cb210a1c1d6ff37c3118753ebcef42d32e364269ad471fc530bcf7dabc2347596bccc3fced49d586adaccd2bbb2765bfec0e204c40d9a75bfdaa48730ec5ad33e3fadaa6197c2b13cf1659280ddffe2c166599d54ec7aeef112f78bddd2d94c8268e0162832436ddaf90cbb470d643e065d8f0ee2bfc7a6973dfa1e9dd6218463895e6da0aad6b7618dabec0e8ed6a57fba939a6aeb138870deceeedba02bbcc6b5c643a01c42c2c2659c60aa3f9744c69d9eedb75d7865ee6d601a68ee703aba5d062e22e474994d560e771de0e03fb74479c574f8ce7c19c2ebd0d74108c3edc97ebd09bda74efed0629eb98394fa422f997a74e87a5724a315b5131d93068ed2229f2a9cc8b90999a22dc52c637ed2f7a7ff5d0a49a1f59e1abe8dcc0374eef0be4bad29f9516ba32bee65e91be171b8b416be1b359fa352e5442ed91e0df99f82ef8b5f1d2e31e13964b1db72055d9f717cd58695daef76aded65b27af0679aca1af40f15486c9e21f4c10feaa1a48da8661f6378c30ead4aeb1ffd0505690d6bc6e211a96f945296c88351a12540b8a40aa18b21db5ffdbb9e53f64279f6f64cc61d91ff52bf097aa5dcd39ed4bb6e3388c89428bc502f7dacecc770905ab5afe4b5b6c7329e01f11522346461ed35a6e3dec87e2e5eec4461b0457fb8e9a30644f93000ae943fc59fe87ec2ed9c25319fef02ea3efa5da91c17c17f5829da31d5bdbf1c0e735c5ef86e14b4a3e506a77410cadb6ef2119c10aeb41759acbe3453cfdc59239c2e04d428323e55a5bad3eec8c9dc93072e57b94ab271327b6e70ef0300b652c7bb1a1f9febc097f76efcbcf4f91c341a2f2c489744aab96d69ceb58d828f604948a4cdfd14364e11081e2df7f046733ae07a50a94a15fb6aede10c4929f76c03e9ed409b90108da3f1239557336b8b53cf3babdce21abbf87e457e2953942224dcb709599ff5cd4ad346eff8c2b4d1ad8c3c74a570c498ea18ec1d95171e1458838a4c6c738434cf4fca8d550fe1cbf7577b2fe413f6da6c2900dd2a12456bfd5f0b7db9cd32349d9f120718d3b795ca48039c831972a6a4916941c1c9a772f107cc7af6ac1746840c640f5d21614cdfbfbc5e5ea6be05f67265a39de495730985ccf21be3914162c4d7c917cdc7c121e1ba1f05563cb82c0460f140c90bcabae16851831ff261d0c6960154fb70d80f576b266ccb152860a73d5599664011feddc68f5a7cb635be413b272be9b17b4c87c831d4fc8e38f8576142766aad59d7ef5e79c4719ed9632a6397968f6a88d93b1c3f3dec7dfb76b28e43cfffb056562e6a93fff4806dc10aa10691a365689e13059ef0b942e457b591ce75e14945bad630ea18457a2e94bb32038166068d8cf6d325497c6d03bfa3f105c1bdc1658b277c21a3d275da369171ac830e7db0b4043162d79c32c76780c410371de782f5e7ee9c1fa6574e52df67a1de81fb802bbad14e3d882fd5a0704eb5cdd61c8a49180b62346a4d4c7f2ade0d016ddf1beb25456f1148f1ec3418d0a10f5af849438e6d0aef7b8e021c9fbf4c8d970792275319fba165582577d4cc40fa81e5f249fe31e42d65c7ef1a214dbf5b5ff95e00601f5240fca028e20b6d083fcda45bf25ad23b8e31e5bfe082278cad33f27160ed9e8cade0498ad0b2874fbeb376a55afdd8acff64d9896f23f77db43ffae15f36ced89b823d2fe2e80ef84d8b55ce7be91d64800837c0c207927e7d007a1bc81703a0bcc32b046524315829d3cb19efce816dfa6c063c19ed94a748f08f37780ddb0560b084d6756321bbb9140fac80a2b084537f18bcb0dfe40396f14a4df3c19bb0cf0ebd9844bcae5f9a83730447df8dc40aad8f39ecb7538e8e6897bd2b598e547d39ba51d36514ae0989d3bbd095029488c18c50df64c2bb7ccca7ddee54e37b4f0b418e8c67efd3986c4549fadbc3d71b3cc8353926f095e54b6e8533f88d29d4cb91ab650a3e83e5bf478fa0834dcf0602baf8d1b4a3995d74342f17efde6d8702ceaad6f0267fadfa96f7a9627302c6b19e4b40a886b64dc2889297b0eb8fc260c4b00fd9d96bfa12cb3a9e11128333e88875b7659a4c74f504fc17590b10e042573f76db6eb70731c63fdb3610d37b83d0d381d272066184c048838b9ee853ae57da9c56b63878dcc827d9f944410ac35276c5b028102ed360c25fee9c0ef7c2e0272ef4fd24403b4cc6748df4f53f688fc1576402114ade5b43481a0368ba27f29a45d405ad5d7f8a8e988dc2ab60d262e1fc91af6bdec46fe69d67b9e57020afc93ba2a41d7c77474a81abffa39edc45ca16d90b5db4d383daac51fcdf4ac8100446f78a70909b07a6c3a962347e8e860de647a79c6e78bbedb1cb3f1f2706eeab0ebc1ca03ef57e07fc93266f6ada0cc9c2ae315c536c1f5f286f5bd559b48079a7b446df1492110eb1aae2799038636f1cb1a86c7ecc7fdef38259e95f20c08c3a86a41f7b6e075ae3bcbd47dcdf9ffa3d11bc8bd77779984da457a9839f9c35025073b3c954cbf37a7a5cef734e54d044ea27abd6ea88f09b914f0f0426ad880cb2dc5218b35ff4238142444284e7376bac8dfe04a67904577ab68b1326c162e8db0d61165d1a24ca69dbeea21e61d67c91a8647ecc6e16bfea5be59f68ffcd35a885cefd758faea1da41e8abfbddea4fc0c06d748e712eee26422bbbd4bf335413e29aa070bf9be389784f7b74c1688261a7c49474299b794e806d05eaedf87072cd09cb37f881c7dffd74df6e31c7098b3cf83eb30a79fdf4a627578d10f1aab1495635c81ef932f15ba547cdb91f92bc30050975f68d8cf0d323897c9023c3a47c83b3808ebe5d4450433c6d172f615ae93b2d924e0125860dc1deca6cda0d5b73483c18eb3ebcf32018d42f961e917ea7a49512a28c90603e3cdfd4a02c2c7ff469adef3c485f656bd01283b863b372ca8f9d3df1f0e334ed49d1ddfd9eb9706fbf925556081324c468ae93e2122c53bf5c8d17179b2472f1fda272d83e45775d0cf45265eaabddff1237916e080456f6dce349df88f3ca67645813f45f4f9836a44b7a3b8a8d0fbc30de9b29e7e4776831eb4873cf8dde001c9600208480bc4cbf987dd987f941b4d7c7619c6c4e1350a4d297b14060264a701627d976ca52aa51c4181c45e781d066e0546462bd15aee49ec87de6d306b261b06d7da7fc88b38b7f09c45e64c31e6ebe034b3eba694476957ca656e8fc5170d10a3a720525a92f224597e05e753f75894466d4e0ace7fe5b81a8bde29dbb2e572d51c08ef27da31da311b44f0dbe8fdba1e8d557962d31516d0779d4a28cd0f6ddfc391e96179d6278e7b355216b68524be4022c9fbf4c059617d9e0151deb627bc9ec7bd8fc1afe3417facbaf1b5358adf8e221165adc9f4b5e880769e3935c3b40fc32f8f4e2ce0be85d38cc3dd5575e00e6a144a443dc77c272d94bbc8123c8a1e498bcacb3b01288d7a7d9ca9713f299d8791a2f53f47b91aa96c2fb3fd606aab1ef3fdb3fa9045a5c4419419c66f84800d0c691af6c9a9edafbd0fb7955bd1d8a5d64709729680c2ddd0102d07a7d4e3f2c8adff67012bc864124087ae06b0af8757a37d47bd5b6dfbddd494fd3842af793e3a815a38921cf6ed10fce170e92dd1ef03c261ffcfa774fdf094f3736db65ad6325a2626b09c6b913fec0b8bb45e8f76ae9d13582036bdb2f4b6156ec33edc0a29a9264c6bd19f250fb210bc922946ea4bd549873cf51ce6dc040fabc4d310ef264a6660ddcf28ecd16c592a4dfccb22f6c67f5504e44181b36fef84ee706424ca79b1951aa1d2181daee5726e12bc0f62fb41e1299e503ff2cf3d5335c4c2d857e4f20706fd885893aed4b709089e497f7b9427282ae946e5e04af9f80015c51714c9d168799e4d711ec369c78ea5a390d1af911e7baafac1e395fffd6e02c0d9addb3c1df60afbeb7805b1766246a56484d9eaf43c10243796e84e8b02b84bf63882ec10205b03bcc108508a7fc46b0a613298177e598046fae13361fd22f05667475e28f9f32c0247d5e65bc17fe9499d3d4d6c4994a7dfef6770d8a1d04bb310c7366088c7d3532654a7071c1cf54002946b08154ca533e0be57c467ba123d1db50b93fd5ff85b51e0a0c4365ebaa9f969ce937f21705c2e88be274a2533523f326da624c464d5b4cfccc4d7778bc2d41b2c289a05d4d42e2c701fd0002bb54d816d754ddffe3456084194bb519849bd3b636a7403c552cc377985763df0b8ae564c7a019f1d37b363e78fc765a28605ca8dc85effecac6b336cc5d335359c98fc4b655cc9de0f05c476f2bd4028c24e36aa36fe2a963c3a194b6de5e6260e4259442c950c732a01bb78e3b9ab4706461c1e1cccb712317f25f2fa85bb241b958d834e768493e33763eaa853d455bf00ccd4a2dace85357a97780ac1ddeefca6274bee3cbe2dcfb70c0d0ee62636934de28fc8957efccceab4c1d58367e9168af4e874711b053840555a38c27e4fb467d7c4e7852374897a8cc221951f30c63a2eb5bf433e62a90ced50aedf0e6f02ccf9d815c93d0c8cbbff12b57e9c9ad2980dfd982a62c89c578c470379f91bed71cbf3781786bd5385df6019b32109b330f80b60a8d7d775882497864df675fb455bdc5ff8900f820ba1470e4f899f0caa90d16198043ca0f1569319ac6d13298fe854855924c7f74e878f12324c1d6a3759aa9c3058bbf5adee526c404c8f26edfceaf3ff7d9ac21c9ee02b6d3fccff98bbf3f31b5f5ef0a6e3ef0cf3252167203f1535024a5a70feb20978e120c95bf4ccd9685db2012717df290cafd05d87ccaf8bf97ec6bcc984ec8c7ba1b1806307f456d225d7cbe3a3d4e7ce85e3cc956886bb9f6a72bb134e0b62041b945eee43da680cb70533fae5ee4c2304376bc6d3539117ee79998376bc38d66528beca9743de43b27332e272aac99cb903adbe3d04dc73750608765148c185b84cf4489f46d1894dcf71aff67b4ed2e2475a1539728530b99ea32016b1b6d6438de6938ae69940f05d2b8b2295488df8aff87182af4ab6c0711bd04cec85dfcc4304a6816274a81a3303fdb7e44e2d4c780b64d9f932a8e1106d4ea05541d90e3994dff66947a4ccb5cf9f922908e6c97e6d4fab09df9b27db04cd8d0af5452ee7d15a06bcecc6fde7689d46d8f64a08bfaa3f654ff8c866e628d4f4b143cddbe6ad103c4fe163a5a08183bf732d78323f4cc9ef772f1ab576f9fc6cde1b59d5b6355237f1b7aeb0098eedc7e16aa4756b6b1e6f82dde9872ca1961cdeeb8b26b2bec131538fbeb461e7de64711aae3998035554da9dd7ed74b6d6c20bff7d2115d95b16c9d0697d9e8d799ee26fa692567d6fa1cf93c153aab1fa4eb62e9c61a81c52948ad1749023e3ecb22acfbbc64eed6d013844c67b4caad4eaf48a195ae13a363a955238991c21d2aec45a456c85472c5cd2de6571573297234deb555d99a3bae5870aa834b6d48769cdb367b39fea2fe18dd3942704109db13e13c616ebd31a7e39ec06e2e50e2ea6d6f45904ce688f4c6f5f00d66e3fc17a50c11ab8864227be4556cd1f5a9b4c5f927c261f41d0f84dfcf22a1a19c54ad5f5841938ae198e3a268ea341f9bfc30ac57c6d09a247024bfab62fbd6473e87c50db787c89d344ee4a02ee2ddb6e522a34952812d875ce36c8aa1fb55f331e5f10de0c0b0a76c5ebcb4f4c43c1f644bd0982259b76ddb66b1188014affb9639c694aa05b0aa6a34b485ba20d820e9a608cd28da4197490d15a2f57362021aa4b097733bcda2372429d3bae0ffe18e4e5d9f073dd416f503e99a9a74854397daf9d96fd37c1852cacffc9f6a3d59c0f2d03cc33fdf70786237bf0ca8bc47f642fc6fb52a76b86bfef575f6163c15d4ac5e9f46dab3f56a3eb78c832020d2cd1376d0c4e0ba77b7637315e785d53a90ee2e7c5b57fa21ec8a7564b9b1abab8c54a8353728e17627e7add4d9c29f8b80bc3eed041ec14ef07e91c01061f409ca8b3c9ca4e56e023412eba9147bf5ac158321edeeb7e0557c053f7d91bfe053f9447a43abd362d0e05b3d7c9c694bf1d177beec3b4c9663e8c156aa09ca5bcfdd002168dcb1371d6d391f2568b21e4afbb434be01b182f193fecfdf4e5f5fa7c402f6676def91a37e679a2a60fa7f51ba318eb5c90ec90e7ffcdbc1e14e150b89b38131fe38d4b54c7be2a1cc425df1d4eef736a56714abeaecd0c9f69bcdf1cd4c745549f660c2895b015ce04e5aea167b2433bd4c4089e4cb9b19958cd9bfe303a03aecac3b7871e79e9e5552da809881c088200555e67f6b36ddc36a7dd102ee4145da5221035323c99d437bb039bebfabcdaca434e67dc6041139a66d22af5baeab35ab4f9c72892ee1c6f5c56a6b5d24d1d6905d71b52354da7dcf2abd670e94788d1480d00b9eb67515ac18d1d60b76ae98f4c680e3039da8fb0297dc278085987d923f05831cfdd42969064178aa8235e3dc68349387f17ea3e8b4cdb5eb607f96dde5d16467735ae8da6924b13edcfe04bf495efff5c3428ea156d384f6de072728d0bce444ae12e909bf59be68ecc20e3f6b397326b43712cfa58f7e249db174e9f3f863bf05f5f9d23c1699cadee06a5725f1a95e7b804c7db04142891618d88e3b08e11dc6854f369615c8b97fcc94ffc07fe599ed2e747589b2f5a7aba8bc1e245292e8071cd9abbf5bee0c5034e200cc9cbe3bf3bbce931620cbcc2b3b9ffdc7820c11e6bb76d3738c1913f317399b0775a839b20618c5cb30f38af14af0d091cee9c3ad6ca6de5eeedcffe1d31b953a7fe3c396a8cc4159fe1c45871cbd30388b0ed27658c1c0bd3742be7039d5fc430fdfc619cc9f16fdf7e385dec07e6324528ca7a9a680ab0d12ba302c47c2e4e72cbc53e2401606562cb9799a0fa03ed0baf741978d5cf6218beb786d181a7640f79f9e1c0cd74af46dc32596222794161cd5bf8c0d919799e4d3b16d61b59a7a1a575d10f950263a6ea78d2fbd2b022abbde0bd33fea8bef8d060fcdaed526262a13ac1726c6ea7ec0f5ad9fcb0f29776ff2139c2104e8abcdbf9b7dd7274460d4b306222de957403c392b8630a033d347dadb5da163156e82a342d4bcc4148686555cfec21f7dd5fbc12adcaf3b3a054cdf716cdd9705d2e31811edb6a4a7f649984cdefae316fc6e62f8b170d78d626a36860dcd434286a1ba8ddb211f39e210f9c927770e5e0a401f0affc19ebbcaa4a4e44964882c7e71ddcbfcbc82427888bbac71cc757ed3266ccd12d6c649d89f0c0c01bb5dbc5c1b48bb700671d4a256ff8fd8586b731362fd84b26541fa20fcdb5e0ee3a6048a6cb9bc803af85a2767906825acd2becd2254e87d979fb80ba59d040309088b993750a7cd989bd1b8aa396c19aa777b467fd1d1507b5dfdedb36164076ee27bde303f4bdd2dce567f94fc4441cc3118f6304fc18fcdf99d51867339cdbf69aef0e03a093a804be841319e9a1f62b4a7c0d4486b8660f3c201dc97b15cdcd695d9e3b711eb665c7a6255987d1efd7957ccaadb81c20683f0ba0091f371cdffc17bbf3afbe88f6bf5ad105662adfaac40682a76b9b5704478c541f2e7f5af34192014a15c2c7eee28569cf253b1b11925930964d7be3b5956d4a47f1d5efe2d720934ee5a2f9f3fc7ebdba33545a642d2c25237475b5169d311e84ab9f5b5f4dedc1ae8cc80e86cb72361d9f6fd1731dfd0286ec9d6375cb8cfbb6706507899d01e302fe2ab82003f84a5ce4b055d525f793bef7b78ff29378f14b3a404df5548d13d2f5c0d8ceae43f08be8d041f4c1a18d7ea4add98ca29777d7e6560d351c9a186fa4e5e3cb1dd204d9ca92f4b9953d5d4ea591c225792119cd5bf7c8dd3079b20d871ffb39467f96898cbcafd86a73ec5dd0f3b5405aa6998e5807e9387c39bfb6c61935b9bf8eddc9cd6360622963d5a9252ecef47998c520ba83a22ffa9ccfd012b7e9424beb8a0b24f02218c0cd4eaa62832ff5648e2d440e3aacd5907e2d714308a7f85d60871ff5c54aa3f9a278d441153a1af5401acdd7f7c0dd5879aeb5709eda2ca3826495b9d1ef2cb26c249d41a22194b43203d6ce174b5310911db986e853a80fb15116d3440959ff324b191e6b5b28ae834212ea7aadb013981251150de13c6313af070cd1419519027c4b9bb2331b6ca75ca24064f1b13f7924429a357ff49c059f3f6ae7ef6f0772aac7e148bb13dd0eaa767bff4b4f21cd413062c18af204949f6690e7d0b0247245fe74000dc3ae24b174de8fb0c3a61cc5aa190a2bf7c98b17a2eab0d4f3819586e9ccd5a2e0d477b71b724456149637e68bfbc4ed3e8b06dd4bdee3e1d8e3e55493d3a67c029555d7dfecc9653efd1121fd475025d90176bfd4b2b46935963f53241d003d05e62e21d11a763dec46fe654885be56f20b0481886a70378f4ce2ee41001ee0748ca061d219fc28b5788e5360d21d09467ba8a64eb9470d513a34ee185109ea2b14b18f32b2421a34b0a53ba12df0e8406678004bca44619907737b20310b0095a76e6e9552dbf70195cca919e89fcf8cea2c5245e54dae2b717efc933696a70d3c2f2c1a65a7964bc84dcda58f3ec4d933f9c766a6c911a0d44d9cd52cea178ed7932c93ee49eb05f807fc9b84f89ca2502520aa62287379a6a7b5e38432c9d01841c91d52396650a6b276710ac3c7fae24dbf8b5e5263dbf13a6f815b9699d5fa174d016b33920d4c39a0a211bd702c5a729aad21a7443f48d11e1ecd4779038646add31afec6ec07e26f40a6c698f44e00806a675d6ffa28fa6c41a6760cc1c07d6e12e1a83daaa35347f50fcf497c3bab386990cb062626241b45874557dbaf53d8299279e9d0b52e95950bfeb968aa2ca2c7054641a751b04325566f55caba3da8ebdb948ce1dd48edb7cd180b2023159f67b684c489d46d7be666d5320bbb0022d9b7f7cc582a5d2ef782ded519469305ab8cadef7c114ca4051979f1d23e84a1b9de1d62e219c54c8185428072540e45899ec6548c5fcd303e70372edd6120be23c238653218aa7519ebf4c25226bbcd6be05b1b2e7a0ea9b7b37ecb69a2c7e6123d585fa6efb2e800ab7c20c532de850bd2c4f3677b1463944d60590d060e5ed11a863decc6e16538ac465a04cb063e587368378f34066b58674f521ed8896052d2f30e099be96d03c541efbbb933d6e61844c6efc6a603c69db4943ffac8e51e7641ba07901cc5681c03d3eccfdced6b44ea1be197de946f13438967694ce370e58c84c3e8ffceddaeb0c98f30a4f87d7a9eb4baecde03bd33b35e641812192bb320cf2a6088b7d7bd30549744d1fb393c905af90feeca9f54b0f8ff658465b2ac73ef850096f1a29a6c4c13700e071094df4375e37512e733a809ec9607f81916444d873e1709e803befbca2ab8f467e65c3ce4d729121274e11b48364ccc524704eadff53cd766cf604f6e7e2788e350763d4fdd1c1c17ed8be2689b92f029b320671b60a8d6d7cd902897c3c0fdf607c89a64fc0ee5b69a4d174d3f0b733166b603adcf670e26091718e3d6309b3b7f2cad79e7563a8e2fbd89ce486e3a01ce775dee299feec7eb09dcbca72e7d0b4a745ce6cd5221268f9dfd195c0db969a5cb702d292ac2704bc6d70489af99137dcf355567ee3ae6c88d3b2b3be061cd7bf2c8d9717922052f97e2290d8f92c199c4af30fe76c6cab6b9f14b2f5e72d99bf49e7d771466dfe7cfa0110063d6fc6f15293ba5a3f7a122b14954c1667640ca395d110d3b4bb8aba60c706a3ecb6fc46afaa869847bc574f4dccac59d2899f951dcb88837f207f0e709f704f0097b5b9dc891302e38503475d609fb8056d1db14cdd97059a2c98f1fdb65ca82d67b49c0cf90124bc6a3c303729a8eb7bdbda12fee230006c47377aeed99d082875dadd9e0f9373fb4bcab12d47ba6eca93982773537b60600e20b09e64eeb3b6f0f285162f0990d8c8a9faed04332579b52e5bb640f2771e9a34d2637879d1e061cdbc1f4bbb8f267519f1061474c811b761df4cb4fa02d4161a2b16ef62474179a90679184b1c60aba8f8de764a6c9751512384fe980e5bbc64ee4f68acf9a11588eef7a41d190ef90c72691397baa4b4bda418ee20945c631cb0cf062e8d0fc4be2d9440008f760879c118c9380374f7e377012671d58fa0fe4cd775f6369fe6900a2715b52b1591c8fe5e1fd2516aec91a7ecbec07feefeea24698064f040db87f752f8d40852a39e26e90ce5329f5d42474e0c99ef3fe2258cfa9d3c9aa99b5d26aa0943f35709d4aa7f98619102027d679019105bfc0ceb308ce7c86012eeb39e73acfe9b44fc667098c4755b5eee969e9027e20fe9722826906e1aacc367cf6c73591c6c41cdfb10ff2eb4a8daf84dbbb4b5f60e5411948bd8d870e8bde9aa167318b3bfa26f6583d49be9a4245f7be395c5c1d6e6b5aa3a223f571df38547b588bf1e32368ba4c17b1c42525ca317e408dd5b915a8c0dce8c95875d4e76b0e51f29d7b7a39024b1333e1c236a373a5c73dff01318748c0c1d3db2d468c6d01a6f8a540f52430663653157a6161dd57f5c85472791e3593deb51a3293359d6db10f938e6f620006d47f62cd0c1bcb564c735fd78ac88e5f724e73007872a1f0e51767bdb24c37b98d371fdbb2f005463886f2a5411c87bb13c8da604bfd4b225d9b869db91d209e6e1d7f728dd682ddb58b3582f9717a7e39e058112a2eafd9daee69e1ed79cc38b13a2bf70016c51715c9d1717db2f74697de72738f1061acd0efc2a173889bd0945125c324093b1e6e83b7564649cbc579406f10e8b57e97acd0c461713775fd3c39b9c477af144e40f1ee9195cd57fbc3cd500ce3e96fc6bf1ada8bc24d1ada393b95321692759175e2ec0a9e44ccca9a724787d00b73c60506c5f59d3550a674722ebba019ddf7f4c4d421591e7f3116e22d796721b344b10f80ca5ba4bf12d9ef3bdd1a1e8b9ad7f566e02cf394d92047054907785e75045cbcbac48d72da14c704891fbb33ba38c6d2cbb9dfe1cb0dbd4e8b0a4c8bdc6b42145a59b1295b349cb4f6ade6e57d6915a4593de34d532135036fde7217600e3052b8a3a03ff76be3689fd1c02bb340bf1b60a8b7cb0d44449f09df7cf640ca9a2cac0a99a38221f71695aad42088bc339878ee01ea2a7f6f13acc5e3ff12f02d9f892f7192c45b742b21c30659e639c147208bb5c6e1c4be7eae393e4b30e69cd4e31044aa0126c26019b62faec87fd6d4f8f67091d1848872e8cf7c19ae73573479c83ac117aed460df41eaabb330c0266088b8d77b3214a7c6cffdf83f0494bcfbf9c31015c54978353676acaf4c56e8beb80bb7c4f43ed34abd576ecb75b79a6b508673e3990ef5875e33393e3a8a6b3c13f682b3b3e6c0ed26174f0ee4d4ea31481ce9ff64bdfb32b45a759e882bcc331eac36438d492bb515af2794795b3acfa01bd39de26e5c9822f1adb310f01b6068c7d72b6c64a7c84bfc3aff499b83c0f6dab9edf9f04062fbf0c700ece4eeb4e96389bfc555678ca09343dc65a91c6261d588ee1891627ceb36194e7fce928caa361fc2bbeadc2c28d6efff67fbe96d72b21d604b52e24d55b731dae776416eeaa73d1103222af49f785505d5b0d54bfabbc5830539385ef2f9abb510d02660a8a8cbfd421897c2b055794184931d08fc872ed22723cabb03275fec55a67833111d61d3178937dc38ef9dd120625384e5bce7c226138065131f446a8476648cb57469fb01cf524af781eb5d4c24127e7952af763d1dac4cac0372c760aa7d8b2912eaadcb7221c6a3de240004e2d480d4fbdd506e483bbf007e6cc5cf4b4b5ded41b525c98ef6c87377e7956bf1aaafd042b20480f774bae7b79a10f7c924b94c07fd17d5a0ab9d57d7adcdb24d9d82c0047c5a79e5743cbe3c1e463f114e4034a15b25b4c872cbf9438fe6fad2f9fbdb979dcbeb956d29659dac4b2c81ddbe57ed65283cc46ecbbd0e88cd1fe41071ae1d8117ba353fe14e3d146debe64f6e8d8dd937f2c9b7943e06a22a119a857c9e1ff70828059bc84359695f77707a6b62a9839fae75b49d462d34a0203f516f69c8ba003afb923c778b4ac6410a57c00cb502eacce44c65574e670858d9c6ed7a8da8a63f592e2b98fe47bd11ee603ac167c3c6f594e3dd6a5941c0eb65f4dd31cc99533a1848de32c92bc52048b75f88c8cfab2608a704ee3df647ca735d780b628f8be59ed1d4462e0485c82e38e37868cee7d8f60fdca4aeef69ccd36b74e95f41055179736390f7303e3cc5cd8923dfa611e2bdfc5f2e6a670ac672ce25077533441db797c3440bdf446ec7885f37987207048ffd65aa107f7da3680ebaeaefc16f1ec9401942f20bb340c80b60a8b8cf5d88049f87a13ef53acc9a26280d8fa5102fb73f24dce9233d0e5620f23f64b395dbc9341d7f7410fefc366b15a6739d878a7465cda4fd26ba817ec5ab1211dafdf1d24ce38b83cb4d49bce111a4581051fecb74881d43586a79afa6b599ad38f2f439eb9a78b02b8281534ed38ef2171096f64cd88200adc310f08a5f68b7d3732848a786ac13b606883ab4db05ab1361f88e0f8ce28ef218b467ff2a7e31f1320bf2f66c2b4a6fde6681202700d368e7a37df672288250868345eba8acfae8bdb9e6c9a48797c74765f494f7615a30ae705519938c228fe315300a6c8dafeeb8374d32940bfb4b45e2d62fea1a37c85682e11d3d215ecd3b17c95d7279b20d47d7b56d6893719dacd0efc6f655a8ee7d9467c301cd1aaad7a6e9347fceb7cef371b7189dfba72583781afe6ec88fb07002e4767ecae54ec63fddf70d9dc2facb00cae089fb638f046df2c9b13e4d36507612a5d813d10b284f80b21710d08f6065f9d6c32a73916d52b1195cda2a9e79855617770056c59712cdd5715d1e7d9316e25be67622836fc10fabc556c6d8b41714c99ecf62279b4e5b4124f4587e80f46379f7899bc04615fb08b919bfa71b6cbee22e317a52123985c927b8ebd49d00cbe8e7e59d87c4ee049591a765cdbc0e8c447275f46f84e63a0fe22d86154dfc441f2a900b404ebac3b4b59b40c5402b34ffc8f8597cc9dbcb5b21c341b5fabcad06088cfe2d97eb10fa78f13ceef1406d9bd6dfa5107fbd65bd5318e73c54abb38762d4e08adbbafc3c2e1d4cdcc27deefe19f793fac57a55891630f97adbb2e3d8c4176ce7c5c43496239afb853a74952b143dde54e582329053aae6e36120ec16a40eb405611d0e23c168202a8fbf5307461e9fd35a7eb9ec0602eaf8bd46daf6490840aa805d6f8ed8856c558b1678158544fc68d5092853579ddb16b9125890c62a14d9bcaa663c78914e50ef34c7f910737b2ec67b69aebfa8fad5a5f6b868d04946c7ff6232146e8fc895bb320693a7bddad5cbd563755f05361045cc98de9b90a71b21f1e42f9818e7a415f045d92ac74d023d643850be1def8d977f5a8fb33e282690499a872cffdcf0ace0c66ed703818ca4e257321e7ae9c5b9d1c9d8f614eb49fa7efa43aa4df9a17a0ed030c6d0be007e81956eb944e0ff0b05ccf809d239eb014f3b86b75980acbba023c09e8f2c5e9b4006ee591f2247e9bc4fc899951e50ed2a14ef29a4674175bcab1a89f9a98679bf475f4ded41b50cc18e8487727e9d9aebd8e5305149ffee6e392a8aad75002c8aff24200efc5bee33f203b21f9fb56c466e6ad0769aab32e89519bff459244e42de2d5437239a0db5dac26334894b1ec5db0738fe51b818ee958c9a7518885deb524396a010262034897014afc97f386d17e92fc08adb64ae2f529e237a7eb7df575b8d4b41e5b4b08a0234a3fe57b6e7d029ed6041062d5fef68abd2b51f661c65b5c7d4004906b00032e735bed55a9bba4b287146b5f161a8fffe75e50b0e79b28621be94570916d0e29ec3d1eb61bc7bf0f9a1204d7203d96bfdbee21f027395d38aad02b518846844a1e978312afeeba9797d08c0578ec10a3b0119d937f6c0505a791ec79a56b6175a937199b4adef4ba24724f424c9457c1079bce5a6208b9fb71fc26d6ce1a712ef4a004456675a871de2cd6e2fbedd2e714df01f663f2e8ca61cbc810da70b3e242c854fece4f4f21d021d89763035e5a0ac4aaf669a663bc8255fd663163ff884da61f3ce97a9990c048cc607d10a16b5001ac9f7f2c051617d9e859b56c219fa76c38350bd0f742d5ba8d43919900a739af23ce3cc600992f8ebc9424dff39f5d3163c954131eb8d9a3b2e9377fd8c97fd40090281f2a71d9a9fd8da09f062c1f06c0b2cf64492670c87ff0c53857faf24e27de48c13411ad27060940e259cf403b2bc3920b562f1f37e47fa2426423486ec168d62674a6b3dae459fb65f5194c8875655c15986487d9ed57837d185c4b3576d13ac6a2bbd315e5b17ec1a77ece535acf7d01f6b01d6454caad39ff44143b2091e82c66a2ba3d6cb0bfcbe6a721938e72152fc24948f72f8acb150ab130ccfc08cf70f57e11633ce4cbbdd4cd1fbe3a3e92149affe533e32afeac605460eaac95af63cec4602e61e7c3ed6041107147a84603793ec0a29d9bb718269c93e78347484cc1448ded5de258a1da3cb1e551bc01a5a65a2aa227f2a37952df42ef2517a7c2acab29935e5a2cee54ec9fa5fe723c8821c10e12c87ac437e019fc51114069801f5d8d06755e6650222882d1da711e000154f418120156ae2fe33a154d13716c1d9597d9e4d7b9ee25d3693567d8cc1afe39d73a8f2d716949251a156178ed8f1f750525b3c7a00f1eb4737b08736c4a083c057caf0ad95dfadd002a8016e428a068cbd1f05d4e6eedc08fdf48b04f6138f27d85c9e6653c64b207de050cd5d5c8234584015fdd9c92e65fee661ffaadf5653859e89b08da71b3039ee2245e3f5cab70dbf654f375591322f06ca861d729b2cc71fdd34055b6fc07301f41e985b9320bc03660248a7b1e8a3569aa06ec6af531cc6f5182f2a2103a5703a7283e58ea6a40ac905bdd14acfcba3e769691aad6598fdaed08c260b2994a8088474bf981a26b05bc452a71d98b21b3224b5bd5a1e2b7dfd5240e226ce885e74ff7f5f4f112fc1d970b00d07ac8a57279de71813daf522651cc0b1a0ca4fd5a458aa5627669cb9aa6f732c461de85471b559e73b497560cfeecf00688e03474bf23836f61788d7350cf4ec388e0a47871054f9d6d34519b082408fa29b541bb3a48f9db17f4eb580b02b6a0d1bf3ca4aa5cea2ecbdcee3ff4f684583f8464df0685c85cec6bdcdf1bf36e5d512eb47b62c49b29990165ce6cc321175c4d3b7555efcda9f01c9b184e77f76517e8c1ebd497e4e677322786fad15548616ddf82ec2819ab116c30f42dbc9e1ca670a600722508285915dff20c050a571540e2bdf874c9a34ff090d32d79358844d647d6185205f94a5574c21f10ca74cdaa1302bc5f06faa5f48c7cfcb10e4afc35f36b6088872b267f15e63a4f5e06e2c0204ffb52adbe4425ce813e17c21cf6df0e473221ec7ee96556bcccc9d984989786b352683fd6376a4b3fada01f05074ef340b0af954998dda7c191751adf6702d0f964cc6a779d5e636ce7a8e55ffad0e61571de8828685bf7643dfa2bb7cd8822f4dc3f0f6965f48c6cfed16449782cd3bf7fa0b3cbb230512c63f1555ab41092b2a1ec70952ed295d48e65b4d14590d517ae85e355207cc349de68ad9c5b25c2c386239a6179ea2b37a0d04d2d27f7b496fe2403939c44d8364bd95a9b06d659ac5cb0339eddeb2c333ba14a1c5ae0daf1fb77cc757900e414434a21727f8c019c9d7f6c8d970791e3f319ed62db1a226bd71c1cfe3aa6b08a29bb8e1dc9d1e2e9327205a5496b905e961fc029706e44defb04710025af657d64a3d4e8039c4f416723aae8aae09e509b2b9e77a6e028c87306a039e6d584512717b3ebbf83b555e8cf24914ce36376a816eee4a22b4c72559a7bc45e42f8e46bd378633a626aacb1aee39ec86de65168ba6db06cada0c988a50b7afe8f5b02bd54eb4b1358ee4f8e0e415505c7c8e5a3e4caebcf110b2936e08fb6e93cd79f493b7130330605f1ee281995818351e17f202cd7cc46991cf054a61abf3937d32730404e3d374cd8167835968d9348b5c38fe9c45c8257e6bc48d4853acffb545f1ef17ccfc3c1cfafc7516cd0a85be1dd83340f9b0d0085258353a98c88edcf530e7f876d3a333769d8f650d74088441d375d98a17bcf63d66cdfeb64aa934bad5c71c681be5af248a826ed0a30d25c3ab16ed3e97eadaef6ff002a8cb4044ee9900e6370f4d61f8fd78788805498b1a34aff1ce3b600f4244d4df0796f9cae7d6ac87f33e057a7eebbbc75ba067416d48bd6d06a88a37169ae7f85d560371907da44beedf792fb7c3f1cd8309d5a55d02c3470d44d7aa45fcee33a4b6e35e7c8736cc9074a16227da81d9cffbaa2770c106cd5ca477ff0bc04f42c8c10dd1bfc755be383826569e265b796c5dac40e4fb226b996bc9442da3dd9ebd88495b4e623e631ff9e060d91bf3ccd8715daeb94816c22b685321a3acb1ef622575a8cab79f3b63443adf791379832865e5af0cf8919b96221044a50a33edf6fb546c6f33dea7f70ae8cd06ee787ded1390cc82f3bde23f2b4793ef6d709ce3396e251eade7a7be272641a2caf947f4e79cad786fa70deed93b3f396a8cf0ba8a125ed7c80b22f7da1e4b6cdbabc74b1c67415c66c5aa84ed933eab9febb05d80de44102b6347244eba3e9ffb2f510152d5a7baf9515a61d4fca63c2409c5f1cd2a0fa2d4df6ed2b95fa338727b763098a054e3e1c2c85a2864d1e7293822f6874541f6759ccf51ec55a039488e85076b71c13b2176cf45e0aaaa017204025b9d86513647958221b5005ec9f715cd512a592e0f29defd7f29a37471a4d12fac465386da4d419030c5d8a42a60a866a3ea9d396b947aa327e709228a389bf4703e78b309b8aebbbf8fcc282df6789db33508cab6bbe5e3704ea2e8eb4f5773ccafa47932d261add0f9bcec4ecc3f850704f04a5cfe21c34ce8e4258966dcde5b70a7926284be3d2a36a11ae137f3c0dc617d224f5197e21bd75d528178a48fa1996664bac9d08bc766672338a4fe4c7d6c5db3a27f458b9ce852957bc6d2d1cf868e3facaf93201171bed6077e7fe212c2b2df11e1f6c5dccbdbd9cbbdc752e68ff06560b0c26f9a6d6deb4c5b847175726a7be4be158bc9aded16549d6cd1e0bf79829b9376a5c6824fedf608b2674c2c3dfe5dc77a3c3393ae889266451aa148315cc24c327fcad3f322de2e5164ad83f4972666fe5cf5e0d4e2875c09b9ef105f1e61699ebe8d13c501422e382571421989cafbbcd1e091dfb76f0c5552cb1fa218d9be846102b3bda20260089dff06cc0520513540376dc9b04d2cd387ed407d32523d1e4d316636f1c91aee4cec87026e0e84be9a0691df90987f70afb818122d57ff0a405563aa2971d90a157eb16bef4ac4e10173f645779823ea0d28f244c8d543492b58c7c22137b6831ac6f53c8ad102feef50c34fa4cbfb6034c90b826b1cd3f7715023f6065842d28f74f980123ebf0b75c286cff2ef5e3de0b94ac325a25d6412f7e545edd31a06cbecc701f0287ebe99f40be8415a646d37d8b81aad03c00d5a876d9d5fec49ea1c59dfadf33121287431380386d8f5133897afab42520749486a4a40092ae27a6e711688f5feb8e1cd7e70220ceb27f69ad257d36b5e490ccf3e4604433316b9852a621881aa1ad491bff2787fa3b035adb9efdc4e502762db10744015dd9717c1dc5979aeff5016da6be0521095b1ad2f9d2260e8b9becc13ffb822f12558d15aff0aa040304125b76ccb68f1b4dd0643f880cf0b0a38515be22903555c2a79f1888abee8e5c5ffe3b860cb5ae7f9481bd5577f8d88d5dc01ced3258a1fa71077381e4520dab12b0ecdd5b0d9335c47b24345b71359e4cf5e782202e8a9b5103f3760a8b7d3fb3a48af02723cf840ce93d4531ed4d0e470e77a1792a66108a6001a8ba365fa32a78431d4ed25784e4ca9ffe90f119deee04ff4b75d662a9679a5e697060c0bececcece36fb05cb6fe4b3ea1b4d5f851918a7ee03a57e4afcc8cc588dcf20fd9287648ad656cb46acf074752caf08a0719c16d07a001cfe88f476cf971ccfed3e761bb53b7465da8b19828df4dd9cd4e424a76dd543db715b0e73aba9cedb4b4e5711bc5e405e2d0b2aae37282591e48fbce9adee935b4a8641d6f7b6aed446acc3e550903eaa4f083831c1a16c155c6b9a6cebf67e3d35777754bce428c6ddaf0ceb364ff052efdd35da2939fcf748d7cd17c495381dfcac7b7751be4cf09d37fff780d19c87ce3c49d2a314ba7fb648ab5d7cc263a3a155def430a89a3dea5770408a5796996ab51b83b02fea449e8818c8df6c630a577241c683a0ac0afc13f4eeeeedfd086768c71ca667117af5ed33a32a3e2e3bfe9d4cb1c274b81783563c6bf0741b7ef162a6a0b3330d3a48d7a5e215342122e137f5cc583159329141dfda15c85d756d48b08fee4e4aa8fc6c7c335864c76f4e65d04833cc2e45ea410e49c0d9edc0e5301f36f1ca8dfdc99d9b57bac9d78645e643224d26b7989ebcf5bb78ce496867fee2131c34954cc48a5c48bb248cc05a2fd9819b9cf73032416c1cd754dc65a389be1d402d7317b9873967749bf120cdc30050965f48b8d3f5e2239fc28e1cf7490e7c8dfffd5b67507b23e75d0cc98c4b8ab49f833d56cf174f96828c97b8514e93d76fe4e046767a2e2d4ac1dc26306a79f58daab0a1c6a4c3eb70058effefbd5244da838833a807f25507fe646f73c7158f853528c26a1ffff659a8f8e63909e4d95b4f7b1648071e46313fa05ae17bf3ccdc295d32fb1e97fe39098fe29387a0afd47d47888c66153e0a963f61d71c419723395a8c9ba2724422bef12a87b1536d70aa0da40b3d517fcfcbbd8e40b27ae5adb78fe1621510cbc86acb4de7c5ec03ef27f294af82d0f7935c7fa96ecc3a5d7d32cdde4a610198a5adcfb213e1ea20421144aed1a1e28c0b5f872e7cf7af4f5b9dc7c19974c5ed05468a575994eb1863aa796ba128147b7fefbbb6e3a4e3080569e2cd1c391a4c1caa166731f267471ff838bc5067245bf9c731b9529677b9bbbebef366abbfeddcc17fc5efb9583919f80d324df1317761e82dba7f1fdc5f5fe91cc92b576e9f204abdfdaac0aa51763dc509c702c00cffa2f549761f8cd74f60e7c13400bd0e840a83ffe89fef7051d06825093461078d5bdf454b2e80497707f2163b6bf815f8d2f2c8b638b03ca348a43d1027fee98ac87b90464e821a4844b3b3f1e4b8c6eec4ddabc71dc794154a3d0f19f7983de38494a2ba656dc35c04ddca6904629243737eca1a515b55d928fab186b639c5063aff0dfa78b215ca97698e7560ffa2713a6807d258418295989e1fbf507bc56dc5d36db71e306452999a68560df71be61241f6d3557cc787efe1b0882c5dc28b05529f32be80bd0f023a04c299efe14a473c13eb63ec52db27c519ad17b3b12110e4033132eb5e3490455b31623816159fdcd3f08b8fbed35f51c62a6fa116f25f421ceea4ad67cc5761fd35883a1405932b062e274d2a843ca9feedb84aabe8cf73e0c3a3667420efa0673130a0ade23004af0189bd6375f828a8c765f70b313f88e20eb2801d8c15a4ef0f09fce76a33d230cb213e841e4aa63440448f99f9277dd02d90579a3af7e8727de9e9e3ebb528d318925cc258f3559d75af9d15efdb721d0c196696ca885dcf45bffefc643237e5d699d1b19e3061ddca581587d4cfc312a76b76668632a42dfb842349c9537d0b8b522fe7b639c6816be3941204adf8fffbe93f4a161c2d1043f3f1c4f02d29624fc84921f091c25ebe10a8684bdb94399fb4e76cfcd6847fcd4c49a17f8ed232a053df49951f9dd1e3a40f4aee9f894f86dddbcf5f50a5413468ac8d048c8afe1d9beb186de28149ed02bb1de12fd424762727d8fdedd66a3fd1c15dfa57819beb184fd2791f0f081368f877ab132a9418fe363e3a34b83d99c9f9c8fc8fd5038bbc715106320fa4cead530e4e031f13d8708d4e0de8eb2bc314a6aed1661fd9a4e751f7ab06b0cffd564c650b739d2e7c6fbc4b5ba067c16da0bd0e06a5723658a2ebb8318808256b1231353ff0deb303d0e232f52e76a682f5c6f3364249fdd3e37ec98f463d1489ef1b4c8985a7172e727f264baeaa905a2501ecc203fc9ecf27e563ba0d0e602427912be51e4f5e47f3dd7bf59b60892c99f0ff36de8fbeffe777ea4fb509f31c7e9b101146166ac95a76c9ec46de6dd8c3be5b040afb808a2a74d7001d1a2bed65fa5587873c520cdd810d12f98c84ef103a0b16468a6239d3364ebc9f8083f71329edddd4543c248e401db3acad42a013aaec626bd4c96f68bdb201b8a3fb332e09618ca67efb781f1195d90814dfeb1d2f03396bfde07d1569a53d0f36ff48ca58f909f8201eddd712cdd8305d323d299ffe6b498224af83ac2fdfc56a04f2ddd88b3296ebd9d4123aa6891a1ac9c2685b4c33d9415e49b4bcc9ea3b2ac69be8280097453efb33467a9d898d9783982c05dcbee62f6b0724797cdbcf42309713d8674be63c31b5f1edddf5d016495613beac51390e0691216bfe5d9a8f5a3a4431f32b37011ac937f7cc55725db2bb805fba1ba57db59da8d0efae51464816587a39b868fc37d6536d790d4e92cd880e1d5825c7236b79b1187cf813c32dc5336cf16041d11e523e7712c83b26e1a9a5efc26e4e4e2ccf5fc3b420503449d523b423e74a5f7ceee65ab68dd3f1100171b823e8b1671063703dec01f26d17660d55270a7f4055cd9b15c5d5595922b32797ba667d7f115744d4cfa03257aad6c81e1e23d6732a115b14804b044ad9b1c2650ad73ac6e8a9ce897e1063cf78a79643866c08e8c40aa27ead8d062ae48aa3d3ef70afecfdcf076244911953255876aa7af5c84d43da22849186210b7edd046f01ae4857b2dd5a63110df335bea343c859dbfd8e4b7e1be0cb5b6023c159a0ad2d17a57a5e67946bf91afacd3e1a23fd60f9f7415ea804e27347c18f8998c8985acd237d499c20446a256afda61bb15a96d4062b4f261282e2154fa5fe86cbb7e5f2b04cd80b2256fa153c846c272ec8437b045c6d9468e857d658b577322813922522677422e4e09b6134f20a2aac184617e62eead35aeecdec86fe71d07da6d7f24dfc3dca1f51cf8f8879a8291c3dee2f07dd370bd3ca42b0e4969ba21f409d98fbcc5858c16b3ab59a8ea18d3caa43e57aa8a54bfe768e4d343e37f4d100cbf82bd617cb41de1cad39f73ea3f29d084b4f96cc260d656dd47a27ead6ad543bc1350ba3135af684475a96401a137d6216b60056cdf714c1d5207d9ecf399e027d388796934bbdcfe2296828f0098db96a2559619c8f3477a4ac36f0671e6645bb9880381903101a44993bd4f53340e732ee4da6272639e2ed47aa1e4ee404eb5ae65c1e6b685adcad1f98411f48a089c8484cf2c7219d89a28c08f7863c3be0705892c593315b86660ae7fa9d114a3f381af2f08bc510e8ab5f68b7d78d14f49705dff57600c472cb6ffdcc2fcee6ec963dc15517804cfd44a1e34c7d8094adcca34f19ac0af68dfd5b65b8aae3236cea5ff9a003fa36ce162a38aa85cdc1c96ec8e5df6f24cf21b167f11d42139dbe7c97857d7bf53d5f1f2729f1e553acb62e2aad072bba4ac92f84815ac83899da22fd201dcddb12c55d6259b27f69dfe15b9781068370bc0fa33256a8c4f426aebbca20dbc864d4507db1671a3e52fbd9c6c2f878b94d8fb11baad6948c05f25fe7d912615cae7bf64ffaa07eb219f9e56c239e82eb097a1ab36f58414ec291edbefa0be96698c8661d9835871569424da9fd8d8bbdcb999ac117ba370f08573a6c1e93c0abc3f0d6b75f68d7d7fb2234afc291f4b540463448b4f8c1f1a0b70a6895317a99dcc9c9d31a8b07bf1d864058b82ad4ed45c69c4f2ed70533ad45ac7a1654953a7a7cce269a090421d3bbe7ea2d0641cb2fbf64c09bd705f54b58eebf777d86c6c2d6678630992739d31ebdea60cc71c0c47131a3c4793d07b5b68406e9803e7e79fbcf5b4d434172c6bc6e74a9739799b36ff9ba71520589d8d093500ce554a769c7364073c7bccff3be3e4a7267736d237bd5960c231d85b4d1d0049854e91f167cb29120091924dbae0c72eefdb20b70fbb102e4af39395ea09a355075ad44e61568c9864c46ed8edab7fa3701a001764c44b9dc35267c5cf715fba5361dcb5af6b8ec46e269a6669e5af693e4928a4f454fa86ce6ecea12e12500d7a22713dcab0a20af530784a1ca713af04d2d5d77eb0abe0fc2bbb4be37104b118a762aba42c569c4b5e85ec4f5d2f8edd96f4706e31ba4cbfc5c1230e408e148a6737a549259623409fc6d33f8c7854bb729bf1fe4d2436aa8f6aef0ac0921380156c13b18cd516a59ae034956b66b6c8f7159accdef35d2444ab741f9755de457ab219675a71e8706b909b1f3e5dfbc0f3da9f94c027e986b6c3986c9e449bd629512d2833ac60e3de84dc3bb0fb8642a19ebbbd7fc0812f54a81e7c6212de17540c2777387e755d2c9fe7439880da07548d9fd36e61bc79f263089a046fe37c055c17712c5cd61599efd309ee26b1993d49fadd1af4fca53c6cfa2f1c7bc430ad471a8c18b8ed450fdc4f7b5dc398d89b47dcde421ad1358911fab4cddc5e3dedb383a7b522e34184e27f3f9c04ae842eecbe3e32143c244cff019e51d970556be35391247d41640481cd4bfb848d9f9768df6b78a3edcd2f49589fd87601f132189c51080ab5f48e7cf530834af879e34b5fc4f3b71f412452e8dd12e7bbd5bfcfb711acd475b391ddbc2e0b1cfc456a13dbeac52247513cd378fdd59bfc13c88235a7c615392910ba4b412e2df8c41c1ebe53a221f78512f1fe570365e8d9c94ba98b5742b3c26ef8f6c2a38ae10e2e26a7de9bdbf9b18f3dff3bc171bac1c6a7479ef5b4f1d2d4160f4b8a914e8aa9e2d99eb100ab0d2dc3200c1bd779f6b595144e64b48f314379803776627196028d952e7b45ec8fd960524027f79f87e983f7e38b2aaa48919f925b6ee6e14d6f98fe8d23b4082e773f2638640ad7055c96a54f746dc10c64f6345a041a907b8c11ad9a092a0d70fe28956dbb643467ffb1c9d5cb6ce1c6e0e1df0f60e49b7efa50a8b096a8d842e7fe158011f93c1f3f6dcde61f025e7d1590c96f767a2c26d029701f9806cfa3c1a8879b2595e39cfe707a67aea66f68f9c97d9d3eb608deff10b46d47c2f56c232b700cfd533df451d849d9c5800d7a9ec87549c665c5a59a09f447533a0940df0cbd5db77849da1202bb540b71b60a8b7cb5588489f878154b73d545b9bdcff4603296b82a227a479b076d096af71362d9ec15b512faa482aaa80fe2dcf2fc99eccdcd76214f07a9a588a81faf4b31c03c51d00e53af3fb2aeb6bf501cc83d23f4e2e198aef6595acce682d8a053e1da09a06d92d20fa07f139d31d49570d771f32bf334519a62ea9d15a8639ecc7fde9287da696f2c9ff3c6a6259b7f9ccd6e8222ccbdd20d29d14ffd15239a5369765f98c7abeff268074a5dee517abf3712c24562793edf0900366c27fcef5263bf726bbbbe1f2052992cb1bc201cf41fb0f417abb9f9fb87c1b0a0fc0546730250ebfdb31d1156d35a4daceec59bd058e423c0e9a5e11a61665c95afeb6ec06e2670e2e1e59f619e092b89345f768b061ae424c287e68276fb2c3d75f24d5dfc4475a3822ca6f4888b6adaae46f60698396e88d698e1ba2489426aa3ac68bb339c9f0cd10cbca85d3b1671cd503df494bd40e8794897ac49c3ba4d08e47aaee4c0619d312815f5dba644b8ba224fa50aba2dbe67080ca6b778f6c1bbc4f4b4c254159eeb48df5698bd7e7b367d99aa96e6986eb61d5c73be29db59c9c8ec108f26af130c5d5c73315fc52cc7706ce92f51388a9a9a4f0925eb112623cf9cc9633010bc6b5f1488d1f566bfee47ae0590665024451dc5dd146293685f678daad8fa2af603c5d60e9c296d71940617079b263a510779452818ddb02fdbec64b7eadfe55efba96e62dace7ea7e052283fcfcdee440bb5ac5bcd3bfa6d5236872beec8b43c35042fc87ebe178a6df0726080d507f9ff385c8a4ca865eea39396e0c89ee37dcf1e4bb6c17bb8b307862a909127cd2e5713ed7c366b7f0b6542832d6c17e3e539e0d2a03e97ec65f2a51e5f74bebcdf1b5c8451ac30c00e977a6d18a35aef1c736aa6d19d606721551829a9c323eebb83a87a8d2b34057d51a698da7b75bba47a490b80248d0e96c2c2c57fd42f034c1414fb40590fdfcad81c2eec3a4e2c9ddb8e23e40183beb21c91bc6d3f2b4d98547ff27804cb351aa4f8e42d5fdf64a06683f7d6c1b26bb36190c5e5aab9aeda47265e6b9f61a6ca9bbd74b11454175d2b4aa04e99376ed95efd0429ae1447802b771f74a24cb79cbcdd7fc35f3a216145b1cb7defa580af603f70aa906e4d6a7c1c19684d67a23ca777207d49eedcc00c6da721f3a2f0b2acae4fcc9f20162a131a5d3a3b55af563386c6e80d6d0b5f6cfd91f157d6c315b8cb0aba81cf5ce9591eb15348114d93717cd54325dae0b69def97b268376cbaca12f445d6368bcf79371434278261b21bc85730a74576226cb54139f34f9a2dd99ec90c679251a6b04f1c122ed212e9237aefbb0983d26ccadf06cb00c666f0466b90f48630b819ddccb556ecc2b9b8cf49744671957d70f85e4f064e9513648ea3541010d48e394225d424a99de6e9baf4b4b10cd412dfab88a7248a3bfe6a3677983737053fb3a7831df9a082810f7b1d62894a618bf43363c4744549041bbc031a292e387188706126345ca5d2f8a4236aeacc5e03dfec8d86aa345806722d742d77ffc5f4835f3f7ed10948f6831c460af3ada2113a7f93068b5fa03f51ffbda072dbd3dd23a5a22f87e001dd19b15c5591a5922c5275ffa75bd8e846751d08f4e928348a0f5c72ffa5ce65cbb0f6789ca1b1eafbbfa4504db0e87d90909954294a920a2e0fa7dc537c2d442423681794f38b2c16cfdaec4e803e649c7bdc619d4970b4d7ece739661b4530f5dde7482f131aa16d9f487d3a7e644bbcd100f3d6917652e1902584264db22308db3004f0b6088b7cb538014afc79b5e3b49c89aa0d3fd58c7b63f8302c3ab5b90dbcad9f8617633f13b00a2179c536870311a3f10b2146486b92288338db11e4e7238118fb611a3d62bafcb601310b04b0e655bc6356e384322a3034b559ddef6a379613564f268d1fcce82d6622940256b73001d41f6f6362c7d53077aa161d157f8c8dd287932c14e97da2b6c73e3c9b4bc2f8d7a532aa58ac7c50aef498d8edd3d7113a02a47fd44761a936f52e25ee63555734530b6b959e361f0aa638330423ba1ae8d1a0741b9efc95e47049c67e4eb3a3e5a146cb32c357b866b357d8a66766fd21e4caf693750f98747bb2135062e5bc8672c7a2578ad16741d82008db3e0e72b6048c7cbcd44449f835d5cf7fc435b5e18098db60b0ba12fd31f6b64a855c2e7bf2872ffd7425f09a7390e7b46f4df417e44580794896e25670ccb617e81b5ca941aff09b9cff0628be7bfebebd33ae399e580adc4014614c98de2353079439665f6992c7ccdb52f997ff7a7175e089322d5c06f01677302099b0f7cb9fb4f5b0d45c1e903bd0d06a77ad7a99b6f795239e55c869732712ed96d72664f1059c41b6f3ca83b4d5a14b3076822cd2e29980595d39403f077be28e2c84e7238510fa6b9ab20c303f6f28ddda46fe4e23acf15081bf203bec044203d2ec67b894f2a3995c51ea3ebb42bf8992e79900e32b2953a0e3d32df7b749da137abb32047066088d7d3f542489f422d14b43e889b4288f9553312c5e0a6c908ba6fc5fad61a8232c089d3ced5abd4a983132b8c2bbb2380ea425c6d9cfa0959792a0677d94a3e06d5bb1bb3c36c2b1d840bc8f91bcd65ef0ea4204c382cf5a6395f86604dc8989587c885a244c8f53d0a122752b28305cd235992352bff19013a6ed9abd74b204541f6a2acaa822b94762dbe6f51948b7e3f7eb74b56a6a4d3398962b9ce82a39299f6cfea3fe17a86a711b4e3bf3c134d698740a626db5a0d6f24c240d6af088c470af2b6f2f8846987470866bbceafb74af10c58f110e24d0e312aaa5db34f1abd8b3ca6c590c9dfc1525b93fc5badc91849522639d39f843d28f9f336510ac5de31e77a22afaee4a5eaa6d5198d94fd9edb4cd866cebb93d0aa1dc47256894e121083eb1f175ec0c6c99f0455c303d1cf28d815b033813d2636ba77e94bbcbe10d40dc3e6dc05325bef396be4d8c5884f1bd5bc692cb6d5da172be2c72f9751b9739ad1f54ff8dc7e6d40d6154f16161792be4475ff051e26d31a064decc6e16d7ea4c65a0650034daa4f784f9f248aa8ece52a1e1d2f1c15e4622f06b2f89086ac95c4dd844fde863779e26bc3e33705bff3bfb464e891be003280153238130c0fa2b4f44c0ee42cef0dd8d9f9bba93bba94c6edc54e7d5b7bb280582c416991549250827c70367fceaa6aa22cc261515593352d0b18898e7ccb8bcf5b21a541b5e0b4aa9449927ea693eb98cc12d7501ac0408c3cfa78a0df8ab8f21026439feaf8eedefa29887042457231b09653a9701aa8da748a9fb5665a3906729cbad6fbc9c2e0d2e097dc4b6460e2dd2b9160a1faf111f4bdc50a89f27065f2e7f795e53daca3ea75d4655c91241322b985db4b3195a7f5a638edec982f36d25b91aedd7f768971b11dc9962b09aa9f78dabdeab0124573c5838576166ce8163db32a642de06358bb65545de443e66a1f268356440be50f92858f484239e6f388c22be0c3c3ec7e8ee96b8fdaf6420ff8f8b0ada72d4a497bad88d72b977936d502ffdb3098b67612f2e589d8a038b7442b3338eedd51f9253673d15a06ceecc6ddedbe2326560251078e5a2f504fc050e5e62db307b0328f55cdf2d8902a509456700a249c1a31d5d793c027f5d5265370b64b5be61cda6e950731167a82ce3591c72513f7d1d009c395cf0dd872bb99dc7b14f853419b987c0b3ec186cd23bc49ab8b7fc3f31473799e91822b203fddae6316e629030a7b001ad197f5c04c5979320d87dfe22db67e845f90acafa1e25fcc930ccd7b5011945f405c1e5904e3e1ca9897f90c15badb768f3f9abddb3d65300f74e186f19e8a580d6242a255b61fd9aeddfbcdce8a5bd38b24795924925565b1e5a191cb9d96e5d3ed6480312b8bcc63ff8a75a19db8e7afa72ebe68296a99a5111215dbd9a24a76e9cfd74f1c4341f69cb4a9926b9af6e8b96fd9e38b83096e0d4cc92be9bf0541edd3c85f000ca08dcd27283547e574d1ffe944903d0ab1bbb2ed4d5ac6715317be3fc688c4acfa15dcbc0af0e625a54f08db3400faef787c6ba5719af21dbb4aa5592bfaecd589c4e5c3e2d054d41e7d84902251554efbfbb799c77507bd0d148df0474f5eb9addd1f36bd02333a45027ec9e19e04d6bcfab8701dd3bd130e0c9f52e513cf373bbbccfce12fa876e7d7ea0c517f5140fcfd39523b1402c0b04b1237b9f940385b52b5b2e84f0d049e4b1c61f9c6637e0513f5de17b78695d836867471a0caba10fe037992e5eae4d00bdbbe93b22247539dd33d6b3c594211abc33050865f88c8d3dd3af49783e115b445083c1a0ceeeb3d7525c514317284e0fa92a0cf93d8688beab537cfde790416ea614da46a7c09928badf839c41f5e155e7f19068c920b6515ceca4c52f7fb0f0ef19c00da91675b2b166893f8d4b8f439c46f4c322089ed710eb5368a44675a9a552cfb2c58525b93c56cebbbf88d841feccf5f60a5c1ad37ad291288aab6a99a6f393a3166237150a64514658c8693b20f4d40c2ed09b60dce87f646db1c02b61f1eb9cd498670150c6b16bad12e28be43b2a7f92ec5cac9fbe34ce623956b40ec3402b0096fa1014217f7386589a25b6a616b642532754c2eec79f13c5b07476d8233bfad9296db76b7861d8bfb1afdadc5cc9a7dec6d907efa3c3447e8863401728d340afce7b8194375bc43ea8d5fafe88423cad653cffadc8a2eb2f1efc33704efeed568119babd09407afcf1a86828daba6431258b3ba01ce6138230b5aed3ac8499a4f2eba6e7b8ef25e8f8d9cbbb6e66fe2b765156c7e440640f7ab21ff157fdb575ab8eef4662b06162ed35af6c9ec47de712e231e170419fc92ca9345b7771c666c689885daac658bedc2153944febc25939fd3f61292717703302eef2d70a0423da087f63c8897ba943d1678f56d388fd2bc13b9c27aabf569eb2d43d3acd34c7d726015f0f8e306791512914e36b11f0648b63fa8fdb4a3a277b60f2c9c0c17dc4f7293a4808278eb1c75e4c4cd74fdbc7d67f604cb166365f250157286602a7ff45c70db99bbd34f77d7a70179954d9951021d83b83a91c6d3da46ae19dfc33330519203796889e41c163c4ef5259b9f8601cac95ca627706bcccfd9fb253542cef3c8b32f6e46eaf6067477e1fc6d9409b60030be5762eb6a179de452222494d539b4b4843b89fdf8d8eb345049469f49d77e52d318cda6fa7255528d48259f11f137ad98bce3b40d169be5ed12ce875395eb6687b5682f8741e9a2ea4fb659e700490c6021b59750b637f253c0c04daef90be550a3231f6fbad31a0bdcd4d3025bec5f97cc55309a501f562c1bd292c8ba4a1527f6c97c550c7140531df15fc6ccca512b663e5ed31a86b7ecc7e1e74e4e1e14f2180492586c49370055f7a6e907c695457c72f12428831c24ce412f5eb07f6adf56bd5690f84ea6ece90ac984e3a0acf8ea33563a3e792d262c8efa95adadca4e668885cb2d5d140334b65806fc8cef66b6dd2cb6c68673015e6133ae2c6e3563adc107990dbf6441b1b9df4e4f793a154626abd11a7ecbec06e2efb666a6d5f24bfc0d6a2851cfe0dcc5e84240e693fab8769a7a19873d6095320de30f2507bec072170a856d98959c88c6390407b1be7f5c105f6a812d0fbb44f2aaabb807d0093451eb41497c942d56f7075c04f88641dd28ac1d3d981bd24f1fa853841ae7241d37687952a1609e609b8655981541bd7e1cf67c2705502e46ae794f3f195391e0e53a6d499a841ca6deff14072dd5c483aaa81a037284b126686351b1e363b8e4920c0ad7749e55c5e7d3c201302004157f283e78996aa20feb890305c45e731728ebe548140574aa2ae523fb128d579c8980e80d9140417b8ff5c749afa74f96a18db68ce7abf7da8c9c626a59f6376161cd3bf5c055227da2c9385fd61999b147cbb7bcaf46fd5668dcaeb45da3c641417c9386662d607d79236440e33e8a3d05ce822c531baa8f40c9343ce884427652495e80a1d18bab13a2aaefea520e28690f28d5b3f747025ac44fd96bb642db8bbccdf277580e75bdd480a17de2c375be91391c66ce8a2ec44303234f02a26f4b6c5fc0c74b90c3c12a70b5e984c6aad79da06ff1bbc3cd4880c83805df2cd46632bd6ab597f328e7356f1e261399ca5cf3e96c609885f8eab11bd45d051c72f038167a29aa27b7fd1fd10dcb5a6cdb3de71b68bcc5b7697684685dd105937588fc1ea6c69519d28df57671c7594e57e6d92d4028db71eda5ffe27e49039a738b7ef9dbd75b61c5c1a59fad29128d9af6a89aef784dd287238ea17b0b8ab68fec7a2978f690360056a25fe41049e6909be6d78d4b68b36fac1fc5072989579f240fde388eb20ba810091ee6c04c4378a3874871f2c357567695d396d5e2c184cd16279168f0603aac6aae365ee694b7a7cf34060e65d420182a5de01927a60eb1cb5afec8ec06e26d8866bedbf694dc036a475c8fbadce9ee1e55a49e8e3e04e3819bcc790842e2520aa7b07b4a26244c322b87135dc6df42383203c87619cfdb337a37ea8eaa90cd73bbb4dbf3e56c994fee451ce9d767f93b7f0306ece36def77b3ba74a6f7595e638b24f476d224ff7d474e4022b73084b7a6ae711e53937a861db0c75f90edc1a9d8c8ee84cb725fdaa06b51e19f7b2b1bf234e317bec11533e890d037cacf07958dd78b5960694db9e64d05ebb4711fc77246710cf5b362240a4066b12c453d86f1bee6824846528f5ad2c3d07d0335e29fbcf377bdfe61f6986fc6dde9156bac568d2aca4ca15759bb8de19d03e3bbaa2e530e0546361dc95a0639ecc7016a7ec4461b064ffc8f9847594f9f00732ae2d21658a5593f1593adfd4c22cae91cfcf46320952faa794b344cb98e3ebeb12e64e3e655a49ac014ee794a302a8ff0d7bbe9c15a26a087e76555922ef252884f02c66e4a8d7d50344436bc1f8e4510229acb3358eef60464078baddcebd067c554075e2bc1885a84efef5b5f204bc15ae0c02e952973d6eaafe7701235710d65e94f7122552d6e582f3e6546a08c274295ad54697d6138f4ec963fac3d150364a42e676e129a4f32ea3655772298dd4cb3bbd1d213dbbf6f2c5421bb1f665ec634a1a182c85d4f67dcc8bbf6f77f04baf25fa37b1560a2e31602fbf49854d43b97bb526c5e93e82dc510efbb5f48c6cfbb5034af44903cf8fb493b62a00b478f31a29acace12b22d9cacd5c6a6c491fd158b1a4907c2e9438887d4ea13bc4b94abcafdc08dae0835b2377a920eb1ca0dbeb9edd0654ccf8f464d42ffc9535e26e5a1f7095c370c8a07fd8abac36aa7c842c61331936de617e4841845ad8707163dc65af7251e67d31a7e37ec06e2e33e64a65402d0024f7a6b4437aa7cf7ee28817cee4cb56b6f4dcf6852aa2c2730a7030c5c18a8ae4d87d6d25e4f490b0d24beb8ff503382e32a3a3ae55aa233cb0704ffedc96adbb84bc64019dcbfb97c302503020ee1fc93c41e804548d2386fd5cb53b7b32d29956b1d674338d0566429154c984c9ba2d04db520f7366068d6cb73de17af462e7678050c5c728b069c1f5325f7926ed018bf6b82db55388c58c71b9cc68b13c2696c97c76614e1ba6603da1765a46f0cca30c27f818b1dbbe784f2fde3422b1f3feb1b5484e46f50747348bd07bf1475beeeb684b718035e0b7878bb52284380a80341998e62271d9c535585b6c03aa7fd20493a97c958358ee59e72b471bc46880a81017a98b422ffd5f07c237fd7c3cdd2da39742116ac418ada7a21ba8fea21c9bac7619d6a08f14b08123d50cd1467371e7b36e229a8c383bde9e7ba0f3cc7cb27e534eb47cf7d50a884837b43ed34622296680826d0fc96807ea2de568a28b7f87d986c1aa0cb3bd4594c3c5d92118db5e0c70b6048b8d3cb5c08af437c167645ca5a2db0f1a629884ec3f4eedf1b9faac2c9fcd9803f553431232ac4354f04fa6cfe574192995bb575ec1e878845108e77026aa32eed77a30ae35eee4c91cf65bebbe315f86027f777fbc51b1fcdd68105c03ef7140a52e40b0d3a56b1b9ceec5d5962203b577f29315bf6ee347e74f9dbdf4f514341ddd0bca912ab9abe2bb26b593596683f0007f751d83ea638f47dde1f316d2c34d3ad0b2e0cb4f652e69bab8543192e330eaab3bcc118158f4f968115cfceacac3411bdfb52a2afd8cb674473d58f7d3619ccdad3172f76e75fb3595700de2982bdd3044b1a4d6ba12d60e7f1db848b18424d6f4e1d261e2fd11a06ceecc7dd7178c5461af64904409a4e61cf5fa46a2adc2c6e1409c82be80e6ab61ff1c222279245d7f8c85541bb1393c7fb7172ab500606771d2b1c8ffb27727b19d0ae30f3ab0dbe0158a36dca07fe7241dc916430fd3548eb6f371d49518912bc9c564225857c693fb8526067ebcc7b07354a971538749d3ffa376161c93bf8c4d5195922757117da1afb8563c951c00f35465ac8feb5d9db3c45f07fbe1bb570555f645faf9407379265344fda66ab0f54712a47e1d6a2666a2db60b371e4162252cbc32e49dc8dade074af7675cdfdcf5078d7351664a358488a6db8b45cf6815071aac7dcdc00a8a29f720ad4a21fe0f996654b8361e68f2fc605acddbf7c4dd19591e876b96f629fbae92c751c5cf66b667c48430935b4051d536e3a657675bc552cb5a5e1738cf9ba4eb23cddc93eae8a98654ea9c348b1f9c81641244b9642e9f0d33b311f062c700a34be4bd24d1fd3794d6350d7436dd4e3c14aa0f9f1f0c72f5a4cb876d7b42047e015a22d37110dc5820cebc862d060eeec95af649ec46def170251ed6f298f803ba673d6fff3476ea44c42c82b0adc58ca85f0b230c0995d5abdf18ec26c044a9d1f2cc123de2f8832284205995704d53284243fab1883e687ee9b4f07ac35d1b67dc6dfa0fea4eabbbdaeb955ec4250e444691806f7de4dc02546cedd8a8b21617994f434099a667cd58ec612aef2e2f7efb9fcb5b4d6fc1edccc02d14ab7ab668c26f593157574f6e8451e5a9caff42abf0339d6cc7501c2abba06ac57f50eeca73f24af85823f6b45a54db955ede40196e43992c84aef8dd15b4e63c0294d86b483d93f8d72e1760647b59fa6286bce8afa62eceba226bb6796e8a7950886fb124814b2c42e62ed2758f467f4d384df81876654c8a30be65ef314c293b6ea60e7605e2894845fc04b5a14bcebe6330b6a0795ad83b106624caf83970de6c5f9827ba962c7945e6f485495b02cf9a992946424117963ff8c825e3c95246fcf38f1c7551090e1e26c504296223df8efa279661586e70d8d3045fbc7d26e00739779d1f47235cde6b3732de9238a0c12089b330d02b60a8d8cbb37848af842c5cf444d05ae3dbf616b6daccea52a1c983929e70d05ee49f1bbe9db1b153ac43f663a724d42b2459fd160e0f7c40a28ca91612449666368fd36f1db7efbee3cf486728c55cc58fce070043c29875fef57e6a9fb7994cfeb563f4e6836a8165b7128cb9e6299c28f2a43f54d348d64d09ca7e998b4b5b10a54119a8b48983caaadfec90eb30d3165f2f328a521b66b80f79b36946e2d648322ba6a6f06c18e1a0b54d334845e868d08f767ac58f42524260fc4d80caf09133c5c7d3c0d34ce54eebcf3d441b43966d5204b270a576b124ad1bd025759f09a8aa35afba75ec1d9ef898060fa4a8201be5d7e2c65132ff94eb84bd935b5f514f417590c06a04ab9277169b6bf9342de40aa3100fde6112a2e1b5c7c62de28dd5cf20f72b2011b654dd3147830227cdae060bd33c000208df51f8ed37f16e1391f4d3d9f9cee02ddc298f4ed8bbcf3df67f1db3c71d0856c61aaf82fb655e01f2055a7d63ae00698590201f6e18e9ab51e939d4d521274efd5e84efefdb5f204d41e87fb08a04aca2df6d9def785034edfc029609f20c1edda036728c6b3014ea1d37e92da8c00856bd8f9e66e28d3ea1e14c923ed1c537c0613b227b754d3e98ef6af1adc3d80734d2c703b81b0e30010b89db9ae61307d7da1073d4acaa16e97b7c7ffdd074b15132ed2cc49cebfcebca96b6e3279506c12b04f96345d209321e51df3a39cf9627667a4b152a8d5cf63dd578f526a5daa389f39352dcfeaebc57bb06829cd78b5889ebf72322ace35b4b64a2e2fc5758680151aa4315e3b11ef1feeb11ecca932b3f6becdc44b961f1416703533ae189333ca3304e88e21bd22bef65eabaa7b038d0a9b311e13ae22f664bc7837f3cdc92072bc5f06eaa5f48c6cbb5d0039744d3557606147b34d81157f3d282896369a0b550f1f4a425800840f19c39da6657856456dd47621c5629077d5b0984890714b7399a7fe2d6bb3ae387fdf8ec3aecf3920b1c6d3a2e6212ca32711c0e623d04888efef75bba252c9beebe68c307cf89c18257f65794d34b66c1b52e53ff89eddd6cbb7fdb4b9d4541eabcac8d842c7b5659c0ef1073b0694589e9bbab9b21343f27adc05d1224ba27452c21c7fe6bb97f5de8f3f1e4f51019aaa39d5dc373d9c517d64155d62e97d4c5b9be05ce8e6ba68b2654320c602d0a6c50e6bb44793de906dcff762f160acd6a75770a65d1ad6677620a18600142ce07ce7825c39e8c2e0ed9f205cacb8cbec5cf72436b7006e83e4acd398f346dbce618f6ca6ec5232e9e1563f52d6a05483745c2b542638ad9774172f532140126b2ccae49a327b405360a3a5d2a1c9923a3cbfcc67ad749226be45623f29db594ab80ff2d277febd47b917997a9b95cbb6a1c3e112a0c7ca9221b8a9aac7046127d128c4d3fcc206f76bbbf4f4f5d2b41dd9cb86e04eb723f5ab76b91d9b16c09f7686f2b813cdabd7de62a26951c7247effde23d6737834302645f87fea521b612e19979a5fb78dd207e42e5919ba508dab5e1dcdc324ac3874af7b1c561d8189ee660b53f0627d59222e5c5fff27a3fb1ed2f4c4145210619d9a7d1d927e2aa533422a70150c5ec0259230752eb95bdb927f62a5b11dba65a7d0d529d384b5eee68275f8ecee3e49718a96334d920ebf2b4946e320f2896ef0f1b03d72615eb4c0aed109793877428ea8115451a33269c0b00d0f04af16febfd5924e12b28733d35b07f93356c80124100a43aa241bf238133c75d6812b6bfb6131ba633d70436f57816b2cecc1d086db3f5cf3bddcd35f0ba78713bb6487e590982900c12deed101a1fb6d073a3d1948f7b060ba8f8b9f3008df9a40250d6d24298c0cd56aff07b1cda26f36b5a1bf676222e2836e369adc6c24cb007eeeb4375db8593bd4004dd5188f13e45e62525cbb08c9ca13824ea8038189b1edc692599a44939d4f7b6d95dfb2ffc8019dddbf3cc58695d9eb3285ec22c2d634563a3b12fa4dd5f04dff62ffab0659f3199ee1785a19230949880f273e7eb4c2a2809243cd96b62155b5ab59900169566068e7b6992aab81535ebb80dbc86de52ebc3e731b169f5570e85f4229f91a5d9130aed5e70e02783b09b92de887484f2fd36ecc4f81599a5a615e0a810fc3eee22791bb7d0aa7dfec997b600dd35d8c6da9a1d829e7ca6ffddb0c8879bd083a08f5b79ea1d425ec9ce207bedddcda81c73b6a691ae4fa0bfcf3384e0baa6c1554db68019341e24e927f30bbee0bf936feb014d99c4cd5e4b50be534541006fb7e2ccd58f9b9061449a67359ef180caab29ebf0441520f139a6ec3945f765365ed35a6e37ec87de67988d4615f44bfc3cd846758ffe1c916c5282d8b1f3df3a9eea8f205af6c7fd70412e3669a01988f4346205cfaaed70abd963be883f3befa12e667f9d99a89243a2eccbe0d283973febed5439df775d407c3715c27f4d75cd241ac576a64c951d76a519ad743059fbe4ea503ba0a05d9643680c21d29efd2976f9ef5b4f0dc5c19c0dc50ef4c673bf6b96ebb0593a5d2528ca2c9792f34679f4b67bc9f519029787225b6611fd89c9a16f1e31b1dd80764b1a635222662e042f3e83120a82ac0c7d99f3eb70250a770b00ca1338aebc87ace2bdcb5a6e6d7cd19e547aab7dd4c132aa768a9b06eb6a05043a53cc18b80781199c71ee828b4a745ff0d74f50e3c1293abd0ef687835f6ba5ebb8e2ecd84011576a1f06da660cddd3533ab8eda5039e5b3f82875cf4f41524f019d6df522029ddae900e2848d039de3f15341a95971701a9edf26ada726feeed12c2f733f9f199d315e798ec2668509c5fecaa6811171265cd8719e470703ac140418f9e1a22fe984e0dc62e29c91a0639ecc601e670c6c65af6cd0340584b5c57a2e402aff9844858d7c747a426522b1e6cc874a2dd7bf91947cfee7e2813cd3417a7f152434b169109c2ed0e133e79312e2c86dcd703b6e0b8a34285eb0fe4d19709069660a4cd71447d4d1c0bcbc36b127cbd7867392c97d13ad9e165644abe7d47dff9b2e7b10dfbfca01ed11b13cd5d325dae378bde016ac97234b387d1eff10d4888fe16955ffa04bb60c41a387e972286afff2c289eec48934b070c4a79bc3f48750fe0bef26cc6c2b71a4a4152ea431c3f37e4f4eaba27a3fc472c5c3bcc957c7500df3998329705465695a280d847e5298ea332c161733c2af689f2486f75643ea44e094b2bc60eb2d35aee4cec86e2ed1866c6d7f4ccfb7d8a8c70f7a748f56857cd6fcecbbefadbfb186c56533c7fda79ad225cd6a3223ef3dcbafda85ed357a0ba71c77e09c28745e23b896808bb6ab7c5feeec249f8f26b1c41630f0a5f74ff6fe93eac32b3c51757ca68be84cc6ac20f2b08d2f9dc5b8a95c8e284505840cff10677db082d1f7e69a04f5b6045c15de0c40e866b72bfe79367b92bbedc4026cf53690d521217aa862c76e2e3555cf2ea810675ff6f4dad263b4cdc94cda1885f8787bb420a86174e814dee8b12e0c5e308c1daa3f3a1c725c5193c581fcfef2098a35c83cd19972370496be1829587badb647635a7035b9fdede37335d45ce3c09872b3fc054cd7b17cddd695d2e0d499eda6b277f5499a4d1ef73bd6846a975fc67b19e28a5b1d18a8d9076807d79a137d4d57852dd2aa37efe98eb0915853e10d64bbce7ba66fe76e6d72b061216a30ddd708ea9ee0b104bb9e68b1521ac8544911bf3aded678eb56876400bf6dd93eb7ac656c61281b7eebe5bbf077340da751b2039201ed57715c14c597dae4d69debe6db6ae77bf97a1af600d55aad7a9934b37b206e1891b14752233993c9d8a0d107a176c9d04fa865d0ee28094a116f097661509383e5241ee4e78bc0febe9b9e8cae923bf8be453e2f21d2a7e33be29ac36b1bd6e238b6774f421c23d7c7fdfb84de66388a15b2e32608efe47a921dd73609b02018bc500e8875f48d7cbd31ef8afc33d567409447cbbd7e81f72aab9aa43ccc1f6c34dc19bddb5ee9279f254317907cd0fe29c94bb555509fdbd812db416c48193453a372a8a44b0e76bd9fbd682acf5778fe6511ca21f3c5f3ad354384c7595dcc29cc57bca41711927dec30c642a5a8303f40fe9cd83dd90dccb6a12243c6119d53bf4c04c5979a2499757de2bd696809d71b00f89ea5de2f25fdd876355193c1c9a6f9623b88425574db8a7471e44d92a6feeb58fde7bc3da064a8e379938723b367a7a2b38b1b8e205d7ca6e82f91fef1de31bf2abfc94e611260750332e2b5e9b857e977a8a67be8995bb79c5dba0735a0d7514472e09110320b0489c21e92bc5205f975f88a6cfbb7a34a704d033b8ff4b3cd817ed8f468b36770fbaf35407a4ad1157b119c587f88168496d3e0666ad9ad0b1da7c6f7fec2d3e42bb8fa23fe279b6701e09bfa5c3b1f13f2c17a1cf2f38da9b9945fb8e2221f8e8f79cfd178d7979ef165cf3506f20839dc582ba94649c614572a7129c3e5423ffe53665cb5a6e39ec87fe650e831e1b060edb12d8834477ad107628252e2cb207d061c25d223d44f67508a9ea10ce5b0c845e4b48383187a8eb97a29485e51a26f20c2e36ba3b650b123bfd4a0910c87ec7f1f347e43924d4dd8625602939bcfe7a65269f20fe5d08a3a925dd5555fe4a5233125008373abd3773c4553c4d8732c9214e84f903dc5f51ed41a831c1ae060884de29986ff155f7d420002cc799150d1f9c438caffb693c91f8daf5ac22e925fb466b1fe0dd29279ee7af95e837486f303c36ba823e521294a09fadfae95ccd0159e74d439ae65931751638c6d99673c40c08666c6d82ac4b44ea8fc5493a5fd20dd49a473355463aedd87995b48d9072fc2619631650cc40ae41cf765a23ad1067aaa5b9599b90f17dabacd2806dc21309ef1ef17ecb08711c1a85b3dfc6a905bc937a5de49ab3506dc46ed81c57348e0934b6397d48b840bf39babde648e2e3a287baefdbcc53e5919e5dcfab71be55768efe5a702eee3e407ed2bd10d0623c80894b637ad0fcfc64379841546c9f7230adc510f88a5f48d7cb131444a709dc5b390a8c7af2ffe858b6da0b6f720cd94f278b5d9cf9441de0fe8205cf6159eb34a8f65b351ad3ff0e9ee58c3c5dcddad122ea775ad231afd89fd3fce3f0cb29f7eb3d633b13a6756a79a199c525c8473fffa6cdb9c399d544d823acab03f812cb67242dd7d5422bc4f830bb15c3b2101dee781d574d177eeefdf7be69856ea3250668198a8dd8d9bcd06ccfc476d22352c7aca7e7fc70b4d96de7fc9f92adcd1a4bad69217b34bbd17bac9510f5bf34771f627c8a14803904f70ac0eccee5eb5aebe3ec21c9b5326396b26d38d7db3bde0aa18d5d313f208a097263e5b7a1d71db3a810fcaf4a3a4cd808cd2affbc401ac1fbf2c8cd31799e8b511ee2294873a7d14dc10f8fbe73a2db95edbf9aaf66db585eff78da724b05efd0e4c567647f4fad121bde22b3d1c67423d81ab7e142a225ca7b8ecbfc081dae11abf27a321ae0eb6fd2bbbb8be7fb17e59a1ded87d4bde0f55cd53dcdd4c01359ba7982b670972dbc805ebd473a6824a5c14918f9605ecddb15c15d597daeb74956be6e049341a357d1cf80457bc6da028df10c2aee21d2227f792cb1e55beba8afdd38d9653a092f5ba84617660ee28ce0cd2e29180c490e7a2ee92cb7196ac3c6066a4af936e7e35e3486e53b393856105602127e653b31f07cb62ef05de4af1037039cc8dab7ce8bb4edfd7b8e1850b2a8dc33c9eb22691f47cb79cded459f335e980dd5e86270c9718c70551c0b996e9386cf9340f31fece535a17ce9
Sending the above message to the server, we have the flag:
hhh hhh hhhh hhh hhhhh hhhh hhhh hhhhh hhhh hh hhhhhh hhhh?
h: d39710...a17ce9
hhhh hhhh, hhhh hh hhhh hhhh: DUCTF{hhh.hhh_hh_hhhhhh_hhh,hh_hh?h_hh_hhhh_hhh-hh,hhh-hhhhh_hhhhh_hh.}
handshake⌗
Challenge Summary⌗
We are able to connect to a remote service which performs the below protocol:
Denote $a, b$ be the private keys of the server and the client and $A, B$ be their public counterpart. The shared secret $s$ is given by the x-coordinate of $a \cdot B = b \cdot A$, and the shared nonce $\eta_\text{Shared}$ is computed by
$$\eta_\text{Shared} := \text{SHA256}(\eta_\text{Client} \ || \ s \ || \ \eta_\text{Server}).$$
The derived key $k$ is computed by
$$k := \text{HKDF}({\color{gray}\text{ikm}=}\ s \ || \ \eta_\text{Client} \ || \ \eta_\text{Server} \ || \ \eta_\text{Shared}, {\color{gray}\text{salt}=}\ \texttt{DUCTF-2023}).$$
On the other hand, we are given
- an unprivileged client’s certificate (with the private key),
- a privileged client’s certificate.
- the certificate authority’s public key, and
- the server’s public key.
Additionally, the flag will be included in the message if we are using a privileged client’s certificate. The objective is to recover the flag.
Solution⌗
There are a lot of red herrings in this challenge. I thought of
- Forge a privileged client’s certificate. The private key that signs the client certificates is disposed after generation, so it is impossible.
- Recover the shared secret. Remarkably, if we are using the same client certificate, the shared secret will remain unchanged.
There are two issues that made the challenge vulnerable:
- The shared secret is computed solely with the server’s and client’s static keys, which will be a constant for the same server-client pair.
- The derived key $k$ is maliciously constructed.
Given that $s$ is unchanged, we can derive $k$ by crafting multiple $\eta_\text{Client}$s and observing the corresponding $\eta_\text{Shared}$s. To begin, we will look at what is under the hood of HKDF.
We can see that $\eta_\text{Shared}$ and $k$ are computed in a similar fashion (what?). Let’s unwrap the HKDF function and express $k$ in terms of HMAC in the first stage. We should end up presenting $k$ in terms of a bunch of SHA256 calls:
$$\begin{aligned} k &= \text{HKDF}({\color{gray}\text{ikm}=}\ s \ || \ \eta_\text{Client} \ || \ \eta_\text{Server} \ || \ \eta_\text{Shared}, {\color{gray}\text{salt}=}\ \texttt{DUCTF-2023}) \\ &= \text{HMAC}({\color{gray}\text{msg}=}\ \texttt{[01]}, {\color{gray}\text{key}=}\ \text{HMAC}({\color{gray}\text{msg}=}\ s \ || \ \eta_\text{Client} \ || \ \eta_\text{Server} \ || \ \eta_\text{Shared}, {\color{gray}\text{key}=}\ \texttt{DUCTF-2023})) \end{aligned}$$
Furthermore, denote the key of the HMAC outside by $\text{prk}$. We then have
$$\begin{aligned} \text{prk} &= \text{HMAC}({\color{gray}\text{msg}=}\ s \ || \ \eta_\text{Client} \ || \ \eta_\text{Server} \ || \ \eta_\text{Shared}, {\color{gray}\text{key}=}\ \texttt{DUCTF-2023}) \\ &= \text{SHA256}(t_1 \ || \ \text{SHA256}(t_2 \ || \ s \ || \ \eta_\text{Client} \ || \ \eta_\text{Server} \ || \ \eta_\text{Shared})). \end{aligned}$$
Here $t_1$ and $t_2$ are two strings based on the HMAC key. Since the HMAC key is known, we have those $t_i$’s. Look into the SHA256 function inside:
- $\eta_\text{Client}$ is controllable,
- $t_2$ is known,
- $s$ is unknown but it is constant for all connections,
- $\eta_\text{Server}$ and $\eta_\text{Shared}$ are known after we send $\eta_\text{Client}$ to the server.
Let’s revisit on how $\eta_\text{Shared}$ is generated:
$$\eta_\text{Shared} = \text{SHA256}(\eta_\text{Client} \ || \ s \ || \ \eta_\text{Server}).$$
If the internal digest for $\text{prk}$ is known, we can readily recover $\text{prk}$ and thus $k$. One idea I had during this moment is to set $\eta^{(1)}_\text{Client}$ to be $t_2$. By sending this client nonce to the server, we will obtain $\eta^{(1)}_\text{Shared} = \text{SHA256}(t_2 \ || \ s \ || \ \eta^{(1)}_\text{Server})$ as the shared nonce.
Since we do not have $s$, we cannot compute the internal digest of $\text{prk}$. Fortunately, since $s$ is unchanged for every connection, we might be able to compute $\text{prk}$ because SHA256 is constructed by the Merkle-Damgard scheme. For the second connection, we can send $\eta'_\text{Client}$ defined below to the server.
$$\eta^{(2)}_\text{Client} := \eta^{(1)}_\text{Server} \ || \ \texttt{80 00 00 00 00 00 00 00 00 00 00 00 00 00 03 80}$$
Notably, $\texttt{80 00 00 … 00 03 80}$ is the padding (assuming $s$ is 32-byte long) before computing the SHA256 digest for $\eta^{(1)}_\text{Client} \ || \ s \ || \ \eta^{(1)}_\text{Server}$. We can recover
$$\begin{aligned} & \text{SHA256}(t_2 \ || \ s \ || \ \eta^{(2)}_\text{Client} \ || \ \eta^{(2)}_\text{Server} \ || \ \eta^{(2)}_\text{Shared}) \\ &= \text{SHA256}(t_2 \ || \ s \ || \ \eta^{(1)}_\text{Server} \ || \ \texttt{80 00 00 … 00 03 80} \ || \ \eta^{(2)}_\text{Server} \ || \ \eta^{(2)}_\text{Shared}) \end{aligned}$$
by length extension attack using $\eta^{(1)}_\text{Shared}$, $\eta^{(2)}_\text{Server}$ and $\eta^{(2)}_\text{Shared}$. With that, we can recover $k^{(2)}$, effectively decrypting the ciphertext.
DUCTF{k3y_der1v3d_fr0m_ov3rsh4r3d_mat3r1al}