0x01 简介
如今不少网站把加密逻辑前置到前端,常见包含 AES、MD5、SM2、RSA 等算法。抓包数据不再是明文账号密码,大多以 Base64、十六进制密文形式呈现BurpSuite 的 Intruder 突然失效,手工重放请求全是 400/403,漏洞扫描器也因为无法构造合法密文而直接哑火。本文从 MD5、AES 到国密 SM2出发结合实战案例,梳理前端加密逆向整套思路,借助Chrome DevTools MCP + JS 逆向 Skill技巧,拆解各类加密算法,实现抓包快速加解密,找出算法密钥。
本文仅用于技术学习与合规交流,严禁非法滥用。因违规使用产生的一切后果,由使用者自行承担,与作者无关。
现在只对常读和星标的才展示大图推送,建议大家把渗透安全HackTwo“设为星标”,否则可能就看不到了啦!
末尾可领取挖洞资料/加圈子 #渗透安全HackTwo
0x02 正文详情
获取GPT/Claude模型API
这里仅做渠道推荐,AI效果请自行判断。如有更便宜或更稳定的渠道,也可自行选择。API中转站:https://www.zovelox.com/
Chrome-MCP、JS逆向SKILL可在末尾下载
Chrome-MCP、JS逆向SKILL作用如下: 基于 MCP 协议的 Chrome 浏览器自动化工具 允许 AI 通过 Chrome DevTools Protocol 控制 Chrome 浏览器 导航到登录页面 获取页面快照 监控网络请求 执行 JavaScript 代码 捕获登录接口请求 分析前端加密逻辑在渗透测试与漏洞挖掘过程中,我们经常会遇到前端加密的登录接口。本次目标是一个管理平台,其登录请求体结构异常简洁:
如果你有安装openclaw那么以下步骤可以全部让龙虾托管完成!CLI启动也不错、也支持用第三方工具比如Cursor、Trae等
(1)AES加密
目标站点:https://www.xxxx.com/user/#/login
{ "data": "mI8rO4S4NF3+1+MIZiOeB6BgdyH3m3OQPIaf+cywysSR4KwOXwoOnQKeSH/ntVne0yxK7DWh5BkFa5M9XDxg7Yia8UTHqY6uJk/mH2vtd6Q=" }所有敏感参数被压缩进单个data字段,且为 Base64 编码的密文。给AI任务是:
定位加密函数的调用链
提取加密算法、密钥与 IV
验证解密能力并生成复现脚本
分析环境:
工具 | 用途 |
|---|---|
Claude Code (Sonnet 4.6/4.7) | AI自动化分析与脚本生成 |
Chrome DevTools MCP | 浏览器动态调试、网络抓包、DOM 与源码读取 |
JS逆向Skill | 标准化逆向流程(Observe -> Capture -> Rebuild -> Port) |
提示词
使用 Chrome DevTools MCP + JS逆向 Skill 对目标站点进行深度登录逆向分析。 目标: 完整分析登录接口的前端加密逻辑、参数构造方式、调用链与请求发送流程, 并自动生成可复现登录请求脚本。 目标站点: https://xxx.xxx.com/user/#/login 任务: 1. 自动打开登录页 2. 自动抓取登录请求 3. 自动分析 data 参数的生成逻辑 4. 自动分析: - 前端JS - webpackChunk - 动态加载Chunk - Sources源码 - obfuscation(混淆)AI通过 Chrome DevTools MCP 自动导航至登录页,填写测试账号并触发登录,成功捕获到请求:
POST https://www.dns.com/api/front/login Content-Type: application/json {"data":"cawebKxBRJ0VrvUBwQGO5/KQNxeZ219pPp16FN1xwDRML9uhpm1GhndVC0T7y5khniHfeExPSSQ11jtbAR3Eq6XQHgbYouHOrPZLZxBofLBp3cDZLp+nGHj7+RCVkh14"}密文结构初判
对比两次不同账号的登录请求,发现data字段的前 64 字节(Base64 解码后)完全一致,仅尾部发生变化。这一特征强烈暗示:
算法:AES-CBC(块大小 16 字节,前 64 字节为 4 个固定块)
结构:固定前缀(时间戳/Nonce)+ 变化后缀(账号密码)
让AI定位加密函数
在浏览器控制台中遍历 Vue 实例的 $utils 对象
app.$utils.encryptString// f encryptString(e){...}
提取到的核心源码如下:
encryptString(e){ "object" === typeof e && (e = JSON.stringify(e)); const t = m().enc.Utf8.parse(p), // p = 密钥 a = m().enc.Utf8.parse(u), // u = IV r = m().AES.encrypt(e, t, { iv: a, mode: m().mode.CBC, padding: m().pad.Pkcs7 }); return m().enc.Base64.stringify(r.ciphertext) }提取密钥与 IV
加密函数中使用了两个闭包变量 p(密钥)和 u(IV)。通过在浏览器中设置断点并 Hook encryptString 的调用,直接读取到内存中的真实值:| 参数 | 原始值 | 实际使用值 |
|---|---|---|
| 密钥 p | 32b85ab5b8cfe30c06b8bff43765f707 | 32b85ab5b8cfe30c(取前 16 字节) |
| IV u | Hf9k3D2pXwLt8VqZ | Hf9k3D2pXwLt8VqZ(完整 16 字节 |
注意:源码中虽然定义了 32 字节的字符串,但实际通过.substring(0,16)截断为 16 字节作为 AES-128 密钥使用。这一点在动态调试中才得以确认,静态审计极易误判为 AES-256。
在t=m().enc.Utf8.parse(p)位置打上断点确定为 16 字节作为 AES-128 密钥
解密流程还原
通过python脚本进行AES解密
#!/usr/bin/env python3 """ xxx.com AES解密工具 基于JS skill技能深度逆向分析结果 密钥来源:app.dbceab58.js 位置177041 - const u="Hf9k3D2pXwLt8VqZ".substring(0,16) - const p="32b85ab5b8cfe30c06b8bff43765f707".substring(0,16) 实际密钥:32b85ab5b8cfe30c (16字节) 实际IV:Hf9k3D2pXwLt8VqZ (16字节) """ import base64 import json import sys from Crypto.Cipher import AES from Crypto.Util.Padding import unpad class DNSComDecryptor: """xxx.com AES解密类""" KEY = "32b85ab5b8cfe30c" # AES密钥 (16字节) IV = "Hf9k3D2pXwLt8VqZ" # AES初始化向量 (16字节) def __init__(self, key: str = None, iv: str = None): """ 初始化解密类 Args: key: AES密钥 (默认使用分析得到的密钥) iv: AES初始化向量 (默认使用分析得到的IV) """ self.key = (key or self.KEY).encode('utf-8') self.iv = (iv or self.IV).encode('utf-8') def decrypt(self, ciphertext: str) -> str: """ 解密Base64编码的密文 Args: ciphertext: Base64编码的密文字符串 Returns: 解密后的明文字符串 """ # Base64解码 encrypted_bytes = base64.b64decode(ciphertext) # AES-CBC解密 cipher = AES.new(self.key, AES.MODE_CBC, self.iv) decrypted_padded = cipher.decrypt(encrypted_bytes) # 去除PKCS7填充 decrypted = unpad(decrypted_padded, AES.block_size) return decrypted.decode('utf-8') def decrypt_json(self, ciphertext: str) -> dict: """ 解密并解析为JSON对象 Args: ciphertext: Base64编码的密文字符串 Returns: 解析后的Python字典 """ plaintext = self.decrypt(ciphertext) return json.loads(plaintext) def main(): """命令行界面""" if len(sys.argv) < 2: print("DNS.com AES解密工具") print("=" * 50) print("用法: python decrypt.py <Base64密文>") print() print("示例:") print(' python decrypt.py "mI8rO4S4NF3+1+MIZiOeB6BgdyH3m3OQPIaf+cywysSR4KwOXwoOnQKeSH/ntVne0yxK7DWh5BkFa5M9XDxg7Yia8UTHqY6uJk/mH2vtd6Q="') print() print(f"当前密钥: {DNSComDecryptor.KEY}") print(f"当前IV: {DNSComDecryptor.IV}") sys.exit(1) ciphertext = sys.argv[1] try: decryptor = DNSComDecryptor() plaintext = decryptor.decrypt(ciphertext) print("解密成功!") print("=" * 50) print("密文:", ciphertext) print("明文:", plaintext) # 尝试格式化JSON try: data = json.loads(plaintext) print() print("JSON格式化:") print(json.dumps(data, indent=2, ensure_ascii=False)) except: pass # 不是JSON格式 except Exception as e: print(f"解密失败: {e}") sys.exit(1) if __name__ == "__main__": main()(2)MD5加密
首先拿到测试站点后先输入账号密码,获取参数值
复制网站地址,写成提示词让AI测试
首先AI会先调用Chrome MCP
使用 Chrome DevTools MCP + JS逆向 skill 对当前网站进行逆向分析: 目标: 分析登录接口的加密逻辑,并生成可复现登录请求的脚本。 已知信息: 登录接口:https://www.xxxx.com/xxxx/login_h.jsp?dogSrc=3 POST参数: admin=sacct pwd=e10adc3949ba59abbe56e057f20f883e autoLogin=true staffLogin=true bizType=5 dogId=0 fromsite=false cmd=loginCorpNews 任务: 使用 DevTools MCP 抓取登录全过程 找到 pwd 参数是在前端如何生成的AI自动分析加密过程
AI 自动识别 pwd 为 MD5
验证 MD5("123456") =
e10adc3949ba59abbe56e057f20f883e自动定位加密函数
$.md5在util.min.js
这里AI给出了断点位置我们来验证一下
直接在$.md5位置断点就可以看到明文
拿到算法
(3)SM2国密加密
也是先登录一遍获取请求的键值加密信息
写提示词发给Claude测试
使用 Chrome DevTools MCP + JS逆向 Skill 对目标站点进行深度登录逆向分析。 目标: 分析登录接口的完整加密逻辑,并自动生成可复现登录请求的脚本。 目标接口:http://xxx.xxx.com/j_acegi_security_check 已知POST参数: j_username=admin j_password=卍㈠䵅04f4290127ebe6c710ab3bdde9ce2bcaeab5e9b8c73f1cc3f27bdc8e970132bdc115f6d52b0c5b19534bd03f6e312ef748311a0a73f541d808c857b98580f3fa16559ad6512c026a28c0191c45753b015def25c9cd75c8d76922c7d7c69ec82477fddd69fce876 j_validation_code=PUFN j_redirectto= 任务: 自动打开登录页 自动抓取登录请求 分析 j_password 的生成逻辑从参数结构可以看出,不是常见的MD5或Base64
原因包括:1. 存在明显Unicode特殊前缀2. 密文长度远大于MD53. 存在“04”开头的椭圆曲线特征4. Hex长度符合非对称加密输出因此初步怀疑:该系统使用了国密SM2或ECC类加密。
1分钟后AI给出了加密算法确认: SM2国密加密
完整加密流程:
明文密码 "123456" ↓ 调用 encryptPassword() ↓ desEncrypt(plaintext) ↓ 获取SM2公钥 (130字符) ↓ SM2Utils.encs(publicKey, plaintext) ↓ 输出Hex密文 (206字符) ↓ 添加前缀 "卍㈠䵅"由于登录请求中的密码并非固定Hash长度,因此推测前端一定存在动态加密函数。
所以重点搜索:
encrypt、password、publicKey 等关键字,
用于定位登录提交前的加密入口。
这里AI给出的断点位置如下,通过console可以直接修改加密参数返回后端
document.forms[0].j_password.value比如这里断点拦截123456修改为123456' OR '1'='1
针对加密请求场景,可利用jsrpc技术调用浏览器加密函数,配合Selenium自动化框架实现Burpsuite明文payload的自动加解密处理。
更多挖洞技术和AI SKILL可加入星球获取Chrome-MCP、JS逆向SKILL可在末尾下载
下载
⬇️回复20260527获取JS逆向SKILL和ChormeMCP⬇️