From ea85ad240a7e54824f86bc199594cfe8f34e10b0 Mon Sep 17 00:00:00 2001 From: TRHX Date: Mon, 7 Feb 2022 09:30:02 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20=E3=80=902021.12.31=E3=80=91PEDATA?= =?UTF-8?q?=20=E5=8A=A0=E5=AF=86=E8=B5=84=E8=AE=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- JSReverse/max_pedata_cn/README.md | 218 ++++++++++++++++++++++ JSReverse/max_pedata_cn/main.py | 57 ++++++ JSReverse/max_pedata_cn/pedata_decrypt.js | 56 ++++++ 3 files changed, 331 insertions(+) create mode 100644 JSReverse/max_pedata_cn/README.md create mode 100644 JSReverse/max_pedata_cn/main.py create mode 100644 JSReverse/max_pedata_cn/pedata_decrypt.js diff --git a/JSReverse/max_pedata_cn/README.md b/JSReverse/max_pedata_cn/README.md new file mode 100644 index 0000000..acd7b0c --- /dev/null +++ b/JSReverse/max_pedata_cn/README.md @@ -0,0 +1,218 @@ +![](https://i.loli.net/2021/08/07/JbP4zaS2TxU6Rkd.png) + +> 关注微信公众号:K哥爬虫,持续分享爬虫进阶、JS/安卓逆向等技术干货! + +## 声明 + +**本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!** + +## 逆向目标 + +- 目标:某投资领域 SAAS 系统 PEDATA MAX 资讯,返回结果加密 +- 主页:`aHR0cHM6Ly9tYXgucGVkYXRhLmNuL2NsaWVudC9uZXdzL25ld3NmbGFzaA==` +- 接口:`aHR0cHM6Ly9tYXgucGVkYXRhLmNuL2FwaS9xNHgvbmV3c2ZsYXNoL2xpc3Q=` +- 逆向参数:请求返回的加密结果,`data: "L+o+YmIyNDE..."` + +## 抓包分析 + +我们在首页,点击查看全部24小时资讯,往下拉,资讯是以 Ajax 形式加载的,我们选中开发者工具 XHR 进行筛选,很容易找到一个 list 请求,其返回值 data 是一串经过加密后的字符串,exor 不知道是啥,但是后面可能有用,ts 是时间戳,如下图所示: + +![01.png](https://s2.loli.net/2022/01/04/r7RGZsgw1M6JvdH.png) + +Payload 里的参数没有什么特别的,就是一些翻页信息,我们再看看请求 header,这里注意 `Cookie` 和 `HTTP-X-TOKEN` 两个参数,访问这个页面需要登录账号,一般来说,Cookie 是用来标识不同用户的,但经过 K 哥测试发现,此案例中,这个 HTTP-X-TOKEN 参数才是用来识别用户的,所以不需要 Cookie 也行,随便提一嘴,Cookie 中我们经常看到有 `Hm_lvt_xxx` 和 `Hm_lpvt_xxx` 是用于百度联盟广告的数据统计的,与爬虫无关。 + +![02.png](https://s2.loli.net/2022/01/04/Mojc4SxJKtAr3yh.png) + +## 加密逆向 + +我们注意到返回的是一个字典,在获取到加密数据后,肯定会有一个取值的过程,所以我们直接搜索键,搜索 exor 结果只有一个: + +![03.png](https://s2.loli.net/2022/01/04/7hS9HNwUPzLYyDs.png) + +这里 `e.data` 就是返回的字典,`e.data.data`、`e.data.exor` 依次取加密值和 exor,这里就可以猜测是将加密值取出来进行解密操作了,我们在此函数结尾处也打个断点,看看这段代码执行完毕后,data 的值是否变成了明文: + +![04.png](https://s2.loli.net/2022/01/04/YfVGsmyRZbqWzOC.png) + +不出所料,`Object(p["y"])(e.data.data, e.data.exor)` 这段代码就是解密函数了,`Object(p["y"])` 其实是调用了 M 方法,跟进去看看: + +![05.png](https://s2.loli.net/2022/01/04/F3CkznfwIpuQyis.png) + +传入的 t 和 n 分别是加密值和 exor,最后返回的 `JSON.parse(c)` 就是解密结果: + +![06.png](https://s2.loli.net/2022/01/04/ivdA5eSPaJh91rt.png) + +关键代码: + +```javascript +function M(t, n) { + var a = L(Object(s["a"])(), n) + , r = Y(B(t), a) + , c = o.a.gunzipSync(e.from(r)).toString("utf-8"); + return JSON.parse(c) +} +``` + +挨个函数扣下来,简单的就不讲了, 其中 `Object(s["a"])`,选中它,其实是调用了 c 方法,跟进 c 方法,实际上是取了 `loginToken`,这个 `loginToken` 就是我们前面分析的请求头中的 `HTTP-X-TOKEN`,包含了你的登录信息。 + +拓展知识:`window.localStorage` 属性用于在浏览器中存储键值对形式的数据,`localStorage` 与 `sessionStorage` 类似,区别在于:`localStorage` 中的数据可以长期保留,没有过期时间,直到被手动删除。`sessionStorage` 的数据仅保存在当前会话中,在关闭窗口或标签页之后将会删除这些数据。 + +![07.png](https://s2.loli.net/2022/01/04/8el92BxjsVQzhg1.png) + +再往下看,有个 `o.a.gunzipSync()`,先放一下,先看看传入的参数 `e.from(r)`,跟进看可能看不出来什么,直接对比 `r` 和 `e.from(r)`,会发现都是 Uint8Array 的数据,一模一样的,如下图所示: + +![08.png](https://s2.loli.net/2022/01/05/id4N1lt9KcYgHTJ.png) + +再来看看 `o.a.gunzipSync()`,实际上调用的是 chunk-vendors.js 里的匿名函数,不知道这个 JS 不要紧,我们注意到 chunk-vendors.js 里面的代码有超过14万行,再加上这个奇怪的名字,什么模块供应商,不难想到这是一个系统或者第三方生成的 JS,事实上它是 vue 应用程序构建过程中创建的文件,对于我们爬虫工程师来讲,粗暴的将其理解为类似 jquery.js 一样的东西也行,我们一般是不会去扣 jquery.js 里面的代码的,同样这个 chunk-vendors.js 也不可能傻傻的去扣。 + +![09.png](https://s2.loli.net/2022/01/04/PAkbFhtoUGWeYmi.png) + +我们重点看看这个函数名,gunzipSync,其他不认识,但认识 zip 吧,可以联想到应该与压缩有关,不了解同样不要紧,直接使出百度大法: + +![10.png](https://s2.loli.net/2022/01/04/3qMUa9sgAF2X5KH.png) + +这直接给出了 nodejs 里面的实现方法,用的是 zlib 模块,随便找个示例看看用法: + +```javascript +var zlib = require('zlib'); +var input = "Nidhi"; +var gzi = zlib.gzipSync(input); +var decom = zlib.gunzipSync(new Buffer.from(gzi)).toString(); + +console.log(decom); +``` + +进一步学习,我们可以知道 `zlib.gunzipSync()` 方法是 zlib 模块的内置应用程序编程接口,用于使用 Gunzip 解压数据块。传入的数据可以是 Buffer、TypedArray、DataView、ArrayBuffer、string 类型,在官方文档中我们可以看到更新历史里面,在 v8.0.0 以后,传入的数据就支持 Uint8Array 了: + +![11.png](https://s2.loli.net/2022/01/05/lLWxekSTArEuQXD.png) + +结合前面我们对 r 值的分析,所以在 nodejs 里,直接把 r 值传入到 `zlib.gunzipSync()` 方法里就可以了,将用到的 L、V、B 三个方法扣出来,然后配合 zlib 库,改写一下就能拿到解压后的数据了: + +```javascript +function getDecryptedData(encryptedData, exor, loginToken) { + var a = L(loginToken, exor); + var r = Y(B(encryptedData), a) + var decryptedData = zlib.gunzipSync(r).toString(); + return decryptedData +} +``` + +![12.png](https://s2.loli.net/2022/01/05/BKywIhs7TUSjk2C.png) + +## 完整代码 + +GitHub 关注 K 哥爬虫,持续分享爬虫相关代码!欢迎 star !https://github.com/kgepachong/ + +**以下只演示部分关键代码,不能直接运行!** 完整代码仓库地址:https://github.com/kgepachong/crawler/ + +### JavaScript 加密代码 + +```javascript +/* ================================== +# @Time : 2021-12-31 +# @Author : 微信公众号:K哥爬虫 +# @FileName: main.js +# @Software: PyCharm +# ================================== */ + +var zlib = require('zlib'); + +function L(e, t) { + if ("1" == t) + return [7, 65, 75, 31, 71, 101, 57, 0]; + for (var n = [], a = 0, r = t.length; a < r; a += 2) + n.push(e.substr(1 * t.substr(a, 2), 1).charCodeAt()); + return n +} + +function Y(e, t) { + for (var n, a = new Uint8Array(e.length), r = 0, c = e.length; r < c; r++) + n = t[r % t.length], + a[r] = e[r].charCodeAt() ^ n; + return a +} + +function B(e) { + var t, n, a, r, c, u, i, o = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", s = "", f = 0; + e = e.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + while (f < e.length) + r = o.indexOf(e.charAt(f++)), + c = o.indexOf(e.charAt(f++)), + u = o.indexOf(e.charAt(f++)), + i = o.indexOf(e.charAt(f++)), + t = r << 2 | c >> 4, + n = (15 & c) << 4 | u >> 2, + a = (3 & u) << 6 | i, + s += String.fromCharCode(t), + 64 != u && (s += String.fromCharCode(n)), + 64 != i && (s += String.fromCharCode(a)); + return s +} + +function getDecryptedData(encryptedData, exor, loginToken) { + var a = L(loginToken, exor); + var r = Y(B(encryptedData), a) + var decryptedData = zlib.gunzipSync(r).toString(); + return decryptedData +} +``` + +### Python 示例代码 + +```python +# ================================== +# --*-- coding: utf-8 --*-- +# @Time : 2021-12-31 +# @Author : 微信公众号:K哥爬虫 +# @FileName: main.py +# @Software: PyCharm +# ================================== + + +import execjs +import requests + +news_est_url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler" +login_token = "token 换成你自己的!" +headers = { + "Accept": "application/json, text/plain, */*", + "Content-Type": "application/json", + "Host": "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler", + "HTTP-X-TOKEN": login_token, + "Origin": "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler", + "Referer": "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36" +} + + +def get_decrypted_data(encrypted_data, exor): + with open('pedata_decrypt.js', 'r', encoding='utf-8') as f: + pedata_js = f.read() + decrypted_data = execjs.compile(pedata_js).call('getDecryptedData', encrypted_data, exor, login_token) + return decrypted_data + + +def get_encrypted_data(): + data = { + "type": "", + "module": "LP", + "page": + { + "currentPage": 1, + "pageSize": 10 + } + } + response = requests.post(url=news_est_url, headers=headers, json=data).json() + encrypted_data, exor = response["data"], response["exor"] + return encrypted_data, exor + + +def main(): + encrypted_data, exor = get_encrypted_data() + decrypted_data = get_decrypted_data(encrypted_data, exor) + print(decrypted_data) + + +if __name__ == '__main__': + main() +``` + diff --git a/JSReverse/max_pedata_cn/main.py b/JSReverse/max_pedata_cn/main.py new file mode 100644 index 0000000..4d5a344 --- /dev/null +++ b/JSReverse/max_pedata_cn/main.py @@ -0,0 +1,57 @@ +# ================================== +# --*-- coding: utf-8 --*-- +# @Time : 2021-12-31 +# @Author : ITBOB +# @Blog : www.itbob.cn +# @CSDN : itrhx.blog.csdn.net +# @FileName: main.py +# @Software: PyCharm +# ================================== + + +import execjs +import requests + +news_est_url = "https://max.pedata.cn/api/q4x/newsflash/list" +login_token = "1796a48fa1968edd5c5d10d42c7b18139a33fcb392b9904a6c08079fc3a3068e" +headers = { + "Accept": "application/json, text/plain, */*", + "Content-Type": "application/json", + "Host": "max.pedata.cn", + "HTTP-X-TOKEN": login_token, + "Origin": "https://max.pedata.cn", + "Referer": "https://max.pedata.cn/client/news/newsflash", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36" +} + + +def get_decrypted_data(encrypted_data, exor): + with open('pedata_decrypt.js', 'r', encoding='utf-8') as f: + pedata_js = f.read() + decrypted_data = execjs.compile(pedata_js).call('getDecryptedData', encrypted_data, exor, login_token) + return decrypted_data + + +def get_encrypted_data(): + data = { + "type": "", + "module": "LP", + "page": + { + "currentPage": 1, + "pageSize": 10 + } + } + response = requests.post(url=news_est_url, headers=headers, json=data).json() + encrypted_data, exor = response["data"], response["exor"] + return encrypted_data, exor + + +def main(): + encrypted_data, exor = get_encrypted_data() + decrypted_data = get_decrypted_data(encrypted_data, exor) + print(decrypted_data) + + +if __name__ == '__main__': + main() diff --git a/JSReverse/max_pedata_cn/pedata_decrypt.js b/JSReverse/max_pedata_cn/pedata_decrypt.js new file mode 100644 index 0000000..3b38ee7 --- /dev/null +++ b/JSReverse/max_pedata_cn/pedata_decrypt.js @@ -0,0 +1,56 @@ +/* # ================================== +# --*-- coding: utf-8 --*-- +# @Time : 2021-12-31 +# @Author : ITBOB +# @Blog : www.itbob.cn +# @CSDN : itrhx.blog.csdn.net +# @FileName: pedata_decrypt.js +# @Software: PyCharm +# ================================== */ + +var zlib = require('zlib'); + +function L(e, t) { + if ("1" == t) + return [7, 65, 75, 31, 71, 101, 57, 0]; + for (var n = [], a = 0, r = t.length; a < r; a += 2) + n.push(e.substr(1 * t.substr(a, 2), 1).charCodeAt()); + return n +} + +function Y(e, t) { + for (var n, a = new Uint8Array(e.length), r = 0, c = e.length; r < c; r++) + n = t[r % t.length], + a[r] = e[r].charCodeAt() ^ n; + return a +} + +function B(e) { + var t, n, a, r, c, u, i, o = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", s = "", f = 0; + e = e.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + while (f < e.length) + r = o.indexOf(e.charAt(f++)), + c = o.indexOf(e.charAt(f++)), + u = o.indexOf(e.charAt(f++)), + i = o.indexOf(e.charAt(f++)), + t = r << 2 | c >> 4, + n = (15 & c) << 4 | u >> 2, + a = (3 & u) << 6 | i, + s += String.fromCharCode(t), + 64 != u && (s += String.fromCharCode(n)), + 64 != i && (s += String.fromCharCode(a)); + return s +} + +function getDecryptedData(encryptedData, exor, loginToken) { + var a = L(loginToken, exor); + var r = Y(B(encryptedData), a) + var decryptedData = zlib.gunzipSync(r).toString(); + return decryptedData +} + +// 测试样例 +// var encryptedData = "L7JsMjA2YmMwOYlua2V5KqbHTzYhJdN4U5repboBzQSW7lfvAbiMHuvR/BqlfNS/aEElhuvlsXIyGkC2IFYR9DC63fonEgoA4LyvTdlnBDYNwEv+CaMgTRTt6Y+OwwwkyJjOpknE/vCp5p38+fK9FCo6GU9WEhg+j1gSRHuhWK7fmxlUz3Yt14MCVuLjRcvQhxYMxEVAFRVu09gxvYhonC0jlu6V+LEFz8QZlQ4m37q7tFrdNVefs+TR6XZxGh5B5cS+U/mv7bj1k/cqhwFlity3V2UV01/5S38XA4KIB84OjtKUWBwUjspmjeB2m1CR/+E0nyQV7RSs0KPW0c7JoARgK6K5DwmauaxJarv1BgW018qBbkKZUgmlxNsRXVYue/w+V624pCMy5DqV/2EjRamh1mXjg4ginW11icwEVkHBwlpJWCNn2A/jP/EEiUjIbZM4mayGZJvTWKj4/uEoSoqmg4lU0xWTPU1iIXhf6qc+1JkKH0c+wDu1LmQa4KhoqqPVbT4NkUx5mCgU48KzIp1r1EC35t016h+9EYuOiqcm0LhunQJkleC6ZwCpMt8KXq1AxdlCuzpKO8au9OJdALPdHKDeECJD/QSj5dyn964K4HWgbbU1N98crJ2gtW/ZYIiLLeUcOdbiG7eTETL5ji4MHrMgzADkfF8tUyRo/641CeULpFLV0nEQCVeCllEftG4IToB6BXBEFyrQiyxLj0t00VFBBGPwpnhzShYxbtW78rLGepvwAlO5mRI1kP8PX7uBAv/Y4NpD1itPjYEDpgBAsn4qCGWgzU4exkvJd909ksph0DKcUR9lcss++L1OueR4NV1W/+aTzp4pG6dPNZNOROBo8iNems4jx9g21oFJz3qPRzEGacDvt0mTIViakk6aFMCqSkss1odOmv6ZVqEO8JJYfkM64AwpAiTvkhCSJzZHT+H/qz0hQ5DvAO9rHk2rluSJ+XKWcgvtvUbS0GtqQHMhGReVB8MQ5G94eSXFIgz15862FPNVjA3gWcLj/vd7HI0VeTZ+yZUMedZ3LTo88JIRf+R/5HU5ZnwLAmW0mfuhiZg5FP7jjKvogFQJus+FX9Tj5O5XLZJerMV3hUnJYZXCqazXuAchx/MMMXah7mh7Z05dBDY8R5LYN/xouau2Dh3o/75eYyB3pAnI7m682WriUDhbpargvZAHzWnXdm/VozZzb20zYL6wGucbDRn9WLCh2/OSIhbyPKjhaz290bmzEjvhuGrPLDHyWWijHZqufKK4Ox/BIXvCLI325f917UewQ4/ynr/IR6GTksKUFJaf4bdqtTN0hkv6Da6uUlwwK8FI1bfJBB2/4VeaU3p3Bd5FepWhGAQVTN+J3lUjtQH+ignlX+XIjc3GUbDBDLeRYyIGqh/zVPrd6IIjPxuf1eenPW90YuWs14xHzWtttdrut1ygzAV4yzasvu921pBFy0pzkF5Gsy8DnuUY3kx9Iy9Ah2av3fN2D+m3HAND3zVtIuzZ0w0GuRDrjpt3PqcBUD56ie25qrkeNxoWqLzttze+i4vK7WjpbUOg8qydrwvL3lsq/4uUWH8o878+zUYV/96Ke3l19K8ZBFfsIQAdUJ9YQgww69S0oeZ8maFVqHAfYq4+RKQsTsalFtPoYdDfyGKh4We+rVlPThfbaI450kjXt4IYFrRuYtKLvzaq49PHUmg9YbicPi1KYGlomit6ETs0a/z7z8RhNzRj+Lwy5MQY0fsUiiQQrINzG0ZQq8F2BdBQUnSDE5Jtt06bgykBSc1GKL4yKIRlKwRnNOWHQJg8mKpt17oE2P4+8qRm9Lst0mPkwx0RsN39mUeuTvLkeNzzcGuQ8eRbk8XDPMHr9IbePLaucb/RdSLgj1G2MGBGR6QaOnVKd+Yh05J4NyMNLT32Qj8+9QbyIoVJ8NDkwaExCwQKf8I5eCKlaPAAiZ/3mNV12EW12RqGc3QlKTI3TP1+BK8d/NnO1ZXMrQv9Q4XpQUBBC1Y85KXXBj0UNBDJOvYDvUgw/SjmrhkGP2q3WaIjZ8pC2rokLjo1xvE9uvMK8hsitJSKoA/tT78IO4wtuXCe36wjN0R3gVZp6xF8prTEykO7oJuaEmXbsP0N1ZLQi4FbKqgG9RkcZy4c0nQ2eJOSqjbGhhEwW3aSeSw4yE+vDPqjyPpWdjRWYzFRqfhQfFUAEPtyLLIPOK9o4hyPLnwDzvciNd9k2BNEsSRaiFH8ZTeIKUJQTYvgNj4l1x8uflM7qd8X2Rvg4JqNYrU71wFICIfiQ4bTrAHIIJCEP7wsD/JjW1QI+xsSKrlqRQv1q8oM8ALf5YrXPXFpLjPsE6oirpWLb8nUbdbav4x0F91a4DET+jVSVw+H2c3aj4db3a9quktbXD+DckLYnbX+7NI+aDy0FIkK/6wwh0SAcOA+ulRPhiL3wQmGAQtevB2lbdNfDOFSNslIUKBNt3U5bvv7kRu+nYgv2CTRZXpWMo/j/y2/5C7/GGDpHcdw+ek9JbXAByl85ZytYvJZbJ0OQwrmAUmI/jEP/ABpCXkfo/JqmdVRwOxJUfOFrqdmwjK6ZVNc3KNypakAKBS6UTeuNd0hF8l2lO31cS6Oe2QPRSERLaPqPG1bXaVNXolimtfsUCWBwVqv6fcCYinFrU8mYDrp793p4bl1kfreqXxp6R/J03pKcYgMugh3+08VuzVmUFI7T/dQKtssLa78FXJAPuTcMNvmyD523i4i7JR/Cw40Gt66gH2fiVIeiUqxt9kNPTLmxEdUlnsL/d4OJogZRd7K22s05c0XITBEd4BHAZYhY1l3l5xMzye43HeHts+rCz3MbGDf0s5ph2xS441H2byOiixSXbfDKvThQr+Vx3OhJb/QNwZ1Y1rNmzDkQ+P0zFttV7pP+0BLYD4/BT/UlGnocKWMxEo13r0wqcnJ6+Ayui5l0LQHT76mHtEFcx4hYSE3IecOXosCzJbSEXmQuMeYhXqEqxkyxSm11ygLP8HT5YiOIXizQpin6qcheqweW1AXXR8zEjAb0jOBi9ZOUlqMnK9lK/hyuDlLuLRHgHeAZNTZI4KzhxcEhXv2fX6F6FcMYv02aXy2KSWHL6dPsSdVZxCMdhaR0gsoRqXACDBSwxakWoSuCSVodvJUPNQSVpCwd3NbSqZv6zXzoKZvoDv3c27eja6nYZHbm1L7VCSp1It6hKy2dhmMsAdb1BFhDSsRyDnz/53i5YX6JbqiWBDWeWsdpCZ3RYtdbFI3j5y2KTkL/TVDMnUhaVwQIpDklxOlrdIzsdf7NWcitaKWJUYyUZLE4yh6yH7VKc+BS2AXZexSgW2g21sRxCnmFAgvw7udk7bbGm9gB26TAyTQjovhbSWjjlBBZF47e/Ik4Xun0TVozIJ4UUSLwPM9aobBtI/xUGzXj7KuDGef2Crmp5cSCo4tPC/nv3bQqpvLJ9bw/CLB0X07ch1LlNJFd9az8qe5k8q6mpdnd27ZAGfm87R5J5dpAK5PP8lYfyVnYPMty74+UpiMnJLxVL9QcyJ7TMMbS0QaOox4t8y7BoTobuOOqprX14YGTamvacSHxuDiTON+415eCIzZi6Gurakn0Vzsxg9i5binq/ka8s6PGR+sNkSNv7JIuelsRtDlyJCpZ0NWk3T8TU6T52pLoycyM4PNhaz5/ef99br5r20nhjwCNEHZ22mK9WeHE1OEMvfJYDIsLVfZeKsZDDHl6U5PIqSCGYfV08nZTprsKqSssxiF/vFbCb6V7fHm9WL5J24XpavupwpI2NXWs2it4cIRLiN2cIUDQDr0b/F5GKXsquUByfE3vfOsvwcm+3UJ2V62j5xV8hwk/15FJUHGZQ63Aj0bJvc1WUp/rNBIxen1CDoCbfGKHERXfYpohTKfghf+tlNeqh+mT2+QpJRwZIb0m3m5uj1tbomQmBvu9O/UxEY+hV+D+tAwy38AvgULW1NnGmZfaUL0uKdSwP+TE9bt8XhohC8z/7UGGiFLWJ0E1lG1gzxY3UV5WP73IP7rko8TC/+TBXKh/q5reFln5+Pl63fYOTv6XjpPTJw7N0be0f/ajIxZ2P36iidjwxHjAixN3rM1yH+5f5PqKl1hmDqvIOOnu2UREJ9gfDygwvK7SM+WBMtGuYB7E+rXxbir0qQlqxdEkEKZY++cOeZXcTNBZYlKUf7mdiekN+kDHk3aSnXtTC7aJ96JG8kgecXufpXxNrCjIlPHC/W87lyAwNL8xSd2QKXtvrsQ3xih7lL4tA4pgPxQkl2mNuiiGZ7nEPlVUAUDWzBw3+e0CnVwZJ3/8xWr1Usxocj5GZTazw1HylvPKw6p+r24CfJfdOymAL1/PNgombTZCDyO3cNYKEzbUipjANvlU+jDXAasazqWl4DqmB3NoJlc2Ms4eF0q1EI8MXOUo+fuZrft2RPWno4NDEB5LoMEsupP3/1QxxiGIvY4ibhzeX89+4T1TmiWHTefbvojefL6q6dyiqIc/21cx1879/yJl1HPtghgrOWazU53g8rBCDyggDWVcaJhlE464MzgwRF8azL+2UPZ/YxKx4rs6R0EXwu+oJODsD5jr3/N4Zg1lnxY22KiUujDq7WOY4FHovV+3nwuMwSlwmybuuZTn3lPCVB1BMDaIONpTCYAa53UvrdL5xaM6jDvsObsBrs+N364S3AUPzQ3fFI06WXLFixTvRBt/2y1ijyxCH8u0cSwY2eYPZy1Mav735SkiTWYxCviMRjBTzLiyehkgB+Rmc3YcXtoS3J5tjf1mWnCoOZrW4HcbWdyFAN7bqn93Kl9xDigYhkUY2rDvajTVk6FNvbauPT5Rworuzw8ujk+zdjsvDk4ACKNgb3dywAOvcXwWB0Tdsjfvy5dYeZ7N4Y0t4dd7b2cvrMoi197iGM54H5BQEIplYdg4DpqlFXSQsHN5qM/0atNedyVMBWGkOoZi4+UOXb0Qs61oHuRaknu4+CJaFmxdrCu1xywXakuoQ4+T96jWv/jHjanxIZEumXYBoINAw06xOtHDn+fjpssqnd7UeImZWAjndQyaZb3eFM7fy2BMFv+t7Q5mZzhSGzoGG3w/fo8zsStDWmbdAAxG/Q+p5cS2+fFhMkDfCTVUkFKchWck7q2/yk+YMnsM+2+9rRDjDwbhirdYEfrofyzaZWkALFgF+FUfzz4ckVJDVVPjcZRMfRttxytoRy/DaP0AVcV3IE4Gi6/Hp9KRGafuD8w5HjEaykPzH6sOyvPMmDQJahkkLMUnprZHEbZzq1roHnJkH7s5IGcH52xKIdTK6erapszDoAWeNSYWEh3sRVChbotqPMbLurSoyVA1jUblsSdF5GqmRJTbN9X/ToxfjaG/771C1M35Q5XrqagXcw9OlxUTwYeJpYVVLY25KySEygrwGH6C2xCiucXNhWI+cefc+i9I64v1uC//9aHNGHEDUfQseIleYNcBhJ5CBjAJ2ZuvC6ErGe4ZLpVh9tp5FNcMiFanaUmmEutYvbamHCpVmoPVnXOU2yfSjqfIs3SNUIMcDdqC72RtK+XAteCPAegD9xoZWCCftIFcaeYppTIRtYzYd2fW4RoYyiTx7bKNOexL91uEw9X+xYkuGHLeom3HP+bwJm9lWNbGwWoqxCRnPdnYSLIdqCjvD3Ur6FiN2S3HrvQySnnjcS0T+badOgdrlGZzr3jbSKQkwdZEEAHKxkc5bvAA8OjweYSgGa7MFALP/p0whHM7C5mNnPfLpHxGOZeu33NKEtySSt3rAs269viHKnfEYs9HZpYGqoDwHA06qvL7KglxfmjFmh3c5lY17GaTdiddqMsSvEPPzyaF30wvbssvF7WKCNg/192QG9oX2Fkge78ycbPAUaSkhDCI/K09X1gbaqiPGW1G485euI9F8JnRPQMi3TQu0xdayintxqdMIl9wspE5eb35wkpIXwDGjoDOt4YObfiB6qFHfwFD401fG4FizMYssZdT/veElNcLg5KK+0bxqAGjnbIjEYZvnDmQgu3xf5VmdvbxxrL7T8Nw+3BDaUsuSaHvaSZqhx75fE+XfsgDz8yNXd2cDIZq/8ej5jftgFU1+sr+BpN0t0sWT9ffMZH+HU8vWDxxK3ER7nJjuXBOTZXyDc7sR3TRyyoArtirvVdmUhOkRduJZ501nRY5d3oHxzTwzbZXcARGjV/lM/I+bJqHw86loDSNuSdtEFZlErkUuXWiUu/3bDcpa4krYPwG2u10kujbXkOP95fU73AEJ/K58eJmcDjHUSZLE+hUOFc4tqZgVwlJ5alG3eRAXR+K3yCDdNkKfVUrLrp/cdV0APxaV5fq/arHpSU9Ml0vluCrhH2mUCKhSWpH5lz+EETtiSscfWxPU3WIYJSqg6WuM4F8Gf9MOjTwko/TU3AHwdE3auqGlF8iZDRKtYzHL638oSLfNxBAWY23dlKt/cLCDz1BGyRwarStRu93ljq15hOBCOK62V3DxDruOngDlzTgTldP3i2qmBWCrD2IThY2UbqzDRUzZ80hDgWtrhd+dXNfDo8PWQeOudBcFi/IbapweBiMnlWWO6T7L5KlZwNZNahdBKQT70slCbPLVJJskP1l3bM+plcWCY94sWRfdyJ8HNJoJ/TbxpNouxmJjIw" +// var exor = "0446092417571135" +// var loginToken = "99a401435dcb65c4008d3ad22c8cdad0c78c433465528f9a941720fa367c900c" +// console.log(getDecryptedData(encryptedData, exor, loginToken)) -- GitLab