爬取小程序加密数据
背景是由于杭州的房地产数据,由于部分时段,官网做了人机处理没爬取到数据,所以需要用其他数据源来补充一下。
数据缺失部分
杭房数据
找了挺久,找到了一款「杭房数据」的微信小程序,数据还比较全,也是拿的官方数据,所以,就简单做个抓取并补充数据。
抓取数据
起个 charles 抓包,但可以看到下述的数据是加密的,这就比较麻烦,还要看小程序的解密逻辑。
小程序解密逻辑
找到小程序对应的代码
参考 https://blog.csdn.net/qq_39408664/article/details/130824133 得知,微信小程序的打包后缀为 “*.wxapkg”,所以,因为是 Mac,不知道具体路径,所以直接在用户目录扫描找找相关的文件:
~ find . -name "*.wxapkg"
...
find: ./Library/Suggestions: Operation not permitted
find: ./Library/Weather: Operation not permitted
find: ./Library/Group Containers/group.com.apple.secure-control-center-preferences: Operation not permitted
./Library/Group Containers/5A4RE8SF68.com.tencent.xinWeChat/Library/Caches/xinWeChat/58d5d9406c746f0cf847b9ca34f96a2b/WeApp/LocalCache/release/wx451aea80e5b4bae8/29.wxapkg
./Library/Group Containers/5A4RE8SF68.com.tencent.xinWeChat/Library/Caches/xinWeChat/58d5d9406c746f0cf847b9ca34f96a2b/WeApp/LocalCache/release/wx7765bb88a39ee9cb/239.wxapkg
...
成功找到本地对应的小程序包后,就需要确认具体是哪个包文件,方案也很简单
# 打开当前目录
$ open "./Library/Group Containers/5A4RE8SF68.com.tencent.xinWeChat/Library/Caches/xinWeChat/58d5d9406c746f0cf847b9ca34f96a2b/WeApp/LocalCache/release/"
# 1、删除所有小程序包
# 2、在微信中,重新开启对应的小程序
# 3、新创建的文件,就是当前要的小程序包
如下图所示:
反编译
其实没有网上 windows 反编译那么麻烦,我们不需要目录结构这些,只需要看对应的加密、解密逻辑即可,所以我们直接用 vscode 打开即可,搜索对应的关键词。
并把对应的 define 模块复制格式化出来:
define(
'A2DD5C571C1F6DDFC4BB345019095B64.js',
function (
require,
module,
exports,
window,
document,
frames,
self,
location,
navigator,
localStorage,
history,
Caches,
screen,
alert,
confirm,
prompt,
XMLHttpRequest,
WebSocket,
Reporter,
webkit,
WeixinJSCore
) {
'use strict'
var e = require('@babel/runtime/helpers/interopRequireDefault.js').default
Object.defineProperty(exports, '__esModule', { value: !0 }),
(exports.default = void 0)
var t = e(require('miniprogram_npm/crypto-js/index.js')),
r = e(require('miniprogram_npm/dayjs/index.js')),
a = {
watermarkText: '杭房数据',
resUrl: 'https://res.hangfang-data.com',
baseUrl: 'https://api.hangfang-data.com',
refreshSetting: {
shake: !1,
height: 70,
text: { color: '#969799', shadow: 5 }
},
loadMoreSetting: {
color: '#969799',
shake: !1,
status: 'loading',
more: { text: '上拉加载更多', color: '#969799' },
loading: { text: '加载中···', color: '#969799' },
noMore: { text: '-- 没有更多了 --', color: '#969799' }
},
systemInfo: function () {
var e = wx.getSystemInfoSync()
return {
height: (750 * e.windowHeight) / e.windowWidth,
brand: e.brand,
model: e.model,
system: e.system,
version: e.version,
platform: e.platform
}
},
aesDecrypt: function (e) {
var a = (0, r.default)().add(-4, 'hour').format('YYYYMMDD')
a = t.default.MD5(a).toString()
var o = (0, r.default)().add(-4, 'hour').format('YYYYMMDD')
;(o = (o = t.default.MD5(o).toString()).substring(8, 24)),
(a = t.default.enc.Utf8.parse(a)),
(o = t.default.enc.Utf8.parse(o))
var d = t.default.AES.decrypt(e, a, {
iv: o,
mode: t.default.mode.CBC,
padding: t.default.pad.Pkcs7
})
return JSON.parse(d.toString(t.default.enc.Utf8))
}
}
exports.default = a
}
)
总体结构比较清晰,也比较简单,就是使用当前时间作为秘钥来做解密。
核心解密逻辑
import dayjs from 'dayjs'
import crypto from 'crypto-js'
function dec (e) {
var a = dayjs().add(-4, 'hour').format('YYYYMMDD')
a = crypto.MD5(a).toString()
var o = dayjs().add(-4, 'hour').format('YYYYMMDD')
;(o = (o = crypto.MD5(o).toString()).substring(8, 24)),
(a = crypto.enc.Utf8.parse(a)),
(o = crypto.enc.Utf8.parse(o))
var d = crypto.AES.decrypt(e, a, {
iv: o,
mode: crypto.mode.CBC,
padding: crypto.pad.Pkcs7
})
return JSON.parse(d.toString(crypto.enc.Utf8))
}
小程序解密数据样例
选取一个小数据量的接口
做相关的解密操作:
小结
从这次小程序的数据爬取中,比较有意思的解密部分的逻辑,有比较大的参考意义,可以作为后续简单的加密操作。
但同时也可以看到,由于 JS 本身就是脚本语言,所以整体的程序安全性是有待加强的。