
1. 项目概述当逆向工程遇上加密流量逆向工程师的日常很多时候就像是在解一个没有图纸的复杂谜题。我们面对的是编译后的二进制文件、混淆后的代码或者像今天要聊的——经过层层加密的网络流量。当目标应用或协议采用了混合加密方案时传统的抓包分析工具如Wireshark看到的就是一堆天书般的乱码分析工作瞬间陷入僵局。这时一个得力的辅助工具就显得至关重要。“用Galaxy插件破解混合加密流量”这个标题精准地指向了逆向工程中一个高频且棘手的实战场景。这里的“Galaxy插件”并非指某个天文软件而是在网络安全和逆向分析领域广为人知的Fiddler Classic抓包工具的一个功能扩展模块——FiddlerScript有时也被社区昵称为“Galaxy”式的强大自定义脚本环境。而“混合加密流量”通常指的是同时使用了对称加密如AES和非对称加密如RSA或者结合了自定义编码、压缩的通信数据。破解它意味着我们要在本地中间人MitM的位置动态地解密、解码这些流量让其以明文形式呈现从而分析其通信逻辑、参数构造和业务接口。我之所以对这个话题有深入的实践是因为在过去分析多个移动端App、PC客户端软件甚至是一些物联网设备固件的通信协议时混合加密是开发者保护核心逻辑的常见手段。单纯靠静态分析IDA Pro看反汇编代码来推导加密算法不仅耗时巨大而且对于涉及密钥协商、随机IV初始化向量的动态流程往往力不从心。而Fiddler配合自定义脚本提供了一个实时、动态的流量拦截与修改平台是逆向工程工作流中不可或缺的一环。本文将从一个逆向工程师的实战视角出发拆解如何利用Fiddler的脚本插件环境搭建一个针对混合加密流量的动态解密分析平台。更重要的是我会重点分享在配置这个环境时尤其是在处理Python依赖环节这是脚本能力扩展的核心遇到的诸多“坑”以及如何系统性地避开它们。无论你是刚刚接触流量分析的逆向新人还是曾在环境配置上栽过跟头的同行相信这篇结合了原理、步骤与大量避坑经验的指南都能让你少走弯路快速建立起自己的加密流量分析能力。2. 核心思路与工具选型为什么是FiddlerScript在开始动手之前我们首先要理清思路为什么选择Fiddler及其脚本插件作为主战场面对加密流量我们通常有几种分析路径静态分析、动态调试、和流量侧录分析。静态分析逆向算法固然彻底但成本高动态调试如Xposed、Frida需要注入目标进程对环境和技巧要求高且可能触发反调试。而流量侧录分析是在数据离开或进入设备前进行拦截属于“外部观察”相对隐蔽和通用。2.1 Fiddler作为流量分析基座的优势Fiddler Classic注意不是Fiddler Everywhere是一款免费的HTTP/HTTPS调试代理工具。它之所以成为Windows平台逆向工程师的标配原因在于中间人代理能力可以轻松让目标应用的所有HTTP/HTTPS流量都经过它这是解密分析的前提。强大的会话操纵功能能够断点、修改请求/响应、重放会话方便我们测试和验证猜想。可扩展的脚本引擎这是最关键的一点。Fiddler内置了基于JScript.NET的脚本引擎FiddlerScript允许我们编写自定义规则CustomRules.js在请求和响应的不同生命周期注入处理逻辑。我们可以在这里调用外部程序如Python脚本来执行复杂的解密运算。2.2 “Galaxy插件”的本质CustomRules.js与外部调用社区里常说的“Galaxy插件”或“黑科技脚本”其核心就是精心编写的CustomRules.js文件。这个文件位于C:\Users\[你的用户名]\Documents\Fiddler2\Scripts\目录下。Fiddler启动时会自动加载它。我们的核心工作就是在这个JS文件里针对特定域名或特征的会话编写OnBeforeRequest或OnBeforeResponse函数在流量经过时调用我们准备好的Python解密程序。为什么选择Python作为解密逻辑的执行端因为现代加密算法库如cryptography,pycryptodome在Python生态中非常成熟和完善。很多从逆向中得到的算法如自定义的AES-CBC模式、ECB模式或者RSA解密用Python实现和调试远比在JScript.NET中方便。JScript.NET更适合做流程控制和简单的字符串处理复杂的密码学操作应该交给更专业的工具。因此整个方案的架构就很清晰了Fiddler代理拦截 - CustomRules.js流程控制与数据传递 - Python脚本执行具体解密算法 - 结果返回并替换原始流量。这个链条的稳定运行高度依赖于Python环境的正确配置这也是“避坑指南”的价值所在。3. 环境搭建与核心配置实战工欲善其事必先利其器。一个稳定、隔离的Python环境是后续所有操作的基础。很多初学者在这里遇到问题最终导致整个解密流程失败。3.1 Python环境避坑第一原则使用虚拟环境绝对不要使用系统全局的Python环境来安装项目依赖。不同项目、不同时期的库版本冲突是常态。我强烈推荐使用venvPython 3.3内置或conda来创建独立的虚拟环境。操作步骤与原理选择Python版本建议使用Python 3.8-3.10之间的版本这是大多数密码学库兼容性最好的区间。避免使用最新的3.12可能某些库尚未适配。创建虚拟环境# 假设你的工作目录是 D:\Reverse\CryptoTraffic cd D:\Reverse\CryptoTraffic python -m venv venv这会在当前目录创建一个名为venv的文件夹里面包含了一个独立的Python解释器和pip。激活虚拟环境Windows (CMD):venv\Scripts\activate.batWindows (PowerShell):venv\Scripts\Activate.ps1可能需要先执行Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser以允许脚本执行激活后命令行提示符前会出现(venv)字样表示你已进入该环境。避坑提示很多人在PowerShell下激活失败是因为执行策略限制。如果不想修改策略一个更简单的方法是直接用CMD进行操作或者在PowerShell中直接输入venv\Scripts\activate不带.ps1系统可能会自动调用CMD的activate.bat。3.2 关键依赖库的安装与版本锁定在激活的虚拟环境中安装核心的密码学库。这里有一个巨大的坑库的名称和版本。(venv) pip install pycryptodome (venv) pip install cryptography为什么是pycryptodome而不是pycryptopycrypto是一个古老且已停止维护的库在Windows上安装极其困难且存在已知的安全漏洞。pycryptodome是它的一个积极维护的替代品API兼容但功能更强大、安装更顺畅。cryptography则是另一个工业级的密码学库提供了更底层的接口两者可以结合使用。版本锁定技巧 安装后使用pip freeze requirements.txt命令将当前环境的依赖包及版本号导出。这个文件应该被纳入你的项目版本管理。当在其他机器上重建环境时只需pip install -r requirements.txt即可完美复现避免了“在我机器上是好的”这类问题。3.3 Fiddler的配置与证书安装要让Fiddler能够解密HTTPS流量必须在其和客户端手机或PC上的目标应用之间建立可信的HTTPS连接。开启HTTPS解密打开Fiddler点击菜单栏的Tools - Options - HTTPS。勾选Capture HTTPS CONNECTs和Decrypt HTTPS traffic。在弹出的警告框中点击“Yes”信任根证书。导出并安装根证书到客户端这是让手机或另一个PC信任Fiddler的关键。在Fiddler的HTTPS选项卡中点击Actions - Export Root Certificate to Desktop将证书文件如FiddlerRoot.cer保存到桌面。对于安卓手机分析将证书文件传入手机并安装。注意Android 7.0以上系统不再信任用户安装的证书用于保护的应用targetSdkVersion 24。你需要将证书安装到系统证书目录这通常需要Root权限或者使用安卓模拟器如夜神、雷电并在模拟器设置中直接导入证书模拟器通常提供了更简单的入口。对于Windows本地应用分析双击.cer文件选择“安装证书”存储位置选择“受信任的根证书颁发机构”。实操心得分析安卓App时使用已Root的模拟器如夜神模拟器在设置-安全中可直接导入证书是最省事的方案。真机环境配置复杂且受系统版本限制多。4. 解密脚本开发从流量特征识别到算法还原环境就绪后就进入了核心的脚本编写阶段。这个过程是逆向思维和编程能力的结合。4.1 分析流量特征定位目标会话首先你需要在不加载任何解密脚本的情况下用Fiddler捕获目标应用的流量。观察哪些请求或响应的内容是加密的通常表现为乱码、Base64编码的长字符串或者Content-Type与内容不符。记录下这些会话的关键特征Host/URL加密接口的完整URL或域名部分。请求头/响应头是否有特殊的Header标识加密方式或版本例如X-Encrypt-Mode: AES-256-CBC。Body形态是JSON中的一个字段是密文还是整个Body都是密文密文是Hex字符串还是Base64编码假设我们分析发现对api.targetapp.com/v1/data的POST请求其请求体是一个JSON其中encrypted_data字段是一个Base64字符串这就是我们的密文。4.2 编写Python解密函数在项目目录下创建decryptor.py根据你逆向静态分析或动态调试得到的算法信息实现解密函数。这里以一个常见的AES-256-CBC模式为例# decryptor.py import base64 import json from Crypto.Cipher import AES from Crypto.Util.Padding import unpad def decrypt_aes_256_cbc(encrypted_b64, key, iv): 解密AES-256-CBC加密的数据 :param encrypted_b64: Base64编码的密文字符串 :param key: 字节串长度必须为32 (256位) :param iv: 字节串长度必须为16 (128位) :return: 解密后的原始字符串 encrypted_bytes base64.b64decode(encrypted_b64) cipher AES.new(key, AES.MODE_CBC, iv) decrypted_padded cipher.decrypt(encrypted_bytes) # 去除PKCS7填充 original_data unpad(decrypted_padded, AES.block_size) return original_data.decode(utf-8) # 假设原文是UTF-8文本 # 示例从逆向中得到的密钥和IV这里用示例值实际需要你自己分析获取 MY_KEY bthis_is_a_32byte_key_for_aes256!! # 32字节 MY_IV b16byte_iv_here! # 16字节 if __name__ __main__: # 本地测试用 test_cipher U2FsdGVkX1...你的测试密文 try: result decrypt_aes_256_cbc(test_cipher, MY_KEY, MY_IV) print(解密成功:, result) except Exception as e: print(解密失败:, e)关键点密钥(key)和初始向量(iv)的来源是逆向工程的核心目标。它们可能硬编码在代码里可能通过密钥协商协议动态生成也可能由服务器下发。这需要你通过IDA Pro、JADX安卓等工具进行静态分析或通过Frida进行Hook来获取。注意填充模式。AES是块加密当数据不是块大小的整数倍时需要填充。PKCS7是最常见的填充方式pycryptodome的unpad函数就是处理这个的。但也可能是其他填充或无填充需要根据实际情况调整。4.3 编写FiddlerScript (CustomRules.js) 进行桥接这是将Fiddler和Python脚本连接起来的“胶水代码”。我们需要修改CustomRules.js文件。// 在 CustomRules.js 的 OnBeforeRequest 或 OnBeforeResponse 函数中添加逻辑 import System; import System.Diagnostics; import System.IO; import System.Text; class Handlers { // 在请求发送前解密请求体如果请求是加密的 static function OnBeforeRequest(oSession: Session) { // 1. 匹配目标URL if (oSession.uriContains(api.targetapp.com/v1/data)) { // 2. 检查请求方法是否为POST且有Body if (oSession.oRequest.headers.HTTPMethod POST oSession.requestBodyBytes.Length 0) { try { var requestBody System.Text.Encoding.UTF8.GetString(oSession.requestBodyBytes); // 3. 解析JSON提取密文字段 (这里假设是JSON格式) // 注意FiddlerScript的JScript.NET环境可能没有内置JSON解析可以用字符串操作或简单正则 // 更稳健的做法是调用外部Python脚本统一处理 var jsonObj Fiddler.WebFormats.JSON.JsonDecode(requestBody); var encryptedData jsonObj.JSONObject[encrypted_data]; if (encryptedData ! null) { // 4. 准备调用Python脚本 var psi new ProcessStartInfo(); psi.FileName D:\\Reverse\\CryptoTraffic\\venv\\Scripts\\python.exe; // 你的Python解释器绝对路径 psi.Arguments D:\\Reverse\\CryptoTraffic\\decryptor.py \ encryptedData \; psi.RedirectStandardOutput true; psi.RedirectStandardError true; psi.UseShellExecute false; psi.CreateNoWindow true; var process Process.Start(psi); process.WaitForExit(5000); // 等待5秒超时 var output process.StandardOutput.ReadToEnd(); var error process.StandardError.ReadToEnd(); if (process.ExitCode 0 output ! ) { // 5. 解密成功替换请求体 // 假设Python脚本输出就是解密后的明文我们需要重新构造JSON var newJson {decrypted_data: output }; // 根据实际情况调整 oSession.utilSetRequestBody(newJson); // 修改Content-Length头部 oSession.oRequest.headers[Content-Length] newJson.Length.ToString(); FiddlerObject.log(成功解密并替换请求体); } else { FiddlerObject.log(解密失败错误信息 error); } } } catch (e) { FiddlerObject.log(处理请求时发生异常: e.message); } } } } // 类似地可以在OnBeforeResponse中解密服务器返回的加密响应 static function OnBeforeResponse(oSession: Session) { if (oSession.uriContains(api.targetapp.com/v1/data)) { // ... 解密响应体的逻辑与上面类似 } } }重要提示上面的JScript代码是一个概念示例。在实际中更优雅和高效的做法是将密钥管理逻辑放在Python端CustomRules.js只负责传递密文Python脚本根据会话特征如URL选择对应的密钥和算法进行解密。使用进程池或RPC频繁地启动、关闭Python进程开销很大。可以考虑在Python端启动一个Flask或socket小型服务FiddlerScript通过HTTP请求或socket调用它实现一次启动多次调用。错误处理要完善解密失败时应该原样放过流量而不是阻断或注入错误数据以免影响应用正常功能便于我们对比分析。5. 实战调试与问题排查实录即使一切配置就绪第一次运行时也大概率不会一帆风顺。下面是我在多次实践中总结的常见问题排查清单。5.1 FiddlerScript调用Python失败症状Fiddler日志中没有任何解密成功的提示或者直接报错。排查步骤检查Python路径psi.FileName必须是虚拟环境中python.exe的绝对路径。使用相对路径或系统Python路径是常见错误源。独立测试Python脚本在CMD中手动激活虚拟环境然后运行python decryptor.py “你的测试密文”确保脚本本身能正确解密。检查参数传递FiddlerScript传递给Python的参数可能包含特殊字符如引号、换行符导致命令行解析错误。可以在Python脚本中先打印sys.argv来调试。查看进程错误输出上面代码中process.StandardError.ReadToEnd()的内容是关键它会显示Python脚本运行时的导入错误、语法错误等。确保Fiddler日志能打印出这个error变量。5.2 解密后数据乱码或报错症状Python脚本调用成功但解密出的内容仍是乱码或json.decoder.JSONDecodeError。排查步骤确认算法和参数这是最核心的问题。AES-256-CBC只是举例实际可能是AES-GCM、RSA、SM4或者多种算法嵌套。密钥长度、IV、模式CBC, ECB, GCM、填充方式必须与目标完全一致。一个字节的差异都会导致解密失败。检查编码密文是Base64还是Hex解密后的明文是UTF-8、GBK还是其他编码尝试不同的解码方式。验证填充如果报错类似Padding is incorrect说明填充模式不对。尝试unpad或手动处理填充字节。分步验证如果算法复杂先在Python中分步验证Base64解码 - 密钥处理 - 创建Cipher对象 - 解密 - 解码。每一步都打印中间结果的Hex与你在逆向代码中Hook到的中间值进行比对。5.3 HTTPS抓包失败或证书警告症状手机App无法联网或出现证书不安全警告。排查步骤确认代理设置手机Wi-Fi设置中代理需手动设置为运行Fiddler的电脑IP和Fiddler监听端口默认8888。确认证书安装在手机浏览器访问http://[电脑IP]:8888点击“FiddlerRoot certificate”下载并安装证书。安卓高版本需注意用户证书与系统证书的区别。关闭防火墙或添加规则确保电脑防火墙允许8888端口的入站连接。检查App的证书绑定SSL Pinning这是最棘手的部分。很多App会校验服务器证书的指纹如果发现不是预期的证书即Fiddler的证书就会断开连接。对付SSL Pinning需要更高级的手段如使用JustTrustMeXposed模块、Frida脚本如frida-multiple-unpinning来绕过。这超出了本文范围但它是分析现代App必须面对的挑战。5.4 性能问题与优化建议当流量较大时每个请求都启动一个Python进程会非常慢。我的优化建议是采用服务化架构如前所述将Python脚本改造成一个常驻的本地HTTP服务使用Flask或FastAPI。# decrypt_service.py from flask import Flask, request, jsonify app Flask(__name__) app.route(/decrypt, methods[POST]) def decrypt(): data request.json # ... 解密逻辑 ... return jsonify({result: decrypted_text}) if __name__ __main__: app.run(port5000)然后在FiddlerScript中使用System.Net.WebClient向http://localhost:5000/decrypt发送HTTP请求获取解密结果。这能减少99%的进程启动开销。缓存密钥和算法对象对于固定的密钥和IV在Python服务中只初始化一次Cipher对象而不是每次请求都新建。精准匹配会话在CustomRules.js中使用更精确的URL匹配条件避免对无关流量进行判断和调用减少性能损耗。6. 进阶技巧与扩展思路掌握了基础流程后你可以将这个框架玩出更多花样应对更复杂的场景。6.1 处理动态密钥协商有些协议的密钥是每次会话动态协商的如基于DH密钥交换。这种情况下你的Python脚本需要具备“状态记忆”能力。思路在FiddlerScript中捕获密钥协商的请求/响应提取出协商好的密钥或种子然后通过某种方式如写入共享文件、发送到Python服务的特定接口传递给Python解密服务。Python服务需要维护一个会话表例如以客户端IP或Session ID为Key将密钥与后续的加密会话关联起来。6.2 自动化与批量处理当你需要批量测试多个接口或参数时可以结合Fiddler的“AutoResponder”功能和脚本。操作在AutoResponder中将加密请求映射到一个本地文件。然后编写一个脚本读取这个请求文件调用你的解密服务生成解密的响应文件再让AutoResponder返回这个解密后的响应。这样可以实现自动化重放和解密测试。6.3 与其它逆向工具联动FiddlerScript的能力不仅限于调用Python。你还可以调用IDA Python脚本如果你在IDA中写了解析特定数据结构的脚本可以通过类似方式让Fiddler把抓到的二进制数据送给IDA Python去解析。触发外部调试器在特定请求到达时通过脚本启动或附加调试器到目标进程。逆向工程是一个需要耐心、细心和强大工具链支撑的工作。用Fiddler插件破解混合加密流量本质上是搭建了一个动态的、可编程的流量分析管道。它不能替代静态分析和动态调试但却是连接两者、验证猜想、理解完整业务流程的绝佳桥梁。环境配置的坑每一个踩过的人都懂希望这篇指南能为你铺平道路。当你成功看到那一段段加密流量在你面前变成清晰的明文时那种拨云见日的成就感正是逆向工作最大的乐趣之一。记住关键不在于记住所有步骤而在于理解这套“代理拦截 - 脚本调度 - 外部解密”的通用框架它能帮你应对未来各种形式的加密挑战。