当前位置: 首页 > news >正文

FiddlerScript实战:动态解密混合加密网络流量逆向分析

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平台逆向工程师的标配,原因在于:

  1. 中间人代理能力:可以轻松让目标应用的所有HTTP/HTTPS流量都经过它,这是解密分析的前提。
  2. 强大的会话操纵功能:能够断点、修改请求/响应、重放会话,方便我们测试和验证猜想。
  3. 可扩展的脚本引擎:这是最关键的一点。Fiddler内置了基于JScript.NET的脚本引擎(FiddlerScript),允许我们编写自定义规则(CustomRules.js),在请求和响应的不同生命周期注入处理逻辑。我们可以在这里调用外部程序(如Python脚本)来执行复杂的解密运算。

2.2 “Galaxy插件”的本质:CustomRules.js与外部调用

社区里常说的“Galaxy插件”或“黑科技脚本”,其核心就是精心编写的CustomRules.js文件。这个文件位于C:\Users\[你的用户名]\Documents\Fiddler2\Scripts\目录下。Fiddler启动时会自动加载它。我们的核心工作,就是在这个JS文件里,针对特定域名或特征的会话,编写OnBeforeRequestOnBeforeResponse函数,在流量经过时,调用我们准备好的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环境来安装项目依赖。不同项目、不同时期的库版本冲突是常态。我强烈推荐使用venv(Python 3.3+内置)或conda来创建独立的虚拟环境。

操作步骤与原理:

  1. 选择Python版本:建议使用Python 3.8-3.10之间的版本,这是大多数密码学库兼容性最好的区间。避免使用最新的3.12+,可能某些库尚未适配。
  2. 创建虚拟环境
    # 假设你的工作目录是 D:\Reverse\CryptoTraffic cd D:\Reverse\CryptoTraffic python -m venv venv
    这会在当前目录创建一个名为venv的文件夹,里面包含了一个独立的Python解释器和pip
  3. 激活虚拟环境
    • Windows (CMD):venv\Scripts\activate.bat
    • Windows (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连接。

  1. 开启HTTPS解密:打开Fiddler,点击菜单栏的Tools -> Options -> HTTPS。勾选Capture HTTPS CONNECTsDecrypt HTTPS traffic。在弹出的警告框中点击“Yes”信任根证书。
  2. 导出并安装根证书到客户端:这是让手机或另一个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 = b'this_is_a_32byte_key_for_aes256!!' # 32字节 MY_IV = b'16byte_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是最常见的填充方式,pycryptodomeunpad函数就是处理这个的。但也可能是其他填充或无填充,需要根据实际情况调整。

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代码是一个概念示例。在实际中,更优雅和高效的做法是:

  1. 将密钥管理逻辑放在Python端CustomRules.js只负责传递密文,Python脚本根据会话特征(如URL)选择对应的密钥和算法进行解密。
  2. 使用进程池或RPC:频繁地启动、关闭Python进程开销很大。可以考虑在Python端启动一个Flask或socket小型服务,FiddlerScript通过HTTP请求或socket调用它,实现一次启动,多次调用。
  3. 错误处理要完善:解密失败时,应该原样放过流量,而不是阻断或注入错误数据,以免影响应用正常功能,便于我们对比分析。

5. 实战调试与问题排查实录

即使一切配置就绪,第一次运行时也大概率不会一帆风顺。下面是我在多次实践中总结的常见问题排查清单。

5.1 FiddlerScript调用Python失败

  • 症状:Fiddler日志中没有任何解密成功的提示,或者直接报错。
  • 排查步骤
    1. 检查Python路径psi.FileName必须是虚拟环境中python.exe绝对路径。使用相对路径或系统Python路径是常见错误源。
    2. 独立测试Python脚本:在CMD中,手动激活虚拟环境,然后运行python decryptor.py “你的测试密文”,确保脚本本身能正确解密。
    3. 检查参数传递:FiddlerScript传递给Python的参数可能包含特殊字符(如引号、换行符),导致命令行解析错误。可以在Python脚本中先打印sys.argv来调试。
    4. 查看进程错误输出:上面代码中process.StandardError.ReadToEnd()的内容是关键,它会显示Python脚本运行时的导入错误、语法错误等。确保Fiddler日志能打印出这个error变量。

5.2 解密后数据乱码或报错

  • 症状:Python脚本调用成功,但解密出的内容仍是乱码,或json.decoder.JSONDecodeError
  • 排查步骤
    1. 确认算法和参数:这是最核心的问题。AES-256-CBC只是举例,实际可能是AES-GCM、RSA、SM4,或者多种算法嵌套。密钥长度、IV、模式(CBC, ECB, GCM)、填充方式必须与目标完全一致。一个字节的差异都会导致解密失败
    2. 检查编码:密文是Base64还是Hex?解密后的明文是UTF-8、GBK还是其他编码?尝试不同的解码方式。
    3. 验证填充:如果报错类似Padding is incorrect,说明填充模式不对。尝试unpad或手动处理填充字节。
    4. 分步验证:如果算法复杂,先在Python中分步验证:Base64解码 -> 密钥处理 -> 创建Cipher对象 -> 解密 -> 解码。每一步都打印中间结果的Hex,与你在逆向代码中Hook到的中间值进行比对。

5.3 HTTPS抓包失败或证书警告

  • 症状:手机App无法联网,或出现证书不安全警告。
  • 排查步骤
    1. 确认代理设置:手机Wi-Fi设置中,代理需手动设置为运行Fiddler的电脑IP和Fiddler监听端口(默认8888)。
    2. 确认证书安装:在手机浏览器访问http://[电脑IP]:8888,点击“FiddlerRoot certificate”下载并安装证书。安卓高版本需注意用户证书与系统证书的区别。
    3. 关闭防火墙或添加规则:确保电脑防火墙允许8888端口的入站连接。
    4. 检查App的证书绑定(SSL Pinning):这是最棘手的部分。很多App会校验服务器证书的指纹,如果发现不是预期的证书(即Fiddler的证书),就会断开连接。对付SSL Pinning需要更高级的手段,如使用JustTrustMe(Xposed模块)、Frida脚本(如frida-multiple-unpinning)来绕过。这超出了本文范围,但它是分析现代App必须面对的挑战。

5.4 性能问题与优化建议

当流量较大时,每个请求都启动一个Python进程会非常慢。我的优化建议是:

  1. 采用服务化架构:如前所述,将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(port=5000)

    然后在FiddlerScript中,使用System.Net.WebClienthttp://localhost:5000/decrypt发送HTTP请求,获取解密结果。这能减少99%的进程启动开销。

  2. 缓存密钥和算法对象:对于固定的密钥和IV,在Python服务中只初始化一次Cipher对象,而不是每次请求都新建。

  3. 精准匹配会话:在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插件破解混合加密流量,本质上是搭建了一个动态的、可编程的流量分析管道。它不能替代静态分析和动态调试,但却是连接两者、验证猜想、理解完整业务流程的绝佳桥梁。环境配置的坑,每一个踩过的人都懂,希望这篇指南能为你铺平道路。当你成功看到那一段段加密流量在你面前变成清晰的明文时,那种拨云见日的成就感,正是逆向工作最大的乐趣之一。记住,关键不在于记住所有步骤,而在于理解这套“代理拦截 -> 脚本调度 -> 外部解密”的通用框架,它能帮你应对未来各种形式的加密挑战。

http://www.jsqmd.com/news/1073482/

相关文章:

  • MPC8641D DMA控制器深度解析:从原理到高性能数据搬运实践
  • Simulink子系统引用:告别复制粘贴,实现复杂模块高效复用与同步
  • 虚拟机安装的三重门:从驱动加载到内核握手
  • Codex CLI 实战指南:subagent、MCP 协议与跨 agent 协作
  • MPC8555E通信处理器架构解析与嵌入式网络开发实战
  • Claude Code多Agent编排:契约驱动的智能体工程实践
  • 数据科学赋能英语教学:量化学习动机与个性化课堂设计
  • 从seccomp沙箱逃逸到实战:CTF Pwn中的受限环境攻击艺术
  • 扩散模型与强化学习融合:人形机器人运动控制新范式
  • 技术演进考古:从2006年云计算、jQuery与Web 2.0看当代开发范式变迁
  • EJSON:基于JSON的配置文件加密与密钥管理方案详解
  • XSS Hunter实战指南:从原理到高级应用的Web安全测试工具
  • 微信QQ域名防红技术全解析:从原理到实战的完整解决方案
  • MATLAB EXPO 2024技术分享指南:从算法到部署的工程实践
  • 遮罩参数获取:从UI显示值到内部计算值的正确映射
  • 深入理解Nmap:从端口扫描原理到实战安全评估
  • Gemini三端使用指南:网页/APP/电脑稳定接入全解析
  • Voyager:开源Gemini浏览器插件重构AI工作流
  • OpenAI开源计划:Tokenizer兼容层与API响应校验实战
  • 大模型四层运行态:从微调、部署到Agent的工程化认知框架
  • MathWorks学生项目团队新动向:如何利用官方资源规划工程学习路径
  • OpenClaw本地AI工作流部署全指南:三平台安装原理与排障实战
  • 复刻6个开源Agent项目:从CLI到多Agent协作的工程实践
  • MPC8272通信处理器:AAL2协议与以太网控制器硬件加速机制解析
  • AES算法逆向分析实战:从特征识别到密钥追踪与混淆对抗
  • 嵌入式以太网调优:深入解析MAC-FIFO与CAM过滤器配置实战
  • AI大模型重塑广告营销:从创意生成到智能投放的实战指南
  • C#/.NET 异常捕获与邮件通知:从基础实现到生产级全局处理
  • ComfyUI无痛部署指南:3分钟启动Stable Diffusion本地环境
  • VSCode 1.109 inlineChat深度解析:语义注入与Mermaid协同机制