某行动态cookie反爬虫分析
1. 预览
反爬网址(
base64
):aHR0cDovL3d3dy5wYmMuZ292LmNu
反爬截图:
- 需要先加载运行
js
代码,可能是对环境进行检测,反调试之类的
无限
debugger
- 需要先加载运行
- 处理办法
- 网上大部分人说的都是添加
cookie
来解决。- 那个
noscript
标签仅仅是用于提示用户的,在不支持js
的浏览器展示。 - 本网站是动态
ck
,每一次的cookie
都是上一次成功请求所返回的,但是python
模拟请求时,第一次请求就是上图所示的页面,于是第一次成功的请求就是解决该问题的关键,- 1.你可以使用上一次浏览器成功请求返回的ck添加到python里发起请求,当然这比较笨拙,哈哈
- 2.使用
python
完成第一次成功的请求
- 那个
- 当然,我们选择使用方法
2
来实现呀,优雅一点嘛
- 网上大部分人说的都是添加
2.调试
- 无限
debugger
怎么去掉?- 右键,不在这里暂停,是可以,但有时得小心,不暂停了出现无限循环带来的卡顿
- 这里就简单的使用不在这暂停
3.扣代码环节
1.扣逻辑,扣需要的代码
从上图可以看出,第一次请求执行上面返回的
js
代码和session_id
,wzws_cid
,js
代码里有逻辑写了,发起第二个验证请求,验证成功的话,返回302状态码,返回新的wzws_cid
,然后带着正确的wzws_cid
、sessionid
等参数进行跳转主页,才能成功请求。- 我们看一下,第一次返回的
js
代码:
这些个在浏览器调试就会发现都是字符串加密之类的,而且整个代码进行了
ob混淆
,为了便于调试,使用反混淆工具,反混淆下:格式前后的
j
:`function u(k){function gR(v,A){return gE(A- -'0x92',v);}var P={'oQHKx':function(C,x,d){return A['cirRP'](C,x,d);},'LJXui':A[gD('93LV',-'0x127')],'JITOI':A['FJQMp'],'ktFbX':function(C,d){function gm(v,A){return Z(A- -'0x2ef',v);}return A[gm('0x40',-'0x3d')](C,d);},'nzZBi':A[gD('kdha',-'0xa7')]};function gD(v,A){return gY(A- -'0x5c',v);}function gO(v,A){return gE(v- -'0x3b6',A);}function gF(v,A){return ge(v,A-'0x48f');}if(A[gR('0x561','0x5b1')](A[gD('DT[N',-'0xab')],A[gF('M1Bv','0x635')])){var x=P['oQHKx'](P,C,x);P['oQHKx'](d,N,x);}else{if(A[gR('0x4d8','0x535')](typeof k,A[gR('0x4c5','0x540')]))return function(x){}['const'+gR('0x5d7','0x579')+'r'](A[gR('0x4e4','0x4d4')])[gR('0x539','0x4ee')](A[gF('Ux5v','0x657')]);else{if(A[gO('0x27e','0x218')](A[gF('UbQE','0x621')],A[gF('%4Ja','0x6ad')])){var d=C?function(){function gL(v,A){return gD(A,v-'0x69f');}if(d){var Y=J[gL('0x523','BpO(')](n,arguments);return z=null,Y;}}:function(){};return i=![],d;}else{if(A['OFxOf'](A[gF('Ms1O','0x5be')]('',A['yUkFe'](k,k))[A[gR('0x582','0x5bc')]],-0x1cbf+0x33*-0x8b+-0x1*-0x3871)||A[gR('0x590','0x509')](A[gD('xrrg',-'0xe2')](k,0x2189+-0x7*0x4dd+-0x4b*-0x2),0x42c*-0x8+-0x3*-0x66+0x202e))(function(){return!![];}[gR('0x5d4','0x5ba')+'ructo'+'r'](A['ChrtP'](A[gO('0x2c3','0x2af')],A[gR('0x556','0x51d')]))[gD('0sv]',-'0x6c')](A['bHBdS']));else{if(A[gR('0x585','0x500')](A[gR('0x4b1','0x50e')],A['zesRv'])){var N=A['RZobL'][gF('z6h!','0x6d4')]('|'),K=0x9a1+0x53*0x55+-0x2530;while(!![]){switch(N[K++]){case'0':var i=new K(J);continue;case'1':var J=n[gF('m7@A','0x62f')+'h'];continue;case'2':return z[gO('0x277','0x1e6')+'e'](i['buffe'+'r']);case'3':var n=A['MBcSp'](d,N);continue;case'4':for(var z=0x31f+-0x2e9+-0x36;A['HWTiM'](z,J);z++){i[z]=n['charC'+gF('xrrg','0x5b5')](z);}continue;case'5':if(!C)return x;continue;}break;}}else(function(){function gl(v,A){return gO(A-'0x1cf',v);}function gr(v,A){return gO(v-'0x3e8',A);}function gG(v,A){return gF(A,v- -'0x5bd');}function gT(v,A){return gD(v,A- -'0x80');}return P[gT('Ux5v',-'0x1e4')](P[gr('0x6b8','0x645')],P[gr('0x6b8','0x6ee')])?![]:function(K){}[gl('0x412','0x465')+gl('0x3ff','0x424')+'r'](P['LJXui'])['apply'](P[gG('0x12','*Ig5')]);}['const'+gR('0x51a','0x579')+'r'](A[gR('0x561','0x59a')](A[gR('0x67a','0x5e7')],A['HINSR']))[gO('0x1ca','0x14d')](A[gF('XuiA','0x5b1')]));}}}A[gO('0x1e8','0x238')](u,++k);}}` ``
格式前后的
j
:
从上图中可以看出:
1.进行了正则校验,
V
表达式,我就纳闷了,格不格式化的会返回true啊,有毒,应该用+
来检测至少一个空格嘛,真是的。第二个正则,
p
表达式,也是一样的,格式化前后我的都是++k
,能能匹配到,这里他应该是想校验是否有++ k
,那么也要用+
号,我真服了,垃圾代码。所以一定会进入else:
最终进入:
""+0/0='NaN'
,进入虚拟机中,执行debugger
,然后继续u(++k)
,不断地自己调用自己,无限debugger;总结:可以看出,无论你是否格式化代码,我都会给你进入无限debugger,而debugger仅仅在打开F12时,才会起作用!也就是说和你格式化代码没有屁毛钱关系,只要打开F12就会无限debugger,大家也看出来了,两条分支,一条进入无限while循环,内存爆破,一条无限debugger,所以有意思的来了,如果你按照自己的先验主义,把下面的test校验 的感叹号删掉,你将收获内存被爆破,哈哈,有点道高一筹魔高一丈的感觉了
- 我们看一下,第一次返回的
分析完了正则校验和
debugger
,我们书归正传,看看第二个请求里面的加密参数怎么来的,这里最简单的办法就是,直接使用它的js
文件即可,没必要自己去扣了,毕竟解混淆之后的代码实在是太清晰了,如下图所示,生成了所需要的地址。对该地址发起请求后,校验成功后,拿着返回的
wzws_cid
、sessionid
即可正确进行数据获取了