筆記-爬蟲-js程式碼解析
筆記-爬蟲-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線上加密