“成都大学”js逆向
成都大学JS 逆向
一、报告概述
1.1 分析目标
本次针对新业务系统的前端加密逻辑开展 JS 逆向分析,核心目标为定位并还原 AES 加密函数的实现逻辑、明确加密参数来源,验证加密算法的完整性与正确性,为后续自动化对接、数据解密等场景提供技术支撑。
1.2 分析环境
- 调试工具:Chrome DevTools(断点调试、调用栈追踪、全局搜索)
- 运行环境:Node.js v16+
- 核心依赖:CryptoJS(前端 AES 加密底层库)
- 分析对象:混淆后的业务加密 JS 文件
二、加密逻辑逆向过程
2.1 加密入口定位
通过 Chrome DevTools 的全局搜索与断点调试
2.1.1 加密函数的位置
在每个文件搜索 encrypt 关键字
在这个位置找到了可疑的函数,去混淆之后发现定位到的是业务层的核心加密函数 aesEncrypt,这正是我们一直在找的加密入口,只是不是我们输入传入的地方
1 | // 混淆前的原始逻辑 |
2.1.2 业务逻辑加密
通过调用堆栈找到了业务逻辑加密的地方
去混淆之后
1 | // 原始混淆代码还原 |
_0x3a9405:加密密钥
this['password']:用户输入的原始明文密码
aesEncrypt: AES-CBC 加密函数
作用:加密后的密码会被设置到隐藏的密码输入框中,最终随表单提交
2.1.3 找到加密函数
现在我们去全局搜索aesEncrypt 这个函数
定位到的是业务层的核心加密函数 aesEncrypt,这正是我们一直在找的加密入口。我帮你把这段混淆代码还原成清晰的逻辑:
去混淆后的等价代码
1 | // 混淆前的原始逻辑static aesEncrypt(plaintext, key) {// 解析明文为 WordArrayconst parsedPlaintext = CryptoJS.enc.Utf8.parse(plaintext);// 解析密钥为 WordArrayconst parsedKey = CryptoJS.enc.Utf8.parse(key);// 执行 AES-CBC 加密const encrypted = CryptoJS.AES.encrypt(parsedPlaintext, parsedKey, {mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});// 返回 Base64 编码的密文return encrypted.toString();} |
关键参数映射
从调试信息可以看到:
0x4e34ef:明文参数(值为"111")0x14850a:密钥参数(值为"DV9fY1l9silfXu8e+ILxSQ==")0x35af68:解析后的明文(WordArray类型)0x2af56:解析后的密钥(WordArray类型)0x5a875:CryptoJS对象的混淆别名
2.1.4 找到了底层加密函数 (AES)
知道了是 AES 加密
函数本质这个 aesEncrypt 函数就是封装了 CryptoJS.AES.encrypt 的业务加密逻辑。
0x2d62d8是明文参数,调试时显示为BFgVB/F1EFFHfGmQJUS553Cg==0x1807cf是加密配置参数,包含了密钥和向量等信息- 加密模式:
EBC - 填充方式:
Pkcs7
混淆特征变量名(如 0x451718、0x327bac)和函数名都是经过混淆器生成的乱码,这是为了增加逆向难度。但核心调用 CryptoJS.AES.encrypt 是不变的,这是定位的关键。
2.1.5 找到了底层加密逻辑
2.2 关键参数解析
通过调试器实时监控,获取到加密函数的核心参数信息:
| 参数类型 | 混淆变量名 | 实际值 | 说明 |
|---|---|---|---|
| 明文 | 0x4e34ef | “111” | 业务层传入的原始待加密数据 |
| 密钥 | 0x14850a | “DV9fY1l9silfXu8e+ILxSQ==” | 加密使用的核心密钥(Base64 编码格式) |
| 加密模式 | - | CBC | 固定使用 CBC 模式,无动态切换逻辑 |
| 填充方式 | - | Pkcs7 | 满足 AES 128 位分组长度要求 |
| 初始向量(IV) | - | 未显式配置 | 采用 CryptoJS 默认 IV 生成规则 |
2.3 加密链路验证
2.4.1 断点验证
在aesEncrypt函数返回行下断点,执行加密逻辑后获取调试器内加密结果,与抓包获取的密文对比,验证逻辑一致性(差异仅源于随机 IV,属于正常现象)。
2.4.2 本地复现验证
将还原后的加密函数移植到 Node.js 环境,使用相同参数测试:
1 | const CryptoJS = require('crypto-js');// 还原后的加密函数function aesEncrypt(plaintext, key) {const parsedPlaintext = CryptoJS.enc.Utf8.parse(plaintext);const parsedKey = CryptoJS.enc.Utf8.parse(key);const encrypted = CryptoJS.AES.encrypt(parsedPlaintext, parsedKey, {mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});return encrypted.toString();}// 测试执行const plaintext = "111";const key = "DV9fY1l9silfXu8e+ILxSQ==";const encryptedResult = aesEncrypt(plaintext, key);console.log("本地加密结果:", encryptedResult); |
验证结论:本地复现结果与调试器内加密结果格式一致、算法逻辑一致,加密函数还原准确。






