这个最新的版本号我就称它是2.0版本(js文件dws2.0.0.js)吧
目标数据是在:/element 这个接口里面
解决范围:榜单排行信息
目标参数:头部里面的xm-sign
难度还算适中,源码混淆了,需要耐心去看
很容易找到这个xm-sign赋值的位置,可以多尝试几次,前半段其实是可以写死的,主要是这个o的值:
我直接和大家讲讲我是怎么来分析的吧:
1、我是直接跟栈找到这个位置,还原后更好分析,我们这里直接看源码:
这里接受两个 _0x3d8670, _0x1c7038 参数,这个_0x1c7038 多尝试几遍,他是写死的,_0x3d8670参数是怎么来的呢,他其实就是我们上面 /report 接口的返回值(不用想直接尝试请求这个 /report接口拿到,他的载荷参数我们看不懂的,此方法行不通!)
提醒一下:最后这个方法的返回值 “sid” ,其实就是我们最后Sign要拼接的最后一段,自己可以记录这个值到最后拼接位置去看下
我呢是就直接先从这个位置开始分析,这个混淆并不难,我是这里直接手动还原了一下,下面是我的(一个aes加密,但是难点不在这里):
// 引用 crypto-js 加密模块
var Crypto = require('crypto-js')
function dec_aes(_0x42bf9a, _0x24981f) {
var _0x10ec79 = Crypto["enc"]["Utf8"]["parse"](_0x24981f);
return Crypto["AES"]["decrypt"](_0x42bf9a, _0x10ec79, {
'iv': _0x10ec79,
"mode": Crypto["mode"]["ECB"],
"padding": Crypto["pad"]["Pkcs7"]
})["toString"]();
}
function func_fromBytes(_0x16dac6) {
for (var _0xecf60d = [], _0x2dcca6 = 0x1fd95 ^ 0x1fd95; _0x2dcca6 < _0x16dac6['length']; _0x2dcca6++)
_0xecf60d['push'](String['fromCharCode'](_0x16dac6[_0x2dcca6]));
return _0xecf60d['join']('');
}
function get_result(arg1, arg2) {
var _0x1bc644 = dec_aes(arg1, arg2)
console.log(_0x1bc644)
for (var _0x176785 = [], _0x487f67 = 0xa3b07 ^ 0xa3b07; _0x487f67 < _0x1bc644['length']; _0x487f67 += 0xbb142 ^ 0xbb140)
_0x176785['push'](parseInt(_0x1bc644['substr'](_0x487f67, 0x43f58 ^ 0x43f5a), 0x5843e ^ 0x5842e));
console.log(_0x176785)
result_data = func_fromBytes(_0x176785);
return result_data
}
arg1 = "HBqoV1TnSk0ReS27LZiL+4HF5SEGBCoGfmdt1mDbHSwINCtsmXUklA1wHHlY+Q3QZc6aAAYokCFoVbEDe+XvfRfkFpdmgEULRkTBFTtdD5mPkm5A5afLYHWMwPqr4S+3U/nizz3WRZcUiYpRWe6qM93W+1ZEIoKmKdiTZAUj0RfUAKgMFKKFknnznlgtzU8n61BhEMaj3iF06GCqY+jpmw7X13B787E6G06Yh8Eb2pT4gBc7vWjdUxqxzILz3D/yg1PXu4wEQShDG7BkHabKXM5Jxuu0PcQNX+lE699xhA4="
arg2 = "m9ZtRrz:qujT8@da"
// get_result(arg1, arg2)
console.log(get_result(arg1, arg2))
2、上面其实我们后小半部分就已经解决好了,但是这个很长的字符串(上面已排除使用python请求/reportj接口获取)继续跟栈回去看,仔细分析后,它还是一个send发请求后的这个responseText:
跟栈,然后断在send发包之前,发现,这个入参是一个ArrayBuffer类型,OK继续往上找:
我是直接找了上一个栈看,中间踩了一些坑,最后发现,这里面的这些乱七八糟的字段值,都是随机值经过 charAt 、charCodeAt、fromCharCode 等等处理(比如下面这个“kz4”,我跟完并记录值,它就是一个经过4次连续处理后的值):
可以直接copy下来,要注意有时间戳和一个类似于uuid的值最好成动态的;然后将这个两个参数传给这个方法生成这样一个ArrayBuffer二进制数据,下面我会提到补环境的好处,导出方法后直接调用这个方法。
3、然后就是这个请求的地址, 其实最上面抓包过程中就可以分析出来,这个 ‘/report’ 接口它后面的参数 "r=bb4ab56c-282f-4dd2-a45c-64d8a306713d" 是变化的:
我后面才注意到这个"/dws2.0.0.js"下面的源码,在页面加载前,会先执行这个js文件,全扣下来,稍微补一下环境【window 、location、navigator、localStorage】就过了。
重点是这个方法,我们上面所用到的方法基本上都在这个对象里面,
最后就是js处理完获取到sid:
最后测试结果OK: