JS反混淆——构造可知DeviceToken、nouce与token

摘要:
如下图所示,浏览器发出的第一个XHR请求为/bind,其中DeviceToken,nonce,Token均为POST中提交的数据。找到访问网页的请求,如下图所示,返回头中没有出现set-cookie字段,可以判断DeviceToken,nonce,Token均为js生成的。找到发送/bind/请求的Initiator,发现只与vendor.*.js与app.*.js有关,且出现了webpackJsonp、computed、updateRoute等字段,猜测该网站是使用vue-cli构建的。该段函数流程大致为发送/bind请求至后端,如果返回的结果中Success字段为true,则将数据中的DeviceToken,DeviceKey放到cookie中。而发送的DeviceToken由newGuid()函数生成。
  • 清空所有cookies后打开任意一本书的详情页,打开控制台中的Network。如下图所示,浏览器发出的第一个XHR请求为/bind,其中DeviceToken,nonce,Token均为POST中提交的数据。
    JS反混淆——构造可知DeviceToken、nouce与token第1张
  • 找到访问网页的请求,如下图所示,返回头中没有出现set-cookie字段,可以判断DeviceToken,nonce,Token均为js生成的。
    JS反混淆——构造可知DeviceToken、nouce与token第2张
  • 找到发送/bind/请求的Initiator,发现只与vendor.*.jsapp.*.js有关,且出现了webpackJsonpcomputedupdateRoute等字段,猜测该网站是使用vue-cli构建的。
  • 下载并解码vendor.*.jsapp.*.js,在app.*.js中搜索/bind,找到相关代码。
    JS反混淆——构造可知DeviceToken、nouce与token第3张
    该段函数流程大致为发送/bind请求至后端,如果返回的结果中Success字段为true,则将数据中的DeviceToken,DeviceKey放到cookie中。而发送的DeviceTokennewGuid()函数生成。
    • 找到该段函数的函数名为registerApp,搜索调用。
      JS反混淆——构造可知DeviceToken、nouce与token第4张
    • 找到调用registerApp的代码,根据上文watchmethods可以判断出这是一个vue的组件,监控到路由变化则调用registerApp
      JS反混淆——构造可知DeviceToken、nouce与token第5张
    • 不难得出得出所有暴露到this中的函数名均存在变量66_0x3458中。
      JS反混淆——构造可知DeviceToken、nouce与token第6张
    • newGuid转为utf-8编码,为x6Ex65x77x47x75x69x64,找到其在变量66_0x3458的位置
      JS反混淆——构造可知DeviceToken、nouce与token第7张
    • 将163转为16进制为a3,在app.*.js中搜索0xa3,找到定义。
      JS反混淆——构造可知DeviceToken、nouce与token第8张
    • _0x6bc57['JiAvF']_0x6bc57['jybZN']为调用的其他函数,分别搜索得出对应函数:
      JS反混淆——构造可知DeviceToken、nouce与token第9张
      JS反混淆——构造可知DeviceToken、nouce与token第10张
    • 用对应代码替换上述函数,丢进jsnice转换:
      JS反混淆——构造可知DeviceToken、nouce与token第11张
    • 重命名变量,最后得出newGuid的代码如下,生成一个32的uuid:
function newGuid() {
    let uuid = "", i = 1;
    for (; i <= 32; i++) {
        uuid = uuid + Math.floor(16 * Math.random()).toString(16);
        if (!(8 !== i && 12 !== i && 16 !== i && i !== 20)) {
            uuid = uuid + "-";
        }
    }
    return uuid;
}
  • 返回/bind的代码,请求中的data实际只有三个字段,与看到XHR请求中字段数量不一致,判断是做了一个拦截器,而一般的vue-cli项目中使用的http请求库为axios,所以直接搜索interceptors找到拦截器代码。
    JS反混淆——构造可知DeviceToken、nouce与token第12张
  • 所有的字段均在拦截器中定义吗,其中nonce字段为调用的uuid函数,直接搜索['prototype']['uuid'],找到函数定义:
    JS反混淆——构造可知DeviceToken、nouce与token第13张
    • 函数中仅有a66_0x39d4('0xb9')是未知的,调用函数,找到对应数值为'0123456789abcdef':
      JS反混淆——构造可知DeviceToken、nouce与token第14张
    • 拖进jsnice,再稍加修饰,发现nouce是生成一个36位的uuid:
function uuid() {
    let s = [];
    for (let i = 0; i < 36; i++)
        s[i] = '0123456789abcdef'.substr(Math.floor(16 * Math.random()), 1);
    s[14] = '4';
    s[19] = '0123456789abcdef'.substr(3 & s[19] | 8, 1);
    s[8] = s[13] = s[18] = s[23] = '-';
    return s.join('');
}
  • 最后剩下Token字段,在拦截器代码中找到定义:
    JS反混淆——构造可知DeviceToken、nouce与token第15张
    • 其中a66_0x39d4('0x87')为default,a66_0x39d4('0x53')为prototype,可以判断两者处理方式完全一致,都是将data拷贝一份,调用deleteKey函数后,再调用setToken函数,将Token赋值进data,再发送。
      JS反混淆——构造可知DeviceToken、nouce与token第16张
      • 搜索['prototype']['deleteKey']找到deleteKey函数:
        JS反混淆——构造可知DeviceToken、nouce与token第17张
      • 稍加修饰,deleteKey函数就是删除无用字段:
function deleteKey(data) {
    for (let word in data) {
        if (data.hasOwnProperty(word)) {
            const val = data[word];
            if (!(0 === val || val || "boolean" == typeof val)) {
                delete data[word];
            }
        }
    }
    return data;
}
-  搜索`setToken`找到setToken函数,初步判断setToken主要是将Object类型的data根据一定格式转为字符串后加入混淆字符`OI2W_YeeUw%OHutl`后再加密:

JS反混淆——构造可知DeviceToken、nouce与token第18张
- 搜索MbnVH找到MbnVH函数,用来判断变量类型
JS反混淆——构造可知DeviceToken、nouce与token第19张
- 搜索_0x1e733e找到定义,发现其上方的与_0x591b6a有关。
JS反混淆——构造可知DeviceToken、nouce与token第20张
- 在app.*.js中搜索fZjL无果,转到vendor.*.js中搜索,找到定义:
JS反混淆——构造可知DeviceToken、nouce与token第21张
- 继续在vendor.*.js中搜索jFbC,找到定义:
JS反混淆——构造可知DeviceToken、nouce与token第22张
- 将未知量替换后,setToken代码如下:

function setToken(data) {
    let c = Object.assign({}, data);
    let s = Object.keys(c).map(function (k) {
        return k.toLowerCase() + "/" + k + "=" + c[k];
    }).sort().map((vo) => {
        return vo.substring(vo.indexOf("/") + 1);
    }).join("") + "OI2W_YeeUw%OHutl";
    return encryption(s,1);
}
- Token的值最终与encryption函数有关,将encryption转为utf-8编码x65x6Ex63x72x79x70x74x69x6Fx6E,找到位置:

JS反混淆——构造可知DeviceToken、nouce与token第23张
- 将174转为16进制为0xae,在app.*.js中找到定义:
JS反混淆——构造可知DeviceToken、nouce与token第24张
- 传入的参数值为*,1时,只调用case 0x1中的代码,看到['toString'](CryptoJS[a66_0x39d4('0xb0')]['Hex']),初步判断是将字符串进行SHA1或MD5加密后,再进行Hex编码。
JS反混淆——构造可知DeviceToken、nouce与token第25张
- 搜索_0x33c78e找到定义,发现其与_0x7558ee有关,简单搜索发现_0x7558ee的值为_0xbc0af2('Ff/Y'):
JS反混淆——构造可知DeviceToken、nouce与token第26张
JS反混淆——构造可知DeviceToken、nouce与token第27张
- 在vendor.*.js中搜索Ff/Y找到代码:
JS反混淆——构造可知DeviceToken、nouce与token第28张
- 根据_doReset中定义的数组与crypto-js中SHA1与MD5代码比对,发现Ff/Y对应的是SHA1:
JS反混淆——构造可知DeviceToken、nouce与token第29张
- 经过修饰,encryption函数的代码如下,将字符串SHA1加密后再Hex编码:

function encryption(val) {
    return Crypto.SHA1(val.toString()).toString(Crypto.enc.Hex);
}
  • 至此已经知道了三个关键字段的构造方法,伪装一个/bind请求测试,返回结果成功:
    JS反混淆——构造可知DeviceToken、nouce与token第30张

免责声明:文章转载自《JS反混淆——构造可知DeviceToken、nouce与token》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇在iOS平台使用ffmpeg解码h264视频流(转)IDEA 版权设置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

drf——接口幂等性,Restful接口的幂等性

一、什么是幂等性 幂等性是系统服务对外一种承诺,承诺只要调用接口成功,外部多次调用对系统的影响是一致的。声明为幂等的服务会认为外部调用失败是常态,并且失败之后必然会有重试。 post请求不是接口幂等性put操作是接口幂等性 二、什么情况下需要幂等 以SQL为例: SELECT col1 FROM tab1 WHER col2=2,无论执行多少次都不会改变...

[python-flask]Flask框架笔记

Flask框架学习笔记 目录 Flask框架学习笔记 笔记 flask的request对象 __name__的作用 flask中的session 利用flask-wtf扩展包的CSRFProtect flask-cors配置跨域请求 视图函数 日志功能 关于ORM模型 & flask-sqlalchemy flask-migrate数据库迁...

js获取select下拉框的value值和text文本值

介绍一种取下拉框值以及绑定下拉框数据的方法    这里用到的jquery-ui-multiselect插件  1、前台html代码 <span class="ModuleFormFieldLabel" style="float: left; padding-top: 3px;">品类:</span> <asp:Hidde...

js 过滤数组里对象的某个属性

需求 一个大数组,里面乱七八糟一堆属性。现在只需要其中两个属性,用这两个属性组成一个对象,重新得到一个新数组。新数组长度跟老数组一样,只不过里面所有对象只剩下了两个属性 示例 handleSelectionChange(selection) { var invoiceGxQueryList = []; for (var i =...

微信公众平台token设置

<?php /** * wechat php test */ //define your token define("TOKEN", "token"); $wechatObj = new wechatCallbackapiTest(); $wechatObj->valid(); class wechatCallbackapiTest {...

使用js的webrtc进行sip协议连接,实现webrtc与电话网打通

1、webRTC应在JSEP协议基础上通过应用层开发sip以实现信令,并且该信令是通过ws进行(TCP而不是UDP),由于谷歌要求正式环境下使用wss,所以通过代理nginx转发,实现wss到ws,软交换只需要实现ws处理信令即可2、WebRTC2SIP网关的SIP代理把ws的sip转换为udp的sip,RTCWeb Breaker提供RTP、RTCP和D...