`
zhimaruanjian
  • 浏览: 32667 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

芝麻HTTP:JavaScript加密逻辑分析与Python模拟执行实现数据爬取

 
阅读更多

本节来说明一下 JavaScript 加密逻辑分析并利用 Python 模拟执行 JavaScript 实现数据爬取的过程。在这里以中国空气质量在线监测分析平台为例来进行分析,主要分析其加密逻辑及破解方法,并利用 PyExecJS 来实现 JavaScript 模拟执行来实现该网站的数据爬取。

反混淆

JavaScript 混淆之后,其实是有反混淆方法的,最简单的方法便是搜索在线反混淆网站,这里提供一个:http://www.bm8.com.cn/jsConfusion/,我们将 jquery-1.8.0.min.js 中第二行 eval 开头的混淆后的 JavaScript 代码复制一下,然后粘贴到这个网站中进行反混淆,就可以看到正常的 JavaScript 代码了,搜索一下就可以找到 getServerData() 方法了,可以看到这个方法确实发出了一个 Ajax 请求,请求了刚才我们分析到的接口:

 

那么到这里我们又可以发现一个很关键的方法,那就是 getParam(),它接受了 method 和 object 参数,然后返回得到的 param 结果就作为 POST Data 参数请求接口了,所以 param 就是加密后的 POST Data,一些加密逻辑都在 getParam() 方法里面,其方法实现如下:

var getParam = (function () {
        function ObjectSort(obj) {
            var newObject = {};
            Object.keys(obj).sort().map(function (key) {
                newObject[key] = obj[key]
            });
            return newObject
        }
        return function (method, obj) {
            var appId = '1a45f75b824b2dc628d5955356b5ef18';
            var clienttype = 'WEB';
            var timestamp = new Date().getTime();
            var param = {
                appId: appId,
                method: method,
                timestamp: timestamp,
                clienttype: clienttype,
                object: obj,
                secret: hex_md5(appId + method + timestamp + clienttype + JSON.stringify(ObjectSort(obj)))
            };
            param = BASE64.encrypt(JSON.stringify(param));
            return AES.encrypt(param, aes_client_key, aes_client_iv)
        }
    })();

 可以看到这里使用了 Base64 和 AES 加密。加密之后的字符串便作为 POST Data 传送给服务器了,然后服务器再进行解密处理,然后进行逻辑处理,然后再对处理后的数据进行加密,返回了加密后的数据,那么 JavaScript 再接收到之后再进行一次解密,再渲染才能得到正常的结果。

所以这里还需要分析服务器传回的数据是怎样解密的。顺腾摸瓜,很容易就找到一个 decodeData() 方法,其定义如下:

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
    }

 嗯,这里又经过了三层解密,才把正常的明文数据解析出来。

所以一切都清晰了,我们需要实现两个过程才能正常使用这个接口,即实现 POST Data 的加密过程和 Response Data 的解密过程。其中 POST Data 的加密过程是 Base64 + AES 加密,Response Data 的解密是 AES + DES + Base64 解密。加密解密的 Key 也都在 JavaScript 文件里能找到,我们用 Python 实现这些加密解密过程就可以了。

所以接下来怎么办?接着刚啊!

接着刚才怪!

何必去费那些事去用 Python 重写一遍 JavaScript,万一二者里面有数据格式不统一或者二者由于语言不兼容问题导致计算结果偏差,上哪里去 Debug?

那怎么办?这里我们借助于 PyExecJS 库来实现 JavaScript 模拟就好了。

PyExecJS

PyExecJS 是一个可以使用 Python 来模拟运行 JavaScript 的库。大家可能听说过 PyV8,它也是用来模拟执行 JavaScript 的库,可是由于这个项目已经不维护了,而且对 Python3 的支持不好,而且安装出现各种问题,所以这里选用了 PyExecJS 库来代替它。

首先我们来安装一下这个库:

pip install PyExecJS

 使用 pip 安装即可。

在使用这个库之前请确保你的机器上安装了以下其中一个JS运行环境:

  • JScript
  • JavaScriptCore
  • Nashorn
  • Node
  • PhantomJS
  • PyV8
  • SlimerJS
  • SpiderMonkey

PyExecJS 库会按照优先级调用这些引擎来实现 JavaScript 执行,这里推荐安装 Node.js 或 PhantomJS。

接着我们运行代码检查一下运行环境:

import execjs
print(execjs.get().name)

 运行之后,由于我安装了 Node.js,所以这里会使用 Node.js 作为渲染引擎,结果如下:

Node.js (V8)

 接下来我们将刚才反混淆的 JavaScript 保存成一个文件,叫做 encryption.js,然后用 PyExecJS 模拟运行相关的方法即可。

首先我们来实现加密过程,这里 getServerData() 方法其实已经帮我们实现好了,并实现了 Ajax 请求,但这个方法里面有获取 Storage 的方法,Node.js 不适用,所以这里我们直接改写下,实现一个 getEncryptedData() 方法实现加密,在 encryption.js 里面实现如下方法:

function getEncryptedData(method, city, type, startTime, endTime) {
    var param = {};
    param.city = city;
    param.type = type;
    param.startTime = startTime;
    param.endTime = endTime;
    return getParam(method, param);
}

 接着我们模拟执行这些方法即可:

import execjs

# Init environment
node = execjs.get()

# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2018-01-25 00:00:00'
end_time = '2018-01-25 23:00:00'

# Compile javascript
file = 'encryption.js'
ctx = node.compile(open(file).read())

# Get params
js = 'getEncryptedData("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)

 这里我们首先定义一些参数,如 method、city、start_time 等,这些都可以通过分析 JavaScript 很容易得出其规则。

然后这里首先通过 execjs(即 PyExecJS)的 get() 方法声明一个运行环境,然后调用 compile() 方法来执行刚才保存下来的加密库 encryption.js,因为这里面包含了一些加密方法和自定义方法,所以只有执行一遍才能调用。

接着我们再构造一个 js 字符串,传递这些参数,然后通过 eval() 方法来模拟执行,得到的结果赋值为 params,这个就是 POST Data 的加密数据。

接着我们直接用 requests 库来模拟 POST 请求就好了,也没必要用 jQuery 自带的 Ajax 了,当然后者也是可行的,只不过需要加载一下 jQuery 库。

接着我们用 requests 库来模拟 POST 请求:

# Get encrypted response text
api = 'https://www.aqistudy.cn/apinew/aqistudyapi.php'
response = requests.post(api, data={'d': params})

 这样 response 的内容就是服务器返回的加密的内容了。

接下来我们再调用一下 JavaScript 中的 decodeData() 方法即可实现解密:

# Decode data
js = 'decodeData("{0}")'.format(response.text)
decrypted_data = ctx.eval(js)

 这样 decrypted_data 就是解密后的字符串了,解密之后,实际上是一个 JSON 字符串:

{'success': True, 'errcode': 0, 'errmsg': 'success', 'result': {'success': True, 'data': {'total': 22, 'rows': [{'time': '2018-01-25 00:00:00', 'temp': '-7', 'humi': '35', 'wse': '1', 'wd': '东北风', 'tq': '晴'}, {'time': '2018-01-25 01:00:00', 'temp': '-9', 'humi': '38', 'wse': '1', 'wd': '西风', 'tq': '晴'}, {'time': '2018-01-25 02:00:00', 'temp': '-10', 'humi': '40', 'wse': '1', 'wd': '东北风', 'tq': '晴'}, {'time': '2018-01-25 03:00:00', 'temp': '-8', 'humi': '27', 'wse': '2', 'wd': '东北风', 'tq': '晴'}, {'time': '2018-01-25 04:00:00', 'temp': '-8', 'humi': '26', 'wse': '2', 'wd': '东风', 'tq': '晴'}, {'time': '2018-01-25 05:00:00', 'temp': '-8', 'humi': '23', 'wse': '2', 'wd': '东北风', 'tq': '晴'}, {'time': '2018-01-25 06:00:00', 'temp': '-9', 'humi': '27', 'wse': '2', 'wd': '东北风', 'tq': '多云'}, {'time': '2018-01-25 07:00:00', 'temp': '-9', 'humi': '24', 'wse': '2', 'wd': '东北风', 'tq': '多云'}, {'time': '2018-01-25 08:00:00', 'temp': '-9', 'humi': '25', 'wse': '2', 'wd': '东风', 'tq': '晴转多云转多云间晴'}, {'time': '2018-01-25 09:00:00', 'temp': '-8', 'humi': '21', 'wse': '3', 'wd': '东北风', 'tq': '晴转多云转多云间晴'}, {'time': '2018-01-25 10:00:00', 'temp': '-7', 'humi': '19', 'wse': '3', 'wd': '东北风', 'tq': '晴转多云转多云间晴'}, {'time': '2018-01-25 11:00:00', 'temp': '-6', 'humi': '18', 'wse': '3', 'wd': '东北风', 'tq': '多云'}, {'time': '2018-01-25 12:00:00', 'temp': '-6', 'humi': '17', 'wse': '3', 'wd': '东北风', 'tq': '多云'}, {'time': '2018-01-25 13:00:00', 'temp': '-5', 'humi': '17', 'wse': '2', 'wd': '东北风', 'tq': '多云'}, {'time': '2018-01-25 14:00:00', 'temp': '-5', 'humi': '16', 'wse': '2', 'wd': '东风', 'tq': '多云'}, {'time': '2018-01-25 15:00:00', 'temp': '-5', 'humi': '15', 'wse': '2', 'wd': '北风', 'tq': '多云'}, {'time': '2018-01-25 16:00:00', 'temp': '-5', 'humi': '16', 'wse': '2', 'wd': '东北风', 'tq': '多云'}, {'time': '2018-01-25 17:00:00', 'temp': '-5', 'humi': '16', 'wse': '2', 'wd': '东风', 'tq': '多云'}, {'time': '2018-01-25 18:00:00', 'temp': '-6', 'humi': '18', 'wse': '2', 'wd': '东风', 'tq': '晴间多云'}, {'time': '2018-01-25 19:00:00', 'temp': '-7', 'humi': '19', 'wse': '2', 'wd': '东风', 'tq': '晴间多云'}, {'time': '2018-01-25 20:00:00', 'temp': '-7', 'humi': '19', 'wse': '1', 'wd': '东风', 'tq': '晴间多云'}, {'time': '2018-01-25 21:00:00', 'temp': '-7', 'humi': '19', 'wse': '0', 'wd': '南风', 'tq': '晴间多云'}]}}}

 大功告成!

这样我们就可以成功获取温度、湿度、风力、天气等信息了。

另外这部分数据其实不全,还有 PM 2.5、AQI 等数据需要用另外一个 method 参数 GETDETAIL,修改一下即可获取这部分数据了。

再往后的数据就是解析和存储了,这里不再赘述。

分享到:
评论

相关推荐

    网络爬虫-如何获取网页中动态加载的验证码图片-Python实例源码.zip

    4. **逆向工程**:对于复杂的动态加载,可能需要对JavaScript代码进行逆向工程,找出生成验证码的逻辑,甚至可能需要解析加密或混淆的代码。这一步骤可能涉及理解JavaScript事件监听、DOM操作等。 Python实例源码...

    芝麻开门博客网.zip

    了解如何使用数据库(如MySQL、MongoDB)存储和检索数据,以及如何实现API接口供前端调用。 3. **前端框架**:利用React、Vue或Angular等现代前端框架,提升开发效率和用户体验。理解组件化开发思想,掌握状态管理...

    校无忧问卷调查系统 v4.0.zip

    2. **后端技术**:后端可能基于PHP、Java、Python或.NET等语言开发,负责处理数据存储、业务逻辑以及与前端的交互。框架可能包括Spring Boot、Django或Node.js等。 3. **数据库管理**:系统可能使用MySQL、...

    校无忧网上选课系统 v1.9.zip

    这部分代码处理用户的请求,执行业务逻辑,如验证用户身份、检查选课冲突、处理选课操作等。开发者可能采用了MVC(Model-View-Controller)架构模式,将业务逻辑、数据模型和用户界面分离,便于维护和扩展。 3. **...

    CC活动报名小程序 v1.0.zip

    3. **后端开发**:对于数据处理和交互,小程序可能采用了Node.js、Python的Django或Flask、Java的Spring Boot等后端技术,实现服务器端逻辑,如用户验证、数据存储和处理报名请求。 4. **数据库管理**:数据库系统...

    启明星员工工资自助查询系统 v1.0.rar

    学生可以深入学习如何实现用户身份验证、权限管理、数据加密、日志记录等功能,理解如何将业务逻辑与视图层分离,以及如何处理并发查询和数据安全问题。 计算机案例中,启明星工资查询系统可能展示了以下几个关键...

    book小说阅读网站 v1.0.zip

    4. **后端开发**:后端可能使用PHP、Python、Node.js等服务器端语言,处理用户请求,与数据库交互,完成如搜索、推荐、评论等业务逻辑。 5. **模板建站**:快速搭建网站的一种方式是使用预设的模板,这可以节省开发...

    MSFM权限管理系统 v1.0.zip

    10. **后端技术**:后端可能使用如Spring Boot、Django、Node.js等框架,处理HTTP请求,执行业务逻辑,并与数据库交互。 11. **安全策略**:系统可能实施多种安全策略,如HTTPS加密通信、CSRF防护、XSS过滤等,以...

    OPEN-MALL电商平台 v1.0.zip

    6. **安全与加密**:电商平台需要保护用户数据,实现HTTPS加密通信,防止SQL注入和跨站脚本攻击。源码中应有相应的安全措施。 7. **性能优化**:高并发访问是电商系统的一大挑战,可能涉及到缓存策略、负载均衡、...

    paascloud商城系统 v2.0.zip

    "paascloud商城系统 v2.0.zip" 是一个包含PaaScloud商城系统源码的压缩包,主要用于软件工具的开发、学习与研究,适用于源码分析、毕业设计论文撰写以及计算机案例研究。这个系统可能是一个基于云计算平台的电子商务...

    网络游戏对战(五子棋)

    这部分通常通过服务器端的后端逻辑来实现,使用编程语言如Python、Java或Node.js。 5. **图形界面**:提供直观、友好的用户界面至关重要。前端开发可能使用HTML5、CSS3和JavaScript,配合React、Vue或Angular等框架...

    魔众盲盒系统 v1.4.0.zip

    这个系统可能包含了各种功能,如用户管理、盲盒商品管理、购买流程、支付集成、库存控制以及数据分析等。下面我们将深入探讨与这个系统相关的IT知识点。 1. **盲盒系统设计**:盲盒系统是一种电子商务平台,用户...

    高校校园生活交友综合型论坛小程序 v1.0.1.zip

    7. **源码阅读与分析**:对于学习者来说,通过阅读源代码可以了解软件架构、模块划分和代码组织,提升编程能力。 8. **项目部署与调试**:从说明文件中学习如何配置环境、部署服务器和数据库,以及调试和测试程序的...

    bee餐饮点餐外卖小程序 v2.0.zip

    开发者需要掌握微信小程序的开发框架WXML(WeiXin Markup Language)和WXSS(WeiXin Style Sheets),以及JavaScript语言来编写业务逻辑。 2. **前端框架与库**:"bee-master"可能是一个前端项目文件夹,通常包含...

    ttltChat在线聊天软件 v0.2.0.zip

    7. **安全性**:软件可能涉及到用户认证与授权机制,如OAuth2.0,以及数据加密,如SSL/TLS协议,以保护用户隐私和数据安全。 8. **多用户同步**:为确保多个用户同时在线时的数据一致性,可能采用了锁机制、队列或...

    乘风下载管理系统 v1.0.zip

    5. 安全机制:考虑到系统涉及到用户数据和文件的交换,安全措施必不可少,可能包括数据加密、防止DDoS攻击、登录验证等。 6. 管理后台:管理员可能通过一个专门的管理界面来维护系统,如添加/删除文件、管理用户...

    linjiashop商城系统 v0.9.zip

    这些后端代码负责处理数据库操作、业务逻辑以及与前端的通信。 3. **数据库设计**:linjiashop可能包含一个关系型数据库(如MySQL或PostgreSQL)的模型,用于存储商品信息、用户数据、订单、支付记录等。数据库设计...

    wenku 类似百度文库的实例 v1.0.zip

    这些源代码通常会涵盖后端服务器的处理逻辑、前端用户界面的HTML、CSS和JavaScript代码,以及可能的数据存储和检索功能。开发者可以通过阅读和研究这些代码来了解如何处理文档上传、下载、搜索和权限管理等功能。 ...

    NGOOS极益开源公益平台 v2.2.zip

    13. **安全性**:开源软件需要特别关注安全,可能包括用户认证、授权机制、数据加密和防止SQL注入等安全措施。 14. **部署与运维**:部署可能涉及到服务器配置、负载均衡、持续集成/持续部署(CI/CD)流程,以及...

    学校实训项目-黑色简洁个性美妆美容培训学校.zip

    这些功能可能需要JavaScript库如jQuery或者更现代的Web API来实现。 8. **数据管理**:如果网站有在线报名或预约功能,可能还需要后端支持,如PHP、Python或Node.js等,以及数据库(如MySQL或MongoDB)来存储和处理...

Global site tag (gtag.js) - Google Analytics