
1. 初识JS混淆与AES加密当你打开一个网页发现所有数据都是加密传输的时候是不是感觉无从下手这就是前端加密的典型场景。现在越来越多的网站采用JS混淆AES加密的组合拳来保护数据安全给爬虫工程师和安全研究人员带来了不小的挑战。我最近逆向一个电商网站时就遇到了这种情况。打开Chrome开发者工具Network面板里看到的全是乱码一样的加密数据。这种时候千万别慌我们只需要找到三个关键要素密钥Key、初始向量IV和加密模式如CBC。就像开保险箱需要密码一样有了这些参数我们就能在Python中复现解密过程。JS混淆其实就像把代码打碎重组让人难以阅读。常见的混淆手段包括变量名替换、控制流扁平化、字符串加密等。比如原本清晰的getUserInfo()可能被混淆成_0x12ab3c()。不过别担心现代浏览器都自带调试工具配合一些技巧我们总能找到突破口。2. 动态调试定位加密函数实战中我最喜欢用Chrome的全局搜索功能CtrlShiftF。比如遇到加密的API响应可以先搜索encrypt、AES等关键词。如果找不到那就试试搜索JSON.parse——因为前端通常需要先解密数据再解析为JSON。最近一个项目中我在一个3万行的混淆JS文件中找到了这样的代码片段function _0x45ab2(t) { var e CryptoJS.enc.Hex.parse(t) , n CryptoJS.enc.Base64.stringify(e) , a CryptoJS.AES.decrypt(n, _0x12f3d, { iv: _0x23ac1, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) , r a.toString(CryptoJS.enc.Utf8); return r.toString() }这就是典型的AES解密函数通过下断点调试我发现_0x12f3d是密钥_0x23ac1是IV加密模式是CBC填充方式是Pkcs7。这四个参数就是我们需要的钥匙。3. 追踪关键参数来源找到解密函数只是第一步更重要的是追踪这些参数是怎么生成的。有些网站会硬编码在JS里有些则会通过API动态获取。在我分析的案例中密钥是通过以下方式生成的function _0x12f3d() { var t 5f8g2#jKlMnBvXyZ , e new Date().getHours(); return t e.toString() }这意味着密钥每小时都会变化如果不追踪这个逻辑直接硬编码密钥解密代码很快就会失效。通过调试我确认IV是固定值0123456789ABCDEF这让我们后续处理简单了不少。4. Python复现解密流程拿到所有参数后就可以用Python的pycryptodome库复现解密过程了。下面是我实际使用的代码from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import base64 def decrypt_data(encrypted_hex, key, iv): # 将16进制字符串转换为bytes encrypted_bytes bytes.fromhex(encrypted_hex) # 使用CBC模式解密 cipher AES.new(key.encode(utf-8), AES.MODE_CBC, iv.encode(utf-8)) # 解密并去除填充 decrypted unpad(cipher.decrypt(encrypted_bytes), AES.block_size) return decrypted.decode(utf-8) # 实际调用示例 key 5f8g2#jKlMnBvXyZ str(datetime.now().hour) iv 0123456789ABCDEF encrypted_data a3b5c7...从网络抓包获取的加密数据 print(decrypt_data(encrypted_data, key, iv))注意几个关键点加密数据通常是Base64或Hex编码的需要先解码CBC模式需要提供IV参数解密后要用unpad去除填充字节密钥生成逻辑要与前端保持一致5. 处理反调试技巧有些网站会使用反调试技术阻止开发者工具分析。常见的手法包括检测console打开状态检测代码执行时间禁用断点调试遇到这种情况可以尝试以下方法使用Fiddler或Charles等抓包工具直接拦截请求在Node.js环境中加载JS文件进行调试使用debugger;语句强制暂停执行我常用的一个技巧是重写console.log让网站检测不到调试行为console.log function() {}; window.console console;6. 实战案例分析让我们看一个完整的电商网站价格加密案例。通过抓包发现商品价格显示为U2FsdGVkX1...这样的Base64字符串。分析流程如下全局搜索U2Fsd发现是CryptoJS的加密特征定位到加密函数使用了AES加密调试发现密钥是通过用户Token固定盐值生成的最终Python解密代码import hashlib from Crypto.Cipher import AES def generate_key(token): salt fixed_salt_value return hashlib.md5((token salt).encode()).hexdigest() def decrypt_price(encrypted_b64, token): encrypted_bytes base64.b64decode(encrypted_b64) key generate_key(token) iv encrypted_bytes[:16] # 前16字节是IV cipher AES.new(key.encode(), AES.MODE_CBC, iv) return unpad(cipher.decrypt(encrypted_bytes[16:]), 16).decode()这个案例的特殊之处在于使用了动态IV每次加密随机生成放在密文开头增加了逆向难度。7. 进阶技巧与工具推荐对于更复杂的场景我推荐以下工具链Chrome开发者工具基础调试Fiddler/Charles抓包分析WebStormJS代码格式化与静态分析pycryptodomePython加密库Node.js在服务端运行前端JS代码一个实用技巧是使用astor库将混淆的JS代码转换为AST语法树再进行分析。比如import astor import ast with open(obfuscated.js) as f: tree ast.parse(f.read()) print(astor.to_source(tree)) # 输出格式化后的代码对于WebAssembly加密的极端情况可能需要使用wasm逆向工具但这已经超出本文范围。