JS逆向 - 东航 FECU参数(请求载荷) FECAS(cookie)
概要
提示:仅供学习,不得用做商业交易,如有侵权请及时联系
逆向:JS逆向 - 东航 FECU参数(请求载荷) FECAS(cookie)
URL:aHR0cHM6Ly93d3cuY2VhaXIuY29tL3NlbGYtc2VydmljZS9iZWZvcmUvZmxpZ2h0LXN0YXR1cw==

整体架构流程
-
输入航班号,点击搜索

-
flightInformation接口会拼接一个参数:FECU(加密)
-
观察cookie,你会发现有一个FECAS,它加密的结果发现跟FECU的格式是一致的,那么我们直接就可以hook这个参数的生成

-
浏览器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;
},
});
})();
-
发现是一个hxk_fec_0defe817.js文件js里面生成的

-
这里我们给它还原一下Ob,再替换上去
-
还原后发现是a0_0x221cae函数生成

-
重新无痕进入断点,进入a0_0x221cae函数

-
观察配置参数生成:全局搜索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
};
}
}
-
可以看到配置参数其实就是全局fecBaseConfig_wsyzwdbq和dom标签里面去拿wsyzwdbq值
-
fecBaseConfig_wsyzwdbq:fec_wrapper文件js获取,wsyzwdbq首页获取
-
_0x38fad5的值是取的浏览器中的cookie:FECW(首页返回的)

-
接下来就差a0_0x1d5399数组了,然后通过a0_0x3af7a3(a0_0x46d3de(a0_0x1d5399))加密生成最后的FECAS
-
这里发现第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)
更多推荐
所有评论(0)