笔记-爬虫-js代码解析
1. js代码解析
1.1. 前言
在爬取网站时经常会有js生成关键信息,而且js代码是混淆过的。
以瓜子二手车为例,直接请求https://www.guazi.com/bj/buy/会返回一个203状态大小为5324的包,核心是js代码。
它负责生成cookie及跳转,想要初始cookie,就需要解决它或绕过它。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript">
eval(fuas';var url='';xredirect(name,value,url,'https://');
//js源码,很长一段,删除了大部分
</script>
</head>
<body>
<p>正在打开中,请稍后...<e style='float:right'>2018-11-22 12:05:37</e><p>
</body>
</html>
1.2. 解析/调试
最简单的调试,创建一个test.html文件,代码如下,使用chrome打开。
就付一般爬虫场景够用了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript">
document.write(xredirect)
document.write(anti)
</script>
</head>
<body>
<p>正在打开中,请稍后...<e style='float:right'>2018-11-22 12:05:37</e><p>
</body>
</html>
其它的主要是对js函数的熟悉程度了;
1.3. JS函数
常见函数
eval() 执行代码
function(){}() 函数定义及执行一体
parseInt() 类似于int(45,8)
2. 一些常见的js代码隐藏方式
欲胜则要知已知彼,也得学习一下前端的代码加密方式,下面是一些常用的js代码加密方式。
1、简单压缩
将多行代码去除多余的空根和注释压缩成一行代码,这样虽然没什么太大的作用,但是对于新手来说阅读起来就会有些难度了。
比如:
1 2 3 4 5 6 7 8 |
function getCookie(name) { var preg = new RegExp("(^| )" + name + "=([^;]*)(;|$)", "g"); if (preg.test(document.cookie)) { return RegExp.$2; } else { return ""; } } |
压缩后:
function getCookie(name){var preg=new RegExp("(^| )"+name+"=([^;]*)(;|$)","g");if(preg.test(document.cookie)){return RegExp.$2}else{return""}}
2、代码混淆
将代码中的变量重命名成其他不规则变量,将代码中的中文转换成unicode编码或者16进制代码降低可阅读性。
1 |
function getCookie(b){var c=new RegExp("(^| )"+b+"=([^;]*)(;|$)","g");if(preg.test(document.cookie)){return RegExp.$2}else{return""}} |
3、简单加密
将代码换转换成eval方式,这样子就完全没有之前代码的样子了,只能通过一些关键词或者函数名来查找。
1 |
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k)p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k);return p;}('9 7(3){8 1=6 0("(^| )"+3+"=([^;]*)(;|$)","5");b(1.e(c.a)){4 0.$2}d{4""}}',15,15,'RegExp|preg||name|return|g|new|getCookie|var|function|cookie|if|document|else|test'.split('|'),0,{})) |
当然这种方式很简单就可以被解密。
4、base64加密配合eval来加密。
比如说:
1 |
alert(1); |
这种写法一眼就看懂了,那如果换一种写法呢?
1 |
eval(atob('YWxlcnQoMSk7')); |
这是什么鬼?其实YWxlcnQoMSk7就是alert(1);经过base64加密后的密文,atob就是将YWxlcnQoMSk7还原成alert(1);然后再丢给eval去执行,atob是浏览器内置函数,用于解密base64密文,与之对应的还有btoa,用于将一个字符串加密成base64密文。
5、进阶加密
就是综合使用了压缩,混淆等方式进行的加密。
比如还是用文章开始那段setCookie的代码,加密后:
1 |
function getCookie(jvA1){var LQuH2=new window["\x52\x65\x67\x45\x78\x70"]("\x28\x5e\x7c \x29"+jvA1+"\x3d\x28\x5b\x5e\x3b\x5d\x2a\x29\x28\x3b\x7c\x24\x29","\x67");if(LQuH2['\x74\x65\x73\x74'](window["\x64\x6f\x63\x75\x6d\x65\x6e\x74"]['\x63\x6f\x6f\x6b\x69\x65'])){return window["\x52\x65\x67\x45\x78\x70"]['\x24']2}else{return""}} |
接下来介绍几个比较另类的隐藏代码的方式:
6、jsFuck
仅使用6种符号来编写代码,(,),+,[,],!
比如:
1 |
alert(1) |
加密后:
1 |
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][[]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[!+[]+!+[]+[!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[!+[]+!+[]+[+[]]]) |
加密的连他爹妈都很难认识了,虽然比较奇葩,但是如果你将上述代码拷贝到浏览器控制台运行,会得到一个弹窗。缺点加密出来的代码超级长。
在线加密工具点击这里
7、颜文字解密
将js代码转换成表情符号
还是alert(1);
加密后:
1 |
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') ;(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_');(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_'); |
很诡异吧,但是他真的可以运行,不信可以试试。
在线加密工具点击这里
除上述的方法外,也有很多很成熟的方案,比如:
1、YUI Compressor
2、Google Closure Compiler
3、UglifyJS
4、JScrambler
我么也可以选择将上述代码继承到webpack中,自动为我们加密混淆js代码。当然具体场景具体分析,实际开发中还有许多其他的技巧,比如添加一些无用的代码来干扰实现,代码执行顺序等等方面,如果感兴趣的可以去找几个做huichan的网站看看。
几个在线加密网站:
在线加密工具Javascript在线解压缩
在线加密工具So JSON Javscript在线加密