长安大学JS 逆向

一、报告概述

1.1 分析目标

本次分析针长安大学统一身份认证平台登录接口的密码加密逻辑进行 JS 逆向,还原前端密码加密流程,验证加密

1.2 分析环境

  • 浏览器调试工具:Chrome DevTools(断点调试、控制台执行)
  • 运行环境:Node.js v16+
  • 依赖库:CryptoJS(前端加密核心库)

二、加密逻辑逆向过程

2.1 加密入口定位

通过查找 encrypt 关键字找到密码加密的 js 文件

img

在该位置截断,发现登录停下来了说明找对了

img

继续跟进函数

img

定位到密码加密的核心入口函数为 encryptPassword(n, f)

img

  • 参数 n:原始密码(示例值:1111
  • 参数 f:加密盐值(示例值:TMLE9qDpvBaRKnVt
  • 函数作用:调用底层 encryptAES 函数完成最终加密,包含异常捕获逻辑,加密失败时直接返回原始密码。

2.2 核心函数拆解

(1)随机字符串生成函数 randomString(n)

1
2
const $aes_chars = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefhijkmnprstwxyz2345678";const aes_chars_len = $aes_chars.length;function randomString(n) {var f = "";for (i = 0; i < n; i++) {
f += $aes_chars.charAt(Math.floor(Math.random() * aes_chars_len));}return f;}
  • 字符集:排除易混淆字符(I、O、l、0),仅包含大小写字母和数字;
  • 功能:生成指定长度(n)的随机字符串,核心用于构造加密明文前缀和备用密钥。

img

(2)AES 加密实现函数 getAesString(n, f)

javascript

运行

1
2
3
4
function getAesString(n, f) {// 清理盐值:去除空格、换行符
f = f.replace(/(\/r\n+)|(\n+)|(\s+)/g, "");// 编码转换:字符串转CryptoJS可识别的WordArray
f = CryptoJS.enc.Utf8.parse(f);
c = CryptoJS.enc.Utf8.parse(n);// AES-CBC加密核心逻辑return CryptoJS.AES.encrypt(c, f, {iv: c, // 初始向量(IV)与明文编码结果一致(特殊实现)mode: CryptoJS.mode.CBC, // 加密模式:CBCpadding: CryptoJS.pad.Pkcs7 // 填充方式:Pkcs7}).toString();}

也是在这一步找到了我们需要的所以参数

  • 关键参数:
    • 明文:拼接后的完整字符串(64 位随机串 + 原始密码);
    • 密钥:清理后的盐值 f
    • IV:与明文编码结果相同(非标准随机 IV,属于定制化实现);
    • 模式:CBC(分组加密模式);
    • 填充:Pkcs7(满足 128 位分组长度要求)。
    • img

(3)加密逻辑封装函数 encryptAES(n, f)

1
function encryptAES(n, f) {// 构造明文:64位随机串 + 原始密码return getAesString(randomString(64) + n, f ? f : randomString(16));}
  • 明文构造规则:固定 64 位随机字符串拼接原始密码;
  • 密钥优先级:优先使用传入的盐值 f,无盐值时生成 16 位随机字符串作为密钥。

2.3 完整加密链路

img

三、验证过程与结果

3.1 断点验证

通过 Chrome DevTools 在 getAesString 返回行下断点,执行加密逻辑并获取结果:

  • 调试器执行结果:Cpw8xoQVA5faSTlNHJuhJPU+oD6ToGAk4pHiAjbU=
  • 抓包获取密码值:m/Tas7969+fMTKe4jx/SKHRaluz+LQ+fl2lcaG07d0HGKOTW4n3AdvIc7yLMD+TONgygHTDF2BfoQqbjm/A8124oau/JiWeDpBJqU=
  • 差异原因:randomString(64) 生成的随机串每次不同,导致最终密文不一致,属于正常现象。

img

img