关注微信公众号:K爬虫大哥,继续分享高级爬虫、JS/Android逆向等技术干货工程!声明本文所有内容仅供学习交流。抓拍内容、敏感网址、数据接口均已脱敏处理,严禁用于商业或非法用途。否则,由此产生的一切后果与作者无关。侵权请联系我立即删除!反向目标目标:网路者反爬虫练习平台第四题:JSFuck加密链接:http://spider.wangluozhe.com/...题型:这道题还是要收集100页的所有数字,计算出所有的数据另外需要提取源码进行计算,主要使用JSFuck加密JSFuck简介JSFuck、AAEncode、JJEncode是同一作者,JSFuck由日本YosukeHASEGAWA于2010年创建,仅用6个符号就可以对任意JavaScript进行编码一个混淆[]()!+的形式,2012年,MartinKleppe在GitHub和JSFuck.com网站上创建了一个jsfuck项目,其中包含使用此编码器实现的Web应用程序。JSFuck可用于绕过对网站上提交的恶意代码的检测,例如跨站点脚本(XSS)攻击。JSFuck的另一个潜在用途是代码混淆。现在的jQuery经过JSFuck混淆后已经有了一个功能齐全的版本。在线体验地址:https://utf-8.jp/public/jsfuc...http://www.jsfuck.com/一段普通的JS代码:alert(1)JSFuck混淆后的代码类似于:[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]](((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])JSFuck中常用的元素、数字、符号转换如下表所示。更多元素请参考JSFuck官方GitHub或JSFuckWikipedia:ValueJSFuckfalse![]true!![]或!+[]NaN+[![]]undefined[][[]]Infinity+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])Array[]Number+[]String[]+[]Boolean![]Function[]["filter"]eval[]["filter"]["constructor"](CODE)()()window[][“过滤器”][“构造函数”](“返回这个”)()+(+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]])+[])[!+[]+!+[]].(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]0+[]1+!![]或+!+[]2!![]+!![]或!+[]+!+[]3!![]+!![]+!![]或!+[]+!+[]+!+[]a(![]+[])[+!+[]]d([][[]]+[])[!+[]+!+[]]e(!![]+[])[!+[]+!+[]+!+[]]f(![]+[])[+[]]我们从以字母a为例,演示混淆过程:“false”[1]:字母a取自字符串false,在false中,a的索引值为1;(false+[])[1]:false可以写成false+[],即布尔常量false加上一个空数组;(![]+[])[1]:false可以写成![],即对空数组取反;(![]+[])[+true]:1是一个数字,我们可以写成+true;(![]+[])[+!![]]:由于false是![],true是!![],导致最后的Obfuscation代码JSFuck反混淆方法JSFuck通常以Function的形式执行(xxx)()和eval(xxx)调用方法时,所以JSFuck常用的反混淆方法如下:使用在线工具直接解密,如:https://lelinhtinh.github.io/...;对于Function的情况,复制代码最外层倒数第二个括号中的内容,放到浏览器中直接执行就可以看到源码;对于eval的情况,复制代码最外层最后一个括号中的内容,放到浏览器中直接执行就可以看到源码;分别使用Hook方法、Hook函数和eval,并打印出源码;使用AST反混淆,AST教程K哥后面也会写,本文就不详细介绍了。如上面alert(1)的混淆代码,将最外层最后一个括号中的内容复制到浏览器中,可以看到源码:反向参数反向目标主要是翻页界面的_signature参数,而调用的加密方法仍然是window.get_sign(),和前面的问题一样。我不会在本文中详细介绍。不知道的可以看看K哥上一期的文章。如果你继续跟进,你会发现这是一个JSFuck混淆:我们复制这段代码放在编辑器中。这里我们以PyCharm为例。由于我们要选中匹配括号内的内容,所以我们可以在PyCharm中设置括号的匹配高度为鲜红色,方便我们查找。依次点击File-Settings-Editor-ColorScheme-General-Code-Matchedbrace,把Background设置成显眼的颜色:这时候我们选择最后一个括号,往上看,很明显看到另一个匹配它的括号,如下图所示:我们复制括号内的内容(带括号或不带括号),在浏览器控制台运行,可以看到源码:除了这个方法,我们还可以使用Hook方法直接捕获源代码然后打印输出。注意这段混淆后的代码末尾没有()括号,即以eval方式执行。我们编写Hookeval代码如下:eval_=eval;eval=function(a){debugger;returneval_()}//还提供一个HookFunction代码//Function.prototype.constructor_=Function.prototype.constructor;//Function.prototype.constructor=function(a){//debugger;//returnFunction.prototype.constructor_(a);//};刷新网页,直接破解。此时a的值就是源码:复制源码到本地分析:(function(){lettime_tmp=Date.now();letdate=Date.parse(newDate());window={};让点击=window.document.onclick;让key_tmp;让iv_tmp;如果(!click){key_tmp=date*1234;}else{key_tmp=日期*1244;}if(time_tmp-window.time<1000){iv_tmp=date*4321;}else{iv_tmp=日期*4311;}constkey=CryptoJS.enc.Utf8.parse(key_tmp);variv=CryptoJS.enc.Utf8.parse(iv_tmp);(functiontmp(date,key,iv){functionEncrypt(word){letsrcs=CryptoJS.enc.Utf8.parse(word);letencrypted=CryptoJS.AES.encrypt(srcs,key,{iv:iv,模式:CryptoJS.mode.CBC,填充:CryptoJS.pad.Pkcs7});returnencrypted.ciphertext.toString().toUpperCase();}window.sign=Encrypt(date);})(date,key,iv);})();可以看出是AES加密。这里,主要注意有两个if-else语句。第一个判断是否有window.document.onclick,第二个是时间差的判断。我们可以尝试在控制台中获取window.document.onclick和window.time,看看是if还是else。我们也可以在本地完成这两个值。其实K哥测试过window.document.onclick为null之后,然后不管用if还是else都可以得到结果,所以这道题,两个window对象无所谓,去掉就行了,随便key_tmp和iv_tmp的值很好。能至此,本题解析完毕,并在本地重写后,Python代码携带_signature逐页计算每一页的数据,最终提交成功:完整代码GitHub跟随K哥的爬虫,继续分享爬虫相关代码!欢迎加星!https://github.com/kgepachong/下面只是演示了部分关键代码,不能直接运行!完整代码仓库地址:https://github.com/kgepachong...JavaScript加密代码/*=====================================#@Time:2021-12-13#@Author:WeChat公众号:K哥爬虫#@FileName:challenge_4.js#@Software:PyCharm#=====================================*/varCryptoJS=require('crypto-js')letdate=Date.parse(新日期());window={};letkey_tmp=date*1234;//letkey_tmp=date*1244;letiv_tmp=date*4321;//iv_tmp=date*4311;constkey=CryptoJS.enc.Utf8.parse(key_tmp);variv=CryptoJS.enc.Utf8.parse(iv_tmp);(functiontmp(date,key,iv){functionEncrypt(word){letsrcs=CryptoJS.enc.Utf8.parse(word);letencrypted=CryptoJS.AES.encrypt(srcs,key,{iv:iv,mode:CryptoJS.mode.CBC,padding:CryptoJS.pad.Pkcs7});返回encrypted.ciphertext.toString().toUpperCase();}window.sign=Encrypt(date);})(date,key,iv);functiongetSign(){returnwindow.sign}//测试输出//console.log(getSign())Python计算密钥代码#====================================#--*--编码:utf-8--*--#@Time:2021-12-13#@Author:WeChat公众号:K哥爬虫#@FileName:challenge_4.py#@Software:PyCharm#=====================================importexecjsimportrequestschallenge_api="http://spider.wangluozhe.com/challenge/api/4"headers={"Content-Type":"application/x-www-form-urlencoded;charset=UTF-8","Cookie":"把cookie值改成你自己的!","Host":"spider.wangluozhe.com","Origin":"http://spider.wangluozhe.com","Referer":"http://spider.wangluozhe.com/challenge/4","User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/96.0.4664.45Safari/537.36","X-Requested-With":"XMLHttpRequest"}defget_signature():withopen('challenge_4.js','r',encoding='utf-8')作为f:ppdai_js=execjs.compile(f.read())signature=ppdai_js.call("getSign")print("signature:",signature)returnsignaturedefmain():结果=0forpageinrange(1,101):data={"page":page,"count":10,"_signature":get_signature()}response=requests.post(url=challenge_api,headers=headers,data=data).json()fordinresponse["data"]:result+=d["value"]print("结果为:",result)if__name__=='__main__':main()
