app检测root怎么逆向(包含脱下来的java代码不正确如何解决)

本篇文章仅供交流学习,侵权删(满满的求生欲)

本次app样本:5LqM5LiJ6YeMNy4wLjM=

逆向部分

1.绕过root检测

首先现象就是打开app,会提示手机已经root,然后闪退。

当然是使用面具的隐藏功能了

我使用的版本是23.0,主界面右上角设置里面有一个MagiskHide

image.png

勾选之后会重启,重启后,点击盾牌的那个分栏

image.png

点击第一个

image.png

然后勾选想要隐藏检测root的应用

image.png

再次打开app就不会闪退了,成功!

2.抓包

这个就不用说了,尿壶直接就能抓到,没有ssl。

有一个sign,但是很简单,就不说了。

返回值是一堆数字+字母,看来回来还做了一些特殊处理,算法部分主要说这个吧。

3.脱壳

众所周知,开启了MagiskHide无法运行frida脱壳脚本,那就先把面具隐藏关掉,再运行脱壳脚本,虽然会闪退,但是还是能脱下来,只不过代码有的地方可能会有问题(算法部分会提及,看java代码+尝试用了一上午才修改成正确的java代码,焯!)

这里分享两个好用的脱壳脚本

一个是yang神的 github.com/lasting-yan…

一个是葫芦娃大佬的 github.com/hluwa/FRIDA…

算法部分

重头戏,论如何被不知道是不是因为检测了root所以壳没脱好伤到了本体的java代码 折磨了一个上午。

首先搜索请求头中的参数,直接就找到了,然后跟调用

发现返回值处理成正确的数据在这个函数里

image.png

看了下f,是"AES" ,看来是个AES加密,hook一下入参和返回值,密钥也拿到了,结果也是正确的,那么重点就是他对返回的加密数据,使用a函数做了些处理,进去看看。

image.png

大致看一下,取了返回加密数据的长度,做了一个判断,然后进入循环,循环是本篇文章的重点,首先charAt()方法就是根据索引取字符串的对应值,然后看一下j方法

image.png

再跟

image.png

具体就是做了一些判断和加减法,python中可以使用ord()函数将字母或数字转为对应的 ASCII 数值。然后作为3里面的入参codePoint传进去,第二个参数是固定值16,因为返回的加密参数就是0-9和a-z的组合,所以ASCII不会超过128,把 >=128的if逻辑删掉就好了,然后用python还原。

这里贴一下,我还原后的整体代码

第二张图的a方法

def data_decrypt(self, decrData):
    length = len(decrData)
    if (length&1) != 0:
        decrData = "0" + decrData
        length = len(decrData)
    ss2 = []
    for i in range(length >> 1):
        ss2.append(0)
    i = 0
    i2 = 0
    while i<length-1:
        i3 = i +1
        i = i3 +1
        ss2[i2] = str((self.r_digit(ord(decrData[i]),16) << 4) | (self.r_digit(ord(decrData[i3]),16) & 255))
        i2+=1
    print(ss2)
复制代码

后面的123

def digit(self, codePoint, radix):
    result = -1
    if radix<2 | radix > 36:
        return -1
    if 48<=codePoint & codePoint<=57:
        result = codePoint-48
    if 97<=codePoint & codePoint<=122:
        result = codePoint - 87
    if 65<=codePoint & codePoint<=90:
        result = codePoint - 55
    if result < radix:
        return result
    return -1

def r_digit(self,codePoint,radix):
    dd = self.digit(codePoint, radix)
    if dd<0:
        return 0
    return dd
复制代码

好,还原之后运行,然后就报错了(我的心情:*(^*&()@&#)@(&#@*&^$)

Traceback (most recent call last):
  File "D:/work_soft/pycharm/__init__.py", line 91, in <module>
    print(eg.data_decrypt(data))
  File "D:/work_soft/pycharm/__init__.py", line 79, in data_decrypt
    ss2[i2] = str((self.r_digit(ord(decrData[i]),16) << 4) | (self.r_digit(ord(decrData[i3]),16) & 255))
IndexError: string index out of range
复制代码

很明显,报错提示的是decrData[i] 这个有问题,也就是最后一次循环,i的值是字符串的长度,我们都知道索引是从0开始,字符串的最后一位的索引是字符串的长度减1,所以这里就报错了。

做到这里我一度以为是我代码还原错了,于是把java代码放到idea里同样运行了一次,也报了同样的错误!当时人都迷茫了,这样的情况还是第一次遇到。

思路与做的尝试

1.控制变量

一开始我还不觉得是代码有问题(其实当然是代码有问题了!),我以为是我hook的入参没有复制对,所以我又去hook了入参,当然是不成功了。

2.多次脱壳

这次我终于信了是代码有问题,所以又用了另一个脚本去脱壳,发现脱出来的代码还是完全一样,怎么能半路而退,这都没有涉及到so! 干!

3.修改java代码

我hook了第二张图的a方法,发现入参的长度是返回值的长度的两倍。

image.png

那是当然的,每次i3和i都是1,2、3,4...所以到最后就是字符串长度-1,字符串长度然后报错,那么我都-1不就完了,因为没道理索引从1开始,那不就跳过了字符串的第一位的字符了吗,这次运行出结果了,但是使用控制变量发现和正常的结果还是不一样。

又观察了一遍java代码,发现出问题的代码只可能在while循环,而j方法里的Character.digit(c2, 16)以及后面跟到的方法对比了一下java源码应该是没有魔改的,而while里面最大的运算就是这一行

bArr[i2] = (byte) (((j(charSequence.charAt(i), i) << 4) | j(charSequence.charAt(i3), i3)) & 255);
复制代码

所以我把i和i3的位置对调了一下,结果就一样了,我擦,看到结果和hook到的值是一样的时候简直就像小时候问老爸能不能玩会电脑,然后老爸的回复是玩会吧一样高兴啊

(然后就想到因为疫情快一年没回家了,哭= =、)

完整代码

# coding: utf-8

import base64
from Crypto.Cipher import AES


class EncryptDate:
    def __init__(self, key):
        self.key = key.encode("utf-8")  # 初始化密钥
        self.length = AES.block_size  # 初始化数据块大小
        self.aes = AES.new(self.key, AES.MODE_ECB)  # 初始化AES,ECB模式的实例
        # 截断函数,去除填充的字符
        self.unpad = lambda date: date[0:-ord(date[-1])]

    def pad(self, text):
        """
        #填充函数,使被加密数据的字节码长度是block_size的整数倍
        """
        count = len(text.encode('utf-8'))
        add = self.length - (count % self.length)
        entext = text + (chr(add) * add)
        return entext

    def digit(self, codePoint, radix):
        result = -1
        if radix<2 | radix > 36:
            return -1
        if 48<=codePoint & codePoint<=57:
            result = codePoint-48
        if 97<=codePoint & codePoint<=122:
            result = codePoint - 87
        if 65<=codePoint & codePoint<=90:
            result = codePoint - 55
        if result < radix:
            return result
        return -1

    def r_digit(self,codePoint,radix):
        dd = self.digit(codePoint, radix)
        if dd<0:
            return 0
        return dd


    def data_decrypt(self, decrData):
        length = len(decrData)
        if (length&1) != 0:
            decrData = "0" + decrData
            length = len(decrData)
        ss2 = []
        for i in range(length >> 1):
            ss2.append(0)
        i = 0
        i2 = 0
        while i<length-1:
            i3 = i +1
            i = i3 +1
            ss2[i2] = str((self.r_digit(ord(decrData[i3-1]),16) << 4) | (self.r_digit(ord(decrData[i-1]),16) & 255))
            i2+=1
        print(ss2)

        # b = ''.join(ss2).encode(encoding="utf8")

        # msg = self.aes.decrypt(b).decode("utf8")
        # return self.unpad(msg)

eg = EncryptDate("rFQJTvMFzm8MtBRy")  # 这里密钥的长度必须是16的倍数
data = '24024f8b111b3140f59d7ce8d4f050bb7d7dbae9244c71f8b6f1ec72bbebc9dd59525d8c4ef5a00d87f5299f44de3e7b4ace4e86d45d4d06204b9686635fa7ed28471803ddc8c3100c534ba66534af3cc94a035888a89d12a1194a69320ce40102c075a1803ece3a7b5ed76d0a0113aa637e3a602b7caba310e547b06f03259cd375e156d71f4b23e0b6c355c7b76d4e6ca6644932260656bb80e3495a1fb24959a5949a32461d46d5d3ae512cf67b831511b6c0120d1b9ed587fbd688556848e2f9bced4eefe8f23c62c523cc1ce67a3192336b2d5b0d2a41b68a86c89b979969d7698bde00ea19d13f88085ef708d4a6e08b3e2afc048f652b985447fd66a47a7bbe51ef90e49a93cf9397e3c18f5019db34a8fa6b2cf11cdeec2e264731e00a2ee1d53543f256d0a64a8eeb6287c618ac0ad16d110a2d09cda5e5e57321deb8a54a4a1be8a1b21ae62bcc64239e0c99a6919f7cc43444053cbc2a80a9a81a062d19aa0d27f12f864398ab671122a2c11dd62c492475bf28c7d99e761048787438f12edbd351391ee834645e88f6778970f71737dddf6d535b740a704e0b6e83644f02a626517e2e80871c4b924c522bf214cd287c5419ccd18fd17b31af2036121499cd1862c6222cb318e2bbc5a57459839ad73fac64d3de620a2b1b6859d72c19189c6d2c6fd53831a665e28f5bdd685e59b1985c41eb0d42e3acd3dc1cf7332ec821c0f4a56a45029ff97d38d67976d00bcc5a36ddc2afdbde8003c28343ee1fdfc0e3f5ed31b06f9e9d72e7d4cd7c64ae8fe67a9068d1e08817760270680eea6289c588c96e9c140e916b6c38234dd1531fbe0b6c6af487f5bfb4c8b200002814bd8e79e581217c6bb9e8b774a66fc4588469945a437a81a2056c3acf650ce1914f00e075cc594e274cf8c81dfa9820654681bea07dce7bba8a097dc4c110edc1179c5bee5f9fb14e2bfad3b17948b05250b245a7d84ede59db380524c078e1cef35165b33cefdb687b7e81e124adfc0d7cb2ecdac5217e9d03c9ca3f6880d8e46df90fb4cc362ea4c76ab3695a1800f8a2df1b91db64305c338051fe983e4b72d27f0496c5e4987dc8ff33efb6561a611a8f4c2526da9c5bcee73b21fe0379d3c6df3ea10731e68636a8b660816f5acef7af5b072126039e93856df062e8b47c6ef1141c48337e641c966c4bc6e0fdb3a60f7c05ac9af757ba89990f54acaa7295ba20efb82a3562fa06a87c2d8075a09ac9b561c1010bf67faf051622a6b6119968b932b0e8adc6c7420682222a5140307ed1bb060bade584043a1d5f87dd0e86f4f6fcd1366712519b93d81af7d1e45e1aceecc2eb9351e08c0fc98218d4c309e2fd29ee7fc3d9d63d0e39e35a93b025e5da59a7df6b46856e5edf66cdb043c9a9b83422e15b3d3faa32a43530974f1832f5e97c9d234e7c97dfbf9e0a80280c293e104941b9bee4a681de95c5f7de9c967ac54b3620556308b9ff8c151d235d052c444be31bd4cad65e4328701703f5bc84a2f67084a54f5addd61419ea222a472acdef766b40b494e03161c3d78c027793e4f23c51b3c4a89255c4fec7260b5d5eb8267f3ec26e2249610883f064eab853fbfaa359413638913de866bf16c3c77743d61adf562bff12c91f2b73fe30ad3b86b1d199d945a60806d116c5a2d50e87460ecd168552d768795eded5556b9d7a2627a378682d4d1ff288858f1958c71be0dcefa775e8a48a59bb62f54fab7366dce49c86be8aea21db5488ea7a00b873fa0087cdde4691de33c77211ab1c5ffaca0497a6503c173ee68f2c2c5f075e93b6ccfe505209f0f41223a7747b57766077e6ded6e4d07028e06fbf5659f9912b472c178ff31af92d837586be9b6ef71c46566b8ccf1e28562c7e0443b7a8d5b81d15aa7c1266c1abaeccbb93dbe5f78f9539133ded0194842c59a5949a32461d46d5d3ae512cf67b83f6ba713f256bdabfc4d1cf7704c8cee7e2f9bced4eefe8f23c62c523cc1ce67a3192336b2d5b0d2a41b68a86c89b9799e5ee6c505f1d18dc189617a39417af114e0b8d8d1a8ede266cd886eabbb678ca7a7bbe51ef90e49a93cf9397e3c18f509ebfb8d865f229f5ed850028188797748d22159a434e4536a7382db01f81ed5273e95e13755ad00c086583de3c2a8428e8210c7dfa0245a93d2fde455b277cd3d651a8374fce498f05415346fe6bae839f361cdf977c4e6a98d4a2eb449d1f2e1795904faa7ed9af3c03929362a06ef83bad60c6525bd0bba0af132cf1a748583347e10c778cd1a8fdb5349a67c8604050e64be67a50a2d8a9974a88a38041de32b9c99e8c73cce399bb4a6b37f1db03fe4d299d87a8a036f9c2f38c10b8a8b45ab54a0da29b9bb15a1d9ac1208b8b4ea58ad69e46ad927b9488a5005fcf228bdbfcdfa73340fa32876687a1d1a32685d28d937e5ca20f50c46b2fbf95483538839739e3d313f19c147331c792676a41d3d3a9594704e7e534115c6b78ac2305daddc288452d34232320eab7c745383e73be44ecbbc07ab9162f4bffe39743086993df6908c1a44492f8c02853ea73296155c814786ad7738aa4037579654695d250a34c4c68ca41ec205f3dc5dfec9c6b5c76f6a6baa2ca9b1cdec4e651a10e8f2b2534d25a10a317f1db7b25e3640e91df475a8042e8e8f12e12829046320fe878744fcab1e63c1fe0bf67539a7254fa2f3101aa492d314ea9936f925dd740e91dcc9610583ca4611062ae026e7ce63a3f3bbdc927ca9458c64b8fdc21ed71526350e17b041dc37efd50b5f9cca04517ee00b6bef24dd02fa7871672e6e9307ee903fd75a9138ef41254291826735e1957f154acfac79d2148fdecbe7471ab3ae2646300dde4ee73564987f403ab27e5d2ea7fd1d60ccfb42c822e2356c01a6db62c6f8b3f710850f094e3f7e29fee5eafc65523161c1fad23fd3ebb51e51a07e3bf034cd304f567557a42a5a2d0b3da504bf0ce77c9f10c50b5ec889dbbf40fa893de9f19a9800fda5be5228ad35c7ab188887960ab7c79fa4d18ff500b4808e264e7872a5af34cd13bafb1b3be4609bd0fa90fbcdb4780182a9b8559d1766d4784eef5b451ac0f5043dbe08272b1a064f339d3769c91e927b5e4d4b47d71744ca7ec4e8d523500bf6fdeecfeb6b8d32e5d67736bb2bbb2fec2f6be634eb0a70b456eb7e5c0ad745e72f15c2d8fde4071aaec6170acde88238c56f169832905477d7d56abac1536eb8160d54ce486d239ec70d8e2bdd27bdf702352327742c9e202e6c72064f41beb4cda534750697a051134f2b9401ebb83e6a4ca1826e340f620b8ddc972f297863ae38fef5da1965492b340a95e4056feebab56a34ff44a3d472c2b1cd5f53adc345e5897c687a1f099cc555f1fc57697557037bb13704ec17187b1c21efa403046700e19ad0a8a23c51f9100e6ab4e72bfe0ba3a8e05acf784578fa91d13d0a200e8b57eb0decd82ece317f5f6f2edbe95d60bc08f0a2bd27bceba06ca63a8ae8649872ceb7d8a23c51f9100e6ab4e72bfe0ba3a8e05acf784578fa91d13d0a200e8b57eb0decd82ece317f5f6f2edbe95d60bc08f0a627df955f65b7d914011a2d10514a2d02ccf09fb9ab9023144d9d9eff03738d1ab7bc1281ee228cd7551116f62e8bd1815f4957ead32c482a58c30179089fbc198c685fc272198cf4347f31d9caa7d5e1105c2640704101efa8f808c81691635d5e9ee2a6935cb8cabbca794c25de3304dca98f1da74ebc79eeddf90d5c39fecff64037687621eea0059fbd8c9816d486e1f8796c650d9cd777c9a68c955f82e8e83e0c72f37529cc9a85dadff7f315b0b3177db25fadbf7520a3cbd1f3332704e31af9e2d48edc0fe58e4c881ac9843f0f8d23033e5e5a9e14bc115dd8df5ceaf7d6090c7fc77079fceeba4d3bec82bc5513822d13f26f7e9b0ab1f295b9304c7f7da9ec531ecd03d9d9b736db25eb983acc11a132bf5cd83c1d7cc98fc208cfed988167e49d8fc9d507bdd92c6982a24c574eb997e6e635257f8412b5fd6ebcb549b3f2509104111cacf60a5114950cb1d0c1ca51748d67fffac56101e7a2aee27d07a98f53308be0962abcd1b918c073eb28cd64d4636d27fc90b3707c8beff64037687621eea0059fbd8c9816d486e1f8796c650d9cd777c9a68c955f82eb86902eb712f3fa5df166e199ce942c70b3177db25fadbf7520a3cbd1f3332704e31af9e2d48edc0fe58e4c881ac9843f0f8d23033e5e5a9e14bc115dd8df5ceaf7d6090c7fc77079fceeba4d3bec82bc5513822d13f26f7e9b0ab1f295b9304a1fe6690ebb84ca5b3d4b676a0a1aeeb61a518af85fcf086156a9c0b53acdbc957a7c0eb4523e023da0d8bb74ef905ff557d904c7c82d00ce38799f104fe44a41e3215680237b2fbb4eedd8adf8f45b2e6f66a496fdd84072ba5bdd08622e063c2ce5b72a695beef5a4ce1c075e4c8c998518f963073da26b5ec6494b452e9068ea0c237a1c55b6bc20281232b68a6276e3dd8f6b17e68bc2016620e09284c07db2e4accfb3688eeec5cfdcec303dbb41329d83b59ccb8305c0e45f20197b9edc4dde65403f38087a0448f789a5f8952875c2f772f756ed4d445391530fc174af488440b6eaa1ce74f4c7c60baf2633486e653999cff9ad660114f3d3ef4a7df1e3ca66b844a3d8924f278969dd004bfcc56787b51f7147ac5137ca539a61bd42a49019b4d5fe8870f9b7f1e4fb25053d1882cdfcb2203335ef70108d519ff331fa7fcdf3fb9cc7877a5d562dd86245691df475a8042e8e8f12e12829046320fe878744fcab1e63c1fe0bf67539a7254fa2f3101aa492d314ea9936f925dd740e91dcc9610583ca4611062ae026e7ce61e4f60bdbf9d73d623aaf67d8d520a6d844509c148bec1429b2de566b1b2c6d51f733b805e70b339cfe14af81ccc4141e1fd161ec529aa4ea838eff27c7adefc03fefc54148a6d7bf568ca79e71a9be18cb89e9b29603186f1c9521f6b656a2938c554e24444ec1ecc01a6206056d5e6dabc1d9d0b014bf58836ebf2f2417c49857e73f1980452f1375fa7929c4099dd79078e8066a3a89a5c61e0bc05ca132ba9b08268f98dfe09ae8dc38a4da19e06433591a693a0605578ff6d3c7ae60f3eb9f187c863bdb2aedc174fd03e17116136575b7c9eb1a2e2e8c2da4294df2ca87fd96b544eef201ea71bf33284abbc0e524cf952a9fa90eab44c50283402b699f86c22097858274b0434951a4dc9bbba820935afbc291476e912a06c80794ddf96e1925975c5a6a355c4aae6ed62690bff64037687621eea0059fbd8c9816d486e1f8796c650d9cd777c9a68c955f82e45a982d085b1920ad69859f6f116f8743f788d7d252f577a832cd77364259a526455c0c67216f1498de59991648434a95f20f5d879adffb87a396d003163cd46e9fbf8ccac8ec182e77bf5df5edc13432739fd534e666f7e9f7d83ab969899ab65b0191ddaac2398004b58424f78a2c33398bb19c6b5b3c292527476eb00b4d2991a6482654b401d33ebbf02eddf53689151e72c1abc90e0a94c7a1e4ef611f0579ef62aee494b95faaf2c8832d3dee45004352119a49d5036efb62974c065c3de3b842da837c4facb44d698ccf6d94ff245ceba85797804fc9b650e3846d4afcf5b7ca6ca26c98b9fb1a714d4d8b9af5eb47fa756740b8370800f16f57af039d8dc209a70e651fb4a5610d1c55e9e4f61817db7471b8c953f6853ddc85042ce7976d00bcc5a36ddc2afdbde8003c28343ee1fdfc0e3f5ed31b06f9e9d72e7d49943c3126ddcacdc7d1486d21cd2b3d68355340b2d91900709b23ad86dc267f7fd07e598978269106073c516a67bd7ecdbb37b3ef645b6ca3fea3779be856165c265eb4d820920eb4c46f15fa6272ce924ab5f08d857ba2ddc2233920f1df4281a45efd4e315c1a41dc27e900f82a61642d87a86a7174f8e70525733851d8343bd07fa5d9ed7652e2d67a9951c3987c5e4be59cfddd107b4aa5abcc358c295c8af7c8f829e5954013d7e9e00bc90bd6ca82d84057f4e4c3fe6661a268cf2b73d72a15904d075713aafa4daeffb6feb9683644f02a626517e2e80871c4b924c522bf214cd287c5419ccd18fd17b31af2036121499cd1862c6222cb318e2bbc5a5e2dc1ea084a2a3f6791fa68b06ac839a172d8f395307df546000d29a9f93ab58e13340e3e9dd4a9f05f10f8ff844d61555418cc3f11fc25e2577edf2938ec2effae1f96f66ceb9feb890c97087c2a681cf8d390d050eb96b4c6d806753cf42df753192e6cd184591e5bc5d8fdf86b34842efca8aabf46fecc2a9045eb8bdd025db051735a29a4c05115757ea4e4944d50b663e60487e1f0984e93072fb6aaea168981ab6d468d35538298ccdf4ffba8fb3a99f4d99ec1f226b37c2d7195595ee1557f541e607504dd0dd81c3a303ef66eeb81ddf208a19e095c1f03132683df6971cfb14c2cfe55fd4930cd2c28e9b906104f5ae28a3d2f40684f354aecc2dde96b2294cbaa899197a92469f6a3218fe23e8d5986616a4753cb61f11058e01d91d3574ba5e5fdabb5ede446d2616866af78e02fad26bb1e05b40a8a5f906f88a605a8d575659e88e5f5900a2372afba6e4b672a7bd75e9908a0a81439e2384832844590ff5e714caab0aff59e2f793d13ed09dd22819f29d93435b3753b6a35d6d85d95308de02e638757269d24be45e471bdaeec07c1f7a82ef47ac6b56dc6495d1d3d7ce4bc2d62d0ba0046f0b361e4c2a06d2180d9fdc1b58426450dffdd649ca4b19edeea0d81cbac0d8dfa7a30e9ea5b9e831236923ba6d9d0e1bd0ad0d39cbddf23bd49f1506e25cf0a9fcdfece3438762b4b689527b5c911729d4d40928f63563c1585d2efa12fe657827f695de62a599becc1c1abed9ff042e84da2dac01da048f6f9fbca7474fa11e020fd582418bdacd33f2735dfea56e951170637b9bc3458327f202da2d473b66e01c7c157cec17002f89273f848458906eea78124c35abf24355fd57c654dbff6e3c02e6efd73e601631ee759ac6d61205d9f6c9e202e6c72064f41beb4cda534750694dae375318e43713a09a8eda74950d117e195cdab7a0d523276767c633bef125c24bd1175cf76b5a0013acfd916ec1b1516ba89c4a2f2fcee37ef0ab424acbcb1d78be21480b832878ee7dde449f9d34073fc7fb15825574019eb436e51ddc0ce6c1b1eb4420ab8ba8e52dd6226b7f3162f33f7e7665c9f30e501b30aeee208de54fde133d068dc6445faf372fc98266a2b4db41cd9f105b021d0b22c1a6ffa951fe4c50ec17508d0a9a27d6788baef72b47f29f4092c866e93f171ee97ae3c70449ca524fc491e616a1941e6f57cd50e80d5ad4f8da89a06ef3bb96d6b119d5fc6ad7f75cef602dfb251ee07e21fcbc84876507ff1afa58116891772e2299171432f2861e8d4a3d0cd8ab57e511730ab56454ecee76664f1c4645663b1b859fe0dee9c5746ee4c4299b3aff7e48137e0572f8f2efb1f5bac33198126d939014bb64bfbf3153e7eb631b57ae466136f874d0470c509c4ecf6c1287da571dcf6d77b0b8ebd1e95db8d2b650be9051fdd42c6b22597b995ce05ea01a25f21f35c409ded4a2d1eeae13115947e9668860344a985bb996b7bc7f838cc3c13da1b3cbb4675576b6c6c7207a6c5911378bed552275288846aabe8763286c3374701c9f44f211898e25200e6b2671737bbe3b7bbd98d9a3e2103b64409043ab6a9db0005f0907a8d76827042a433043e6d67a3481625c53235dabf50076637bef3100ec4c71ddda85449c12e78bfc972908b397ae4286c9fb40b44d9fc5a94e90d7492c95d5ef57597070146ffa4096a98efe0038e44b4b36811960319e32c47eab5f07676d3a9dded7df2bf3136c9dc05b6c505bfe2854d878f14bc81bf712b6bafa3d29dcdde9bcea7ca4adc0593ebf4224a0182072237ce6fe9851f7e35781206f84f1b2c9bd98682d286e9ec491154811bd9cbbd6de89bc39b4d19e36b470638d29ddcedc4cd5e4350a89defa50c6d75fb5b634cebb76c66c0fd7cd61b3dfaf16b03d30bd90521aaca92e2ea6cb7b1d02737c656d8be2510e4970ca4017232c2829be7b84888311665756fb99305be1a8bc676feb7a198794a307597ee98d55ef76036cd498cea2771d979a72a00ee66ea79b47533b751e4992a7141a8d75063fdde8621e9f814a8b3abff2c5d510950d00b377012f7c9ad26db484a8066f2d1c82ad10b5209d6f6e73ef4a8fe766071baa2e1efb5d8508ed5ce855b99820a643e2f076f321ffa49736b88cfa0c53307684f7a7d794611e46c96fd348630edb3e74fa170aa7c4977002b78d46764603b906abf4e012e695391d8e5dd912d56e1874ded851c1d9366e820197fee8e6b941ff8f3d461e97217383c0834872f6f669b182aa0e7e597c18fe2ec57f15751f65af72065dc56e9d04039379e66f5efdfcdcdd72fc9ebae4abac95a163398838a0a9eaf550bd468923a00c7dfd92f816497f83a7148c1bf8806215f83e2d4eea4dcc6993df6908c1a44492f8c02853ea73296155c814786ad7738aa40375796546954649c391acc97a7f6b70c6c1cbecc28eef2da3ffcd8ada70b9ca189c2526ed040d5d0ac67d9d52f4165e446dfd0a1f0c966668fe965cd4c724c7e7783c9011cd6f2e17fb3d6d5d02858610e6087210c1ccda0b81324e999f86ac6dbb5aff02470d2a69201ced4a33c3b9e68febce2c6aa2a4d1834e1c8df21afc12fb45d73d68e4723f97df45e5b07d1042b902bb704dad871266acb7e3376bf0cec76e133d1015fa31c3adadd05a4c7e5acacef847c4f70bccd5be57f02f944ed8ca18655b4f45cad1dcd8a9b28e97fa0319a1c7bd704391b5ff536279627077f737e1bb597fcdc23a60401797e56a19c61ccad07194034caaa4fb8f053c5aa85d2e755a75a3c170e5eaa492631460a1cb3cea1bf69e6a137f9f07245c4b5413888fa5d4158f035d3511e5d45f8820f5043d270b5997506d22d3cf9b909ad360cc526d7cfe409c8fbb133c846c3080c78451bbdea1399aced47ba5c1ce11220edf63d45d7099f57ea9e75e18eb46609846acab1bc93eb21bb28b07f8db4b125cd88b857989b9c8c0451f8dda72ea9fe6c5717202c73b8211b5e78441c986393f8d3a0c837d443f90d73b021fa31f6bd5f31ca57e4cd9bc6a9e998f5a74818cccc6c2be9e6be016188777cc1c868ef2897199067edf0e067ef78fc920f5e469edb774bafd2d5de6b7df46fdc8d0652fb42bdbed22b9a6020935bfd55399a65f43f63980ecbb13e98c2e2a0d71f7bbd8f1404d1799bd8335c52159bdac76acd8a10b150bd252ce50df44828d3fc3a32c1eada61846bb982089663245129158a6683edd1b22d6951567f37e10e4b73707a560c456461570181f0f950eec60f2eaee3566803891d92065b703309f55abcf4f96c3e67eb16a72cfbb1894c7522432a7d82fb42e06af1728bf4cf71a399a6ea6edd971408fc81405463fe322e0d53aff30a12ce4384bb4f3ddcfb45bc7321555e310a36cd4b4498b303e4ea64fa5d3b41078a1e8c2a0d03b79af6718f7d26946c5e01bda3dd0859b13bb182ed692250a58b389215654a611f54fe2175bfc163c18c1d33251ba803c0869699bca3652422ae95ce2c1a8214b5491677e1d9d0bd67fbd7abf1cd2a3a73bbe51207f06b2f6bc88ca898d2f38e6aed5c5551d13c1f48fecbd14f0086513f6fc4809bcb87480148be190450f8747312d360c128ab774d9866d553e42dc89e6e1ae46c9c65d7d96c07bc6c635236d5c7248cd839c88e178fa1f0c6cd51a7f8484276fd519d5fde01b780788937976d00bcc5a36ddc2afdbde8003c2834994c56bd4297689b4228481056f860bf9bce52b638526c9315ad05b77b09a8bbd3a1214430bd1e15d500ded038b8da2b478065349ff4fd56c202cfb67ed96eebfcb7d9bb63b5d9926808b2e5875ec564e4cd13cb24db3eb91bf62c6d69fb1018dea0fb017519f553551f6cad9442d0b8549f32aeb7ed4b2313a235af7cf6662181a38b581220852f0b977e4fa4e42b16aa2c486a6e8985c86ae8269cba590a4fd6e1dead9ee8631167183284d9778ac502d510137329d9e17f7eb118f5823fa8103d196cdbb62e232f40635ae472b39077fda0cabf454b53fafb7fdc74bfd81ed79e09669da782fbaa71351629c1bf7d7e457dcfd70a52918af95846ef882fbb1374c6a9d9015c23bc478f8b6a62247f9b96c6c9cbd5a40e3a68fd4c6e0c42e6cb1ba4186cac7ec605dda044d01fa45d06920f6557d07fed5b659363e442eb6b87c3c6758066aaf93bbbb0bf33d71731475bff049fbe5ee4136698695fccb11d5034809de5aa96878f57c2c1b15efbe8c86b44e7ae14d8947b987a146ba59c3d6a419afac246724578541182d371ba6ccea8c221f27738ebe920f0cc8d234bcd66587a0f6f3d3f563fb6e1a0ecfa6e231a5733016f6388f36f72e8eb449c81fc7d464c3942ca35fe1cf3dba15a802a5d382350661d37b234b359ce40b9f84691d1438b561618860789d0ad358aecc1e7083235237b0493369b8102e00b1bb3cbda4b7e69741989aa691e508a93e2ddd7d8fef2bbe9ef9b56eb1ab7ef9bbc47c2406b4d1229ad618b846f3216359e4cd73677a78882349feab52398bf15615b02aa88012e9d1a6c292db2c77d55067f1dc6f63565e930216bd71b8a0ab7ae00c3ac74ba8ed36e3af6ff83fd91115d89e2ed594e0575230236dd2b3d2d5496dfe18383a10cbb8299be8827e174cfabd957c5beac3c045dfc7229091f171b30b51095a23957e2f6e55c3086bdd9dda257336a5eadc301abbb4a89131ea1005e2bc04742433f9d2ff5a7a3252d15d1f51f8ab876128295c9b31afab0260a1e9b0093d8128c9c770b400ccdb48c1dc547252ed579025398018ac91ee7f263011f5f3baebfaec21c750d76774b073e6d3b1df3a2a366b789412007b25f982a400466ee8a2ed5b827e5a73fcb471163df4f2c958884a56a04e4712a9257d7fe6311444476e2b19cb6c438e2d1bfbedac3e5fe4a106fd152c4f2e62542973a84ed65f58b6232f8d2a1acf02d1afa10bb727abd8615f39188142e6527c2685d29575fda0581b2a7644af85cd681f2848607315cf9fd50f39ff6bd6e42f024d7dcda423e47320846290b129db41664e3ca759d36ef71074fd99ff2d34fe50185dceed5289a3d8e92332a0e7a6e294c0f8f3da130ad36d98839ef99ee8f7c599593f31786197cdd286c9ba09c1ded93db1f58c0c63ce91a2174c916f866ad801aa7c111c2369f2732986b2d36ecb724ace420046573feca1012d302854ed7ad54ee1bf29e53f696d70ff9e0ecddf94a8913c4199c43c3b31250383d6b5fb80934b77beb103a5fbec99e170b6a8d40e57790be474c49b2358dac6e5ae604e18612bdf59bff4e9ab3b3428c6339d16e40d14517c1b3bcc2d0d42d10cea522e2703d4c9aeee63f3a9874136542df5169611b8548b5063065858d428dab97f05225e064e42fc4653116de047e62599be689d36b5b6a2c88c58f2ec64054cd95f95c45a816e2c4c08dc510fd877316730e4ddd5c5db1b128b324e2712822d7c90811d7ed56fabc5a6d79f7267ab7a1df836208b0018dc000f7cb2751c558d36844e70a31d8da1815b2509f561126b306aff125c1195f614b457b838509ebed5bad8e913e28939d9bbd37a18eb08d9556066c946c25b9f2dc9c5289299ec2205b9e041a11094d63268cd3c67d3b15504549ff768e4bec4e1e8190894a0a75f03d4f47cf872fe1865ec4c65ca6548a999d6cc8ca3eabcfb6ad0b9fd2666c87420a90b4b6122835678874b0177506bd3c118dcd879886214ae6dfa23e28447256dd7e0b9d0ea96e2a1f75e0312406f8c4369e84321a4fc1ddb06b0ace269fdc5df017f7bc2ca0a6a53046fa3492a1f1df996272d6221ca369e9df55de6e25ee52a02130641cac3b1226fafeaabd5f187a4fde2703e10a12dc362a2503b94985d50e2bc6e62b37a5830174c320e9d8189663cee7b54d7d65f12a39fcd25ea101130a627f1ad55016e22273d97e129742a1a2aa27a1d9963145fe4c490ac3c424f0418eb9110f9de8674a9e14339ced7dca090b472a2525d61441d1b7294937db38b27313b699759f0a278a5250e6440307b66e5c9bbd7514f59e49bbb20c7c38bdac72c35cb24131e817d8fef2bbe9ef9b56eb1ab7ef9bbc47c2406b4d1229ad618b846f3216359e4cd73677a78882349feab52398bf15615b02aa88012e9d1a6c292db2c77d55067f1dc6f63565e930216bd71b8a0ab7ae00c3ac74ba8ed36e3af6ff83fd91115d89e2ed594e0575230236dd2b3d2d5496dfe18383a10cbb8299be8827e174cfabd957c5beac3c045dfc7229091f171b30b51095a23957e2f6e55c3086bdd9dda257336a5eadc301abbb4a89131ea1005e2bc04742433f9d2ff5a7a3252d15d1f51f83ec3f387c8fe3995a2b88800fa30ca64a7eb9e7c1eb9d1f827ed24e3cd56d32b77734d3479db6e0f4117ff38e98f16a62d32aba517bde8bf4687f6a2a6dadc8527440b0620276a42a0817bf84888811f9010bb9de605c579bbea5540b2685e6fb8796bd89d9ff63b9b56924db3aea8cf615e004f38b56bb32cef0b7ee3f3f55f97c14091ad83ba2ea2f1677fa1dc814c5d1c0cc9b1c1502868c7372bbdbe81dc70521ae4815281f1f8b7baa6e2a43007bb62f54fab7366dce49c86be8aea21dbc2de580ff65e802de5c25eaab5d0589c73757cb7571b593a769b7c47387f90ffeaf588eb85dacfc51e366bb73bc48e4d31174ed5d80a1d6204a001c3670e006f58e75130c1921e80db9db8af3df03ee59662f626272a953bf8ef7de2e37801edc425eb2674405a81f69df5eeb20e9e97c67af3461ba6e1c1f7b46a87a748529579e3e622cbc3f0d515e461fb29126815dab27ac249b29fbd75e2ffd26e50f58dc3e7d4e8a9e8e559c419ccedb17f5cf982023225ea87df37a92ee34af0412eb6a58ad69e46ad927b9488a5005fcf228bdbfcdfa73340fa32876687a1d1a32685d28d937e5ca20f50c46b2fbf954835383de258b9cb11ea777403771d2f56b160cd8ae839a572a039de525f6e639987fdd65c28b94ed3461828643064f0d7dca235bf89c1698ed941cd35a7e571753959ab25bccf72268b3b41ca4f7b1dd1cbf984d98e67fea4894ffbc136961d5bc15ea6d79f7267ab7a1df836208b0018dc00a2a7210637f95a923bdc31f4b94985e2adf4a1bc4fd1e29a624945f4cefca0d1b60ce2b299f5d7c26d41a4cd6d069023abd6f781a71bd973b31ad0fa31cc3cfdf2554b9e80079e173828735808e7e58ae5c27cdd0d2cf1eaeaa3243aeae7319985e4770038f74648c81bf9fc4df188cc5f9d5f1248620025cdbbe424cf3dba86bc4c31f2521cd28feb56f774e8293b10ffb5a2c847c31eae89e8a6c9e671358068a941cb4a8b949e8df285e286a17c2c2b17bc6ce64664b93b340bd9bf2e9921db32b8da1dbb423f89079a36d12874dd6fabc46a095a4a7e467332ec38225ba108047fef0003ffdd248bedc5cba7e692799e4f82673d29160a57a76f99794943e94ee0cc875ce2cc5def35856482fbcbd3ed291394da1f627220962623453b828fcc1eac9657700d7e26c7b7d85dedb9aa433555d89f17a7daec3846d1f0b64c829f7836156592f6050e3712d25b7c58bce5625931bccaed2f68f276bddac1fd7f59c31976be0e4c0d50457718013a42e77529017af026009ca5dc64b7819914f589b5fd6046f9b593da905d2c012ccbed16dcc19217335e43f17dd08c8755cb2b6e7ce772568e17349ee038decc81e1b4166aac9c0b77deac778309acc1209eeab48b3ba8f8481a89df13327b5bd8c1173bac55dcc8541b1c9a245f25a3a529358424da6b9e285a8a8add1655e6f8a821267473c4dbad3cad78e5f8aef20552a2b4db41cd9f105b021d0b22c1a6ffa996e19c50bc6c2deefde7c1c7b7cdc42afe4f33773880da3e5d2c1118f78e6f6404742433f9d2ff5a7a3252d15d1f51f83ec3f387c8fe3995a2b88800fa30ca64a7eb9e7c1eb9d1f827ed24e3cd56d32b12e393d1bae105dd989cff88f21a053c5ae041c903c1df1f91d52d116f052fd5e119739b0929473baa07373553ddcbdf124c35abf24355fd57c654dbff6e3c027e0b81d1b465a4f4faf651ed0a4d90cbd015f9290f987a764d45c7066a1f102a2477fc4c30612f2d4706dc5455406dc09fc61739ce3765d89fb647021d2ac02646595012e467d89e5926e7736965b6fb2b3cb8c2bc53c63d461620a0c2d2a792ce083bcb4982f83cc644a57dec8e136baccae695e6a370756c8cb05ae890a4a0ed95d45c30eed7ea7aa1c4b5446f26cc7d32e956b11730d53a05a9d265aff24c3cfd5411d806df4deda2f5fdec6822606d4784eef5b451ac0f5043dbe08272b1dd197c74052bc79989beb6e983ec9d56d452806db73d54f2007ca559303561d3a66fc4588469945a437a81a2056c3acf6d5c32ca80862b0a20513b21845d9b83e6024be794529fce01a3d7c8b13c73353b8585ecca7d0ebe79c1c1bb277d0bbbe54fde133d068dc6445faf372fc98266a2b4db41cd9f105b021d0b22c1a6ffa951fe4c50ec17508d0a9a27d6788baef77695980ea5aa81a021521bd059e0bc3a3fe82ec9052dfa02cb80ac79adad2457e80d5ad4f8da89a06ef3bb96d6b119d5fc6ad7f75cef602dfb251ee07e21fcbc84876507ff1afa58116891772e2299171432f2861e8d4a3d0cd8ab57e511730ab56454ecee76664f1c4645663b1b859fe0dee9c5746ee4c4299b3aff7e48137e6939afec5a7537aabf9f3323b0ee24bbbb64bfbf3153e7eb631b57ae466136f874d0470c509c4ecf6c1287da571dcf6d77b0b8ebd1e95db8d2b650be9051fdd42c6b22597b995ce05ea01a25f21f35c409ded4a2d1eeae13115947e96688603415d1b98cbc60e6360a80166988a2d595b4675576b6c6c7207a6c5911378bed552275288846aabe8763286c3374701c9f44f211898e25200e6b2671737bbe3b7b2cac4083368406785ea17515c3a53234a6d79f7267ab7a1df836208b0018dc0070d452c3f91172c2d57a524b8204725b8f19b368846c0abce4078c29cc6035371ce75225442dfaea4474e7454d9e1b4c50d2c97d8ff017d8d45e2deda7083ff9ffa8046146f60684f8759845639f061c11c89b732535290c3332f978052569cd49918900783c84ce1a441ba1ed6f1e1f7b915906a2d72641ace21b111309a2f5e4d374302726a774a468fab9c09aa09161b20979d2f2bd4e8b0c94264c7b775087328265242cc61e5107eec1f894ed5d9099784a57e70354f726697d1686411a902919e4e5ffc9d022e5d6346038f1c402497f356a2a55f341bfd7016cc0d308d49834564c2f19615ca0c0a33c8902ff7cf87caff695d5c3557210668fc4048aafed1b584fce20ce60e6271cb8befd558f5e593276e4c66e803146e37bd11a19955c44867e0fccace4ae4927c6ccfeb4a9794e16bb985c296d18d00003bb73d9f43fd2844eb50ec77736a508483a37d202a76bca58fbac44f3cc1db47c108f0ec8b287699c6997eabd275baa33b23413ee46fecfb93b62f55df75ac94ef4fca936c162f5f8adc46f40f85b1697de2cea4fdd0f3406bd5676df53f9d9632d6ba8e3438762b4b689527b5c911729d4d4096c934e7353c173faed75c15491df05c70c1b61b4471400a9324ce53e0318cd431acc653839de21e124a84e38948cac2d46cf7ce13986e0578f91bbfbfc6e0db6e197f6de5fe8093a83cb494f12d0874ae4da557b912f309b76515241f3d7e841df9bca694c39371eb4829d4de492f5dc41a9fdbcdd3ade3dae20a27f33b3d979c158b57ee7abaada9921b5aba24a7657a229a4f41f8b66ec92475f1663fd3cf349ca4b19edeea0d81cbac0d8dfa7a30e84c5c9db0d567cac63d1d1b4ea9ea39c3169514f7473bba6cd221461ff839196d90a58f7c301a988572601d1392567a0b9acbff3b3040b5b1e471ae2d4642efc6a62efcbaa08659e8ecfc4b415ce72609902b5b1e129d372e0b2e0b7b6e221bacd19ad563a337dae67e338f106c629d1b8ebc9947d8c2c073fcdd22216602337ce90b928c9a30714a38edac92500ceff98dad8607b07461a32dc29102ba3cdfc24da6be032043f5bffa4f6801863deac5b202d3e8a236a957e470af19fde0bac247040ab5c8827dcdad792fa8b61ea9b688a3eeb4e8f9202f725ace4a946aabca578c2c152f80bef8643b37616ef8a61d797e0eb6f72a049818123c8fff773e566c3ac394cc643b6c759e304dddda85df3ce9c64092ae1170ac8bf0e0e6db2fe1a001ed5f216017e9717ce2cc7e94a3dda4114d6f4fbfd2bce98d6997eb771c2760eed2ba79e64573899b494cf48697a71199a9091b6bb00a437201da2c2f3643bc21ac569147971ba62cb2c73386a266ebfffd182533f840f4fbcefaa8bc83bd94b44b7dfe10d5f5950f69943e37c1141a4d90a618122de4b5aa542432f5d81f37708d0e9c0683ee7ddd7dfe69f455797fd58d92686c374870ee5387d28185fa4ff74bebdd5168c8351ea61355e8dd58e7fe0a71494c267d6786262885f04971f27579c4767ee8422a45d14a23394af6cfd3528d0ce2bb1656f62bc67d286adde3db9a5bd1c2edb56a645d31a0600a6970d5ae157b400174f43a0abd2a2787157fd85d53855bcca3b9c0fee5ea1f36846048b0e5a3b044dcd0c241a0630c5123dc641fc71a0f33bfefa2582287ef97d50df44828d3fc3a32c1eada61846bb982089663245129158a6683edd1b22d6951567f37e10e4b73707a560c456461570181f0f950eec60f2eaee3566803891d92065b703309f55abcf4f96c3e67eb16a72cfbb1894c7522432a7d82fb42e06af1728bf4cf71a399a6ea6edd971408fc87ccb4d40135c025c348d3b95815620ec93e2344fdbdfd3f36df29ac12fa911b90fb5816e61885fbc36fa871a177ebb09b7e9b946c242331dfa0f103cd0f619d74479052e1ff6153ed46ed357a8594c3000773f089e68b2af2e7f5ae84073d8e6216eb2c26d2a8a691418355686826230a9dc0908951e8dc4999d941baa93f995f6d38b7a0153f63f59f4abcb41cce83f25bdafc9ddf5c8e19e7e7bbb623b44fe1475a8064d5b57e02ceaabfb8f1cbe20dc89e6e1ae46c9c65d7d96c07bc6c6357294604e0ed21194be807b07bc15d81352e5b8008291ecf06288d749f39c9c8d7976d00bcc5a36ddc2afdbde8003c28343ee1fdfc0e3f5ed31b06f9e9d72e7d4d536c2c59cd95d6184d661b4881734bb9beac27c1b4ee1d168ad543e78fd7920234dd1531fbe0b6c6af487f5bfb4c8b2dbb37b3ef645b6ca3fea3779be856165c265eb4d820920eb4c46f15fa6272ce924ab5f08d857ba2ddc2233920f1df4283227384fab0fce57ce44415365e170d280fd8c097fda50335fb10ca2cff67e320db2024a818708fdebe3a3574a40751408c40df2d9676870709f50dd3cf05d910bf8c0fb7966fd86504141bd8981450ca6d83bd35a4ffee2ccd80650762b82e997c2ab65dddbf7b6821410cd1b5fa181c83cb43bdb1dd3c4f9904b7cc581eb0d0af50493002e203697f47446e969b956a0b78fe7498eb67dbf7e586ea07cad1ca5578ddfcdb837658f6dca894141c46f5babcbaafe923d48fbf5df81992f99d6e35b9cb91c4809318e4ab8cfec5b5c4e2ed1dee8ee015d16d9628be2bde7551000db5dec01ebe9738d4b38d2e27e4ff00ea96bc8f1caa5cbbad2d8b01d8b99fb0f187e9a80c9d8d83666b240c454a9b81e8c2a06ea9244d204398ad36ac53085f437a0f46006f40dcb2402535929df13ccda650a976b87e7443e313a4c45549651c4ea48fad2d0bdce76d5a2b9e648b961258a1f40663df13d80d60d5bd6aac5b8ef99caccc219697d681a673d76ed0550df44828d3fc3a32c1eada61846bb982089663245129158a6683edd1b22d6951567f37e10e4b73707a560c456461570181f0f950eec60f2eaee3566803891d92065b703309f55abcf4f96c3e67eb16a72cfbb1894c7522432a7d82fb42e06af1728bf4cf71a399a6ea6edd971408fc87ccb4d40135c025c348d3b95815620ecc9c31bbd9cbc38e32ff40e34163be81c0fb5816e61885fbc36fa871a177ebb09b7e9b946c242331dfa0f103cd0f619d74479052e1ff6153ed46ed357a8594c30b122de6750eca1e5940d1981a4493982a8d0a232145090d22054f3c5a380ed5b28884228cdf373e87e1710baf373fb4c7f812cfae409d5ef5f94c6e2dcb213f9b8772bf7a432ee204eda47bffb9c508a5369aa1afbdd9aaaf64ff4e70af41635549419e025cd45f2b4de8238101ac95c728c326593514ae42e9ab5a91fd09cc5ada549b605872c06e5af9b8f4aedc2e7f1fb8b24fd024f2fb1f3c412ac9f299b43ee1fdfc0e3f5ed31b06f9e9d72e7d4bb6290171d66f958487d22b0663181b4939f83fa15e9d1d030cd9894d65af49825a778148e904542f9764a6cf2fe7e326ed8f4b21173b1582b74750c4d226bd5ddfbe4397ae131275ee32aa8adfb4da82f1ed956ecdd729d53630bfed9f9e12a54649a4ed8f456561907b986637b7ff1ec834a8eb5330629414f12b8cf488e25d85629887c1e784ff76c30f5527d76b4278211ff4bc4809de5427a818fdf8f0f11ad0e01fc39a841e3748a7d422445685dfdbb22fb37ef754f88340ee567b2d9440f086e1af74f3622a30a9b6bfba0b86f6c39636d7772d700dd715929e9700a233b894f20517e1ed2047351be9b684c69ac63d1299acdbb68f268e3fbec69f545f70b78d88e53e02ec779f4d5c23d943ae9dd54b96ae3af9a6fdd6a4426d7fc99b6474e553d04935688f953b627a14056878c85e0db7d6d8c7e26c8cb372066880bdac58d9b2281a83fd95e27dd42766b19fc5fbfd61d8e76f28e43ab8da80f21cfacdf8ec07515cd1e81882791474526e017ac65c8bb8431b3700bbb230dd4f6ca3db56427b9b5d6dd09cc4a7ac74e8c86b44e7ae14d8947b987a146ba59c30f5986c5ba5a550214f61268e0895211914132cb7ef071606ea48391ab7ebede7d77b61c6029825b1941b95f4cc8ffa56f5221ec870810c64d5423e771ae88707378cc87b5f5ec5638bf5f2d3146e3e98a4de40a6195659a3c457ed90d49a93d6928e519753ff98f0f67a04b944388bc6cb0a2f97ae55be51793a917cf28d402ea357f774e7f17ca1c1fd402d25d2e9a59d1adcc9a0624b3b6f98271004b9f09e4e153c657ec522f6a01e010487f0c769f5dd6745811a01ac2bf2a3cec3ab1df35ff4d70c149ba32ae87b88eeb028be3857895929c7053cbf0678d23a516d51779f789290900c66f9c64b89ced646a45b9468cb44b39025c06077601948dadfb0e794d60c424777c2bc079c288397c596a5abde05a354be062f5d2b41d10cb9fe2c56a51a78af8180dcdfe9b4b4ce71bb158c4bee8ef7ffe1d8578884672f179dfaf166432d1f3a3094c82341c932a36e866bf16c3c77743d61adf562bff12c9ad2def52498128121099e8264de20c9bf42eed76aca5d35a9187e538e58d184e23d963e327d2cafb275d2bbd6c5cb3d21ab1dab1c19663372f153e5b0fc502ccaeb52ebbc95369e7b391b6ed14df7718de3b673c4bd2a412e600a5576abf3865c80d7f4b4a54460f013b3d34bbfd74dd9ca49c909830ec39c16c4a10ab5d102bb5ac055a7f4b8fe2ba8b99b952f848459fe50c0f6afb1966599a4e5170d1103145a3e53bb7c8e13be3c6a9659f16b6589d3fb9b5b1145e1f226f7a430f9addec980f774e7f3e5bb0c8f64b384ed0ad8ae1440cf51f4eb3974503959eda6aae5f6c9cba1196321f9be82c43a03e11c4cbd88da110f7c87a45180252fd1e0e68176f2c0692e30b0e86a4919154f7b702a1c4e04fbbbfd9dd690662f10057954ef081b67fa67239a668ebedd04f42391a58b28f8ac6caf659bf50be1f98ac83fcc1e866bf16c3c77743d61adf562bff12c91f2b73fe30ad3b86b1d199d945a608062823ee1bcb6ee95b6efd9036a22a4d8e52c615d359e299c7b3427f89fa223efd91f3a79e596fb5b3a585f3fd473d529c8dea0fb017519f553551f6cad9442d0b8549f32aeb7ed4b2313a235af7cf6662181a38b581220852f0b977e4fa4e42b16aa2c486a6e8985c86ae8269cba590a4fd6e1dead9ee8631167183284d9778acc6632bc105c6e1878624c026d1fc55ed8103d196cdbb62e232f40635ae472b39077fda0cabf454b53fafb7fdc74bfd81ed79e09669da782fbaa71351629c1bf7d7e457dcfd70a52918af95846ef882fbb1374c6a9d9015c23bc478f8b6a622479cd2315497f0be5ddf6c099e8334e25b31e5d39e756ce49d9229eab1515673aed06920f6557d07fed5b659363e442eb6b87c3c6758066aaf93bbbb0bf33d7173958758f3d5752e4bc80eca47cd908e9300db5dec01ebe9738d4b38d2e27e4ff0fdbc065abcc7c7cea9cb5b6cd39616216d72ff762efc7b92eff3988a4e4b3532bdb26e0ff57ee876f7e1c0dc3f50208471355bb5237f0f4836cc665b316e32509dc1de0ff4af7d58fd8a7775fc62c37cd61bcf0af0edfe4e5570552d2882c9f800cbc229c268f970d5381178e24536441f2c7b34bd677eda34c58b2d59821f083f2b131ae234cfeb7ab14bcb3f07b6319f9020141f305a2e58407f107f9d4f1860e383d7b50a0a81b6bd6b8051ee11101a57e69499e62ae5ca9421b444a43e4ee8032e50b1ecf42bc69b63e1e2a86d620ebfa70d59723c64886382394dd955d27cf87caff695d5c3557210668fc4048aafed1b584fce20ce60e6271cb8befd558f5e593276e4c66e803146e37bd11a19955c44867e0fccace4ae4927c6ccfeb4a9794e16bb985c296d18d00003bb73d9f43fd2844eb50ec77736a508483a37d22744f145deb4a87b936d755d5d8198a7ddfbe4397ae131275ee32aa8adfb4da819dd7b5e1f147e7fc9f50537364ef279674c117138e2730f87223559390f4583d03b79af6718f7d26946c5e01bda3dd0859b13bb182ed692250a58b389215654a611f54fe2175bfc163c18c1d33251bac022939b2ae3cf5c92e51674be0f12bb09a1685bf5b95777f00e9ba8eae43148b432848e4e4ef65f48fcfe1bc54e697dc3ad68416c55408de0ae368a77057bcdd352b307f9719e10befa562298d58a39f36af2c9ab685bc0fa0b35fb87124c555eb47fa756740b8370800f16f57af039728c326593514ae42e9ab5a91fd09cc5fe59cbce2aa093c49263411a8d800323f1fb8b24fd024f2fb1f3c412ac9f299b43ee1fdfc0e3f5ed31b06f9e9d72e7d4bb6290171d66f958487d22b0663181b45dcdcee4e9a6d70c2a96751873a06acd08aa32d951d6b96366263b09b7ef2d146ed8f4b21173b1582b74750c4d226bd5ddfbe4397ae131275ee32aa8adfb4da82f1ed956ecdd729d53630bfed9f9e12ae72d66db68c0166214094052604cdf1ae5a5d5986dfb88a2460033bfe9407e03d85629887c1e784ff76c30f5527d76b4278211ff4bc4809de5427a818fdf8f0f11ad0e01fc39a841e3748a7d422445685dfdbb22fb37ef754f88340ee567b2d9440f086e1af74f3622a30a9b6bfba0b86f6c39636d7772d700dd715929e9700af96f9ee97418aa6a4b720eb58d4bb38669ac63d1299acdbb68f268e3fbec69f545f70b78d88e53e02ec779f4d5c23d943ae9dd54b96ae3af9a6fdd6a4426d7fc99b6474e553d04935688f953b627a14056878c85e0db7d6d8c7e26c8cb3720667b68da671f849012df15c83f432830476b19fc5fbfd61d8e76f28e43ab8da80f21cfacdf8ec07515cd1e81882791474526e017ac65c8bb8431b3700bbb230dd4f6ca3db56427b9b5d6dd09cc4a7ac74e8c86b44e7ae14d8947b987a146ba59c39d444c8e4cfe3d8b06d2b4638ee0988b204f160cc36537a1fd26fbbb12fa55196e7da3be4b7927381c36d4ccd3dba3233376a1337fe68b0acc4f8dd5e9a18cf889af531687e5ad891c8af2a7abcd63b05a4ae08511e72db079e55f5537b856ce701df0ace562ef2d37a2d52e0986a8123dc006baf13fb18e5017805f190384313dbb945ad533ee8b65ad0f61e09a07e82b746d3b20ddf4f3e4021aa1dd577d76e524c1274af2bb0a41a74dfb99bdc2f85b44dacad8257f7c29b64eb2dff67b50a490b541123805bf052a07e5eda778bfd4f2c43a80d5cc220be3db95e748769fe1a6dd003199bc9d00ce96ac0e3e3ad5ebd8353014b1a4f3a833522ca2ef46342bac528678f75469eb86af35350fab986faa6605bc9664c162763f6f85e817b308d7b36f56a69aa78fa7b8c1d22586355abab544e3f6de6d79691dff077f81bb7094f90001a3f85acb62c0f56364400031fe4babfbef67037f4b42d1908c14a67cbb86459dcdadb325ab0f5ee578b3511fdbde6f881062c8aa86ea3c48140020d67983dd2fce1f9d0f3cc7111d16c3b1b23beda7c6f69b02477e85d2785f38ef457d9a8581a7fba5712fb1702d43ea78eb027c9c58675bb7a4136f11ed14155a7c64bc819fc90a6fa86432b267af75dd254ec8c90adb52216e2fd27b6a12e4596155c814786ad7738aa40375796546956074ec2b8bb3696b91cfd215b6563b03c102704adcc4dea1dd5831b334250d6234e6a74434d12abbbc8185b2cdcc416d4f8602bdc5a71a34ef38b2e4746896abcff0f850e995b5bb01d1b4be770e877a3dee6f009c872c09efbfea8d49e2cd81e03ced436934bafcdf71fe62853b23df1180dacf8acc39f8f3a4a4e3488397ae0c8e3c40d4384dfc0afd260a78625692fa469f5b3aa1ba83d2e7f10e5574681067f5bd44702b55e1556f84792bc871e858884a56a04e4712a9257d7fe63114441ca20dd7b0743fe1e2d669d43def51b150fd76ddd165fda40acd978bc2b29200b6232f8d2a1acf02d1afa10bb727abd8d88da110f7c87a45180252fd1e0e68173b454fad6fe931887d6fb81f88b8afe1b258cffadfe94e4668efb0a69eea0622b8c56f93f5b4e38f68d01f4f1c361753e50342ee9365ff06212e61822062e000b12e5c738dc36816f39f99a8b5893459a839be77e3ca33b74ef96e447b74e4a07d21b3eb6e226cfbda51c3fb6896e49321e46d538ebbab318d106d6cbb9e30aac465fa901f37a23359b68fcb1074b5ff08aa53068391534aab3d8a337f60fef0cfccfb8632f251c682099a3c995b4ba0c2c7342b667c29fc6c35dffa256a7680da504bf0ce77c9f10c50b5ec889dbbf40fa893de9f19a9800fda5be5228ad35cc93a4a6c5ebd58c9b668eca05821e5c3560a0bdcc9abcb51c1869f903eeeff94c21b5ca510ea1f538863f4820914558ac9ccc4718c8e06e3504adf363bd59f818f6c151ae7a588e9557d77512851ff205a2b7cd93ea100724206e38d646c0f4c579ef62aee494b95faaf2c8832d3dee4e8490e170952bdaa04911e3d035c289528c621b5023f7be4bdc85f906c764ee019d4f2c21151f8efd576638bbe116ca3dc271bb661c5cea36058792d7669163f9e27f47f7b4781e0bb0f9b07d9d381dbf78468fa13bae9267b2e7105729bb68b98cc3137571002e926eddefac571004617fd06be69affa25d7724a82e50557d0e5fb00322eadb5b0f6723ad0c53b931007eaaf89f7e5d42b7bfeb0297ce9784ccacf1c70529814e8374ef535753f5b61d071d4bd5747062094b587b2ae3d3816c453a870d9ee6a29fafaa90a47277603b62571a97a1ccb4e81ddc68cc7ba7735b55c98df4f0d56cadd8524dc15040cd0b9406abdb7d1fb86c58e27f8cf210b5412001769da35f991e4a07b906b0ca2f0185728ec6273707dcd0c3f5109f8bbed66bb9d709c8685e2be890e90789c536363a23c3c470238bb5ee4f60843c76d5189471fdec374a54044cd552aef90097d45bb940e7b8a109a4088b04977d0bc5ffe91d16556546330e8c1ba59c658613eae13d0862d20c5431e7a09f68c3515612135ac894ab109410e940f716010b301241af52b60d078626b476f950aaddb6fce107dbd6914ef660d2ca243680da123f7cf8ca7058f38eff1007af4f0a90834f1ff5643a9b5c5e3e7b79f803a064b8b28c39779ce111de1b2c751f708031f5f43ee1fdfc0e3f5ed31b06f9e9d72e7d40d0c1f1b08993856eb639242d6655510500c961439afa5ea12d181d0a132b06268ccbe5cb66f328e8d0f27665bb0e681f076f321ffa49736b88cfa0c53307684f7a7d794611e46c96fd348630edb3e74e4b3513a100629ac24ff6dadcfd9ac10155a1702e5fd6ff9e8b41ecefa6d39e94b285361b3bf217ad8e9595858d524b488db54eb808381d187c6af170d139f9282aa0e7e597c18fe2ec57f15751f65afe1417dd90453fa10b0ffb71cb22fd18add72fc9ebae4abac95a163398838a0a9d11a424edd81b58c76c4b42699b64b4c70cdefa9b98695ce4295b28f17fe8c316993df6908c1a44492f8c02853ea73296155c814786ad7738aa4037579654695943fa7403496f2ee2300fdfe12142ff7db5d5a336e1e1f4db5c1664b0464ca6d304d58cd1528c474fc5bb85558f894b0966668fe965cd4c724c7e7783c9011cd6f2e17fb3d6d5d02858610e6087210c1ccda0b81324e999f86ac6dbb5aff02470d2a69201ced4a33c3b9e68febce2c6aa2a4d1834e1c8df21afc12fb45d73d68b76a45838b11bc95fab7ca5782ade3e2e552de5c224b0eb64d2fe423eb8deef615fa31c3adadd05a4c7e5acacef847c4f70bccd5be57f02f944ed8ca18655b4f45cad1dcd8a9b28e97fa0319a1c7bd704391b5ff536279627077f737e1bb597fcdc23a60401797e56a19c61ccad071942208769547570f27d91a92140d1ee205c170e5eaa492631460a1cb3cea1bf69e6a137f9f07245c4b5413888fa5d4158fa7e75eeacc50d42a926564005f0e7577efdd96774ab9f3c6c65868afc4ef6436f83825e3d84017026f9c0443410baf0727460e771d9ee12e5e9de0bdcbd83fdcf4d345099a545b2d9c985b6a535e03d4c2dfc1561e3cf34ed463224992fa7fe7c9895886d670f70bf376bca0b876ecce67644febc3bfae6ef3d6277a8c1ac2d67c18b53d111449dd35d5c6ed5a0d0ed4e84e18c2bc058e0180feb2bf48498ff0a3cae07f8827ec470b85b3b984c6da4e02a9ff91713ca579a3118eaaf07ffcd76c24c00ba1362f5fd4815af08f87491a59730b3faa9ae425c2f0af8459ee89e34771af6e3d967bb0732781e64d7faeaf5e58611655549ddf6de250d03f6223feca650e56040c1e5ad7702b738c880b2c4326992de03cbe0d8d5849ccee8a10a6131e6d41532d327d345561b2d0dd496080f94053dbd8b5696f1c06e5d5fdee093b874a7f71a23f0b899fc10c100129f266bcb3bd1584ca17de169b00390e5002f37b4a07e84e04751f424f96e344ce2fb3e8a54bfb797da06c70201c0fada6b1e50ba7f12d9958e55d6e56673b01e949c4eafc9795d83c70f934ad03ee0fa571ed83ce42f69aa18adaf847c77230781748140410b7748aacc12d194e22283ce91b3d30ee8bfb47229f4c536ace32476c3f65fd3285fdd0aacf31c4431876a56546048b0e5a3b044dcd0c241a0630c512be37ed125ab60538fdb2bd1ebea0a3f150df44828d3fc3a32c1eada61846bb982089663245129158a6683edd1b22d6951567f37e10e4b73707a560c456461570181f0f950eec60f2eaee3566803891d92065b703309f55abcf4f96c3e67eb16a72cfbb1894c7522432a7d82fb42e06af1728bf4cf71a399a6ea6edd971408fc87ccb4d40135c025c348d3b95815620ec93e2344fdbdfd3f36df29ac12fa911b90fb5816e61885fbc36fa871a177ebb09b7e9b946c242331dfa0f103cd0f619d74479052e1ff6153ed46ed357a8594c3000773f089e68b2af2e7f5ae84073d8e6216eb2c26d2a8a691418355686826230a9dc0908951e8dc4999d941baa93f9951fa40357578cd0423ad715b4a9c077a62490a4a96ad87974779baff8d4485e399cc5d6979241d0932ad643dea73bd2dca454edd4ce608e7611e3908a05b7ba7307bbde3652ab470207aa36c5f3976dafb8f81d3a714b1fd87efea0d666b2137a62272005d81b329a3247eb556d784b5282915a9b76e91212d7ed12c7a797b21ed6be5d6dc4991c9ef1d8885c5eb67e3e5e7a3acf13da73c00adfccc14c83a76f6fa91f18d6df29b7666f0648dff79e32e05dec83f67f9575b06a36dc72a105bc1728bf4cf71a399a6ea6edd971408fc8dd2ca11f9d49559f1eb84b4a647c00dc1611137b2a4ad8efa209e553d947548e1a2f46406a87fb1ab30408d29bae0a96b94abc3ffb6866efa940c5a0c23a6bae3398bb19c6b5b3c292527476eb00b4d29e2ad4b78e123580cd05d44f3ee1f712cc0490a4722e7190c312e68d03424a973479e5659fb21abdf95ccfd78f75210768e72a5c137bdc2b1bb31cd1be8727beed855046ecec3e1dfd9b62832fd5a4e015fc8fd2bc0bd86aa35c5ba7f56e8c78f96915abea4b8114ca6284f21d1be8b24a38adc9a799c0783646443b218d7a8950af0ebe8940e4df1b8d700aefa0862e2a2b289fae29e6ebdd74a5c5a7c6b519970267f04924199ae7c1802f14604f398282c433cf89b94025dec94b53c509d2f498aaaf06a767171c5006594f6a343b767214841b9f4dc928fd12bc2a09911849d71a78cebc257167fa2637774b46660ff5aea353ff7134e4fc05d261c57285b81bbc1442db040dd7805868c44879430f20dbcad37d2fbd48dc72a1880788a957b68817bb6f26aa2e3bb616988dde631073ff6f11d883cb09531eec6ab051abf1acb6fa4f2fdf2bcd24f2bd2b695efc3eb2ed8caf06f49802a380a8fcd1d99c0c0e653de62acd08760a2c6a49385f4c6c4af14ab5825af1c48eb4482df37c446a5b322396d4ed6c72e1691aae6567715f11e1a2c27adfce5f748b4e15e66c0e8a2ce93efe76590b9ef95b3cb22c57c96b2e60bd7543372dbffd22dcc380eb358fedc663c2b3fd8b546a799f6ff3008c791953c2b80fbb2856f4ff3b5c0eb5a3109c467efd5caa0cc00b2ec4ea8ba25bca195e199db12bca8f011bd07738e52966f8b5fab6ce3f44c742082ad9f16ef9297fcf8f75995e474a0bccd037e9955b1f4531b60b1e93cbfc1c764cc395c654a19f206385e6ab9ec988fc3b06857b8401da0749d6534eb87b86a62e0491771e7a765889ec89439f159318939af22849d67fe1f61500e6e23c7f0ac7bbcb2cc3a21b7a711d4cd9f64d73c1d7e00381605a53aa54bdb3f210814b40cec3afd4937cc522252358ef6123738464a28704b4db28ddbb36f010960e116e57ee81a725f4788f8c6f5c5f5a6d88c7b055dace27fdc7978c2368b77dfe3926facd1672d8318ef5e2a62cccb59b6a56830897d03da66fc4588469945a437a81a2056c3acfaac26569278022aab1317cbe9caa977bde8f3bfa073e1b8ac4b6c74256559b6f9fb3ed2abb1b01f714d8036a811b1eae4adc1eb3f817109c26a151aeca61f8ac45a0ec01962b887238f342f0731078a8f259ee011a00a28d1b5dd3323fd6801701eb579b8fe0e173135852a28a64f658a966fecf3cd070cab9cf858da6c5bddee197f6de5fe8093a83cb494f12d0874ae8af2bba0971d8f5ab85fabd7b744902a10c13db242b33f9bbb48c9084bd36f452f64d1b234c0f4a46418cc7b90d3b8d71bf889f87d36b7cdee780221fbd2d7a06c3f91fb10fd66b4f9c1c2b7b335e33a2b4db41cd9f105b021d0b22c1a6ffa9a8cc35a7b2eb2be85f31fbd9f448f4758f292a84f75d5f5b0881603ad0fc6a040466b7f9be5d99f14125d0a753015237e9e8bf4684711e39457632c15fa66a3e02c075a1803ece3a7b5ed76d0a0113aaa66fc4588469945a437a81a2056c3acf570152f1e828a5a1e65215cec081516cf2d2b079b5469e8f1518b5fba6f69b053b8585ecca7d0ebe79c1c1bb277d0bbb17e5f9c154ca4840c8c84228cd06131508045f40c13b8a24fc3f12388bdc796d89e57f1edff82a7e4a73b4db4ad048fc3313a6bee6d9056a581a7ddac9b82f58136ee1f27db7396b8186683b089ce736b8fc8221d5c18554cb50c6469f588c16e4f493db05dd4f2befeeafcd159e7cb63be1db25a6cd72989ff88412ffbcc885d685fb559e6b1cb6cf79b0b09229e7dc95c5f7de9c967ac54b3620556308b9ff8c151d235d052c444be31bd4cad65e43499ae83374186a9ecabf1c54819e4f53f7504d3a472ab74f176659e49aa541ee73933c94cf61aece990c963eec464570c38d1c1246c03b5dd32e065ce267665693af26ed29ef4e6edffea596850cf5b8f83825e3d84017026f9c0443410baf0727460e771d9ee12e5e9de0bdcbd83fdc897115b827378dbdb6cfd487d69454980c0ce1eb450e534a3b014b08cb006090d231edce79cf13c0fa08a6b019dbf0c95973fc5bff7857e4387437c64808c6f534443141411d93ca964ed595f483b2711a47af3483b4dee51c478147b4fa344c2c6eca1b835a53d04eaa0b46b2dc2e01d228982bfafbc6c6d51ab2b1ecae71d7dbb6484ae57c391e2ee518152b1551cdf087add80cc101a7307f72d1ced280a7389a5e92e0f2797530d9d30c72a2cc847b473cce82c2cae5f84f2110de56898ab26dfc71e3c12563db336f4817a23b0b8d9126c7fb509b64c743fd29075bd08bd074e7fe8679bd4cd08da6f174f1721478e8aa4495bd2ff451f9537d4a4f5cef1c641fdd682c2cb23895b0d9daa7702d99405796407919ae82bb6fa9ba002340f7b0c20ccc721d8be12640a6baf6438b599393f158fbb289aace4c9b8ae65815a3e82774e52be0d4bd3d9dd65ef7be44dafa7403d54faf3ca7e93f3a885ac11716244ac85e4ae4e2d344e2afea77df1ef94fd9e50f1e23bd3df19c913605f97ba6f6eba656210d9c307360b65444be3b2aa88012e9d1a6c292db2c77d55067f1dc6f63565e930216bd71b8a0ab7ae00c3ac74ba8ed36e3af6ff83fd91115d89e2ed594e0575230236dd2b3d2d5496dfe55351124dc9a02b2f5f198f0e47dd32ab06036a3c50ceeb99756e43eda109d22af4516f07e0bfadb0925388a831dec8636e6cc966861a70a10e2346292194827a70e732c0f5495e5cc747b487e251706c56687741943122ef0bd9fbdeb18c412adf26eac81e00d37a8a40f5975e40e266473287692a48512f2a9e1a3c764a6183b682eb8e7c5bbda3212dc34af0f45da739114ef7561cd620f6127defee0067fc76c3e52d4883d7a6beeaa65e53800c80e6fc13c8cbc8b99e855e2d891b48d949dfb62fd3beb1af7785c20c22c944d885009cbbbe6fcc66cf9e8c6c4f40c23fb660c52729b56fe0302204fa322f6feb17a7f18c925b7606d2a50326aa20f29fb6155c814786ad7738aa4037579654695d67f86763be7b555378a6d5c8e363a0cd19bccc069e885a4fa55be0a6d51d2fdbdc60d64cbea1ef0b33f8a8137cbe7e2d4807f8c268a3788d3fffbb6d92f313b55351124dc9a02b2f5f198f0e47dd32af8820174f68396b2684f35c6d4406e972fe5069f18524dd8290954760f56e37d90316aed8fdbe597f6c3b4ac65c7dc1383a2cacac5169a3da35335f10cb561b0d36d98839ef99ee8f7c599593f31786197cdd286c9ba09c1ded93db1f58c0c63ce91a2174c916f866ad801aa7c111c2369f2732986b2d36ecb724ace420046573feca1012d302854ed7ad54ee1bf29e5c248adfe668249105271db2b96b0d89b3c3b31250383d6b5fb80934b77beb103a5fbec99e170b6a8d40e57790be474c49b2358dac6e5ae604e18612bdf59bff4e9ab3b3428c6339d16e40d14517c1b3bcc2d0d42d10cea522e2703d4c9aeee63cc7f29bca955eba10049148284854359cd29bbdd42aa9e7e4150748582c2cc2353116de047e62599be689d36b5b6a2c88c58f2ec64054cd95f95c45a816e2c4ce1e57fa6ad37f59ee2e00cdd4298d65950a43afba5032c1414f1a160695732d479442338ef5c377da0632c713628a094c171b8a37ff4d3a23eca6938abfb22adfc1dd1e8bece11b9ceee7dbce4febeb41d8d2930e69706898d589b089424791b41cce0ca63175c72f4b1e41002a346b75f3479ef7a950d3b20be3a510b55ac565dd79363fcba048566c5ae0b61e1c1f53df156ef993a52af9f20920148446d8943cd28d2338d3be71b861bac9da7dbae7c90066b3594e6ac7d03b50b77ac7d54905c2d651ed8c51a4ccabcabd7b02744b93133cd31d64aaaaaff2f1d1f7f4fa5cc69af55d284e3f2ca86f5ef64273c6c4381268ea45c7de60c00c87176360bee9f8c49f0c861175f41fd56b0cd99ee1996b2294cbaa899197a92469f6a3218fec3c95871174fb6e17bc8469f0beafc51f4640b39ab1a8363de44645cef2de7961d1145a9e8deebb9b7f75ab0583af69d65a6f822ebe2605f17555fcc4f55bd4241603539875c31704461efb6dd48d0e60431eb1b8c66e7eacb148cf50b7c8ed44184229dfb0ed279736905fe27dd7f49b63bb590e50f015ffc1725f69d9858318e716cc8335099efc06dbfd41259a189ba997d22b9847db6ed6ffa86e326cd98b9dfacf33c2bb80ace5189afdfbb9334f02138035051c35f99718651a3de85341b6121242004174d1d7f06362e45c0d6e4f42f1a5befeea357402703a4810e268064f4a94ba4d061e466c4959b0f08b48e36d7a0bb1100b51e43fb02e43c7cdf05d7811c66c97de4388b91f2d0f9100b33e217b4cacc0f3ca492d40faa9d647fcc8cb80d5df6277ef748510ef94d990f4854d0abf9e2080be9d798f3e7760993da4dfc4039b3d3624320337c6abcd6b7bb62f54fab7366dce49c86be8aea21dbc2de580ff65e802de5c25eaab5d0589c6a72ab6d317a95951edb9a3655c2b74268d4aecefb39d480fc28289dc7ba81a88614e3da6e1c6c5e1e4a43f4fcf3231f9625a32d6c58e1f0f26e17ab4efe03464184229dfb0ed279736905fe27dd7f4941d51bb247011753c83861fdc207dc0d283a345f9da53b7155eb25fb4a2672572d98256212a3720cc16a3334f2d21c18a4cb128b96b5af0ad4995eeaf596b9a00663666e09536e067426ef87bff2962d603bf74eb7d15efa6a07da35c41514266eb234054212eb929aa1d36ccaaac36e42d87a86a7174f8e70525733851d8343a3b34257f09a725f40a45367e3e2769bb67499370582935cca6792b4e0c5ece8af7c8f829e5954013d7e9e00bc90bd6c3949ba2516f7f379a88949de1baeec99c9bd1a2e4a81d48085f4c971fcb59727ae6e17612259c7fb5ba3a169d2ae440c82de7a27b1293ad70830a4deec13d4e2faf2f89ea0fa98c412ba159af85f69777987f39ba4f21494b63ed0e21f176c5cb089af6e9cc70d008959f53700f7146f9025570131fe067ae6e260171a54f2f05d9442d7edd60c54a3cd86aa672baa2f2a55a3ea2d76ff981aac6a98aba0b48136696e41e5984b13350a83725d96746770cda0f851f0c28ce297d8a39efe0c85497bed38cb484f0eb8cf1a386e2e45a5bcc7c4b96b51f102820a1f0815023256686cfeff775fd0ee42eca4bd10feb1d3c71c13701ba872dde084049cc546d8c35ab4ea65a600f85ec71ac82f427a8d66b62982ad17e356250224626964c2135788fbaf77d31fc2ca1a60c7dee50ce9685991f1c58c7b3153442f31e1bcb0731bf4131b609619705b835d7275ad17ddc497e74a4db492a3f1258f5ca957e8f0edb8b3243258cc66a300281617116e934f5279bb43fc9900784f805a519555a846a21b7a711d4cd9f64d73c1d7e00381609956214509ba8e894f29d4597772cdf32b0ccc6b1259fdd4240b58d30815558a6d85d95308de02e638757269d24be45e471bdaeec07c1f7a82ef47ac6b56dc6495d1d3d7ce4bc2d62d0ba0046f0b361e4c2a06d2180d9fdc1b58426450dffdd649ca4b19edeea0d81cbac0d8dfa7a30e965ec1ea4ad8c1b1aeedc46335e5f9d5ebfdfd7d3674d8c34286f538411a27e3e3438762b4b689527b5c911729d4d4098cc707bf1dd1075afe8e158b583f7d4f4ccfc3987699581bc7a3ef2ae790f84d3296b933f516b2c7acdcd86e1f5475fdd1bcbfd82a1d26feb9508cce3aee6150448a76e11533f074b5eedf5c2bc2bc3c85d0fd0bcc6b0b5c57ee4b3507dfb3e582aa0e7e597c18fe2ec57f15751f65af5387e775aa6e21ea16e148139ddb82c9ceb81837b85b86a55a70a2ec7b901cd5aaba7a4a0af22240a3acb01bad92e1f047d059503d5de60067d300684f44b5d8442e1d6f7b049a9b0e7473a6482d91026fbf5659f9912b472c178ff31af92d837586be9b6ef71c46566b8ccf1e28562ccbe766717f37b2ff5b7c94835881f1a08457cd9f92c99be1d33051cb8f4159a8e37d248422d6602d7e9be5cdb1220d4e54875ec74de88b07abfbafb37a762115075122a9b4b2b1471b9e516237733c3ad890489fff35d643de293361af379a69864553db9271466055f258e31ce53a01484cdd0cadc27bee977b0f42b62ec07c1728bf4cf71a399a6ea6edd971408fc8dd2ca11f9d49559f1eb84b4a647c00dceb5da2c0c50efc9854dc128098c147db374455aab1888f3fa71102cd96143eac53973ae847d762f16b03cc5efbba60f4e866bf16c3c77743d61adf562bff12c91f2b73fe30ad3b86b1d199d945a608063400db780334b8806a5a2adbe0f29d936bd7ff5880d5a3e8fa049f3168f8c3d591f3a79e596fb5b3a585f3fd473d529c8dea0fb017519f553551f6cad9442d0b8549f32aeb7ed4b2313a235af7cf6662181a38b581220852f0b977e4fa4e42b16aa2c486a6e8985c86ae8269cba590a4fd6e1dead9ee8631167183284d9778ace66ac6d8618072f026fcf92d6b66d17a8103d196cdbb62e232f40635ae472b39077fda0cabf454b53fafb7fdc74bfd81ed79e09669da782fbaa71351629c1bf7d7e457dcfd70a52918af95846ef882fbb1374c6a9d9015c23bc478f8b6a6224774d79d9ed65ca848c65ac192984d1f823e834f027bcdd050aa554cf6f416fde4d06920f6557d07fed5b659363e442eb632ee1eaa87277c09b6e4e0a3e4ab2f2b958758f3d5752e4bc80eca47cd908e9300db5dec01ebe9738d4b38d2e27e4ff0adac74b3cf83d25edf5f949bb43be0f69f1f5319f8a09d6894d88fdd8977550e186a9aa3cf342aeeab36f2dd99ac1f8a90f028f54c85d1cbd7604f375331ab73333ff27eb19d9802ff7c60f440847580bdb872f93a11243a0719215ee2536884c92c9f9ff199cc5584e5ce56e3bfd57a9d0b073b33db5d68fb2680cc32919a0bb41de0b1243e8b167af153fef640beb839032cb6bbd01773ee3942778a772bccbacd60039748aae4329d22f0a53031f3af4a230ee4f5b436a56850479770c2a4d33eb4f1439903725db76d7eec5a0628ed90614c7bcd7268f7bd81eb605fd5ab81b85fb763ed8d09b312609c280612d79fa2c1287132b62e9e910c4ff6f23c8ad88672f16ef1951378cdc768171f2ad875a05f5eb8c3cae8a816d09ea8a4d1a6faeb5ef41e165fd343e98cd43667c3ee95f92314e9bfd72a7bd3fbd70c1246d2252e20b20e650dd08f75edb8278e5729fee29c6c2960e95affce2721dc4c80d787751305237642018db3e295f1aa4cfcf250d141e577d1c12b198b8f31d6a00d25ecb48c928e62746beb535d0442c5f9424cf72b26aabd11325de7664f4109597157b3ba015b47cc10b4d822bb82375604fed7a74fcaab8dc524abf0efc93dca02b78fcfb28a94d90d0ba1966b968c16399cf0bb75b9df2ab646eca59bfd4d256fbf5659f9912b472c178ff31af92d83befcd399b211a34c2a285d51fb42a69995ccfca578d72065bfa14f99a8a11b3b866c73deac6349b898bf884a2831c1d63cc6c8da927fc468f79c77c720b231639fbc1a69b6fa27252b25da00dca969a0d710d761e6d8035afcc3bbff733451fb4381268ea45c7de60c00c87176360bee82a1464c7aaa6e12f48e2ab44dae68e8fab79d2e53fe918527c6fd48c60a5ae876340aec073544dd803184cf4ec6278040360b7540e8d59656a18c84bfaea184c8d115446a7fdb536ec9cafd43921b0ef7914ae07107e8ad51412e0fed8f6d5d'

print(eg.data_decrypt(data))
复制代码

然后现在就是到了最后一步

image.png

现在已经得到了a(str),就是我代码中打印的ss2,那么在python中怎么使用一个列表(java是一个字节数组)进行aes解密呢,我再研究研究,研究出来会修改文章,大佬看到可以指点一下吗(图穷匕见)

=======================================分割线==============================================

看了一下午终于解决了,原来把列表里的之前的字符串改成int,然后bytes()转一下,就可以了。算法学的不好啊还是,= =。

def data_decrypt(self, decrData):
    length = len(decrData)
    if (length&1) != 0:
        decrData = "0" + decrData
        length = len(decrData)
    ss2 = []
    for i in range(length >> 1):
        ss2.append(0)
    i = 0
    i2 = 0
    while i<length-1:
        i3 = i +1
        i = i3 +1
        ss2[i2] = int((self.r_digit(ord(decrData[i3-1]),16) << 4) | (self.r_digit(ord(decrData[i-1]),16) & 255))
        i2+=1
    print(ss2)

    b = bytes(ss2)
    msg = self.aes.decrypt(b).decode("utf8")
    return self.unpad(msg)
复制代码

猜你喜欢

转载自juejin.im/post/7110096972308185102