概要

提示:仅供学习,不得用做商业交易,如有侵权请及时联系

逆向:JS逆向 - 东航 FECU参数(请求载荷) FECAS(cookie)

URL:aHR0cHM6Ly93d3cuY2VhaXIuY29tL3NlbGYtc2VydmljZS9iZWZvcmUvZmxpZ2h0LXN0YXR1cw==

在这里插入图片描述

整体架构流程

  1. 输入航班号,点击搜索
    在这里插入图片描述

  2. flightInformation接口会拼接一个参数:FECU(加密)

  3. 观察cookie,你会发现有一个FECAS,它加密的结果发现跟FECU的格式是一致的,那么我们直接就可以hook这个参数的生成
    在这里插入图片描述

  4. 浏览器Hook-cookie

(function () {
  'use strict';
  var cookieTemp = '';
  Object.defineProperty(document, 'cookie', {
    set: function (val) {
      if(val.indexOf('FECAS') != -1){
        debugger;
      }
      console.log('Hook捕获到cookie设置->', val);
      cookieTemp = val;
      return val;
    },
    get: function () {
      return cookieTemp;
    },
  });
})();
  1. 发现是一个hxk_fec_0defe817.js文件js里面生成的
    在这里插入图片描述

  2. 这里我们给它还原一下Ob,再替换上去

还原网站:https://webcrack.netlify.app/

  1. 还原后发现是a0_0x221cae函数生成
    在这里插入图片描述

  2. 重新无痕进入断点,进入a0_0x221cae函数
    在这里插入图片描述

  3. 观察配置参数生成:全局搜索a0_0x37e883,发现是a0_0x4cb936函数生成
    在这里插入图片描述

function a0_0x4cb936() {
  try {
    var _0x3bc9d7 = window.fecBaseConfig_wsyzwdbq || document.getElementById("wsyzwdbq").innerHTML.replace(/[\r\n]/g, "");
    var _0x56bb09 = _0x3bc9d7.split(",");
    var _0x2bf7e0 = [2, 3, 6, 7, 8, 9];
    var _0x2c9f0e = "";
    for (var _0x3335d3 = 0; _0x3335d3 < _0x2bf7e0.length; _0x3335d3++) {
      var _0x31ce27 = _0x2bf7e0[_0x3335d3];
      for (var _0x1a2034 = 1; _0x1a2034 <= 32; _0x1a2034++) {
        if (_0x1a2034 * _0x31ce27 >= 32 + _0x31ce27) {
          break;
        }
        _0x2c9f0e += _0x56bb09[_0x31ce27 - 1][(_0x1a2034 * _0x31ce27 + 1) % 32 - 1];
      }
    }
    var _0x44566e = _0x2c9f0e.slice(0, 32);
    var _0x1cbe58 = _0x2c9f0e.slice(32, 42);
    var _0x476068 = _0x2c9f0e[42];
    var _0x5136c2 = _0x2c9f0e[43];
    var _0x3146ec = {
      key: _0x44566e,
      server_time: _0x1cbe58,
      is_debugger: _0x476068,
      secure: _0x5136c2
    };
    return _0x3146ec;
  } catch (_0xf7a550) {
    console.log("getConfig error");
    return {
      key: "",
      server_time: "",
      is_debugger: 0,
      secure: 0
    };
  }
}
  1. 可以看到配置参数其实就是全局fecBaseConfig_wsyzwdbq和dom标签里面去拿wsyzwdbq值

  2. fecBaseConfig_wsyzwdbq:fec_wrapper文件js获取,wsyzwdbq首页获取

  3. _0x38fad5的值是取的浏览器中的cookie:FECW(首页返回的)
    在这里插入图片描述

  4. 接下来就差a0_0x1d5399数组了,然后通过a0_0x3af7a3(a0_0x46d3de(a0_0x1d5399))加密生成最后的FECAS

  5. 这里发现第8个数组会取sessionStorage.getItem(“fi”),后面会发现它其实是一个FP指纹ws2024_hex_md5(JSON.stringify(new Fingerprint().get())),ws2024_hex_md5是标准MD5加密

window.sessionStorage.getItem(“fi”) === ws2024_hex_md5(JSON.stringify(new Fingerprint().get()))

这里a0_0x1d5399[“8”]取的ws2024_hex_md5(JSON.stringify(“none”))

 	_0x55ff4e = JSON.parse(JSON.stringify(navigator.userAgent));
 	// cookie_FECWS 进行MD5
    a0_0x1d5399["0"] = ws2024_hex_md5(_0x38fad5);
    // 
    a0_0x1d5399["8"] = window.sessionStorage.getItem("fi") || ws2024_hex_md5(JSON.stringify("none"));
    // ua 进行MD5
    a0_0x1d5399["9"] = ws2024_hex_md5(_0x55ff4e);
    // window下面属性
    a0_0x1d5399["10"] = a0_0x5315bd();
    // 自动化检测
    a0_0x1d5399["2"] = a0_0x157b45();
    // 固定false
    a0_0x1d5399["3"] = _0x2383e8;
    // 固定返回“None”
    a0_0x1d5399["4"] = a0_0x32de1d();
    // (start_time - end_time) 随机时间差 + (config.server_time * 1000)
    a0_0x1d5399["11"] = a0_0x182b18 - a0_0x34ed04 + a0_0xb1b990 * 1000;
    // 随机5位字符串
    a0_0x1d5399["12"] = a0_0x3934be();

最后就是数组中5,6,7的来历,和a0_0x46d3de、a0_0x3af7a3的加密

  • 搜索a0_0x1d5399[“5”]发现是dom的事件计数处理
    在这里插入图片描述

  • a0_0x46d3de加密
    在这里插入图片描述

function a0_0x46d3de(_0xe176b7) {
    var _0x2bf531 = {};
    var _0x3dc013 = {
    None: "00",
    other_webdriver: "01",
    ie_webdriver: "02",
    chrome_webdriver: "03",
    firefox_webdriver: "04",
    phantomjs: "05",
    selenium: "06"
    };
    var _0x442653 = {
    None: "00",
    DebugJs: "01",
    ConsoleCore: "02",
    Other: "03"
    };
    var _0x2657d3 = "";
    if (true) {
        var _0x1282e9 = ["0", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
        for (var _0x1a346d = 0; _0x1a346d < _0x1282e9.length; _0x1a346d++) {
            var _0x44f14f;
            switch (_0x1282e9[_0x1a346d]) {
            case "0":
                _0x44f14f = _0xe176b7[_0x1282e9[_0x1a346d]];
                _0x40f914();
                continue;
            case "1":
                _0x44f14f = _0xe176b7[_0x1282e9[_0x1a346d]] ? "1" : "0";
                _0x40f914();
                continue;
            case "2":
                var _0x1770a3 = _0xe176b7[_0x1282e9[_0x1a346d]].webdriver || _0xe176b7[_0x1282e9[_0x1a346d]].auto_tool || "None";
                _0x44f14f = _0x3dc013[_0x1770a3];
                _0x40f914();
                continue;
            case "3":
                _0x44f14f = _0xe176b7[_0x1282e9[_0x1a346d]] ? "1" : "0";
                _0x40f914();
                continue;
            case "4":
                var _0x4dc5eb = _0xe176b7[_0x1282e9[_0x1a346d]];
                _0x44f14f = _0x442653[_0x4dc5eb];
                _0x40f914();
                continue;
            case "5":
                _0x44f14f = _0x1ff818(_0xe176b7[_0x1282e9[_0x1a346d]]);
                _0x40f914();
                continue;
            case "6":
                _0x44f14f = _0x1ff818(_0xe176b7[_0x1282e9[_0x1a346d]]);
                _0x40f914();
                continue;
            case "7":
                _0x44f14f = _0x1ff818(_0xe176b7[_0x1282e9[_0x1a346d]]);
                _0x40f914();
                continue;
            case "8":
                _0x44f14f = _0xe176b7[_0x1282e9[_0x1a346d]];
                _0x40f914();
                continue;
            case "9":
                _0x44f14f = _0xe176b7[_0x1282e9[_0x1a346d]];
                _0x40f914();
                continue;
            case "10":
                var _0x20c797 = {
                chrome: "1",
                firefox: "2",
                msie: "3",
                opera: "4",
                safari: "5",
                wechat: "6",
                qq: "7",
                uc: "8",
                other: "9"
                };
                var _0x17a14e = _0x20c797;
                var _0x2c4a4a = _0xe176b7[_0x1282e9[_0x1a346d]] && _0xe176b7[_0x1282e9[_0x1a346d]].length ? _0xe176b7[_0x1282e9[_0x1a346d]][0] : "other";
                _0x44f14f = _0x17a14e[_0x2c4a4a];
                _0x40f914();
                continue;
            case "11":
                _0x44f14f = _0xe176b7[_0x1282e9[_0x1a346d]];
                _0x40f914();
                continue;
            case "12":
                _0x44f14f = _0xe176b7[_0x1282e9[_0x1a346d]];
                _0x40f914();
                continue;
            default:
                _0x44f14f = _0xe176b7[_0x1282e9[_0x1a346d]];
                _0x40f914();
                continue;
            }
        }
        return _0x2657d3;
    }
    function _0x40f914() {
      _0x2bf531[_0x1282e9[_0x1a346d]] = _0x44f14f;
      _0x2657d3 = _0x2657d3 + _0x44f14f;
    }
    function _0x1ff818(_0x2831bd) {
      if (Number(_0x2831bd) >= 999) {
        return "999";
      }
      _0x2831bd = _0x2831bd.toString();
      while (_0x2831bd.length < 3) {
        _0x2831bd = "0" + _0x2831bd;
      }
      return _0x2831bd;
    }
}
  • a0_0x3af7a3:通过这个去加密生成_0x4789e4.apply(this, arguments)
    在这里插入图片描述

  • 观察_0x4789e4发现就是从配置参数里面取key进行处理分割,然后进行AES加密
    在这里插入图片描述
    在这里插入图片描述

// AES加密
function ws2024_encrypt(data, key, iv) {
    var key = CryptoJs.enc.Utf8.parse(key);
    var secretData = CryptoJs.enc.Utf8.parse(data);
    var CBCOptions = {
        iv: CryptoJs.enc.Utf8.parse(iv),
        mode: CryptoJs.mode.CBC,
        padding: CryptoJs.pad.Pkcs7
    }
    var encrypted = CryptoJs.AES.encrypt(secretData, key, CBCOptions);
    return encrypted.toString()
}

// 加密   config配置参数对象
function encryptData(_0x3ffdf7,config) {
    var _0x4918df = config.key;
    _0x4918df = _0x4918df.substr(0, 4) + _0x4918df.substr(2, 4) + _0x4918df.substr(26, 4) + _0x4918df.substr(28, 4);
    _0x2a8836 = _0x4918df.length;
    _0x4918df = _0x4918df.substr(0, 2) + _0x4918df.substr(1, 2) + _0x4918df.substr(_0x2a8836 - 3, 2) + _0x4918df.substr(_0x2a8836 - 2, 2);
    _0x349c68 = _0x4918df + _0x4918df;
    _0x192226 = ws2024_encrypt(_0x3ffdf7, _0x349c68, _0x349c68);
    _0x5d6228 = _0x3ffdf7.substr(3, 1) + _0x192226 + _0x3ffdf7.substr(7, 1);
    return _0x5d6228;
}

提示:cookie值FECAS生成

技术名词解释

提示:观察请求载荷里面的FECU生成

1、前面我们知道了它是从哪里生成的了,所以我们等下直接在ws2024_encrypt进行AES加密哪里进行断点,观察

在这里插入图片描述

2、发现加密数组基本上不变:变化点数组下标:5,6,7,8,11,12

数组下标5,6,7:document.keydown  count次数、document.mousedown  count次数、document.touchstart  count次数
数组下标8:ws2024_hex_md5(JSON.stringify(new Fingerprint().get()))
数组下标11:时间戳,会计算时间差 + (config.server_time * 1000)
数组下标12:随机5位字符串

技术细节

提示:nodejs实现加密

在这里插入图片描述

小结

提示:学习交流主页,星球持续更新中:https://t.zsxq.com/AJTw2(+星球主页+v)

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐