微信小程序逆向

学习目标:

  1. 熟悉 微信小程序逆向
  2. 熟悉 webpack模块导出
  3. 熟悉 开发者工具检测
1
本教程仅供学习交流使用,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,请各学员自觉遵守相关法律法规。

一. 小程序逆向

1. 准备工具

  • 注: 会有封号微信,用小号调试

  • WeChatOpenDevTools 工具包(git地址:https://github.com/JaveleyQAQ/WeChatOpenDevTools-Python)

  • 微信pc端安装(注:由于版本的问题要是不能用使用课堂上提供的工具)

  • 安装好WeChatOpenDevTools 工具需要用的py

  • 进入到文件解压地址

1
pip3  install -r requirements.txt
  • 开启工具启动注入端(自动打开微信进行登录,要是关闭的话用课堂提供的配套安装包)
1
python main.py -all

2. 逆向案例

  • 小程序:六六找房
  • 需求:解析请求头关键字:Authorization

3. 逆向代码

  • python代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
import execjs

js = execjs.compile(open('demo.js', encoding='utf-8').read())

Authorization = js.call('generate', "/v5/search/bed", "GET")
print(Authorization)
headers = {
"Authorization": Authorization,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) XWEB/8555",
"xweb_xhr": "1"
}
url = "https://apiservices.zuber.im/client/v5/search/bed"
params = {"city": "长沙", "sequence": "WyI5NDI2LjUwMDE1NDgxNjEwNCIsIjE2ODY0Njg4MzUiLCJ6dWJlcl82NTI3NTIiXQ==", "sex": "",
"cost1": "", "cost2": "", "longitude": "112.861160", "latitude": "28.198201", "region": "", "distance": "",
"stations": "", "room_type_affirm": "", "has_video": "", "layout_single_private_bathroom": "", "elevator": "",
"separate": "", "tenancy": "", "free": "", "pay_type": "", "has_photo": 1, "entireTenancy1": "",
"entireTenancy2": "", "entireTenancy3": "", "jointRent0": "", "try_rent": "", "pet_limit": "",
"isShowFilterShield": 0}
response = requests.get(url, headers=headers, params=params)

print(response.text)
print(response)

  • node代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

// 引用 crypto-js 加密模块
var CryptoJS = require('crypto-js')

function MD5Test(text) {
return CryptoJS.MD5(text).toString()
}

var timeStamp = function timeStamp() {
return Math.round(new Date().getTime() / 1000);
};

function generate(route, method, params) {
var _timestamp = timeStamp();
// var _timestamp = '1713771957';

var _secret = '';

var _oauth = MD5Test(_timestamp);
console.log(_oauth)
var _method = method ? method.toLowerCase() : 'get';

var _params = '{}';

var _url = "client" + route;

var _source = "request_url=".concat(_url, "&content=").concat(_params, "&request_method=").concat(_method, "&timestamp=").concat(_timestamp, "&secret=").concat(_secret ? _secret : '');
console.log(_source)
var _signature = MD5Test(_source);

return "timestamp=".concat(_timestamp, ";oauth2=").concat(_oauth, ";signature=").concat(_signature, ";scene=").concat('2567a5ec9705eb7ac2c984033e06189d', ";deployKey=").concat('');
}

aa = {
"city": "长沙",
"sequence": "WyI5NDI2LjUwMDE1NDgxNjEwNCIsIjE2ODY0Njg4MzUiLCJ6dWJlcl82NTI3NTIiXQ==",
"sex": "",
"cost1": "",
"cost2": "",
"longitude": "112.861160",
"latitude": "28.198201",
"region": "",
"distance": "",
"stations": "",
"room_type_affirm": "",
"has_video": "",
"layout_single_private_bathroom": "",
"elevator": "",
"separate": "",
"tenancy": "",
"free": "",
"pay_type": "",
"has_photo": 1,
"entireTenancy1": "",
"entireTenancy2": "",
"entireTenancy3": "",
"jointRent0": "",
"try_rent": "",
"pet_limit": "",
"isShowFilterShield": 0
}

console.log(generate("/v5/search/bed", "GET"));

// timestamp=1713771957;oauth2=124238c16aae99245e53f8c62f38d08a;signature=48e2bb445b344e78d30a5ece6a3e9862;scene=2567a5ec9705eb7ac2c984033e06189d;deployKey=
// timestamp=1713771957;oauth2=124238c16aae99245e53f8c62f38d08a;signature=48e2bb445b344e78d30a5ece6a3e9862;scene=2567a5ec9705eb7ac2c984033e06189d;deployKey=

二. webpack导包文件

1.逆向目标:

2. 逆向分析

  • 关键字定位,解析w参数
  • 批量扣模块方式,下断点刷新页面
  • 进入到加载器内部,删除缓存的模块包让他能进入执行代码
  • 清空缓存的模块r = {}
  • 在给一个参数用来接受的模块参数
  • 在当前位置下一个条件断点,这个代码没有断点的作用给的条件是0,作用就是把方法都收集到aaa当中
  • aaa[n]=e[n], 0
  • 在到方法下面下个断点就能把所有的方法进行收集
  • 把所有方法都收集下来
1
result = '{'; for(let x of Object.keys(aaa)){result = result + '"' + x + '"' + ":" + aaa[x] + ','}; result = result + '}'

注意: 复制下来代码的\n需要去除一下, 很多情况下格式也会有问题,要注意排除

三. 网站监听调试工具

1. 了解关闭窗口方式

2. 案例1

  • https://landchina.com/#/givingNotice

  • 通过脚本断点的方式让页面停止

  • 要是看到控制台有输出,清空控制台多半是console.clear()方法 可以追踪当前这个方法看看在哪里有调用

  • 可以通过脚步的方式来进行断点

  • 替换文件把内容置空

  • 替换文件在注释代码

3. 案例2