当前位置: 首页 > 科技观察

爬虫中JS的逆向破解_0

时间:2023-03-18 17:45:32 科技观察

爬虫中很重要的一点就是JS加密的逆向破解。今天就来分析一下。背景首先简单介绍一下为什么会有JS解密。目前大部分网页都采用前后端分离的方式。所以一般爬虫的破解方式都是从后台接口做文章和突破。不过道高一尺,魔高一丈。Web开发会对API接口的请求参数进行加密,提高爬虫爬取的门槛。为此,可以通过js逆向分析破解加密方式,模拟浏览器发送请求获取接口数据。当然,首先这篇文章不是很专业的JS解密,因为JS解密涉及的解密种类很多,行为的解密也很多。本文只是对其中一种情况做简单介绍。来吧,让我们一起简单地学习一下。上图是请求翻译的全过程。我们可以清楚的看到,这是数据直接以表单的形式提交给后端API层,然后由API进行翻译。接下来,我们使用python来模拟以下过程。需要注意的是requestheader一定要写完整,包括cookie和user-agent,后面的params一定要和网页一致。代码给大家。importrequests#请求头headers={"Accept":"application/json,text/javascript,*/*;q=0.01","Accept-Encoding":"gzip,deflate","Accept-Language":"zh-CN,zh;q=0.9","Connection":"keep-alive","Content-Length":"255","Content-Type":"application/x-www-form-urlencoded;charset=UTF-8","Cookie":"OUTFOX_SEARCH_USER_ID_NCOO=1992896419.125546;OUTFOX_SEARCH_USER_ID=1708647615@10.108.162.133;fanyi-ad-id=306808;fanyi-ad-closed=1;DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|;JSESSIONID=abcJJxrChyTjz_26EmBgy;___rl__test__cookies=1656205889631","Host":"fanyi.youdao.com","Origin":"http://fanyi.youdao.com","Referer":"http://fanyi.youdao.com/","user-agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/102.0.0.0Safari/537.36","X-Requested-With":"XMLHttpRequest",}#提交参数params={"i":"loveyoumybaby","from":"AUTO","to":"AUTO","smartresult":"dict","client":"fanyideskweb","salt":"16562058896377","sign":"f85458213e7db4207f135599c7ddfac7","lts":"1656205889637","btypev":"bdc0570a34c12469d01bfac80d","doc":"doc":"doc"2.1","keyfrom":"fanyi.web","action":"FY_BY_REALTlME",}url="http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"#发起POST请求response=requests.post(url=url,headers=headers,data=params).json()print(response)部分是header信息,部分是我们可以看到的params信息,在参数params中除了我们要传递的参数translation外除了内容之外,还有很多我们不知道的参数,如果这里出错了会怎么样呢?改其中一个参数就可以看到效果了,直接返回错误,显然是禁止的,or说验证失败,是非法请求,我们再看一下,只有改变翻译的内容,这些盐和si才能翻译成功性格?原来我们只改了要翻译的内容,结果还是不行。显然,这些验证参数的生成过程与待翻译的内容有关。搜索不同的关键字,请求体参数如下,分析发现除了我们要传递的翻译内容外,还有4个参数是变量:"salt":"16562058896377","sign":"f85458213e7db4207f135599c7ddfac7","lts":"1656205889637","bv":"bdc0570a34c12469d01bfac66273680d",这些是请求salt和校验参数,有对应的加密格式。接下来,我们将破解这四个参数。接下来我们打开控制台,打开我们要分析的JS程序,直接ctrl+f全局搜索salt关键字。找到我们要分析的地方,然后设置断点,重新请求。F10逐步执行。当执行到图中所示的位置时,我们将鼠标移动到对象r的位置。我们为什么要看这个对象?因为可以看到后面的salt、sign、lts、bv等参数都属于对象的r属性。我们可以看到此时r对象的这些属性已经被赋值了。然后看看这个r是什么。varr=function(e){vart=n.md5(navigator.appVersion),r=""+(newDate).getTime(),i=r+parseInt(10*Math.random(),10);返回{ts:r,bv:t,salt:i,sign:n.md5("fanyideskweb"+e+i+"Ygy_4c=r#e#4EX^NUGUc5")}};进一步分析发现:r:当前时间戳。i:当前时间戳+(0到10的随机数)。盐:盐=我。e:搜索关键字。符号:md5("fanyideskweb"+e+i+"Ygy_4c=r#e#4EX^NUGUc5")。至此,签名算法的实现就完成了,接下来就可以通过python来实现了。代码如下:importrequestsfromhashlibimportmd5importtimeimportrandom#请请求地址url="http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"appVersion="Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/102.0.0.0Safari/537.36"headers={"Accept":"application/json,text/javascript,*/*;q=0.01","Accept-Encoding":"gzip,deflate","Accept-Language":"zh-CN,zh;q=0.9","Connection":"keep-alive","Content-Length":"244","Content-Type":"application/x-www-form-urlencoded;charset=UTF-8","Cookie":"OUTFOX_SEARCH_USER_ID=-1506602845@10.169.0.82;JSESSIONID=aaaUggpd8kfhja1AIJYpx;OUTFOX_SEARCH_USER_ID_NCOO=108436537.92676207;___rl__test__cookies=1597502296408","Host":"fanyi.有道网","Origin":"http://fanyi.youdao.com","Referer":"http://fanyi.youdao.com/","user-agent":appVersion,"X-Requested-With":"XMLHttpRequest",}defr(e):#bvt=md5(appVersion.encode()).hexdigest()#ltsr=str(int(time.time()*1000))#ii=r+str(random.randint(0,9))return{"ts":r,"bv":t,"salt":i,"sign":md5(("fanyideskweb"+e+i+"Ygy_4c=r#e#4EX^NUGUc5").encode()).hexdigest()}deffanyi(word):data=r(word)params={"i":word,"from":"AUTO","to":"AUTO","smartresult":"dict","client":"fanyideskweb","salt":数据["salt"],"sign":数据["sign"],"lts":数据["ts"],"bv":数据["bv"],"doctype":"json","version":"2.1","keyfrom":"fanyi.web","action":"FY_BY_REALTlME",}response=requests.post(url=url,headers=headers,data=params)#返回json数据returnresponse.json()if__name__=="__main__":whileTrue:word=input("请输入要翻译的句子:")result=fanyi(word)#提取返回的json数据,Extract我们需要的数据r_data=result["translateResult"][0]打印(r_data[0]["src"])打印(r_data[0]["tgt"])