某东log校验--解密log
本文最后更新于 2024-07-06,文章内容可能已经过时。
本篇文章为log生成逻辑(终于算搞到最后了,嘻嘻)
重点来了,本文出现的前端JS代码片段均为解密后的代码,未解密的代码截图也没有办法进行分享
准备工作
首先还是需要找一个需要log校验的活动,这里直接以炸年兽活动为例,所有的电商节活动除了前几天,基本上都会开始上校验。
找一个抓包工具,然后将活动地址抓出来,因为很多活动其实都是网页版的。使用Chrome将UA修改成APP抓出来的UA就可以了。
初识log
其实一直在说log校验、log校验,很多人都不知道log校验到底是啥,我们进一个活动,点开请求仔细查看一下。
文章写的太晚了,不过没啥,起码还能看到一些东西。这里标注出来的log就是我们要拿到的东西。
定位生成代码
在Chrome中可以查看到请求的调用过程,这里只是需要“亿点点”的耐心就好了。
或者使用字符串搜索大法也可以尝试一下,不过京东前端加密后,能不能搜得到还是一个未知数。不行的话还是要老老实实的搞一下,肯花力气一定是能找到入口的。
解密后整理一下,然后直接翻到方法的首页,然后开始进行分析。获取log的方法应该是window.smashUtils.get_risk_result
了。
分析JS
提前说一声,这里面有一部分变量已经被我修改了,后来发现没啥必要,但是已经和最初始的不一样了。
生成log —— window.smashUtils.get_risk_result部分
看一下这里面的入参t对象的生成内容,可以看一下id
和data
里面的random
都是随机的。然后random
这个随机内容调用的是window.smashUtils.getRandom(8)
,这个看着应该是生成一个长度为8的随机字符串。
然后下面一部分还会用到初始化的变量initParam
。
getRandom方法 —— 生成指定位数的随机字符串
这里面看一下,就是获取一个长度最大为15的随机字符串。并且字符串貌似并不会出现0。
初始化变量 —— window.smashUtils.init() 部分
查看一下initParam
变量是什么时候进行初始化的。
可以看到实际上这个变量就是调用window.smashUtils.init()
进行初始化的。搜索一下,或者打印一下调用堆栈信息进行查找一下。
window.smashUtils.init({appid: "50174", sceneid: "ZNShPage_h5", uid: Object(je.getUUID)()})
appid
和sceneid
应该很明显就是用来定位活动的了,然后uid
后续没有用到,可以直接无情的抛弃他,不然也可以看一下它的值,好像也就是个空串吧,就不清楚了。
我们会看到会将入参的Object
直接传给initParam
完成赋值,但是init
方法中还有很多其他的的变量也进行了初始化,而且后面会发现直接参与的log生成,所以我们也进行解密一下吧。
getLoadData() —— 载入时完成部分变量初始化
这里就很明显,_t
应该就是判断有没有进行一些变量的初始化,然后H就是当前时间戳,encrypt_id
给了一个true
,这个看着就不太对,这个后续应该还会把值进行改变,然后还调用了setInter()
方法。
setInter()
里面就是重新设置了定时器,去上报了一下数据,这个应该埋点数据了,可以直接忽略掉。
然后调用getBatteryStatus()
给 Lt
变量赋值,可以查看一下变量的使用情况,有且只有在getInterfaceData()
方法中用到,根据setInter()
的分析,这里面应该是埋点的上报数据,那么可以先不管他,直接注释掉,不对了可以再重新返回来进行查看吗。完全没有必要一步到位。
clearjoyytoken(i.appid, true) —— 清除JoyToken
其他又出现了一个新家伙,R
变量,查看一下变量初始化。
这里可以看到R和getTokem()
先按下不表吧,因为这里逻辑很明显跟他们俩没啥关系,因为下面的if分支中又一段e && tt === 1
,如果为真将进行一些操作。
还记得tt
吗,初始值为0
,调用window.smashUtils.init()
会加1,然后e变量也是init()
方法中传递过来的为true
,所以会直接走下面的清楚操作。a
变量也没用到,下个地方再说getTokem()
方法吧
getTouchSession() —— 获取session
这个方法就很简单了,就是根据调用方法的时间和随机数来生成了一个字符串。
getjoyytoken(i.appid, true) —— 获取JoyToken
又遇到熟悉的表达式了,这说明这里肯定要进getSwitch()
方法的,入参是appid
,也就是50174
,这里肯定每一个活动都不一样的。看一下getSwitch()
方法的代码。
这里总感觉那个collect_rate
变量的判断有一点点多余,算了,继续向后看吧。
$t.decipherJoyToken(y, initParam.appid) —— 解密JoyToken
朴实无华的解密JoyToken
,直接拷走就能用了。不过不知道为啥getjoyytoken()
方法中为啥要加上appid
,后续解密的时候还需要移除,再往后看看吧。
其中A.default.atobFunc()
可以看到其实就是普通的window.atob
,他只是在没有这个方法时,会重新实现一下。
shshshfpb初始化
可以看到https://rjsb-token-m.jd.com/gettoken
请求中的whwswswws
变量是从Cookie中拿到的,那么要找一下从哪里初始化的。
其实刷新一个网页可以观察到,每次和gettoken
接口一起发送的还有两个接口,一个是https://blackhole.m.jd.com/getinfo
,另外一个是https://blackhole.m.jd.com/bypass
。其中bypass
是在$t.reportInterfaceData
中调用的,这个方法暂定为埋点,其中getinfo
接口的返回值和whwswswws
变量相同。
再去代码中确认一下。
可以确定是getInfo
接口中初始化了whwswswws
,说明还有一部分变量不是在window.smashUtils.init()
中初始化的,还需要看一下从哪里调用的,找出另外一部分变量的初始化。
到这里,window.smashUtils.init
应该就算结束了,剩下的参数初始化都是在另外的地方初始化了。
剩余参数初始化
从getInfo()
追上去,看一下哪里进行了调用。
$t.getLocalData()
很明显就是获取这种标志位和初始变量,用于判断活动环境的。这些变量可以直接通过正常环境中直接拷贝出来。
$t.getAppOs()
和$t.getBlog()
就是我们上两篇文章说的,获取用户的设备信息和Blog
变量,可以直接翻看其他的文章。
$t.getFpv()
方法是初始化shshshfpv
Cookie变量,但是后续好像没有地方使用到。
$t.getInfo()
即为上个段落中,初始化shshshfpb
。
$t.setjoyyaCookie.init
一时间不知道是干嘛的,看着是初始化joyya
?但是后面好像没看到用处,解密都懒得解密,后续再说。
$t.getJrInfo()
应该就是获取京东金融的环境了,像电商节的活动,有些任务就会区分京东和京东金融的环境,应该就是这个方法了,这个可以暂时不用管,先搞定京东环境再说吧。
那到这里基本上变量的初始化应该就完成了,可以重新看log的生成逻辑了。
重回window.smashUtils.get_risk_result部分
这里比较有意思的地方在这里,还记得gettoken
接口拿回来的东西吗。是不是放到joyytokem
下面了,这里的getTokem
就给取出来了,然后并将其中的xcd
属性解密后居然是个JS代码块?高级高级,然后重新执行可以后端自定义的JS,如果后端也可以根据执行结果看出来环境是否异常吧?
然后截一下后面的代码吧。
这里面应该就没什么东西了,根据加密字符串的特征,可以判断出L.default.toString()
就是sha256Hex
,S.default.toString()
就是sha1Hex
。getCrcCode()
就是获取冗余校验码,utoa()
实际上就是window.btoa()
。
附带一份那个log对象的属性含义。
然后就只剩下最后一个xorEncrypt()
方法没有揭秘了,解出来看一看。
到这里log的生成逻辑应该就已经被扒的干干净净的,最终的ie
变量就是log变量了,body
中的random
经过分析,其实也就是调用window.smashUtils.get_risk_result
传递进来的random
。
进行测试
啊,可以直接跟你们说,实际上还是不能用的,请求接口会出现请从正常途径参加活动,原因有两个,一个是上面埋了一个坑,嘻嘻,可能遇到也有可能遇不到,完全看运气。
另外一个坑就是炸年兽活动居然在Cookie里面还有校验,一整个大震惊。