Web爬虫处理参数js加密、js混淆、js逆向

鳄鱼君

发表文章数:642

Vieu四代商业主题

高扩展、安全、稳定、响应式布局多功能模板。

¥69 现在购买
首页 » Python » Web爬虫处理参数js加密、js混淆、js逆向

中国空气质量在线监测平台(https://www.aqistudy.cn/html/city_detail.html)在众多的练习中,关闭了前台数据信息的展示,也就是说现在网页是这样的:

Web爬虫处理参数js加密、js混淆、js逆向

但我们主要学习的是如何应对js加密,而不是数据,前者学会了,数据哼!这个网站使用了js对参数进行了加密,js加密的过程还进行了混淆,我们根本看不懂,但是我们可以使用一些js反混淆平台,对js代码进行反混淆,你可以直接百度搜索在线js反混淆。反混淆我们也不可能实现参数的重构,还需要借助它本身的js代码来进行参数解密,所以这里使用PyExecJS 库来实现模拟JavaScript代码执行获取动态加密的请求参数,然后再将加密的响应数据带入decodeData进行解密即可!后面用到在详细说明。

对于所有的爬虫来说,发送一个请求,参数是最关键的吗。一般来说网站都会对个别参数进行处理,让你不能随随便便就知道参数拿来的,你可以看一这篇文章:Web端虾米音乐爬虫实战分析 处理参数JS加密,它就是简单的对参数做了一个md5加密,这个我们可以重构参数,也比较简单。

想要完全理解中国空气质量在线监测平台的加密方式,你需要补充一些ajax的知识。我们在它首页进行简单的搜索,你可以看到页面不刷新,但是发送了请求,那么说明网站使用的是ajax或者是jQuery发送的请求。我们需要对此进行分析。

Web爬虫处理参数js加密、js混淆、js逆向

关键就是参数d的来源,我们需要知道它是如何生成的。对于搜索按钮,绑定了click的点击事件才会发送请求,所有我们从这个click点击事件来突破。通过火狐浏览器查找click事件的函数,然后使用chrome浏览器进行全局搜索(万能)查看:

Web爬虫处理参数js加密、js混淆、js逆向
Web爬虫处理参数js加密、js混淆、js逆向

谷歌的全局搜索非常好用,我们直接搜索click事件的函数getData,然后再这几个js文件中进行分析,这就需要要求你能看懂一点点js代码才行。这里搜索出了4个js文件,那么可以简单看一下,先看function getData()这个函数,发现它里面没有值得关注的代码,但是看到了两个函数getAQIData()、getWeatherData()

Web爬虫处理参数js加密、js混淆、js逆向

getData函数内部调用了getAQIData()和getWeatherData(),正好就在下面,我们可以简单看一下。在getAQIData()和getWeatherData()两个函数内部都调用了getServerData函数,这个函数非常的特别,代码不简单呐,现在刷新一下页面然后全局搜一下getServerData方法,结果如图:

Web爬虫处理参数js加密、js混淆、js逆向

你应该会毫不犹豫的打开jQuery中的getServerData函数吧!然后再这个js文件中定位它,你会发现它都是一些数字加|的代码,getServerData就在中间,其它的都看不懂。其实这里是经过 JavaScript 混淆加密了,混淆加密之后,代码将变为不可读的形式,但是功能是完全一致的,这是一种常见的 JavaScript 加密手段。我们想要查看到该方法的原始实现则必须对其进行反混淆。

反混淆:JavaScript 混淆之后,其实是有反混淆方法的,最简单的方法便是搜索在线反混淆网站,在这里不提供网址(https://beautifier.io/),网址可能会挂掉,所以你自己百度搜索一下。我们可以将getServerData存在的这行数据粘贴到反混淆的网站中。

Web爬虫处理参数js加密、js混淆、js逆向

在反混淆后,我们很清晰的看到了ajax请求发送的实现。然后还看到了ajax对应post请求的动态加密请求参数的加密方法getParam(),并且将method和object作为了函数的参数。method和object是从getServerData函数的参数中获取的,那么getServerData函数中的method和object表示的是什么呢?我们需要回过头去查看刚才调用getServerData的函数getAQIData和getData,这里发现method是固定形式字符串,object就是param是一个字典,里面存储了三组键值对city表示查询城市名称,startTime和endTime为查询起止时间,type表示为HOUR:

Web爬虫处理参数js加密、js混淆、js逆向

getParam()函数中的两个参数的表示含义我们已经清楚了。getParam函数的返回值就是ajax对应post请求的动态加密请求参数了,我们需要定位到其函数内部的实现,看看是如何对请求参数进行加密的。在getServerData中我们发现了ajax请求对应的操作代码,其中还有一个非常重要的一步,就是ajax请求成功后的回调函数实现内部,接受到了响应数据data,data我们知道是一组密文数据,然后调用了decodeData对data进行了解密操作

function decodeData(data) {
    data = AES.decrypt(data, aes_server_key, aes_server_iv);
    data = DES.decrypt(data, des_key, des_iv);
    data = BASE64.decrypt(data);
    return data
}

在getParam函数内部使用了 Base64 和 AES 对param进行加密。加密之后的字符串便作为ajax对应post的请求参数传送给服务器了。

现在我们呢知道了加密方法,那么现在应该有两种方式解决:

一、可以将js函数改写为Python函数
 
二、使用相关模块进行js逆向。
PyExecJS 是一个可以使用 Python 来模拟运行 JavaScript 的库。我们需要pip install PyExecJS对其进行环境安装。除此之外还需要安装nodejs的开发环境。
Web爬虫处理参数js加密、js混淆、js逆向

这里我喜欢第二种方式,那么首先需要安装PyExecJs,接着需要将待执行的js函数全部定义存储到一个js文件中,模拟执行js源文件的js函数。加载js源文件中的代码并将其重新编译,在这里需要在刚才反混淆的代码中定义一个函数getPostParamCode,它接收五个参数,参数我们在前面的getAQIData函数可以知道是什么:

function getPostParamCode(method, city, type, startTime, endTime){
    var param = {};
    param.city = city;
    param.type = type;
    param.startTime = startTime;
    param.endTime = endTime;
    return getParam(method, param);
}
#使用模块进行js逆向,模拟调用js源文件(test.js)中的getParams函数获取动态变化的加密之后的参数
import execjs
import os

os.environ["EXECJS_RUNTIME"] = 'Phantomjs'

# 实例化一个对象
node=execjs.get()
#params参数
method='GETDETAIL'
city='北京'
type='HOUR'
start_time='2020-05-08 00:00:00'
end_time='2020-05-08 23:00:00'

file='test.js' #待加载编译的js源文件
# 加载编辑js源文件中的js代码
ctx = node.compile(open(file,encoding='utf-8').read())
# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js) #eval表示模拟执行编译好的js函数
print(params)  #返回的是加密变化的参数

这里的test.js文件,你可以直接把反混淆过的jquery全部拿过来。如果运行代码报错:execjs._exceptions.RuntimeError: SyntaxError: 语法错误,需要修改node的驱动,默认是JScript:

import execjs
import os
# os.environ["EXECJS_RUNTIME"] = 'Phantomjs'
node = execjs.get()

到此我们已经成功的构造出d参数,那么一切就变得简单了,再使用reuqests携带上参数发送post请求就可以获取数据,只需要在上面的代码中添加一下发送请求的代码即可:

#发起post请求
url = 'https://www.aqistudy.cn/apinew/aqistudyapi.php'
response_text = requests.post(url, data={'d': params}).text
print(response_text)

#对加密的响应数据进行解密
js = 'decodeData("{0}")'.format(response_text)
decrypted_data = ctx.eval(js)
print(decrypted_data)

由于网站已经崩了,所以数据不重要了,主要的是如何应对js加密,你学会了吗!

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《Web爬虫处理参数js加密、js混淆、js逆向》 发布于2020-05-08

分享到:
赞(1) 赏杯咖啡

评论 抢沙发

5 + 6 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册