概要
提示:仅供学习,不得用做商业交易,如有侵权请及时联系
逆向:狗dong log参数及joyytokem
URL:aHR0cHM6Ly9wcm8ubS5qZC5jb20vbWFsbC9hY3RpdmUvNFhyQXpkV1lVRml4elNzRkw5V1VtMm02WWZ0Ny9pbmRleC5odG1sP2JhYmVsQ2hhbm5lbD10dHQyJnV0bV90ZXJtPUNvcHlVUkxfc2hhcmVpZDZkNzdmYmEyM2JhZjUzZjFhMGUzZjE3NzAwOGM1MDlhZmYyMWEzNjgxNzQ3ODc3OTg2NjgwNl9ub25lX25vbmUmdXRtX3VzZXI9cGx1c21lbWJlciZ1dG1fc291cmNlPWlvc2FwcCZ1dG1fY2FtcGFpZ249dF8zMzUxMzk3NzQmdXRtX21lZGl1bT1hcHBzaGFyZSZfdHM9MTc0Nzg3Nzk4MjYyOSZhZF9vZD1zaGFyZSZneGQ9Um5Bb3hUTmViMktMbXBvV19kVWhXTTNnUEQ2Vzd6UXVBTWFudDBJbGg5eDFJNWo5T3c0Sk5YTWZ3Yi1BV3pVJmd4PVJuQW9tVE0yYnpmY21aa2RxSVVqWGc2WlVaQWVrMGs=
整体架构流程
提示:开始分析参数
1、这里直接观察window.smashUtils.get_risk_result,也就是,咱们加载进来之后,可以直接搜索get_risk_result,然后断点
2、进行观察它怎么定义给window的,往上翻动发现是一个webpack
好家伙,这些咱们只需要导出改方法定义的那个位置,重新刷新,发现它就是单个文件,而且已经自己加载好了
3、继续分析它是怎么加密的吧,观察smashUtils发现
在加密之前它还需要进行init初始化,所以得在init方法那重新刷新断点
window.smashUtils.init({
"appid": "xxx",
"sceneid": "xxx",
"uid": ""
});
这里看一下appid怎么来的,直接全局搜索,发现是当前html返回的
4、最后看一下咋加密的,点击领卷触发加密
这里我们可以看到n = 'coupon_receive’固定,r则是一个s方法生成的
打印可以看到r就等于window.smashUtils.getRandom(8)
5、最终处理
window.smashUtils.init({
appid: "xxx",
sceneid: "xxx",
uid: undefined
});
randomc = window.smashUtils.getRandom(8);
log_value = [window.smashUtils.get_risk_result({
id: "coupon_receive",
data: {
random: randomc
}
}), randomc]
技术名词解释
提示:补环境的检测
代理-------自吐环境
function setProxyArr(proxyObjArr) {
for (let i = 0; i < proxyObjArr.length; i++) {
const handler = `{
get: function(target, property, receiver) {
if(property === 'window'){
return target[property];
}
dtavm.log("方法:", "get ", "对象:", "${proxyObjArr[i]}", " 属性:", property, " 属性类型:", typeof property, ", 属性值:", target[property], ", 属性值类型:", typeof target[property]);
return target[property];
},
set: function(target, property, value, receiver) {
dtavm.log("方法:", "set ", "对象:", "${proxyObjArr[i]}", " 属性:", property, " 属性类型:", typeof property, ", 属性值:", value, ", 属性值类型:", typeof target[property]);
return Reflect.set(...arguments);
}
}`;
eval(`try {
${proxyObjArr[i]};
${proxyObjArr[i]} = new Proxy(${proxyObjArr[i]}, ${handler});
} catch (e) {
${proxyObjArr[i]} = {};
${proxyObjArr[i]} = new Proxy(${proxyObjArr[i]}, ${handler});
}`);
}
}
- 将node中有,浏览器没有的可能会检测的删除掉
require_ = require;
process_ = process;
delete global;
// delete Buffer;
delete process;
delete require;
delete module;
delete exports;
delete __filename;
delete __dirname;
// delete setImmediate;
// delete clearImmediate;
- 挂代理时一定得把window,globalThis分开挂,不然有些环境吐不出来,如:setProxyArr([‘window’,‘globalThis’]);会发现很多环境
提示:createTagProto我自己写的一个创建函数的方法
createTagProto('CSSRuleList');
createTagProto('CSSStyleDeclaration');
createTagProto('DOMRectList');
createTagProto('DOMStringList');
createTagProto('DataTransferItemList');
createTagProto('FileList');
createTagProto('HTMLCollection');
createTagProto('HTMLFormElement');
createTagProto('HTMLSelectElement');
createTagProto('MediaList');
createTagProto('MimeTypeArray');
createTagProto('NamedNodeMap');
createTagProto('NodeList');
createTagProto('SVGLengthList');
createTagProto('SVGNumberList');
createTagProto('SVGPointList');
createTagProto('SVGStringList');
createTagProto('SVGTransformList');
createTagProto('SourceBufferList');
createTagProto('StyleSheetList');
createTagProto('TextTrackCueList');
createTagProto('TextTrackList');
createTagProto('TouchList');
createTagProto('DOMTokenList');
createTagProto('HTMLAllCollection');
createTagProto('Plugin');
createTagProto('PluginArray');
createTagProto('PromiseRejectionEvent');
createTagProto('Storage');
- Navigator.prototype.getBattery电脑电池管理信息
// 创建电池管理器对象原型
const BatteryManager = {
level: 1,
charging: true,
chargingTime: 0,
dischargingTime: Infinity,
onchargingchange: null,
onlevelchange: null,
toString: function toString() {
return `BatteryManager {
charging: ${this.charging},
level: ${this.level},
chargingTime: ${this.chargingTime},
dischargingTime: ${this.dischargingTime}
}`
}
}
Navigator.prototype.getBattery = function getBattery() {
dtavm.log("getBattery", arguments);
return Promise.resolve({
__proto__: BatteryManager,
// 动态参数配置(示例值)
level: 0.99,
charging: true,
dischargingTime: 'Infinity' // 2小时放电时间
})
};
- dom检测removeEventListener、createElement(checkDevTools)、createTextNode、querySelectorAll(取标签的长度)
- process这里需要注意哈,不是没有,一般浏览器没有这个的
process = {
env: {
NODE_ENV: "production"
}
}
- 然后就是重点检测Error,懂的都懂,有俩处,会取值的
- 加密的时候会重新设置cookie,发送xhr得到cookie值joyytokem,然后该值会参与log参数的计算,所以一定得有
- 其他的自己慢慢补吧
技术细节
提示:结果
小结
提示:学习交流主页,成品已发星球