声明
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
逆向目标
- 目标:某建设部&某市场监管公共服务平台的企业数据
- 主页:aHR0cDovL2p6c2MubW9odXJkLmdvdi5jbi9kYXRhL2NvbXBhbnk=
- 接口:aHR0cDovL2p6c2MubW9odXJkLmdvdi5jbi9hcGkvd2ViQXBpL2RhdGFzZXJ2aWNlL3F1ZXJ5L2NvbXAvbGlzdD9wZz0lcyZwZ3N6PTE1JnRvdGFsPTQ1MA==
- 逆向参数:请求返回的加密数据
逆向过程
本次的逆向目标是某市场监管平台的企业数据,来到某市场监管公共服务平台首页,依次点击数据服务 —> 企业数据,尝试抓包一下所有企业的数据,可以看到返回的数据是经过加密的:
数据看不出来是什么加密方式,但是加密分析得多了,就知道一般都是经过 CryptoJS
加密模块加密得到的,那么我们可以尝试直接搜索 CryptoJS
,decrypt
等关键字,或者搜索加密算法中经常用到的偏移量 iv
、模式 mode
、填充方式 padding
等,还有一般的 JSON 数据可以搜索 JSON.parse
等,这里直接搜索 JSON.parse
,在 app.a9f6bb6d.js 文件里定位到可疑代码,埋下断点进行调试:
可以看到 e 就是解密后的数据,观察语句 var e = JSON.parse(h(t.data));
,直接跟进 h 函数,可以看到很明显的 AES 加密:
function h(t) {
var e = d.a.enc.Hex.parse(t)
, n = d.a.enc.Base64.stringify(e)
, a = d.a.AES.decrypt(n, f, {
iv: m,
mode: d.a.mode.CBC,
padding: d.a.pad.Pkcs7
})
, r = a.toString(d.a.enc.Utf8);
return r.toString()
}
加密模式为 CBC,填充方式为 Pkcs7,而缺少的偏移量 m、f 的值,在上面也可以找到:
f = d.a.enc.Utf8.parse("jo8j9wGw%6HbxfFn")
m = d.a.enc.Utf8.parse("0123456789ABCDEF")
在 Python 当中,直接引入 CryptoJS,重写这个函数即可。
完整代码
GitHub 关注 K 哥爬虫:https://github.com/kuaidaili ,持续分享爬虫相关代码!欢迎 star !
以下只演示部分关键代码,完整代码仓库地址:https://github.com/kuaidaili/crawler/
参数 JS 加密关键代码
// 引用 crypto-js 加密模块
var CryptoJS = require('crypto-js')
function getDecryptedData(t) {
var m = CryptoJS.enc.Utf8.parse("0123456789ABCDEF"),
f = CryptoJS.enc.Utf8.parse("jo8j9wGw%6HbxfFn"),
e = CryptoJS.enc.Hex.parse(t),
n = CryptoJS.enc.Base64.stringify(e),
a = CryptoJS.AES.decrypt(n, f, {
iv: m,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}),
r = a.toString(CryptoJS.enc.Utf8);
return r.toString()
}
// 测试样例
// var t = '95780ba094xxxxxxxxxx'
// console.log(getDecryptedData(t))
Python 关键代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import execjs
import requests
data_url = '脱敏处理,完整代码关注 GitHub:https://github.com/kuaidaili/crawler/'
def get_encrypted_data(page):
headers = {
'Host': '脱敏处理,完整代码关注 GitHub:https://github.com/kuaidaili/crawler/',
'Referer': '脱敏处理,完整代码关注 GitHub:https://github.com/kuaidaili/crawler/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
encrypted_data = requests.get(url=data_url % page, headers=headers).text
return encrypted_data
def get_decrypted_data(encrypted_data):
with open('jzsc_mohurd_decrypt.js', 'r', encoding='utf-8') as f:
jzsc_mohurd_js = f.read()
decrypted_data = execjs.compile(jzsc_mohurd_js).call('getDecryptedData', encrypted_data)
return json.loads(decrypted_data)
def main():
# 30页数据
for page in range(30):
encrypted_data = get_encrypted_data(page)
decrypted_data = get_decrypted_data(encrypted_data)
print(decrypted_data)
if __name__ == '__main__':
main()