1. 逆向工程入门:理解mtgsig 1.1与H5guard
第一次接触某团商家后台的加密参数时,我和大多数逆向新手一样感到无从下手。mtgsig 1.1参数就像一扇紧闭的大门,而H5guard算法则是门口凶猛的看门狗。经过多次实战,我发现这套加密机制主要包含三个关键部分:版本标识(a1)、时间戳(a2)和动态生成的加密字符串(a3/a5/a6)。其中a3与用户会话相关,a5和a6则是核心加密结果。
在最新抓包数据中,mtgsig参数通常呈现这样的结构:
json复制{
"a1":"1.1",
"a2":1741916388817,
"a3":"z0u89y82y7xw599w021x55v507v835448057y35v7uw9795864z8z9zu",
"a5":"Th0orxZzYh0ZXe+pBUBrPj+76C/HwcrP",
"a6":"h1.5z8Lbkh4D/SJax6K/k+Zd9u+3R4tPZU3wbPUHiGt/LyvmIf/fUTjT3yqkuOjCpsY7HzaCmgkUvrWOaiSyB/Rpz166brpcXHldVTwITgaT47mFCZCtQerceGUDaFEU2Dp7dECDUFJjS3UFV0A81ULHxY2ZwrOvOasJZo+K+ht4ftU0B2MxsfeFQxKhH2jVswdorFMpx7yAXHT4qvGC19d5RXEcNMv/YD6Ar4j2dozKkjED2isCXXDSmnTFejxYJ1OHatJaeoyBUynvqQTJvnTW9APzB81UWQq7MUx36uaaCjoiuvMCJYMkJg96JwSheMRB38a36cOnLa7oE0LQksGOwApM+N420Xkyxw2a89mh4SNqXGKeNeTjJAWf5in4+HVC7L39K56s1gpHnsPl1H9PQA==",
"x0":4,
"d1":"44339d845fc1562ef39a80651bf2cbae"
}
2. 环境检测与反爬机制破解
2.1 关键环境对象检测
某团的H5guard会像侦探一样检查浏览器环境,主要关注这些对象:
- window/navigator:检测标准浏览器API是否存在
- location:验证页面URL是否符合预期
- performance:检查时间相关函数的调用痕迹
- screen:核对屏幕分辨率等硬件信息
我在Node.js中补环境的配置如下:
javascript复制const jsdom = require("jsdom");
const {JSDOM} = jsdom;
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`, {
url: "https://h5.waimai.meituan.com/waimai/mindex/home",
runScripts: 'dangerously'
})
window = dom.window;
document = window.document;
navigator = window.navigator = {
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X)'
};
// 必须精确配置的location对象
location = {
href: "https://h5.waimai.meituan.com/waimai/mindex/home",
origin: "https://h5.waimai.meituan.com",
hostname: "h5.waimai.meituan.com"
};
2.2 控制流混淆处理
H5guard的JavaScript代码经过多重混淆:
- 变量名替换为无意义的短字符
- 插入大量无效控制流
- 关键逻辑分散在多个函数块
我常用的破解方法是:
- 使用AST解析工具还原代码结构
- 在关键函数入口插入console.log
- 通过调用栈回溯参数传递路径
例如这段典型控制流:
javascript复制function _0x12ab(a,b) {
return (a << b) | (a >>> (32 - b));
}
// 实际是标准的左循环移位操作
3. 加密参数生成全流程
3.1 参数a3的生成逻辑
a3参数实际上是多个环境变量的组合产物:
- 从cookie中提取特定字段
- 混合设备指纹信息
- 经过自定义哈希运算
实测生成过程需要这些步骤:
javascript复制function generateA3() {
const cookieStr = document.cookie;
const deviceFingerprint = getDeviceFP();
return md5(cookieStr + deviceFingerprint).slice(0, 32);
}
3.2 a5/a6核心加密过程
这两个参数才是真正的难点,其生成涉及:
- RSA公钥加密基础参数
- AES加密中间结果
- 最后进行Base64编码
关键代码段示例:
javascript复制const crypto = require('crypto');
function encryptA5(plainText) {
const publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA${keyData}...
-----END PUBLIC KEY-----`;
return crypto.publicEncrypt(
{key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING},
Buffer.from(plainText)
).toString('base64');
}
4. Node.js完整实现方案
4.1 补环境注意事项
在Node.js中完美模拟浏览器环境需要特别注意:
- 定时器函数(setTimeout/setInterval)的重写
- DOM事件系统的模拟
- 内存泄漏的预防措施
这是我总结的必备补丁:
javascript复制// 修复定时器问题
const originalSetInterval = setInterval;
setInterval = (fn, delay) => {
const timer = originalSetInterval(fn, delay);
process.on('exit', () => clearInterval(timer));
return timer;
};
// 补全缺失的浏览器API
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = (cb) => setTimeout(cb, 16);
}
4.2 完整调用链实现
最终可运行的完整流程应该是:
- 初始化补环境
- 加载H5guard.js
- 调用加密入口函数
- 验证输出结果
核心调用示例:
javascript复制const H5guard = require('./H5guard.patched.js');
function getMtgsig(params) {
H5guard.init(); // 必须初始化
const result = H5guard.encrypt(JSON.stringify(params));
return {
a1: '1.1',
a2: Date.now(),
a3: generateA3(),
a5: result.cipherText,
a6: result.signature,
x0: 4,
d1: md5(params)
};
}
在逆向过程中最常遇到的坑是环境检测不完整,比如漏掉了window.outerWidth这样的属性检测。建议大家在开发时准备好浏览器环境快照工具,将真实环境的所有属性记录下来逐个比对补全。