Js逆向实战案例
字数 1461 2025-08-11 08:35:42
JavaScript逆向实战案例教学文档
目录
-
案例一:某平台数据加密分析
- 加密特征识别
- 加密算法定位
- 请求包加密流程分析
- 返回包解密流程分析
- 调试与修改技巧
-
案例二:某平台数据加密+签名分析
- 反调试处理
- 多重加密参数分析
- AES与RSA组合加密
- 签名验证机制
- 密钥获取与解密方法
-
通用逆向技巧总结
- 关键词搜索方法
- 调试技巧
- 加密算法识别
1. 案例一:某平台数据加密分析
1.1 加密特征识别
- 请求包特征:
abchtrne/rerhn34rhnfe(无固定格式的字符串) - 返回包特征:
{"data":"reene43jygrnd534htrfdre"}(JSON格式)
1.2 加密算法定位
- 在
encryption文件夹下的JS文件中发现国密算法线索 - 主要算法:SM3(哈希算法)、SM4(对称加密)
- 搜索关键词:
sm3、sm4、encryptData
1.3 请求包加密流程
- 加密函数:
os和rs方法 - 加密步骤:
- 第一步:使用SM4的CBC模式加密原始数据
- 第二步:使用SM4的ECB模式二次加密
- 第三步:使用SM3对JSON格式的加密结果进行哈希处理
1.4 返回包解密流程
- 解密函数:
ls和cs方法 - 解密步骤:
- 第一步:调用
ls方法进行初步解密 - 第二步:调用
cs方法获取最终明文数据
- 第一步:调用
- 特征:返回包JSON中没有
iv参数,只有data参数
1.5 调试与修改技巧
- 在控制台直接调用解密函数:
ls(encryptedData) // 第一次解密 cs(decryptedData) // 最终解密 - 修改请求数据:
- 在
debugger中定位到t字段(包含加密前数据) - 直接修改
t中的数据会影响最终加密结果
- 在
2. 案例二:某平台数据加密+签名分析
2.1 反调试处理
- 反调试特征:右键点击检查时网页自动进入调试状态
- 绕过方法:
- 在
debugger处设置断点 - 修改断点条件为
false
- 在
2.2 请求/返回包参数
x:AES加密后的JSON数据x1:RSA加密后的AES密钥sign:签名参数
2.3 加密流程分析
- AES加密:
- 使用动态生成的密钥
- 加密原始数据生成
x参数
- RSA加密:
- 使用固定私钥
key_1 - 加密AES密钥生成
x1参数
- 使用固定私钥
- 签名生成:
- 通过
sign()函数计算 - 可能基于加密数据或特定规则生成
- 通过
2.4 解密方法
- 获取AES密钥:
// 使用RSA私钥解密x1 const aesKey = RSA_decrypt(x1, privateKey) - 解密数据:
// 使用AES密钥解密x const plainData = AES_decrypt(x, aesKey) - 签名验证:
- 调用原始
sign()函数重新计算 - 与请求中的
sign参数比对
- 调用原始
3. 通用逆向技巧总结
3.1 关键词搜索策略
- 算法相关:
encrypt/decryptsm2/sm3/sm4aes/rsa/des
- 功能相关:
sign/signaturekey/iv/secretdata/param/request
3.2 调试技巧
- 格式化代码:点击调试器的
{}按钮使代码可读 - 断点设置:
- XHR断点:监控特定URL请求
- 事件断点:监控表单提交等事件
- 控制台操作:
- 直接调用加解密函数
- 修改内存中的变量值
3.3 加密算法识别
- SM系列国密算法:
- SM3:32字节哈希值
- SM4:16字节分组,固定密钥长度128位
- AES特征:
- 常见模式:CBC/ECB/CTR
- 密钥长度:128/192/256位
- 通常需要IV(初始化向量)
- RSA特征:
- 公钥/私钥对
- 常用于加密对称密钥
- 密钥长度通常1024/2048位
附录:常用调试代码片段
SM4解密示例
// 假设已加载相关JS库
const sm4 = new SM4();
sm4.setKey(key);
sm4.setMode('cbc');
sm4.setIv(iv);
const decrypted = sm4.decrypt(encryptedData);
绕过反调试
// 方法1:禁用所有debugger
eval = function(){};
// 方法2:修改断点条件
// 在Chrome调试器中右键断点 -> Edit breakpoint -> 输入false
动态调用签名函数
// 获取页面中的签名函数
const signFunc = window.sign || findSignFunction();
// 生成新签名
const newSign = signFunc(dataToSign);