1. 虎牙Web登录加密机制解析
作为一名长期从事Web安全研究的开发者,我最近对虎牙直播的Web端登录流程进行了逆向分析。这个案例非常典型,涉及现代Web应用中常见的两种安全防护:请求签名(appSign)和密码加密(password)。与大多数主流平台类似,虎牙采用前端加密+后端验证的双重机制来提升安全性。
在虎牙的登录流程中,当用户提交账号密码时,前端会执行两个关键操作:
- 对登录请求参数生成唯一的appSign签名
- 对用户原始密码进行不可逆加密处理
这种设计可以有效防止:
- 请求重放攻击(通过动态签名)
- 密码明文传输(即使HTTPS被破解也无法直接获取密码)
- 自动化脚本攻击(签名算法需要执行完整JS逻辑)
重要提示:本文仅用于安全技术研究,所有分析过程均在虎牙直播的公开Web页面进行,未使用任何非公开接口或工具。
2. 逆向工程环境准备
2.1 基础工具链配置
要进行完整的JS逆向分析,我们需要准备以下工具组合:
bash复制# 推荐工具清单
- Chrome DevTools (最新版)
- Fiddler/Charles (网络抓包)
- Node.js v16+ (执行JS环境)
- VsCode + JavaScript调试插件
- WebStorm (可选,用于复杂代码分析)
特别建议使用Chrome的"本地覆盖"功能(Local Overrides),这允许我们直接修改线上JS文件并在本地生效,这对动态调试加密函数极其有用。具体操作路径:
DevTools → Sources → Overrides → 选择本地文件夹 → 启用覆盖
2.2 关键请求捕获
通过抓包工具分析登录流程,我们可以定位到核心请求:
code复制POST https://www.huya.com/login.php
FormData:
username: test@example.com
password: encrypted_string
appSign: 32位哈希值
其中password字段明显经过加密处理,而appSign则是每次请求动态生成的签名值。通过多次请求对比发现,即使相同密码,每次生成的加密结果也不同,说明采用了动态盐值或时间戳等变量参数。
3. appSign签名算法逆向
3.1 签名定位过程
在Chrome DevTools中搜索"appSign"关键词,很快在login.vendor.js文件中发现关键代码段:
javascript复制function generateSign(params) {
const secret = 'hy_web_2023';
let str = Object.keys(params)
.sort()
.map(key => `${key}=${params[key]}`)
.join('&');
return md5(str + secret);
}
这个函数揭示了appSign的生成逻辑:
- 将所有请求参数按key字母排序
- 拼接成key=value&格式的字符串
- 追加固定密钥"hy_web_2023"
- 计算MD5哈希值
3.2 签名算法复现
基于上述分析,我们可以用Node.js复现签名生成:
javascript复制const crypto = require('crypto');
function generateHuyaSign(params) {
const secret = 'hy_web_2023';
const sortedStr = Object.keys(params)
.sort()
.map(k => `${k}=${params[k]}`)
.join('&');
return crypto
.createHash('md5')
.update(sortedStr + secret)
.digest('hex');
}
// 示例用法
const params = {
username: 'test',
timestamp: Date.now()
};
console.log(generateHuyaSign(params));
实际测试发现,虎牙在不同子域名下可能使用不同的secret密钥,遇到签名不通过时需要尝试其他常见密钥变体。
4. password加密机制解析
4.1 加密函数定位
密码加密逻辑比签名更隐蔽,通过搜索"password"关键词,最终在login.core.js中找到加密入口:
javascript复制function encryptPassword(pwd) {
const salt = generateRandomStr(8);
const encrypted = RSA.encrypt(pwd + salt);
return `${salt}$${encrypted}`;
}
这个加密流程分为三个阶段:
- 生成8位随机字符串作为盐值
- 将密码与盐值拼接
- 使用RSA公钥加密组合字符串
- 返回"盐值$加密结果"格式
4.2 RSA公钥提取
进一步分析发现RSA公钥是通过接口动态获取的:
code复制GET https://www.huya.com/api/getPublicKey
Response:
{
"code": 200,
"data": {
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ..."
}
}
公钥格式是标准的PKCS#1,可以通过Node.js的crypto模块加载:
javascript复制const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ...
-----END PUBLIC KEY-----`;
function rsaEncrypt(text) {
const buffer = Buffer.from(text);
return crypto.publicEncrypt(
{
key: publicKey,
padding: crypto.constants.RSA_PKCS1_PADDING
},
buffer
).toString('base64');
}
4.3 完整加密流程实现
结合以上分析,完整的密码加密流程如下:
javascript复制function generateRandomStr(length) {
return crypto.randomBytes(length)
.toString('base64')
.slice(0, length);
}
function encryptHuyaPassword(password) {
const salt = generateRandomStr(8);
const combined = password + salt;
const encrypted = rsaEncrypt(combined);
return `${salt}$${encrypted}`;
}
5. 逆向过程中的关键技巧
5.1 反调试绕过策略
虎牙在前端代码中设置了多个反调试陷阱:
- 定时检测:通过setInterval检查DevTools开启状态
javascript复制setInterval(function() {
if(console.log.toString().length > 100 ||
console.debug.toString().length > 100) {
location.reload();
}
}, 1000);
解决方案:在控制台执行以下代码禁用检测
javascript复制for(let i=0; i<10; i++) { window.clearInterval(i); }
- 代码混淆:使用变量名混淆和代码控制流平坦化
建议使用Chrome的"Pretty-print"功能格式化代码,并通过AST解析工具辅助分析。
5.2 动态参数处理
在实际自动化登录时,需要注意以下动态参数:
- 页面加载时生成的token(通常隐藏在HTML中)
- 时间戳必须与服务器保持同步(误差不超过±30秒)
- 部分接口需要先获取cookie才能正常请求
推荐使用Puppeteer等工具模拟完整浏览器环境:
javascript复制const puppeteer = require('puppeteer');
async function huyaLogin(username, password) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// 获取初始token
await page.goto('https://www.huya.com/login');
const token = await page.evaluate(() => {
return window.__INIT_DATA__.token;
});
// 执行加密逻辑
const encrypted = await page.evaluate((pwd) => {
return window.HuyaEncrypt.encryptPassword(pwd);
}, password);
// 提交登录
await page.type('#username', username);
await page.type('#password', encrypted);
await page.click('#login-btn');
await browser.close();
}
6. 安全防护升级应对
近期虎牙对登录流程进行了多次安全升级,开发者需要注意:
- 签名算法动态化:部分接口开始使用AES加密签名参数
- 行为验证:增加鼠标轨迹和键盘事件监测
- 环境检测:通过WebGL渲染指纹识别自动化工具
应对建议:
- 保持加密逻辑的定期更新检查
- 在自动化脚本中添加随机延迟和人性化操作
- 使用真实浏览器指纹和UA信息
我在实际项目中发现,完整模拟用户行为比单纯破解加密更稳定可靠。特别是在处理滑块验证时,可以借助第三方验证码识别服务,但要注意合理使用频率以避免被封禁。
