Windows 11 下用 npm 装 crypto-js 踩过的那些坑,以及如何用它逆向分析一个网站的登录加密
Windows 11 下逆向分析网站登录加密的完整实战指南
最近在研究一个网站的登录流程时,发现它在提交密码前会先进行加密处理。作为一名对前端安全感兴趣的开发者,我决定深入探索这个加密过程,并在本地环境中复现它。本文将分享我在 Windows 11 环境下使用 Node.js 和 crypto-js 库进行逆向分析的完整过程,包括环境配置、加密算法识别和本地复现的详细步骤。
1. 环境准备与 Node.js 配置
逆向分析的第一步是搭建合适的工作环境。在 Windows 11 上,我们需要安装 Node.js 和 npm,这是后续所有工作的基础。
1.1 Node.js 安装与验证
从 Node.js 官网下载最新的 LTS 版本(目前是 18.x)。安装时需要注意几个关键点:
- 建议自定义安装路径,比如
D:\DevTools\nodejs,避免使用包含空格或特殊字符的路径 - 安装时勾选 "Automatically install the necessary tools" 选项,这会包括 npm 和核心模块
- 安装完成后,验证是否成功:
node -v npm -v如果看到版本号输出,说明安装成功。我最初遇到的问题是环境变量没有自动配置,导致命令行无法识别 node 命令。解决方法是在系统环境变量的 Path 中添加 Node.js 的安装路径。
1.2 npm 配置优化
npm 默认配置有几个需要调整的地方:
修改全局模块安装路径:
npm config set prefix "D:\DevTools\nodejs\node_global" npm config set cache "D:\DevTools\nodejs\node_cache"更换为国内镜像源(显著提升安装速度):
npm config set registry https://registry.npmmirror.com/注意:淘宝源已更换新域名,旧域名(taobao.org)将停止服务
常见问题排查:
- 权限不足:右键 Node.js 安装目录 → 属性 → 安全 → 编辑 → 赋予完全控制权限
- 缓存问题:执行
npm cache clean --force后重试 - 网络问题:临时关闭防火墙或杀毒软件测试
2. crypto-js 的安装与核心概念
crypto-js 是一个强大的 JavaScript 加密库,支持多种哈希算法和对称加密。在逆向分析中,我们主要关注它的 AES 实现。
2.1 安装与导入
全局安装 crypto-js:
npm install crypto-js在项目中引入特定模块:
// ES6 方式 import AES from 'crypto-js/aes' import enc from 'crypto-js/enc-utf8' // CommonJS 方式 const CryptoJS = require('crypto-js')2.2 关键加密参数理解
AES 加密需要三个核心参数:
| 参数 | 说明 | 示例值 |
|---|---|---|
| Key | 加密密钥,长度必须为16/24/32字节 | "mySecretKey12345" |
| IV | 初始化向量,增加加密随机性 | "initializationV" |
| Mode | 加密模式,如 CBC、ECB 等 | CryptoJS.mode.CBC |
| Padding | 填充方案,如 Pkcs7 | CryptoJS.pad.Pkcs7 |
在逆向网站加密时,我们的首要任务就是找出这些参数的值。
3. 浏览器逆向实战:定位加密逻辑
现在进入最有趣的部分 - 逆向分析目标网站的加密实现。以某电商网站登录为例。
3.1 捕获加密请求
- 打开 Chrome 开发者工具(F12)→ Network 标签
- 勾选 "Preserve log" 防止页面跳转丢失记录
- 在登录页面输入测试账号(如 user/123456)并提交
- 筛选 XHR 请求,找到登录接口(通常包含 login/auth 等关键词)
观察请求负载,发现 password 字段值为 "A7428361DEF118911783F446A129FFCE",明显是加密后的结果。
3.2 定位加密代码
在 Sources 面板中搜索关键词:
- 直接搜索 "encrypt"、"AES"、"CryptoJS"
- 或者搜索密码明文 "123456" 看在哪里被处理
找到类似如下的代码片段:
function encryptPassword(pwd) { const key = CryptoJS.enc.Utf8.parse("2017110912453698"); const iv = CryptoJS.enc.Utf8.parse("2017110912453698"); const encrypted = CryptoJS.AES.encrypt(pwd, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); return encrypted.toString().toUpperCase(); }这就是我们要找的核心加密逻辑!记下 key、iv、mode 和 padding 的值。
3.3 提取加密参数
从代码中可以提取出以下关键信息:
- 加密算法:AES-CBC
- 密钥(key):"2017110912453698"(16字节)
- 初始化向量(iv):与 key 相同
- 填充方案:PKCS7
- 输出处理:转为大写字符串
安全提示:实际逆向分析应仅用于学习目的,避免未经授权分析商业网站
4. 本地复现加密过程
现在我们在本地 Node.js 环境中复现这个加密过程。
4.1 创建加密工具类
新建cryptoHelper.js文件:
const CryptoJS = require('crypto-js') class CryptoHelper { constructor(key, iv) { this.key = CryptoJS.enc.Utf8.parse(key) this.iv = CryptoJS.enc.Utf8.parse(iv) } encrypt(plainText) { const srcs = CryptoJS.enc.Utf8.parse(plainText) const encrypted = CryptoJS.AES.encrypt(srcs, this.key, { iv: this.iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) return encrypted.ciphertext.toString().toUpperCase() } decrypt(cipherText) { const encryptedHexStr = CryptoJS.enc.Hex.parse(cipherText) const srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr) const decrypt = CryptoJS.AES.decrypt(srcs, this.key, { iv: this.iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) return decrypt.toString(CryptoJS.enc.Utf8) } } // 使用网站提取的参数初始化 const websiteCrypto = new CryptoHelper( "2017110912453698", "2017110912453698" ) module.exports = { websiteCrypto }4.2 测试加密效果
创建测试文件test.js:
const { websiteCrypto } = require('./cryptoHelper') // 测试加密 const plainPassword = "123456" const encrypted = websiteCrypto.encrypt(plainPassword) console.log(`加密结果: ${encrypted}`) // 测试解密 const decrypted = websiteCrypto.decrypt(encrypted) console.log(`解密结果: ${decrypted}`)运行后应该能看到输出:
加密结果: A7428361DEF118911783F446A129FFCE 解密结果: 123456这与我们在浏览器中观察到的行为完全一致,说明复现成功!
4.3 处理特殊字符问题
在实际应用中,加密结果可能包含特殊字符(如 +/=),直接作为 URL 参数传输会有问题。需要额外处理:
function safeEncrypt(plainText) { const encrypted = websiteCrypto.encrypt(plainText) return encodeURIComponent(encrypted) } // 使用示例 const safeEncrypted = safeEncrypt("123456") console.log(safeEncrypted) // 输出URL安全的编码字符串5. 逆向工程中的高级技巧
在更复杂的场景中,你可能会遇到以下情况:
5.1 动态密钥生成
有些网站会动态生成密钥,通常通过以下方式:
- 从服务器接口获取
- 基于时间戳或其他变量计算
- 使用 RSA 加密传输 AES 密钥
应对方法:
- 在开发者工具中搜索 "getKey"、"initKey" 等关键词
- 跟踪网络请求,寻找密钥相关的接口
- 设置断点调试密钥生成逻辑
5.2 混淆的加密代码
现代前端常用代码混淆技术增加逆向难度。可以尝试:
- 使用浏览器格式化工具美化压缩代码({} 按钮)
- 搜索加密字符串特征,如 "AES"、"encrypt"
- 关注 CryptoJS 特有的方法调用链
5.3 多阶段加密
某些安全要求高的网站会采用多阶段加密:
- 先对原始密码做 MD5/SHA 哈希
- 添加随机 salt 值
- 再进行 AES 加密
识别方法:
- 在密码输入后设置 DOM 断点
- 跟踪密码变量的传递过程
- 检查是否有多个加密函数调用
6. 安全实践与法律考量
在进行加密逆向分析时,务必注意:
合法合规:
- 仅分析自己有权限测试的网站
- 不要绕过付费墙或访问控制
- 尊重用户隐私和数据保护法律
安全建议:
- 在沙盒环境中测试,避免影响生产系统
- 不要存储或传播获取的敏感数据
- 使用测试账号而非真实用户凭证
防护措施:
// 示例:检测运行环境 if (typeof window === 'undefined') { console.log('运行在Node.js环境') } else { console.log('运行在浏览器环境') // 可以添加额外的防护逻辑 }在实际项目中,如果发现安全漏洞,建议通过正规渠道向网站管理员报告。
