极验滑块验证三个W超详细解密(2)
书接上文
第二个w获取流程
第二个w也可以不用去获取,因为第二个w不涉及到验证码的获取和验证,至少现在还没有
点击验证码,获取到如下包,一个 ajax.php 和 get.php
4.第四个请求,携带解密后的w,用于识别验证码是否加载成功
第二个w解密流程
第二个w要找到加密位置,需要看html页面,他是通过动态加载script标签,然后通过加载js来完成加密
打上断点,刷新页面,通过观察加载德script标签,发现并不是我们需要的请求,所以直接过掉
过掉所有断点后,我们再点击按钮,将验证码加载出来,这一次断点再次打上,通过观察会发现是我们要请求的接口,然后我们向上追栈
向上追一个栈,我们来到这个函数,我们分析一下 [$_HCDk(340)]
就是调用最上面的那个方法, 他传入了一个new le(f),
往上面看,这里创建了几个参数,其中n已经包含了src,也就是在这里已经完成了w的加密,我们在上面打一下断点,看一下n在这里做了什么
在n下面重新打上断点后,进来发现n里面的script标签里面并没有src属性,第二步将n里面的script标签传给了r,再往下一步,发现是对s进行正则操作,我们看下s是什么,发现s就是我们想要的src,接下来 我们要找到这个s是怎么生成的了
我们在往上看,会发现s是传入进来的,我们也可以在这里打断点看一下是否是传进来就已经加密好,还是就是在这里加密的,经过测试会发现是传进来就加密好了,所以我们要去找是谁调用了这个函数,传入的第一个参数是什么,同样进行追栈
往上追一个栈之后来到这里,同样的,验证一下,发现n在进去函数c之前就已经完成了加密,所以我们追函数C的栈
就在下面,进来之后我们会发现i参数里面包含了该接口请求的所有参数包括加密的w参数,所以我们得去找一下i的来源,再往上看,D函数传入的参数包含i,同样的验证一下是否是传进来就加密好了
答案显而易见,我们再次追栈
来到上一个函数,继续验证,验证结果,继续朔源
发现还是传进来的,继续验证,验证完成,继续朔源
断点来到N的上面,我们会发现n在这里进行了组装
我们再看一下这个代码,t是this,而t[xxx(1481)] 等于我们想要的w,xxx(1481)肯定是做了混淆,但是可以肯定的是,在某一段代码里面肯定执行了,xxx(1481) = w 的操作,xxx我们搜不到做了混淆,但是1481应该是可以搜索得到的
这里一共就三个,去掉本身那个,还有一个是一串数字,剩下的就只有这个符合我们的要求了,我们在这里打上断点。会发现 i[xxxx] = w ,而i在上面, i就是this,而我们要完成的就是 p[$_CGBDY(1303)](_[$_CGBDY(12)](r, i[$_CGBDY(1361)]()))
的解密
第二个w获取流程
我们先把w加密的这一段代码扣下来,前面五行也是跟之前一样毫无意义的循环,都是一样的值,直接删掉
删完之后我们来看一下这个控制流,发现会走所有的流程,所以我们直接精简一下
1 |
|
1 |
|
我们先看一下 r ,o和n视乎是现成的,就在上面,我们看下 o['toString']()
和 n['toString']()
,以及 e['toString']()
怀疑这里是否是做了代码检测,这里的运行结果肯定是会和我们精简话后的代码运行结果不一样的,我们直接把这三个的值给写死,直接复制控制台输出出来的
1 |
|
接下来 我们来找一下 i['$_CEG_']
是怎么生成的,源代码是i[$_CGBIC(1448)]
,还是那个逻辑,从某个地方取值,那肯定会有从这个地方存值的操作,直接搜索1448,搜索出来的结果有三个我们直接在其它两个地方打断点
可以看到,在最开始的时候,做了一个赋值空字符串的操作,接下来就是一个大号的循环在循环里面做一个拼接的操作,这里一大串都是 for(;;) 也就是for循环里面的判断和自增条件,而真正的循环体只有最后一个拼接的操作
我们把代码复制出来,处理一下
1 |
|
从上到下,我们先处理前面一大段赋值的操作,先看 i['$_BJJF']['$_BIBF']()
,进去打断点,我们先看一下
this[$_CDDIY(34)]
很显然 这是一段轨迹的操作,下一段代码又将其制空,这一步操作没有意义,后面肯定是要对轨迹进行处理的,而这一段轨迹我们可以用算法生成,也可以直接复制,这一段轨迹来自于你对点击生成验证码的操作进行鼠标轨迹检测,这也就是为什么用selenium无法成功的原因
我们往下执行一步,输出一下 this[$_CDDIY(917)](e)
,这里传递的值应该是上一步的时间差值,并没有对时时的时间进行计算,所以我们可以直接复制这个轨迹。到了这里,e参数的加密入口就处理好了,现在要解决的是 this['$_BHIh'](e)
方法
1 |
|
接下来就是扣代码的环节,把没必要的给删掉,需要注意的是 ce(['down', 'move', 'up', 'scroll'])['$_EHc'](p)
这里需要在ce的原型链上添加新的方法,需要注意
1 |
|
然后运行一下 this['$_BHIh'](e)
控制台输出和我们的运行结果一致,这个方法就解决了,现在要解决的是 this['$_HDc']($_BHIh(e))
方法,这个方法比较长,需要扣仔细一点
抠出来的代码会精简很多,极验的控制流都是假的,直接把控制流的主体部分拿出来就可以了,抠出来运行一下看一下是否和浏览器的一样,验证结果没有问题,e参数解密完成。那就回到加密入口,去看一下t参数
1 |
|
t = i[$_CFJHp(1378)][$_CFJHp(1419)]()
我们看一下这个函数,直接看return this[$_CDEDb(34)]
是一个空数组,this[$_CDEDb(942)]
就在上面,也就是我们上一步做的轨迹加密,但是这一次它传入了一个空数组,所以这个方法我们可以这样写,验证一下,没有问题,这一步其实也可以写死
1 |
|
接下来看参数n n = i[$_CFJIy(1313)][$_CFJIy(1419)]()
,其中 n[$_CEAIT(34)]
其实就是上一个w里面那两个数组中包含浏览器指纹的那个,而下面的 n[$_CEAHd(1374)]()
就是另一个数组,所以 这两个数组都可以直接复制过来,里面的时间戳改成 new Date().getTime()
就好了
1 |
|
然后我们再看一下 new ce(n[$_CEAHd(1374)]())[$_CEAHd(19)]
是个什么东西,ce方法 我们在前面已经扣下来了,现在我们在ce方法的原型方法上再加上一个 $_EAz方法
1 |
|
这下n也加密完成了,我们看一下加密结果, 没什么问题
接下来就看一下r参数 r = i['$_BDHN']['$_BIBF']()
,看一下这个是什么方法,简化一下
1 |
|
我们先看一下 this['$_BGq']
是什么,这里貌似是一个固定的值, 这里也可以直接写死,
再看一下 o = i[$_CFJIy(336)]
参数o,发现其实是上面两个请求的返回值,所以这边也是可以直接写死的
最后一个参数 s s = $_GY() - ot
参数s应该是两个时间戳相减,这个差值可以随机,也可以写死,这里我们直接写死
1 |
|
然后接着往下面看,中间这一部分就让他自己算,我们直接看下面的,直接看 V和p方法
这是p方法,精简一下, 我们把 this['$_HCh']
和 this['$_GHz']
补一下,其实这一步的操作和第一个w获取参数i的操作一模一样,正常扣代码就行
1 |
|
1 |
|
接着 我们来扣V方法,这个V方法其实是个md5加密,我们可以导包或者直接扣也i选哪个
1 |
|
接着 我们把后面的一些参数补起来
i['$_CCGM']
是第一个w里面算的指纹,我们直接把它给拿过来,这里可能会有问题,因为如果我们拿第一个w里面指纹生成的方式,就相当于是重新生成的,而这里应该是拿上一次的指纹
接着来看 i['$_CEHV']()
,看一下ren的值,搜一下,这里有可能是GPU的信息,这里应该也是指纹信息,fp和lp这里有两个时间戳,有可能又是检测鼠标移动,我们可以把一个值设定成当前时间,另一个值把这两个值得差值给加上,而下面的tm的值,我们也算和当前时间的时间差,完成是这样的
1 |
|
o参数里面没用的参数可以删掉,后面还有个 ge['stringify']
,这个和第一个w里面一样,这里就是个json,stringify,然后运行一下,看上去好像没什么问题,我们回到最开始的加密入口,看下r值能不能获取到,这样r也能获取到,接下来就是加密算法的部分了
最后一段 return p['$_HEf'](_['encrypt'](r, i['$_CCIl']()))
我们将断点打到下面来,然后去看一下 i[$_CGBDY(1361)]
是什么, 点进去之后能很明显的看到 又是判断aeskey是否存在,不存在就生成,如果存在就直接返回,那么我们可以直接用上一次加密的aeskey,而这里应该要的就是上一次生成的aeskey,而不是重新生成,那么我们就需要通过传参获取上一次的aeskey
我们直接把第一次w加密的aes算法拿过来
1 |
|
接下来 p['$_HEf']
的操作也是和第一w生成时 $_HEf(o)
的操作一样,所以我们也可以直接拿过来,最后我们将浏览器中的aeskey拿过来,测试一下, 没什么问题,我们再将代码整理一下
1 |
|
我们修改一下第一个w生成的结果,将里面的指纹信息和aeskey一起返回出来
我们前面的o参数里面,还有一个s的值,该值是从上一个请求结果里面获取的,我们还需要把它给拿过来
这段指纹呢,我们也直接用上一次加密完成的
最终的结果也是没有问题,
python代码:
1 |
|
js代码太长了,这里只给出入口的js代码
1 |
|