Python处理JS加密和混淆算法获取__jsl_clearance(二)

通过上一个教的详细分析,我们理出来思路,用Python来实现

第一步拿到源码部分Js,python请求代码如下

 1 import requests 
 2 from urllib3 import disable_warnings
 3 from urllib3.exceptions import InsecureRequestWarning
 4 import execjs
 5 import re
 6 
 7  
 8 
 9 disable_warnings(InsecureRequestWarning)
10  
11 
12 header = {
13          'User-Agent':"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36",
14          'Accept-Encoding': 'br, gzip, deflate',
15          'Accept':'*/*'
16         }
17  
18 
19 url = 'https://www.xxx.com'
20 
21 response = requests.get(url,headers=header)
22  
23 html = response.text 

 本教程是为了验证正常性,不用重新请求了,源码直接从浏览器抓包那复制过来了,JS源代码如下:

1 <script>var x="@@join@g@36@__jsl_clearance@false@parseInt@location@@@rOm9XFMtA3QKV7nYsPGT4lifyWwkq5vcjH2IdxUoCbhERLaz81DNB6@firstChild@@2F9k@hantom@@0xEDB88320@56@RegExp@e@2FMLE@@m0@else@8@fromCharCode@for@match@GMT@href@challenge@__p@19@d@@@@@@catch@29@while@@captcha@JYf@as@JgSe0upZ@s@charAt@onreadystatechange@Expires@@try@@@@0@charCodeAt@2@replace@18@@@06@length@eval@toLowerCase@@1500@cookie@f@function@@reverse@toString@substr@@new@@@Path@@a@@@chars@Sun@1534655216@return@@@Aug@if@DOMContentLoaded@@https@@var@@@search@D@String@@@window@Array@@2BAz@addEventListener@@@0xFF@@document@createElement@div@@@@attachEvent@setTimeout@split@g9@innerHTML@1@pathname".replace(/@*$/,"").split("@"),y="25 2l=1q(){2t('9.v=9.2y+9.28.1e(/[\\?|&]J-w/,\\'\\')',1n);2m.1o='6=1G.G|1b|'+(1q(){25 2=[1q(2l){1H 2l},1q(2){1H 2},(1q(){25 2l=2m.2n('2o');2l.2w='<1B v=\\'/\\'>2r</1B>';2l=2l.d.v;25 2=2l.t(/23?:\\/\\//)[1b];2l=2l.1u(2.1j).1l();1H 1q(2){s(25 2r=1b;2r<2.1j;2r++){2[2r]=2l.13(2[2r])};1H 2.3('')}})()],2r=[[(+!2d['x'+'g'+'10'])]+[(+!2d['x'+'g'+'10'])],([-~{}-~{}]*((-~{}-~{}^-~[]))+[]+[[]][1b]),[(+!2d['x'+'g'+'10'])]+(-~{}-~{}+[]),(-~~~{}-~[(-~![]+[~~[]])/[((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10']))]]+[[]][1b]),(-~((1d)*[(((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10'])))*[((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10']))]])+[]+[[]][1b]),((-~{}-~{}^-~[])+[]+[]),[(+!2d['x'+'g'+'10'])]+[~~{}],(-~{}-~{}+[]),[~~{}],[([((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10']))]+~~''>>((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10'])))],[(-~~~{}+[((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10']))]>>((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10'])))+([((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10']))]+~~''>>((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10'])))],[-~-~[]-~-~[]],[(+!2d['x'+'g'+'10'])]];s(25 2l=1b;2l<2r.1j;2l++){2r[2l]=2[[1b,2x,1d,2x,1b,2x,1b,2x,1d,1b,2x,1b,2x][2l]]([[[(+!2d['x'+'g'+'10'])]+(-~{}-~{}+[])],'29','o','K%2g%m',((-~{}-~{}^-~[])+[]+[]),[[]-{}+[]][1b].13(1d),'2v','l','12%f%',[{}+[]+[[]][1b]][1b].13(-~{}+[~~{}]-(-~{})),(!~~''+[]).13((+!2d['x'+'g'+'10']))+[!''+[[]][1b]][1b].13(~~{})+[!{}+[]+[]][1b].13((-~-~[]<<(+!2d['x'+'g'+'10']))),({}+[]+[[]][1b]).13((1d)*[(((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10'])))*[((+!2d['x'+'g'+'10'])<<(+!2d['x'+'g'+'10']))]]),[[-~-~[]-~-~[]]]][2r[2l]])};1H 2r.3('')})()+';15=1F, y-1K-1f 1i:1i:j u;1z=/;'};20((1q(){17{1H !!2d.2h;}F(l){1H 7;}})()){2m.2h('21',2l,7)}p{2m.2s('14',2l)}",f=function(x,y){var a=0,b=0,c=0;x=x.split("");y=y||99;while((a=x.shift())&&(b=a.charCodeAt(0)-77.5))c=(Math.abs(b)<13?(b+48.5):parseInt(a,36))+y*c;return c},z=f(y.match(/\w/g).sort(function(x,y){return f(x)-f(y)}).pop());while(z++)try{eval(y.replace(/\b\w+\b/g, function(y){return x[f(y,z)-1]||("_"+y)}));break}catch(_){}</script>

 

过滤掉Scrpt标签:

1 #匹配js代码,只取以<script>开关 以</script>结束
2 ret = re.findall('\\s*?<script>(.*?)</script>',html)
3 
4 #获得到js代码
5 js = ret[0]

获取到,第一次console.log打印的代码,自定义一个函数名getResult调用返回值

#由于Js代码加密了,需要解密,即第一次console.log打印的代码,返回给Python做处理
js = js.replace(r"eval(", r"return (");

jsstr = "function getResult(){" + js + "};";

ctx = execjs.compile(jsstr)  

#调用解密,得到返回的代码
js = ctx.call('getResult')  

效果如下图:

 

由于Python调用Js库的特性问题,只能return返回值且最外层只能用一个函数供外面调用且不支持像window,document这类元素,JS代码中

若包含都统统要去掉,通过分析如下代码没有无用

 

 

 首先获取正则获到_21的函数体部分代码如下:

 1 code = []
 2 start = False;
 3 deep = 0;
 4 for c in js:
 5     if not start:
 6         if c == '{':
 7             start = True
 8             deep += 1
 9         else:
10             continue
11     else:
12         
13         if c == '{':
14             deep += 1
15             code.append(c)
16         elif c == '}':
17             deep -= 1
18             if deep == 0:
19                 break
20             else:
21                 code.append(c)                
22         else:
23             code.append(c)
24 #获取函数主体               
25 func_body = ''.join(code)

接下来正则去掉__jsl_clearance=和之前的部分,代码如下:

1 #去掉前面设置Cookie的部分
2 pattern = re.compile(r'(.*?__jsl_clearance=)')
3 
4  
5 #设置为返回值,去掉前的值
6 func_body = re.sub(pattern, '', func_body)

 

经过多次测试__jsl_clearance=有可能是一个变量替换的所以用时间戳来判断,并处理

如果不是时间戳开头,就再次处理下,从头到时间戳,也可以直接到时间戳的位置

1 if str(func_body[0:10]).isnumeric():
2     func_body = 'return \'' + func_body;
3 else:
4     ret = re.findall(r'(.*?)([0-9]{10})\.',func_body)
5     if len(ret) > 0 and len(ret[0])> 1  and  (ret[0][1]).isnumeric():  
6         pattern = re.compile(r'(.*?)[0-9]{10}\.')
7         func_body = re.sub(pattern,'return \'' +  ret[0][1]+'.', func_body)
8     else: #没有找到时间戳
9         print(func_body)

 

接下来处理document.createElement的位置按图上的位置到href值是url

1 pattern = re.compile(r"document\..*?\.href")
2 func_body = re.sub(pattern,"\""+ url+ "\"", func_body)

接下来处理windows元素的干扰问题,windows这个干扰随机变化的只能用则处理,还有可能是多个种

1 #去掉window干扰
2 #func_body = func_body.replace("window['__p'+'hantom'+'as']","\"\"")
3  
4 #func_body = func_body.replace("while(window._phantom||window.__phantomas){};", "");
5 
6 
7 pattern = re.compile("(window\[[^\]]+\])")
8 func_body = re.sub(pattern,"undefined", func_body)

经统计有多种类型的windows元素干扰

#(window.headless + [[]][0])

ret= re.findall(r'window[^\+\]]*',func_body)
if len(ret) > 0: 
    func_body = func_body.replace(ret[0],"\"\"")
    

关于干扰问题还有多个变量的干扰比如retrun,function被他替换成了

一个别的变量名,这种比较变态了,只有少数的情况,基本上面的处理

可以达到90%以上的能返回了

最后直接合成完成的JS函数给Python调用,代码如下:

 
jsstr = "function getResult(){" + func_body + "};";


ctx = execjs.compile(jsstr)  
 

#调用获取cookie
cookie_value = ctx.call('getResult')  

 
print(cookie_value)

得到如下结果:

 

 1534655216.29|0|Og99ebJYf%2BAz%2FMLErtem0mNs%2F9k%3D;Expires=Sun, 19-Aug-18 06:06:56 GMT;Path=/;

 

上面就是Python实现的全过程了,如果觉得对您有帮忙,请给一个赞!!!

  

posted @ 2018-08-19 15:50  永不褪色的心  阅读(870)  评论(0)    收藏  举报