如何破解滑動驗證碼?

本文通過自動化查詢域名或公司的備案信息,來演示其中圖片滑動驗證碼的破解方式,以此來思考驗證碼的安全性問題,思考如何設計出安全性更高的驗證碼。

注意:破解驗證碼進行網絡內容抓取可能是一種違規行爲,可以以此進行驗證碼安全性分析研究,不要用於惡意活動。

什麼是驗證碼

現在的 web 應用,在進行重要操作時,比如用戶登錄、信息修改、重要信息查詢等,往往都需要驗證碼。驗證碼的主要目的是防止自動化程序或機器人在網站上執行惡意操作。

圖片形式的驗證碼是最常用的一種形式,下面列出幾種常見的圖片形式驗證碼:

  1. 字母驗證碼:字母混合數字的組合,要求用戶根據圖片中的字母和數字進行識別並輸入。
  2. 數字驗證碼:由一組數字組成,要求用戶根據圖片中的數字進行識別並輸入。
  3. 滑動驗證碼:用戶需要按照提示拖動圖片中的滑塊或者完成一些簡單的拼圖等操作來完成驗證。
  4. 變形文字驗證碼:字母或數字倒立或者扭曲的形式,要求用戶對倒立或扭曲的字母或數字進行識別並輸入。
  5. 算術驗證碼:要求用戶在圖片中計算出兩個數字的和或差,並輸入正確的結果。
  6. 圖片識別驗證碼:用戶需要根據給定的提示,從一組圖片中選擇符合提示的圖片,例如選擇帶有車輛或路燈的圖片等。

這裏要注意的是,雖然同一個種類的驗證碼的前端表現可能相同,但是背後實現的方式可能不同。

自動破解驗證碼

破解驗證碼是通過各種技術手段來自動識別或者繞過驗證碼驗證,儘管驗證碼的設計者在不斷改進驗證碼的安全性,但是驗證碼破解方式也在不斷創新,這使得驗證碼的安全性不斷受到挑戰。

通過上面的介紹,我們知道驗證碼的種類很多,因此不同種類驗證碼的破解方式也不相同,而且由於實現方式的不同,往往需要具體情況具體分析。

圖片驗證碼破解的總體思路是模擬用戶的操作進行驗證碼驗證。

舉例:

  • 針對圖片內容識別類驗證碼,可以識別圖片中的內容進行自動驗證,這裏可能要利用機器學習或圖像處理技術來識別內容。
  • 針對圖片滑動、旋轉類驗證碼,可以模擬用戶操作,如計算圖片要滑動的距離,要旋轉的角度,模擬人類鼠標操作時的軌跡曲線等。
  • 或者直接人力破解,針對有價值的目標,也有聘請人工智能平臺或工人手動識別並解決驗證碼的情況。

本文介紹圖片滑動驗證碼的破解方式,這是一種破解起來相對簡單的驗證碼。

圖片滑動驗證碼

圖片滑動驗證碼是一種比較常見的驗證碼,一般都是通過滑動圖片的一部分進行圖片拼圖,以進行操作驗證。示意圖像下面這樣。

從用戶體驗來看,用戶只需要使用鼠標拖動滑塊到指定位置,如果位置正確,則通過驗證。這是一種十分好用的驗證方式,相比輸入形式的驗證碼,省去了用戶鍵盤的輸入過程。

這類驗證碼的實現過程一般如下:

  1. 服務端準備圖片若干個。
  2. 用戶請求獲取圖片驗證碼,服務端隨機選取一個圖片作爲驗證碼大圖,複製指定形狀的一小部分圖片內容作爲滑塊。
  3. 記錄複製的滑塊位置,響應大圖,滑塊圖給前端。
  4. 用戶拖動滑塊拼圖,把滑動的位置信息發送給服務器。
  5. 服務器驗證滑動位置是否和記錄的相近,允許一定像素的誤差,驗證是否通過。

具體案例分析

我們通過分析一個備案查詢網站來演示滑動驗證碼的破解,目前網站的操作流程是輸入一個域名或者公司信息,點擊查詢,彈出圖片滑動驗證碼,用戶滑動圖片驗證碼進行驗證,驗證通過則返回查詢信息。

本文僅用於學習交流,不可用於商業及非法用途

我們先通過查看網站的網絡請求情況,分析操作背後的流程(以下的操作並不是一次完成,所以截圖中的某些值可能對不上)。

訪問網站

訪問網站 https://beian.miit.gov.cn,發現自動請求了 auth 接口,在請求時攜帶了兩個參數,截圖如下。

其中 timeStamp 很明顯是一個毫秒時間戳,那麼 authKey 值是怎麼來的呢?通過分析網站 javascript 代碼,可以發現它的生成規則爲 MD5('test'+test'+timeStamp),分析截圖如下。

請求後獲取到了一個 bussiness 信息,作爲後續請求的認證 token。

請求信息

獲取驗證碼

在網站上搜索一個域名,彈出圖片驗證碼信息,再次查看請求信息。發現發起了一個 POST 請求,並且在請求頭中攜帶了 Token 信息用於認證,這個 Token 就是第一步獲取到的 bussiness

響應信息是 base64 編碼後的圖片,一個是大圖,一個是用於滑動的方塊,其中的 uuid 可以認爲是圖片 id,在圖片驗證時需要傳給服務器。

// 下面的響應信息,爲了方便查看,我刪去了部分內容,所以不要直接解碼,解不出來的。
{
    "code": 200,
    "msg": "操作成功",
    "params": {
        "smallImage": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAA0JCgsKCxxxxxxxxxxxxxx",
        "bigImage": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAA0JCgsKCA0lFAj/2Qxxxxxxxxxxx",
        "uuid": "87db2dbb-4c1d-4633-a624-0045305e61e3",
        "height": "81"
    },
    "success": true
}

如果我們拿 bigImage 內容進行 Base64 轉圖片,可以看到驗證碼大圖。

驗證碼校驗

我們滑動圖片驗證碼到準確位置,這時會發起驗證請求,我拷貝出了這條請求的詳細信息。

curl 'https://hlwicpfwc.miit.gov.cn/icpproject_query/api/image/checkImage' \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'Accept-Language: zh-CN,zh;q=0.9' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Cookie: __jsluid_s=ef117b2a4d0d504c0f729f605e22bea7' \
  -H 'Origin: https://beian.miit.gov.cn' \
  -H 'Referer: https://beian.miit.gov.cn/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-site' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' \
  -H 'sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'token: eyJ0eXBlIjoxLCJ1IjoiMDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjYiLCJzIjoxNjg5MDg3OTIxMTEwLCJlIjoxNjg5MDg4NDAxMTEwfQ.RdP9am6518e4z9EsrFQz18ZQjwvhgserJ5y2ZVx7rqo' \
  --data-raw '{"key":"6af2c1bb-47a4-479d-a9f1-1ab17f86214e","value":"320"}' \
  --compressed

從中可以發現,依舊在請求頭中攜帶了 Token 字段。同時請求體攜帶了 keyvalue 兩個字段,其中 key 就是上一步獲取到的圖片的 uuidvalue 則是滑動驗證碼滑動的距離。320 也就是表示滑動了 320 個像素位置進行了拼圖。

驗證通過後得到響應信息,其中 params 是驗證後得到的可以用於請求驗證的值。

{
    "code": 200,
    "msg": "操作成功",
    "params": "eyJ0eXBlIjozLCJleHREYXRhIjp7InZhZnljb2RlX2ltYWdlX2tleSI6IjZhZjJjMWJiLTQ3YTQtNDc5ZC1hOWYxLTFhYjE3Zjg2MjE0ZSJ9LCJlIjoxNjg5MDg4NDQ0MTM2fQ.cYPpQya1KiWZgC3T8ZNr9cWAM2aTHDtFUpzPIO-sMhQ",
    "success": true
}

信息返回

驗證通過後會自動請求域名備案信息查詢接口,下面是複製出的請求信息。

curl 'https://hlwicpfwc.miit.gov.cn/icpproject_query/api/icpAbbreviateInfo/queryByCondition' \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'Accept-Language: zh-CN,zh;q=0.9' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Cookie: __jsluid_s=ef117b2a4d0d504c0f729f605e22bea7' \
  -H 'Origin: https://beian.miit.gov.cn' \
  -H 'Referer: https://beian.miit.gov.cn/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-site' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' \
  -H 'sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'sign: eyJ0eXBlIjozLCJleHREYXRhIjp7InZhZnljb2RlX2ltYWdlX2tleSI6IjZhZjJjMWJiLTQ3YTQtNDc5ZC1hOWYxLTFhYjE3Zjg2MjE0ZSJ9LCJlIjoxNjg5MDg4NDQ0MTM2fQ.cYPpQya1KiWZgC3T8ZNr9cWAM2aTHDtFUpzPIO-sMhQ' \
  -H 'token: eyJ0eXBlIjoxLCJ1IjoiMDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjYiLCJzIjoxNjg5MDg3OTIxMTEwLCJlIjoxNjg5MDg4NDAxMTEwfQ.RdP9am6518e4z9EsrFQz18ZQjwvhgserJ5y2ZVx7rqo' \
  -H 'uuid: 6af2c1bb-47a4-479d-a9f1-1ab17f86214e' \
  --data-raw '{"pageNum":"","pageSize":"","unitName":"qq.com"}' \
  --compressed

其中 sign 是圖片校驗通過後的驗證信息。token 是第一步獲取到的驗證信息,uuid 是驗證碼唯一標識。請求參數中的 unitName 值是要查詢的域名 qq.com

請求後成功響應了域名備案信息,至此,我們完整的分析了備案信息查詢的全過程。

{
    "code": 200,
    "msg": "操作成功",
    "params": {
        "endRow": 0,
        "firstPage": 1,
        "hasNextPage": false,
        "hasPreviousPage": false,
        "isFirstPage": true,
        "isLastPage": true,
        "lastPage": 1,
        "list": [
            {
                "contentTypeName": "宗教、宗教、出版、文化、新聞、文化、文化、文化、新聞、宗教",
                "domain": "qq.com",
                "domainId": 190000203203,
                "leaderName": "",
                "limitAccess": "否",
                "mainId": 547280,
                "mainLicence": "粵B2-20090059",
                "natureName": "企業",
                "serviceId": 4134047,
                "serviceLicence": "粵B2-20090059-5",
                "unitName": "深圳市騰訊計算機系統有限公司",
                "updateRecordTime": "2023-07-10 11:58:09"
            }
        ],
        "navigatePages": 8,
        "navigatepageNums": [
            1
        ],
        "nextPage": 1,
        "orderBy": "",
        "pageNum": 1,
        "pageSize": 10,
        "pages": 1,
        "prePage": 1,
        "size": 1,
        "startRow": 0,
        "total": 1
    },
    "success": true
}

圖片滑動驗證碼破解

如何破解驗證碼呢,通過上面的具體案例分析,我們發現其實在訪問網站獲取 Token階段,獲取驗證碼階段,以及最後的信息返回階段,都是比較簡單的 HTTP 請求,只要能構造相應的 HTTP 請求,並攜帶具體的請求頭信息,就可以模擬請求了。

比較不好辦的是驗證碼校驗這個階段,因爲要計算驗證碼的滑動距離,這裏需要涉及到圖像處理知識,那麼該怎麼辦呢?

驗證碼圖片分析

我們獲取幾張驗證圖片觀察,明顯看到在要滑動的目標區域有被陰影覆蓋,那麼這一部分的 RGB 顏色就有所變化,一個正常的圖片很少有這種矩形方塊的顏色突變

灰度圖片

通過上面的分析,我們發現色彩其實並不重要,圖片的灰度變化(或者叫亮度變化)比較重要,因爲目標區域有被灰色覆蓋。會產生一個矩形突變,那麼我們可以把圖片轉換成灰度圖片,這樣更有利於觀察。

準備驗證圖片一張,對應的 base64 編碼如下:

/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAA0JCgsKCA0LCgsODg0PEyAVExISEyccHhcgLikxMC4pLSwzOko+MzZGNywtQFdBRkxOUlNSMj5aYVpQYEpRUk//2wBDAQ4ODhMREyYVFSZPNS01T09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0//wAARCAC+AfQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwCOaLyZf3k2+Oo3+S1lSP563fssaf6yaJ5KqfYp/Klf/Xx/34933f8Ad9KxAy4UkeKKCSaptm/5P+WdadtFA91vjh3x7Puf55/GpIbeBPn/ANJ8z+5Jt2/99VJPIZz2sbxfvJtkn8CJU0NvG/8Ay2igj3/fn/z1q2j3cMu+3022/wC2m59lO827SLzJP4/91KA5Cl9luEutkn+rf7j/AC7ahdI/N2W/+rT77/3/APZWte+tZ0/cedvj/v8Amfw//rqg9rOkUsckO/ft8j/Y/vfpQSVbe1+3XUXkQ738v7ny10ttLGn+i2kMVrIn+66p/U/WsL7FIkWz7lTWn+iXUTyfuI4f7n3v9qgqBcutNjuZJZP7X86T+MJUT2uzynj/ANKkRNm/y1/xqpN5FzLvjmlfZ/B9n2VoW4R7WSCeL7TaP9zyPvQt7f8A16CjN3yfav8AS/kjT/pn/wCO022tZJvNe3h/efwfvPmrRtvt/mxQed/on+3tSprbT54fnkhigk/6Z/PQTyGJ5sfm/wCkf/sVYhitE/494f3j/wCf0qvqk7tfy3X/AD2//ZP6rVpH/deZHQSCRSQxbI6Jr27SLZJNv/2Pufyq7+7s7Xfceb/20jqvN/yyf78k39z+D+61BXIXnt47OKKe/wDnu9n3P8/qazLa9/tGWWCSGJJP+WH93d/d+h/nUbvsv/3f8f8Alqbc/wB+3/1dAEi3qeba2M8Pl2tt/rk/nUlp9k826uvOln8n/j1tUkb+KiF7S/sJftfm+fD9/Z/Gv96prSy0W4/1er/+Q9lBJm/aJHl8+T5JEq3Z3uyKX7R5v+3WnNpFi48w6v8AvP777f1qgkUENrsk8p5P4P41f/a9x/M0ASWNxYW3+v8A9F87/vrb/D+J/lXQw3FgkX+uiSOuYmljSKJPJ/eff3+X/e/n9aih8u2l8+Pyvv7/APfoNOc2NWlv/JkktQILX/b+9N+FYtndRpFsuIf3if8APD/JrRfUJ/N3x/6x/ufdeqttcWjy3X7n9/8A53UE85M8v2mKKeSGWDZ/zz+7+nNOT7IkW+3m8+T/AJ4P979etYV9dR2fmpXNzahvl/eTS+X/ALFV7EDsL6/khl/eeba/9d/9V/31/j+dZ811v817iHZ/n7y9iKoW/ieT/V3H2l4P7/mfvf5Y/Bs1o21xO8Ur2ENtq8H8cHl+VOn/AAAfzXNHwlF6zikmtftUf3PlR/8A7L+lNSyt/NieOzi/uf6xnX/PzVNot7aJa77OHyfO++k8n/jvH9a13Swm8p/3vl/88PM+X9Kkkzb6KS2+eOb95/B/+z6VraXsmEX2v5Lh49k3+3t/qKhS3jml/d/JJ/0z/wA/hQ9u8NhLayTbJEfzv7/Xg0AcwjyW3/LaWD5/k/8AZa0Ev9S86KG4m32tz/u/J23L2/D+VGrpJ9v8iT/ZT/7Jabp1vB5strd3n7vf/q/mZvT5cUEl+a3ks5ZbWT/Vum/f/n0/lVT949/a2v3JPIjTf/tNXSXFrBNax+bEHxHs86b90v8A3zWVc6fHN5Xmf8sU/wA/L9KDQzJtNnt5dk/3/wDbpty8f2X/AKaVN9tj+y/Zf+WH/Tf/ANC9qrwvH9qij/5Z7/8Ax2gOcdD5flRP/c+/V/7PBeWu+4s4n/2KgmSP7VKlpN/9h/vUPcR2cX+u/wCB/wDxNZ8/KHPylN3khi+wxzb5HT5H+X5JP7v49PyrI066ke6lS7+eN/v/ALtUatFH+0y7PJ3yfwPJ93/Oaqeb9pi+1RwxeZ/y3SP/ANC/xrYoup5mnXXnx/Ps/wDH1/vVavLi0f57eb92/wD3z/wGqttL9si+yyQy/wCx/wDE/wCHvUenWtvN5sEn8fzp/wABqQJIXj/evH/cq5Zv53ySf3Nn/Af8R+oqj9tgm+SOG58v/rnUiXGz5I4Zf/QK0mUTJbyebKn7r9z/AM9Pu1I9x5MX7ubz4/8AppQ6fbrXz/8Alon3/wDP+ePpVd0jhi3yQ+fI/wDBH/n9KxMx1ne2kN1/qdn/AFz+7Wu/lzf5+ZP8RWAkXnRf3JP4K19Iuo5ov9IhoMxtz5c0X+lw/u/uJPH95P8A63t+VNmso7aLfHNsjT/Pyt/n0pn2f/W/Z7yX/cf51fb/AIfNRvkf5JIYv+2Hz+/3e34UFEP7y5tZYJPnkqrNdSTS3X2f/no2yr0MsH2/fHN+7/8AHk/3lrN+xbJf3n8dBIO8jxReZVbyt9XZk2Rf79Nht9nyeds+eqAjmt4/K3+TsnqJIo38p/Oq28UafJH/AKv/ANmpqJ5P/LH93QA3j/lnD8tFTSW8DuW8zy/9n0oqgNt7KeaLZ9yT+/5e/wDrVyGy2f8ALb/0JP51XT7XZ/PJ/ndVp5buGLf5NTyGxl/2Vf3N/LdRw/uP4Nn8dWki3yxeZ/rE+So7zWpIfkj/ANZ/fpqSzzS/6n/PRaoktPazpFE8c3/oNQw28jy77ibz46sbJLaK1T/SfPeP/UffVP8AepsPmJ+/87/yHs+7QBDvk+55P7um740qaFftf+iyXmz/AD/KpIbKT909v9mnj3/89Kn3iSnC8H3P+W//AE0/+tUzpInyf+OVa+xTp88cMXmf9dKjm0+R5d8kP3/+ee2gCN3n8r93N9z+CSPetVd8kPzyfZv+/dWE0qdIrp/9jen/AMTTU0qd4t8kP/kSgod5thD/AMsZXkf+D+HdVd/Pf5P+PWP/AKZ//WqTyoPN/wCWv/A42qwibIpfL/g/9moAypnjSX/pp/1z/u/zqyj2ltF5/nSzyf8ATT7v+fxpyRRvL/pEMTyf36c9rG/yed+8/wCmf+c1POSH9pbJZXkh8+hNVj82J5LP9/8A3/Mamw2Un+o/5Zp89FzaxvL5kcMr/wDbTZ/KjnJ5xtz9nm/1fleY9QW0saeb5n9xv+B0/ZOn7jyf/In+P+FSW2nzp5X2f/Wff+f+7/d/+vQURpF+98+3h2SJ/wA8/wD2apLnSo3l+1W/lQbPvp/c/wDrVcS1kT9/J5SSf+h/7zVVuJ3b/Sv3s0b/ACTfvP8AP4VQFT+z4LP/AEqSbz/76JH/ABf4UJ5FzL58k37z/virfm7JYk/2P/Qqa6WifJ/pP/jv+NAGY/mTSyv52z56tWyQf8s5v3n3/kj37/8AZqf7LHcxb4/k/wBii2tY7b55P9Z/0w/+K6UElZ/+WryQy+X/AAJJTtIf/T9kkP8AAyb/AP2XmrL3V3cy+RcTfcqRPPf/AEWT/So3/wCen8H+7/WgDhdXlk+1SpJ/BWQ6SebXaaj4Vv7mXf8Afkptz4LntrD93889bc5scW71Ys0ne6i+z/6yuqs/AN3N/wAfE2yuu0vwVp9h+8Qyef8A36CTFS93xRJfw79m35/+Wv8A9epfKk/5dP38H/TP/W/98/8A662W8Obfn80zfWsOXTXtLr5/NTZWPIZj4dV8m1unkm2SJt2J/n0pn2qB7r955v8Ac/1ny/5/Grtp5D3X+lw208+zZ57/AOcH+dZ1zZR+bv8AO37Pv/3U/wAKko0/NjubWJP+Wls6+S//ALK1Z0Mt+kuyP5JE+/8Ad/zj+VS/aIE82eSH94/8EH/16d5sf34/NgoJL1t5kP8ArPNnkf7/AJnz1DqKfvYnt5v3kL1GmpQfunj/ANZ/3x/I/wBKHuo5vNePzU/9B/z96gooXnlzS7/8/wCfWobaLzpd/nbPJrVS3tJopfs82z/x/wD+uPrj8qqTP9mtf7Ojh2XfzO+/9FX/ABoJGw3EdzL/AK6Ki5t55pdkcP3Pv/7FOh+0WEsX2ib+Nfk/+KqvfalO8svmQ/u/87ajk97mALaKO2l/eXn7z+5H/s/xM3Qe/Wsj95bX++3+Sr8N1+6/eQ/c+592qT+X9q31vA0gXUigm/fx/JH/AB+XI37n/wCt/Kpnf/l6j/1n/Lf95/nrUNm8ifPH5v8A47Vz935u/wD5Zv8Af/d/+O/4UTKIb6L9758f+rm+f/X7Kp/c/wCeX/bSRnrWhi/0DZH/AL8H/wAT9az3SR/+f5/+2eyiAEltL9jut/8A7T+X/aqxeRbP+Pf545n3pVe2TZ/yx/77kq+iSJ/otx+43/PB/vf4H+dZz+IzmZ33Jd//AC0SizeRLrf/AMs3qS5SPzYkj/3N/wD8VVe58zzf3fz7H+R/92gk1HtftN1vj/j+eo4beO5v4vM/cQf30/vfjU9tcRzRbJP9enz/ALv/ANm/zmmebOku+Tyv9jy6JgT3kUEMX+u3yeR/r/0rMvLKN4vtUc37t/40+7u/pUnlbIrqe48r99t+5+f/ALLVXS5ZH82OP9xJ/B/8TQUNmt5PK/dzffp2yN4v9d9ynXnlpa/arf5I5vv/AO9/c/qPaqm/yYv9d9/7iVRPwkr3H8f9z7n+7TftG+X95/rKiRJLmWJP+WlQzeY8v9+RKALc8yPKXk+8/P3tv6UVU+/81FAHeXMUd5aypH/5EqNHu7byoP8AY/8AQahS3j83/XU65spJv+PS8/3EkkrQ2LXmzvF+8h31TSWe5l2SQ7P3dTeVf+VvqN0v0/4BRyAWvN2RbJP9X/tx0fu7m18i3mi+T/nnHvqr9tv0/wCWP/oVCalv/wBZDF5lADUtY0uvPt7zfRDZTw/8trZ46m+0W7/8sYqd5sD/APLH/wAiUcgEaRTv/wAtv9z95s/4DTnS/T/ljc1M7wTf6yGX/wAdpqRWif6v7Sn/AH1/SgCv9tnT/nrUiXUltF/c/wA/5H5VZfy/K/d6lL/wOokinf55Jop/+2lT7wDodSkej+0P+uVWLd5If9VaXLo//LRHWmO8FtLvks5fMf8Aj8hn/wAaoCD7RG/+ss6ElgT/AJc6a8umebvk83zH/wCmbU6a1s4RmS88v/rpu/8AQqkA/wBEm+ST/V/8CqdEtP8AlnVRvsJi/c6tCPrIKbi1Xpqtp/38FUHIWPKg/wCe0v8A47S/ZbTzfPjml8yqytEJsHUbPyP+ug/xqC61FJLnapthGg25Mqt/Wp5Ihymk9rG8u+O82R/9c6EsoIf3kc37ys1L2Nn8o3UGPXzBSLqWDuW4jC+hZf8AGqtEC9Nb+dFskh37PufvNny//rqv/ZX+teSG58z/AIDtqH+1kM0bu8Owdf3gq2+p26NuS6gdfTzBUk8hU+xSJ/yxufkT+OOpEuJ0/wCWOzf/AAVsaeHulEqkLEeQR3rUigSLoKrkDlOf07SHlEUkn/fdb8NrHFFsFT0tVygN2r6UbadRVAFFFFACVHLEkw2OM1LSVIHPatpgMRfyY/8AfSP5vxrI+xTpL58cMX+/5n/167isfUNOtIv3/nC1H8ZFZzgTyHPzWsHmxJJD5Mn9+P7v6dvp+VRzW/k+bBcQ/wDfv/P/ANetSHTYE8ry6spFJDdb45vv/wAH+f8ACp5CuQ52a1jSKLy4ZUkf+/WjbeWsuz7Jsf7j/vN7bvdc8Vc2STXXnyTf6n+/8y/8B/8Ar/nVmZ5Eil8yH/vj/wCJqOT3g5DmdRijeWJLf/WP8n/Av6VOiXaWsqXfmvPD/wB8/wC96/lTUtftOq/u/wDV/M//AHz/APXrSmSf7Lskh3yJ8m/7+/8A3vcU+QDAe6jfykk83zNn+W5p2yCb5JPtKSbPv/L89asNlJDFK9xZ2LyP9z93/D/tf4VHcpIl158dn+7RP+WH8f8As7arkJMq2itEl/d3kvlwvv2eX/gfzqveW8c11K/2y2+d9+yrlz9rubXf9jlgk3/c/wDQW4rI1G1u7byn/wBRO/8A9aiBUC6lr/zz+zf8AkqRIp0lleOH7/3/AN//AI1lW0t39z909Ne9k+5JpsT1RRt20Ultdf8ALX5/uPJJ/F/Cv9Kjvrf97vjhuX875/8AWf8AfS1jebs+T+x66GH/AImmlb/J/f8A/TT+9/8AX/nUgZ9sn+t/1XmP/wBNN7f8Cq59okT9xJ5vz/wf56fhVGzlkSL95D5H/TCpN87+U9v88n3Nkn+1UTn7xnP4i8kX2nyvtHlff+f/AL5+Xp6/zqmiRv8A+h/99U6G4jhl3xw7I/7lF5cR2MUSR+a/8e//ANmpgNtnks7qJJP9X/BU15/o11+7/j+es/7RJeRf67fJD8/+r2f/AFq0keO5sN//AC0T/wBmomSQ6jLHDpcT2nySO+//AL5Uf/FVQhvYIYt8nyT/ANyrt5bxvpdr/vt/30yisa5t40l8iSiAG7M8H35P+PS8+/8A/Y+46iqFzp8kMuyOaJ/7n+2v978ansU+02v2GT/gFEPl3kUWnXH+s+byH/2v7n0P6GgoqPbyJ8nk1Xmik/dVNbRbIv8Afq7bWt/N5X/PNK0JKH2Lf83mJH/svMFI/A80V0MegF0DSTRbv+uaf1GaKCuQv/2b/wA+95TXsrtP+Xy2qbzbCb5PJ/791YSKwT/ltVGxVS31Pyv+WVNhlv0l/eWdXtkf/LOan7Lj/ntFQBS+0Sf88Zf/AED+dCahJ/y0hl/791fd5P8Alp/6Mqt+/uZf+WTxp/n5qCRqXthNFv8A3T07fYP/ALFHmyffuLOLy/8APtU6fZPN2XEOygB3+if5/wDrU17KD/lnNsqDzbS8l2W/mvHTX8h/3cfm0c4E32KT/lneRUf2fcf89oqWG33xSpJ5X+fxqR7eSH/ltQBW8qeGWVPJ/wC/dSO88P8Ayxlp7pdw/P533KmeWT/lnNL/AN+/8TQBWS6n+5+9qPUbgPpt0hOH8l/kzjse1T+bd/6zyf8AyHVHVVkltpZZP3DxQuOm3f8AKfloA4bzcDByKU3CIvIFIz5++grJv7pZH8pPlA64qxGotwsvcHHpUqsNvFY9rcxRptYHNaUBidNyMefWgCYEDo1O3A/xVC0D9d9Hkv8A31zQBIck8HiiNAWwcZphjk9sVKVKIH7ikDPV9GVF0ey29fs8f/oIq9WZoU3naJZlOogQf+OitOgQUtNJC9aj82P/AJ6igCaio1dH6U+qAWiikoAWiisvUb/Z+5g/1lROfKAahqkNp8ifPP8A3B/Ws/T7afUrn7bf/cT/AFY/hP8A9aorKx+2yZ/g/jeukjRFjCoPlrL4iTJ1CN4rnIMSRv8A35NtZaXXnea8fmv/AN9V090iPFz/AAViu8D/AOWrQ0FmtY/ssU8c3+/We97JD5vlw7/9jzKvpLBbf8e/yb6ra7dbLDZ/fepAr2PkP/x7zf8AAJPvf4VYmlk8rZb/ACSVDY+XDpUUEnlfPUfmyJLsuIaCuQsQvInySeVUjy1D9/8A1fz1Gj7/APltVEkz3scMW+T/AL48usLXbiS8iinuJv3iVu/cpqP/AMs5KYHHp/5E/gqzbJH9qirqfs8H/PGof7ItH+eOGkUZSJv+eOo7OX7NL+8/4HWu+lfuv+WtQvpEj1PIBBfWsby+fH/rP46wneRP9XNs/v10T+ZDFs/5b23/AKD/APq/lWZc6RJefPYf6t65+Q55wKttqEnlbJIYrqP+/J95P+BdauPFHcxeR/3x5n/oO70NU00XU4Zf9TVjyruGL/SIZfLoALa3ks5YvMh/1336kRPsd15H/LN/nqxbP/y0+/H/ABp/f/2tvr61Jc+RNF+7/wBYj7//ANmqAh1G1ke1/d/8922f8CUVjXNvAkuyObfJ/wBM/wD9db6eZeaL+7/1+/5P++ao2Nldp5qRw7I/7/8A9jWkCiqkUkMu/wC5srWS13+a9vD/AK7a+/8AuVOlv9m+e7vN8n/fC/8AfNRQ3H72VI/njf50oK5C2mmxvdefJ/H/AAfw/wC1/jViaW0totkdU4bif975f+s++lZ1zcR/fk/+xo5zbkNH7a7/ADR/doqtYXsa2qt/f5/p/Sip5wLb6baf8s5pUqN9Pu0+eO83/wC/WVc3F3YXWySbfTYdVnStjM0vK1P/AJ476bNLf23/AB8QypUMOtT/AHJKuw61In+sqiismqyf89v++6nTV5Eq4mqwTf6yjZYTf8sYqCSNNXkqZNa/56U1NN0zzd/73/v5Un2WBPkj8ry/+udAEyarH9+P5KH1CN/nkrNfQrh/+Pe8tqP7Fv0l/wBd+7qSi8n2B/8A95VmHyEl/dzVnW2m3f37v5I/7ifeeo0sr/7/AJNBJpXMXnf6u8/d/wAdRpF+63xzbI/4/wDerP8AKkT55Pkk/wA/5xTbx/Ji3yVjOfKTM2bOX+CObfTdQ+1LYXe6XI8l8/8AfJrBs7qPzd/nfu/79Wr25nGmXDeVKIzEwy6e1VCfMEDhNTnMMPUZbpWGDubnqetWtVlZnCt0HSqMYJbitxlwRxjldxx1z0rS02UEFG/Csx1KBQT1p9m2JhyQQaQzfG0N8xYj0NI4Q9CRTVlyKBKDzgUCHwnL4BOKnkI24qKJl7ACnuaAO78PXnl2dtbSd4kKfkKua1qslja+ZHWbbwyNpVpNH2gT/wBBFWtU0/8AtTRdkf8ArP4KmIzgLzV7+8+TzpfLesqF53l8itP+ytThuvIks5fMq6nhjVv9fHZy+ZWxJif2hf2EvmW80sE6V7NpcslxpdtNOP3jxqXrzrRfB099qn/EzhuYIIf/AB//AGa9KRAkeyP7iVMwJGal3VB+8f8A1dSp/t1IFa/uvs8XH326VkW9vJff6v5I/wC/Wm9hHcS+ZcfP/sVaHlpFsT7lY8nN8Qco6GKO3i2IPkp9N303f+9rQCWsO7WTzZUkm/74rm/GPiyez/0Wwm2Sf364mHWr9P8Al8l+eqKPVni/55zfcTZ89c7qNxJNLsuPk+euSTWrtJf9dL8//TStm8vfscsXmfPWc4BI6F3jeL95/q6znlj83/Xfcqm8VpefPHNLB/202L+tVLnT7+H545t8f+fwqeQ05zZ+1Rp/y2qf+0IHl/0j/vuOuTeK/wDv+TLUfmzp/wAsZarkJOy3z+VvsJonj/uVB/auz/WVzEOoSQ/P+9q4muxzfJf/AD/7afI1AG3/AGrJ/wA8asw6vHWCkUlx/wAgyaK6/wCmH3Jf++e/4VTe98mXZcQypJ/t1RJ2Vtq8c0uytFL2P/frgk1CCpX1Xf8A88qCjp759/8ApVv/AKxP/Qaob/7Out8f/HpN/wCONWXDqtp9ySGr0Mv2ywlSP59lZzJmbfm/9MakR4H/ANX/AKysCxuvtMXkf8tE+5TrN57mX935tVCQG26b4v7lV5kje1l/c7JP/Zqkd/s0X7ybfJVF7r97s8mX/bomUNdPsf8A1zmuvk/75qxNcRp8/wDfqHUf+PDz4/8AWI/yf5+lVoXkvNKleOb94nz/APxVTAn7Q6ZLR5d9x/3xVe81KN/K/g2fcrCudX8n/V/PJVC2uJLm/ieT/O2q+Io6q+up4ZYp7SHfv+eo7zT4P7Vl+1+a8fyukEf3fmXP41U06WS/sJbWT/WffT/eqzN5lz9gf+/B5P8AwJGx/LbRAnnLtpJbwRFXR2UsfL2dAo4A/SisyR3SV1j+7uoqSTbs9XguZfIkh+//AJ/WnfaNJm/1lnF5n/XOtLyrS8/1cMT/APfNVZtNtLmXfJD+8/v+ZVGhXht9F83f5MVWJtP0m5/1cPkSf9MJP/ZelQvoUb/6ubZ/4/VZ9Au0/wBXeRf+PVRJbTRbRIv9dK8n+3/9aqk2i3EP/Hvef9905NNv4f8AltFT/wDibQ/8sd/+5QBAmn61/wAs/wD0YtR7NWh/1kMtX4bq/wD+WlnLVyzuJ7n/AFdnLQUZkMupv/y53NSpqVwn/PWtTzZP+WkNylRve+T/AKybZ/vx0AVU1eT/AJaVYTV6k+2wTRf66pofs/344bZ5P+ua0AQ/bY5v9Z89V7x7SaL/AEiGJ605orSb/Xw/J/sfLVJNKgfzf30qJ/A7/wDoO2pJGw2umQ/8e8OypNYigns7mR5ZPMELcF/Y1C+kT+Vvjmi8yoNStb8Wkh8sSx/Zm3sj9ODzQB5trMYXYy1QgYDkrzmtS/jBjZXLce1Yykh9orUReyspC/rU9vbk3IXvUVmgVtz8gdak85fPba5HpSGaf2Vhj5xjvxSfZ23Z3DbUNve7kxnkdamN0tADo2VWwMmp87l4rMe9Uy47elX4n3rkdKLCPR9Hi8zTLRH/AOeKf+gitm0iMMWx6ybJ3h0C0eL7/kJ/6CK2oFKRfPUxGS0tQW1zBcxCaCUOjdDTppdlaEj2O0VT83f8lSea7U94o3qQDfH5VUJtQjSua8Y+IpNLi8i0/wBe/wByvOnvb+5l/eTS/wDfygD2yG6jf/V1Nv3y1zHhe4+06VFPJ/rP/ia6NP8ApnUlE++oHuP9an+xTtm/56zdUf8AdS+ZQB5T4ml36pLWXWv4jijS63x1g/vK0JNPRYvtOqWqf3Pnf/gNXdXl87Vf9yjwvFs+1XUn8CbKrWfmXl//AL71n9ok7TSLKO8sP3nleZ/48lW4Ujs/9X+4/wCucdVLPy4Ytkf+s/65tU8zyf8APb/v5G1UaDrlJLz/AFk3/fz56geyjeLy45v3lRzJOnzyfZvL/wCme7+tNe68m1if91/38+apAbDa2iX/AJFx8+yDzn8v7vy/5/8ArCsDV4vJ+Tzon/j3pWy9vHN9q8ybZ9pTZ8n93d/7N7fzrIvNPkhllSSaJ/k3/Ju2pub7vNAENtax33m/Z/NSSFK17O6nvNKieSGK92fwT/P/ALy7uo9qyrZ5If8AVzbN/wDH/s1q6dqUdtdbLuH92/33/i/3vf8AnUgRJa6Lf/8AHvNLZSf9NPni/wC+uo/HNTw6LIkX2W7+eN/9RdR/Ns/4F/jUmqWUFtfy/Z5ov33z/wBz738Xp+tGnafqb3W+PzYP9v7i/wD16AMZ7LZdSwSTbNj7K19Ft7uz82f/AJYV0c0Uflb7v7NdSJ/z0jpr3HnRbPub/v1IchV/sW0htZbqObZI/wA8P/xP0qaG6nubX938kiffqO2lk+yywXE2ySH7nmfxrWdNex2115//ACzf5HomBop5cP8ArP8AWVBearaW0X+kTSp/uVm6il/5v+j/APHp/fqPTrKB5d9x88mz79HxFc8S5q91/oGy383z9/8A47/s/wDjtU/D97JDL+8rWvHk/wBF8v8A55/+PbjVGa3j8qWe3/v70T/Z/i/EVmY85majbx6Xqkv2eH9xN86f3dv91vpRClp5V1dW/wAmxP8AUf73Hy+3zfUVs31v/a+ixTxzbJ7b/wBBqnpcU/m75Lzf/c/d/L6/X+GtOcrnMq2uPJl310v2iNLX7V/yzTc6f722o3tY4ZftX7r99/An8H/1qjS3jeWVP79STzmN/aH/AE2orR/0VPlkhi3f9c6KOcr2o2HXY0l3/ck/z/DVx9Xjml8+3miSerVzpFpfy+fJDsk/2Nyf+O//AKqhm8N2Dxf6BeSzyJ9+D/lr/wB81pyFEk17InlPHDKkb/8Ajjf3f8KamtSJUNtZSW0v2W4/f6bN/B83yf7XQdKr33h3yZdlvN+8/ufN/wChUc4Gumtb6mTVYHrnk0jU0/1f+s/uf/rqCZLu2ll8zzU/66R1QHZJqEflf/EVNDdf89PNrkoXkeLfHeRf7nzVYuXv7HynuIf3b/cdJPlegDrIZY0/1dGz/rl5dcamryJ/z1q1DrtAHR/ZYE/5c4v+2clQvax/88bn/wBDrKTXf+m0VW01eR/9XQUXobeBP+ev/A//AK1PfzH8pPtn3P8ApnVRNV31N/aVUSEPmebsjmio1Hzv7Iut8W5tr7T6DBpr3EDyxP5NP1B4H0m58uXb+6fj14NSB5xcyMsL7kPSuZY/vCfeulvATCwR8+x5rmnBDtnrmrEX7eRdpQtUb/LKc9BVZGwpqaKOSYnFADkkMZyOn6VeWaJ4NxG0jvWbNGY32sCKQSkJs7UAP37ps9RW1YzBl+auf3fNV2zucSKo5PrTEetTy+X4XtH/AOmKf+git27fztHkMf35oD/6DWT5UT+FLATfxQp/6CKhvtUe2sNjw+Wn/Lt5Hzf7q/jUlGJoWq/2XL5En+rmf5P8/WuyR/O/1leYX1vdwy+fcQ79n8H9ytPw54qk+1RWN3/wDfVEnoSfJ89Ne62VC9x5P/A6xNR1DybWV46kDlfHV1Hea1sj/gSuYdKLy6kub+Wf++9WNOt/tl1ElUB6T4UspLbRbX/b+f8A76roUSq9nF5NrFB/c+SrCPI/ySVmUSf8sv3lY2qfP5SR1sv/AKqsTUZdksr0Ach4g0X7T/q/krl5tIu7aXy5Ia7j/j8uv/QK29OfZay/aPn2VPOVyHD29rJb6B5Ef+sfc9O0uWCx/wCWP7yuu8Pxed9vurj/AJ5+T/31y3/stcfeW/kyy+ZNFBH/AAf5FEDOBp/21I//AC2qg97JVXfH/wA8d/8A10+SnPLOn/HvZxJ/1z+eq5zQkmluLmLZHVX7LInyfukk/go3yTf6zzf+2launaLvl33fzx/3KkCZHkhitX/5aInyf7Hy/e//AFmqT/Pf745vPjf7/wC72NWveJJVe20i7vv9X8kf996krkMa5i/e/wBz/brTs9Iu7+L/AEeHZH/z3krfttA0yw/f3H7+T/pp93/vn/Go7nVZP+XeGqAbbabaWEUX2j9/InyfvP8A4n/Gi51D/nnNsrOme4f57ib/AIBVK5uPJqiTXm1CPytkn+sqneahBDWM9xPNL/yyg/8AQqjm8h4pf+W8n+f88VmUaFtdbLqK68793Utzp89tdefb+U8b/wB/b/WsH948u/ydmz+D/wCxroLO4/tTRfL+/IlTMxJra3kvLWW1k/30/eL/AI06a1u7CKV7eGLzH+T93WR9njtpfPj+ST/rn8tavm/abX7Vb/6z/lvUkjrl44ZYo7v5JHj+/TUuo7n/AFcOz+55n+e/5dKbqKSP8/8Af/8AZlFZH2iS2l2Sf99yUiTb0K6jhutknyR1I8Udnf8AkSf6vf8A/WqjcyxvF9qj/wBZ/H/n3/nWpc+Xf6XFdf8ALRPv/wDAf/rfyoAhuZf9Kigt5v8AU/uf+BfxVHbS/wCqnk/g/wDQaq3Kf6VdPH/faq0Pmfcj/jpgT6sHgv5F875W+dfoeaK3LCWGa1Vrj/WD5TRSKG+VqcMv7v8Af/8AXOSjzZ/Ni+0WcvmfwVL5sH/LObZ/1zk/xqb7R/zzmrrNAS4n/wCeMtXEupPsv7zzU2f+g/8A1qhS4kepEuJEl3+TUzAbDdb/AJ45pf8Atn/9ajzY/K/z/wCPVDc6bYPdef5P3/7lRpawfcjmlT+5UgF9pEF5Fv8AJtnkf+P7n8jSxW//ABTZ06/+SCF/v/e+X9OfT9eKfcpJ+6eOb9x/cj3f5x7UW0s95FE8cOz/AGH/AM81QDbPRdMS6i8v7S+/d8k/3fu1znlSJdSxyQypH/Bs2/8A1jXXp5if6z5JE/z2zR9t/wCW/wC6eP8A2/8APUelTMDnk0iSb5/tkSf9dP8AJqvNpF+ksX7nfG/8afOtdpbXUflf67ZJUc17B5v+jzf+Q6AOTS1u4fN/c/u0o+0Tp/z1rqYXnhl8+4m/g2JVnf8Ax/un/wC2dUBx6XUn/Pb/AMh1curmIQRhQJAY8EHvWvLpthc+a/2OLzH/ALm75P8APtWf/Ytv5v7zzfL/ANj/ADmpKMa5FmYZQloqP/1zFcJKq+ZK+Bj6V6hqOhWn2D/R5pf+B15teJIkuyStIEzGW0S+bskUf3ulbGmmGHEjxRsjeqg1iJLInmv/AMtHq5Z3GyLyP9hv++v/ANVUBs6z9hntI2jhjSZXwQqgZrnfKV5PLjUb39qe7x/89qhd/wDnpUgaGuaM+jywxuA6TR7w/wDOs63eOOTeUUj3atp72PVPDnkTzf6XZfOn+2veufoiSe26NcRal4ehtpQFYR4AAwAKw7mX+zr/AGXHzwf+h/8A6q4fRdau9Ll3xzfu66b/AISqwvItl3DQUdHbahYajF+7mief+NKzLnQtMeXfHDs/7aVzk0sHm+fafuK17bUp5v8Ab2bqkDfhT91s86qGqeWnyVnvqEjxVDv31JRSm8OxvLvt/wCOtnQtIjs/nk/1iVDDcbP+B1eS4k8393VAdAl7v+eP/V1Ytrrf89YUPmJLVrzfJi8/7lAG3c3EaWu+uRvriS8l2Rzfu6h8Qa1H/wAetvNWbDqEaeVJJ/uUEm7bJsqS+uI0sNkf/Lb/AC1cimu7ItlOhvZJrCW6km/2Kzn8ITmac2tR2elRWsf+sd97/wDAqqw2v9r/APPL/tpXK/aJH/1ldDov+mfJJ8kdbcnuAaf/AAjsnm/vJonj/wCmf/18VD/ZE/m+R5P3P+ee773+zViGyj83Z52yP+N//wBfU+laNnb+T88fm2saf3/vP/h/OswMpLeBJdlxDL5f8f8AB/wHmujht9n+r+SP/wBlqmj2ln89vD+8/vyfO3/fVVptV/e/36rkKNlEgT55PnkqO81K3T/rpWFc6lI8X9ysqbUI/wDlnUlG7c3v/PxNs/2Ky5tQghl8z/lpWdMl35X+p/8Aiv8AgVUvuS0EmnNcT3P+r+SOo0ij83/ppUif8etHlSffjoAxNUt/9PlerNnpt2/mpHNs+StJ4oHi/eQ/vP4HjrRtpYPtW+P5JNjJQSYUNrI+l/bp5tlTaXdWltdf6P5vmf8AjtXvtH7qL/VPv/z92ruz7N5SSfJG/wBz9Plb/PvUkzG6ikf/AGwmqpZvcWd1V+HyJvNtfvwP86VTT7e91Knk/u9n3PL2bP8AP61JJc1e6jhii8v54Pub/wDdX7tc9c2880sU8nm+Q/8A30i1s6Rcb5ZbG4+T/wBk/u1HeRXfmywR/wCsoArI/wBjl/1O+N/kf/drV0WX7NdS2Mn+rm/1H/sv+FZH22Sz/cX8OyT+/wDwvW2lv9p0u1vrD/V/K6f7En/1z+uKAKqW8n9v/Zf+Wc377/4quhtrKNIv3dVbuXyfNvo4d8nkb/8AgLfe/I1gQ+IY7nVIkj821/ufvKo2gbd3psz3DNB93v8AWirkFxHcxCVLyLn737zvRUmhiXmmz20uyObz6IYrt4t/k/u634dS87/VzbJP+ulTW97O0nkweZHO7/8APP8A+tWhmcw8uz/ljRDe/wDTaWul1NbHzJYJf30if8Bb9Krzabaf88f/AGeqAq2Oob5fIkm/133H/uN/D/hR/aU8MsqSf6z/AKaR1JNpFon/AB7wyvJ/c/yarX0Udz88n7if+Pf/AOhf0qQLKarHNL+8h/74k2VG6RvLvjvLmCN/916w0i/e+RHeRP8A99VfhsrtJdlAGzZ+YnySalv/ANt//r1Yh0/ZLL5k0U8E3z/6v7jf3qyEee2817j5Nn/j9FtqH73955VUSarywWcv+kWdVftVh9yPTZf9j7tWIb+S4il8v/WQ/wDj8f8A9b+VOttSkSgCH+0pIfkkh37/APpp/jUkNv50X/LX/v5/9Y1M91BN/wA8v+/dV4bXZLvjvN9AFq2ljhl2SWcsEf8AsSM++iHy3l/0f5P9/dVd7edJf3f+rpvm3EMW+SH/AJaf8C/4DUzAtTP9p/49JvufI6P8n/fLV5X4it/s+tSp50fmb/8Aln/B/s/WvVkeCbzf31yn/bP5a4zxz9neP5Jo9/8ABBHu/wC+j6flWkCThN9Hm7KWmVQDt9Nd6KKAG0U779Sx+R9ll8zzfP8A4P7vvmgCKn7/AN1ElFI6UAWUuJK2dI1CO2v7XzP9X9x/+BVz1JvqQOuvH+x38tr/AHH/APHauw1ka1P9osNL1SP/AJbJ5L/7y1Sh1eSpK5zqn+T56mS4jtv9ZXLTa7J5X7uqk2tSfco5A5zrptdjT/rp/wDE1hapr+/5Lf8Ag3VgTXEjy7/OqOq5CS59qkf/AFlE11vqnRVASb99b+qL9h0a1tf+WlZWi+Z/bVr/ANdN9XfFF79puok/uf8AAazkSZCV0Phy42XX/slc8la2kfJLWhR3tze7It8nlQf9c6zprqT/AJZ1RfUPJ+eT+Oqn22e8l2W8NZmhYmlk/wCWk1VXuv4Lerv9mxwyxPdzefH/AB/3ammTzpfIt7yJ4/40tYPuf7P3akDO+xTzWsU8k0Xz7v8Ax2oZrWeGKWCOHfW+kUn/AFwj+5sSTf8A+PcfjxTv36fuLiH93v8AkSP73+z/AJ6UAUbFP9F2f8t3/wA7fypyRQTfPbw/u6guU+zXUXmfJBC//LP73+83+FWbN4Hupfs83n70b5/L+439KAKSS/vf3kP7v+OnfZY0ll8u8i/7abv8K09nnfPbw7JH+/P5f/oNOfSo7aKV4/8AXvt+eSgkz3t5Pv28P7v+P/bq5Z2/2nynuLP/AIHH/BUkNlJoVh/y1e+m/wCWCSf6mPd9447+lV/tElzF/pf7+P8AueY1BI7ZBY3XnyTfuE/z8zelDvvllT7+/wCffVxLrTHi2eTKkf8A392f7rensajfSvJ8q6tPK8j76T+Z8tZzAz3S7T9/9+NPn/2quXNxI/lXUf8Aq/uPUzxR/wDLOaJ43/6af99flUMLxwyywSeV5E38FBJC9v511En3J/vo9XJv9Ji3yfJPbff/AM/54ps1vJDF/f8A4Kh837Hqsqf8tE+//n2qSR02lf2jLFPbzW0+z+D+H/61aEOlPY+HJdP/AHryO7TIn06LVN9NgSWKe0+SR3+R0+T71aeo6ld2d/sjs4rq0TbC7+Zsb/CqNPdM6zvf3USX8PkTw/wf7NZt9oFpNdfu/kjf7ifxVc1e6sJpfPtIZYLuH/x//gVSJ/p8UU8c2zyf/Qf4l/wqivhOSk0Uo5WS48nH3f8AbH97+n4UV0sj2ly5luXzIf4dxGwdl44OB3oqucC8+pQJ89xD+7/getGG4gmiinjh3x/c3wSfc/4EP61iOkkPz+T+7f76f+zUfZbRP39v5sEn9+CRk/rQBpvp9g8W+3ml/wB/+5/vVI9v+6ieOaL/AD/tf981Vtnj/wCWk37z+/8Acb9MVYdJJrXZH5Xmb96eX/H/AMB7VQFeaK783/pn/sSU62t5Hl/eWf7v+PzKaj36fJJDQ+oTw0AakOi74v8Al2/3KtppUaRfvPKrK+2xvaxTyQ7/AOB//ZamS9gmi8jyYvL/ALlSA2+t7eGWLzJpfkf/AJ6f3qkmt4PuSTS+en/PT5P/AK1U5re3+yy/Z5pU/wC2m+tVJbSa1i+0fP8A+yf7vTiqAzE0+Tzf+PyL/wAd/wDQutN/s+f/AJ47/wDrhIv9avTWUaS7JIZYN/8AHHJvX9aDp0gkzBd2z/8AA9tAGalrf/8ATX/tpTniuE/1kMtWJpb+0/18OypE1KP/AJaUFFNJZP8AlnUz3U/lfvP9XVxLiOb5P/sKciQP/wBc0/75qQKv2v8A65Vma1FHeWuz90n9/ZtT/vpuw/DNbNnawPFL9oh+47JUd9ZWn2WXzIf3af5+73qoEnj0ybJZfLptTXif6VL/AK3/AIH96oa0JGUU7fTaAG0UUUASJT6aj7Kcj0ANpj1K9RUAdBpf+meFtUsf47bbcp/7NXP1s+FLjydfiST/AFc37l/+BVn3lv8AZLuW1k/5YuyVP2gIaZUtFUBFRRT6AGUUUUAbfhmL/SpZ/wDnin/oVZt5L511K9bNj/onhuWf/lpN/wDqWudqYfESSpWlY/JLvkrNStSz+SqKNPZ9pi2VcheO2+SSGVI/43jkWs9Pklro9OewuYtl38k//odTMqBT3zzRSvJNv3/6j/8Aa6fpVrTv3MW+7/17v/3x/WtOGyjT/j3m+5/n8akm0+P968flPJ/03+7/ACrMojeLZFvj8p56pfuHl/eTW3np/n5ecVf+yyQxS/Z/KST/AMd/757fh9fanReZ5u97OL/bST/2R/8AEUAZ1ykiS75PKeN0+f8Adru/X/PpUk1vsiif7n8ez+//AMB6Vb1Gwnufnt7PfB/wHdC1RpZX/lfvJv3f/AaCTMmT9159v8mz/X/vP++a35njtLWK6k+eSb/UwP8A3v8Aa9h+tQ/ZZLaKW6ks4p5NnyQfw/L/ABN/QVX+0X80X+kebP5yfP5f3oZP9nPGP6UElK+e7ufKnjm/0ub/AIB/wFar3MUln88n7+P+OryRXbxfvIfIk/vwfPv+X68frVmG3gmsN/k+RJ/Hsj2f8C9xQUZWyT91Pb/6h0/g/g//AFU221W7tvtUEkO+D+P/AHf734fyrTeLZaypHDvjmff/AKz5f+A5/lVZ0k/e+XDL8+3/AFkdAENzF9p+S3815E+dEk+8n+79f8Kj1HUpEluoJId/9x/L2bP7rK/epPs873USf8es8NbeyR5dkf7+P+5H/wCPbc8H8DUk8hT066+02v8Aqd8ny7//AIql1S/v/tcVr5Nt9k+XZ5kmxpt3+elV7yKTTr/z/OieOb/nn8n/AI7V+5v54YpYI4YrqDy49n97d/F/kUAQ6dcR2eqy2sf7+OF/k/z9aqfZ/OupUkvPv/wSbvn/ANrb9auzJPeWu/8As3yJIf44/n3/ANfzqDfH9lluv+Wj/wAHmfxVJJXmso4fKTyfPqrC8mnX+ySHyP8AYkrQ/wCPmKWf97B/1z+f/vqo7nSp5rX935Xnp8/+s+b/AHfX/wCvVGkyGSw3uX8uKRX+ZW9RRUcEu+IN9q8v/ZoqeczNeZJ/N8//AJaJ/n/OPyqpc+Qnz2/+o/5bp/cb+8qnnFX0ln/57f8AkP8A+vVe8Se5/wCW0SSf3/8A2Xr0quQ2GTafviie0/8ARlRw2t3/ALlCPd2H+r/fwf8AoFaNtcR3kW+3/wBXVAV0up3/AHFx5qSJ9yf/ANlb/HtUj3s6S7LiH7lWklkqaG43xbJJpf8Af/z2oAq2d7G8v7v5N/yf/E025e0uYv8ASPk2fx1Yd5PuSU7zd8W//O6j7QFN7KB4tlvN/wB/KLO1ke1ifzv3eyrnmx1DYvH9giqgI0/tOztZYI4fPg/g3/eT8u38qEvbtP8AWQ1Ye62U37V53yUAH9of8/EP7unPLYTRbJIdm/8A6Z0fuEi8j/ln/cpqW9p/uf8AXOgA/s20m/49LzZ/4/Uc2nzpFElveReZv/8AHf8AO6rU1rB9l/0e8l/3Kj8rZL/rpaAK/wBlnSX93RM935UvmQy1Yd9nlSed/sVZd98Uv76pA8n11Nl1/qZf+/eyst67jxdaxva7/ubP8/5xXC1sZhTN9FFABTaKKACp0Soqv2afupXkoAjSKoXq08u/56qvUgEL+TLE/wDc+etbxWn/ABOfPj/1dyizf99Vj1v6v/pPhzS7ofwbrZ/6UT+IDCSpHSo0TfXaeHPDcD2v9sa1+4sU/gf+P/e9v50Aca/yVFvrqNa8VT3115Fh/otinyJB5a/P/vf54rnni2SypQBWoT55dkdOerei2/napF/sfP8A981QGr4gaO3sLW1j/wA7axPv1a12Xzr/AP3KoJUw+EknhT+CStez/wCecn+srKh/v1q2aR/9s60KJt8afuLirFtcSJL+7m/eVV3/AGnzYLj/AFif53U22f8A55/PQB3lndSTRfvKsb5H+SOGsjw5dSJ8nk7/APYrfT/lr/t1mUV/NoS6j/5aVYTy0+f91/v/APstEySTSxeZ5TwJ/BUlBbXWz57f/gf/ANlTftVo/wA8c3yf3P4k/wBmp7byLb5PJ/d/9c6imitE+eOH94/+e/8ASgkHeD7lQv5dO8qN4v8AU7JP9iTf/wCO/wD16JrffFF9n/1lBQ7Z+63/AO3soeo7a1n+wXSfc/1bp+8psNrPN/rPk/8AH6CSSmulRva3aS/u/wD0ZRfJcW1rF5cMryOm9/L/AIKAK/2ifzf3fyVNbJ5MX/TT/bqnDLP5W/yZfL/651YS6k+/QBNeW/2nzUuPKrO0755fstx/r0+Srv8AaH/PSqGqP5N1Fdf8tE+//u/w1IGjb/a7T/j0m/d/3Hj+Wqtz/o1/v/5YXP8A6FWhbSxzWvn/APLOoby1jvLWVPubPn3/ANz+7/hRycwFhLe0h+f975j/AHNm2i3020uL+LjKW3z73/u/3ap6RdSXMWz/AJaVpTXUdjLKlxN58jp/qP8AH/CiAHN6xoWqf2lNLaIrxTsZBtxxkng570VvfbZH+b91RRyByGElxU32qqzRyq0qrKQvpUUkkscXyMKo0NH7VGn/AC2qo6R+b59pNsn/APQ6oPcS+V/rH/Or1mscn+tUmpmBZtr3fLsuIfIn/wDHX/3at+bWbdW6SNtdRt9MmoVmngeGGZw6n/VuOWT86kPhNpLjfFFBJ/33Tk/5awSf6z7/APn8KzfIuf8Anon5VYtZLlikbGMyKxWJ8dx1B/2TRMCbzahsfktYqoSXTL91QKlgZlt4lU4X0rQC4776clxslqNKh3UAXvtUdD3Ub1mJS7m9aANL7RHTftUf3KzdzetHmP60AaVzcR+VQkv7r/gdZL3H+wKsTyOtrFtOPvVP2gFvnjeL93DF5lee6pb/AGa6/v127My/dOK5LXpN118zufxrQmZjUU+mVRmNp1FFADkSrqPv/wCudU6mSgCSZ6r1YembV9KkCLZXQ6Q8FxoN1ZXfmf6zzk2feSsNlVfujFdF4bjii+1XDKW+T7vapn8IF3SNPtNOtft2p2cUH9zfuZv+Bdv0qHXddsNRsNkkMrzo67E+ZV2/getY2oXl5fXjNdSAqv3Yx90VQephHuBaR7Dzf+POVP8ArnP/AIitOz01H/06/s/stj/HPP8APv8A91eP5VXsbe2srL+09QjNz8+xIhwu71Oe34VT1XVL3U7pVnZFSMZjhThFH0HetAKVy0b3Urwfc/grX8PxbIrq6k/3KxK3/wDV+G18rjdjd7561MiTCd/Ollf+/RS07y09K0KH23yS1q2yfx/36zratez+5t/h9KoCO5SR4tn34/4P/sf8KqQvslqxcKq/eGOcfJ/6F9apyfN97mgDrPD8v72uvhlj8r95Dsk/66Vwuhffib+L1rpNWvPs9qXQMu3rtPT6VnM0gb/lQP8A6zzaPKg82JI5pfLrGtbzdF8oY/75qZLprmPy41Cyf3+n8qkDZSKN/wDWTVJ9i3/P51ZCf6jyZ+W/vDn+dSQyeWm2J3C+makC+9l/z0oS18mXfUJklb7zA01Jn/56P+dADt8cPmp/fSqm+0f5P+Wn/XOory6vI7zbFIAvpW7Azou7yYFb/YGKoDJfT4Ln/WQ/+Q6j/sq/hl3282//AGJP4P8AdrqKWpJMO4gu/t/mW8P7t/v7/wD4nvTbu3kf5JIf3f8ABW9RVBc594pHi8iSH93UVzp8b2vkeTXRVh3OupFdfZ1tR/vbv/rVJRgv5lnf/Ybv/V/fT/drQ/0S5iitbeaXy9/zv/fb/wCtT/Eq79OWbYiTxsGjZB0B6iodPm2wKykhm+8cDmgkrXyR6dfxXVp5qQP8j7/7396rlnYedH50nl/9s32N/wACBzVq6hSW0ljnjRov4wB/KszQWZf9HnPmf7VT9sC39niT5Y/tO3/r13frRVzavpRWhR//2Q==

我們把這個圖片進行解碼,然後轉換成灰度圖片。

其中灰度值通過公式 R * 0.2126 + G * 0.7152 + B * 0.0722 計算得到。

public static void main(String[] args) {
    String base64String = "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";
    byte[] decodedBytes = Base64.getDecoder().decode(base64String);
    try (FileOutputStream fos = new FileOutputStream("image.png")) {
        fos.write(decodedBytes);
    } catch (IOException e) {
        e.printStackTrace();
    }
    changeImageGray(decodedBytes);
}

public static void changeImageGray(byte[] imgByte) {
    try {
        // 讀取圖片
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(imgByte));
        // 獲取圖片的寬度和高度
        int width = image.getWidth();
        int height = image.getHeight();
        int[][] lightArray = new int[height][width];
        // 遍歷圖片的像素點,將其轉換爲黑白
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                // 獲取像素點的顏色
                Color color = new Color(image.getRGB(x, y));
                // 計算灰度值
                int gray = Double.valueOf((color.getRed() * 0.2126 + color.getGreen() * 0.7152 + color.getBlue() * 0.0722)).intValue();
                // 將像素點的顏色設置爲非黑即白
                Color newColor = new Color(gray, gray, gray);
                image.setRGB(x, y, newColor.getRGB());
            }
        }
        // 保存黑白圖片
        File output = new File("gray.jpg");
        ImageIO.write(image, "jpg", output);
        log.info("驗證碼圖片已保存爲:{}" ,output.getAbsolutePath());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

這樣可以把圖片轉換成下面的這個樣子。

其實這時,如果我們輸出圖片的每個像素點的灰度矩陣,已經可以發現灰色方塊處的灰度特點了。可以很明顯的看到灰色方塊區域的灰度值變化。

如果你檢測這個灰度矩陣,你已經有辦法找到灰色區域開始的位置了。

圖片二值化

爲了更方便的分析,我們可以對圖片再次轉化,我們可以選取一個閾值,超過指定閾值的像素點直接轉換成白色,低於指定閾值的顏色轉換成黑色。這樣更方便後續的分析。

改造代碼,添加亮度閾值判斷,這裏選擇 100 作爲閾值。

for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        // 獲取像素點的顏色
        Color color = new Color(image.getRGB(x, y));
        // 計算灰度值
        int gray = Double.valueOf((color.getRed() * 0.2126 + color.getGreen() * 0.7152 + color.getBlue() * 0.0722)).intValue();
       // 將像素點的顏色設置爲非黑即白
        if (gray > 100) {
            gray = 255;
        } else {
            gray = 0;
        }
        
        Color newColor = new Color(gray, gray, gray);
        image.setRGB(x, y, newColor.getRGB());
    }
}

轉換後的圖片變化如下:

如果我們打印這個二值化後的圖片像素矩陣,可以更加清楚的看到灰色矩形區域幾乎都是 0 值。

滑動距離計算

對二值化後的圖片進行計算,可以非常方便的找到灰色矩形開始的位置,只需判斷每個 (x,y) 像素值和前一個像素 (x-1,y)的值變化情況即可。如果某一列出現大量從 255 變化到 0 的像素,這裏很大概率是達到了矩形的第一個邊界,這列所在的 x 值就是要移動的距離。

簡單的計算方式如下:

// lightArray 存儲了二值化後的圖片像素信息
// 掃描發現 255->0 變化的最大數量
int maxChangeCount = 0;
// maxChangeCount 對應的列值
int index = 0;
for (int w = 1; w < width; w++) {
    int changeCount = 0;
    for (int h = 0; h < height; h++) {
        if (lightArray[h][w] == 0 && lightArray[h][w - 1] == 255) {
            changeCount++;
        }
    }
    if (changeCount > maxChangeCount) {
        maxChangeCount = changeCount;
        index = w;
    }
}
log.info("分析得到驗證碼座標值:{}" , index);

針對用於測試的熊貓驗證碼圖片,計算得到滑動距離爲 127,驗證圖片發現距離也大概是 127px 左右。

至此,圖片滑動驗證碼自動化破解完成。

由於測試的網站並沒有加入拖動軌跡的驗證,某些滑動驗證碼會分析鼠標拖動的軌跡來判斷是否是人工拖動。

如果我們模擬 HTTP 請求,串起所有的步驟,那麼就可以自動化查詢域名的備案信息。下面是我的測試(合規原因,完整代碼就不貼了,如果需要完整代碼可以找我(公衆號或微信))。

總結

本文介紹了常見的圖片驗證碼形式,緊接着具體介紹了圖片滑動驗證碼的實現原理,並選擇一個網站進行具體的圖片滑動驗證碼驗證流程分析,最後介紹如何破解圖片滑動驗證碼,主要是如何計算圖片滑動的距離。

一如既往,文章中代碼存放在 Github.com/niumoo/javaNotes.

本文 Github.com/niumoo/JavaNotes倉庫已經收錄。
本文原發於網站:如何破解滑動驗證碼?
本文原發於公衆號:如何破解滑動驗證碼?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章