JS逆向 - 全国物流查询(sign)WASM
JS逆向 - 全国物流查询(sign)WASM
概要
提示:仅供学习,不得用做商业交易,如有侵权请及时联系
逆向:JS逆向 - 全国物流查询(sign)WASM
URL:aHR0cHM6Ly90LjE3dHJhY2submV0L3poLWNuI251bXM9TFoyODU2NDYzMTRDTg==

整体架构流程
提示:观察需要加密的参数-分析加密位置
1、刷新网页进入,会发现有一个无效debugger

这个其实是wasm里面的debugger,有点恶心,格式化检测了,还有toString等,直接上魔改浏览器
2、直接通过堆栈断点去找到加密生成的位置

3、重新刷新界面,发现断住了

这里的{
trackingNums: e,
fc: t,
sc: n
}其实就是data,直接单步跳进去
4、从上图可以观察到,e = await this.createRequestData,C = JSON.stringify(e),那么猜测肯定是这个createRequestData异步方法去生成了sign,直接单步进去

5、这里可以看到l = await this.fingerPrinter.getFingerprint(),sign: l,如果是老手应该知道这个getFingerprint是个啥,它其实就是fp指纹加密(window的一些配置属性,navigator的属性,screen的属性,canvas标签绘图的一些属性和toDataUrl)
-
直接找fingerPrinter对象函数从哪里来的

-
从上图我们可以看出,肯定是Q对象进行实例化的时候,去加载了fingerPrinter对象,直接搜索

-
constructor这个就是构造器,实例化时会执行
this.fingerPrinter = new O.Up({
maxMovePoints: 0,
obfuscate: L.Br
}),
this.fingerPrinter.initialize()
-
那么现在我们只需要找到这个O对象是这么来的就可以了,往上找到这个O

-
其实也可以全局搜索的,发现是一个webpack

-
这个东西就不用我多说了吧,直接扣加载器,然后用全扣自吐

-
(()=>{});这个就是一个自执行方法,es6语法,不用管,全扣,e相当于一个字典,里面全部都是键值对,值是方法或者属性
-
说一下怎么导出来:

// 存放键值对的属性(就是需要加载的键值对,拼接字符串)
window.strc = '';
// 存放已经加载好的键,如果不存在,那么字符串就拼接,存在就跳过
window.listc = [];

-
console.log(‘error::’, n)这个是用来观察没有加载成功的键函数

-
最后我们可以看到eval(‘debugger;’+‘datac={’+strc+‘};’),这一步是让字符串的键值对变成对象,然后讲原来e里面的所有的键值对替换掉,减少代码量
技术名词解释
提示:说一下坑点
fingerprintModule加载不成功的情况,是因为wasm没有加载成功

正常情况下r.e(748).then(r.bind(r, 27716))里面有一层会去创建script标签,然后去加载一个新的js,生成wasm文件,然后加载起来

这里我直接替换掉了,r.e(748).then(r.bind(r, 27716))替换window.wang(27716)

技术细节
提示:扣完webpack就需要补环境咯
给个代理
no_print = ['window', 'globalThis','navigator','top','self','plugins','String','console','Promise'];
function setProxyArr(proxyObjArr) {
for (let i = 0; i < proxyObjArr.length; i++) {
const handler = `{
get: function(target, property, receiver) {
if(no_print.includes(property)){
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});
}`);
}
}
验证结果:
-
错误的sign:

-
正确的sign:

小结
提示:学习交流主页,星球持续更新中:(+星球主页+v)
更多推荐




所有评论(0)