Wireshark 解析器插件开发
在网络开发与调试中,我们通常使用 Wireshark 进行抓包分析。Wireshark 本身提供了大量常用协议的解析器,方便我们对抓包内容进行详细分析,比如 http、tcp、udp 等数据包,我们都可以通过 Wireshark 直观的查看相关协议头、payload 等信息。在游戏项目中,我们经常使用自定义的前后台通信协议,这部分内容 Wireshark 就无法直接解析展示,分析起来比较麻烦。为了提高私有协议的问题分析效率,我们尝试使用 Wireshark 提供的插件扩展的方式,实现私有协议解析器。
实现私有协议解析插件的核心即为编写对应的协议 Dissector。解析器(Dissector)是 Wireshark 的 “翻译官”,负责将捕获的二进制数据包转换为人类可读的协议字段(如协议头、载荷内容)。Wireshark 支持两种方式实现私有协议解析插件:
- Lua 脚本插件:轻量化、无需编译、开发速度快,适合简单协议或快速验证场景。
- C++ 原生插件:性能强、支持复杂协议,但需配置编译环境,适合对效率要求高的场景。
Lua 解析器插件
Lua 是 Wireshark 内置的脚本语言,无需编译,直接编写脚本即可实现解析功能,适合一些简单协议的快速开发。
解析器开发
官方文档提供了 Lua API 实现解析器的相关说明,我们可以根据其官网文档 Chapter 11. Wireshark’s Lua API Reference Manual 章节内容,实现私有协议解析器的开发。
核心 API

创建协议对象
首先,需要创建一个协议对象,协议名称、描述等信息会用于在 wireshark 的界面展示或过滤器筛选。
1 | -- 语法:Proto("协议名称", "协议描述"), |

定义协议字段 (ProtoField)
接着需要定义协议中每个字段的元数据,如名称、数据类型、显示格式等。这些字段将在 Wireshark 的 Packet Details 面板中显示。
1 | -- 为了方便管理,我们将所有字段存储在协议对象的 fields 表中 |
实现解析器主函数 (dissector)
这是脚本的核心逻辑。当 Wireshark 捕获到一个与我们协议关联的数据包时,这个函数就会被调用。
1 | -- 语法:function 协议对象.dissector(tvb, pinfo, tree) |
将解析器注册到 Wireshark
此步骤用于告诉 Wireshark 什么时候应该使用我们的解析器。Wireshark 中有两种解析器:
- Heuristic-dissector(启发式解析器),直接解析原始数据。
- Post-dissector(后置解析器),会在标准解析器之后触发,依赖标准解析器解析出的协议字段。(比如 DNS 协议是依赖 tcp.port 为 53的前置解析结果)
1 | --场景1:仅需要针对tcp 的 8085 端口情况进行解析,因此添加到"tcp.port"这个DissectorTable。 |
对于注册的解析器,可以在 Wireshark 解析器表中查看。

部署与加载脚本
第三方的 lua 插件统一放置在 Wireshark 的 Lua 插件目录。可以通过在 Wireshark 中点击 帮助 -> 关于 Wireshark -> 文件夹 来找到这个目录,通常是:
- Windows: C:\Program Files\Wireshark\lua\plugins 或 %APPDATA%\Wireshark\plugins
- macOS: ~/Library/Application Support/Wireshark/plugins

放置完脚本后,点击工具 -> Lua -> 重新加载 Lua 脚本,即可完成私有协议解析器加载,如果当前分析的抓包文件中包含私有协议消息,则会直接在 wireshark 界面中展示出来。Wireshark 在启动时也会自动加载插件目录下的所有 .lua 文件。
注意:如果自定义协议解析器太多,或协议比较复杂,会影响抓包文件的加载速度,这时可以通过停用协议的方式暂停解析器加载,待抓包文件载入完成后,再根据需要启用对应解析器。
C++ 解析器插件
对于复杂的协议,尤其是涉及到加解密,或者 pb/tdr 等序列化算法时,使用 lua 开发需要重新实现相关算法,耗时耗力。这时就需要借助 Wireshark 的 C++ 层开发能力。
Wireshark 本身就是基于 C++ 开发,其代码也是开源的,官方文档也提供了 C++ API 实现解析器的相关说明,我们可以根据其 官网文档 Chapter 9. Packet Dissection 章节内容,实现私有协议解析器的开发。
但是在实践中我们发现,C++ 插件的开发,依赖 wireshark 项目中的很多接口符号,需要跟 wireshark 项目一起编译才行,导致我们必须额外熟悉并搭建 wireshark 项目的开发环境,极大提高了开发门槛。
经过探索尝试,发现可以通过以下方式绕开 wireshark 核心逻辑的编译,将开发重心重新转移到自定义解析器的实现上来。
解决头文件依赖、动态库链接等问题
获取头文件
Wireshark 代码是开源的,我们可以根据自己安装的版本,直接从 githlab 下载对应的源码,以获取到我们开发所需要的头文件。然后将头文件路径添加到我们的解析器开发工程(dll 动态库工程)中。
1 | {path}\wireshark |
获取 glib2 头文件
由于 wireshark 的头文件存在 glib2 的引用,但这部分依赖不在源码中,因此,还要额外准备 glib2 头文件。
根据官网文档 5. Library Reference 章节,Wireshark Windows 平台所有的依赖库可以在 https://dev-libs.wireshark.org/windows/ 下载获得。
下载所需的 vcpkg-export 包:
1 | vcpkg-export-xxxxxxxx-x-x64-windows-ws |
将 glib 的头文件路径添加到到我们的解析器开发工程(dll 动态库工程)中即可。
1 | {path}\vcpkg-export-xxxxxxxx-x-x64-windows-ws\installed\x64-windows\lib\glib-2.0\include |

链接 libwireshark.dll
配置好 Wireshark 和 glib 头文件,解决了代码的编译问题。但是,最终生成 dll 还是需要依赖链接 Wireshark 中的相关接口符号。
我们直接可以将自定义解码器源码合入 Wireshark 开源项目中,编译出带自定义解码器的完整 Wireshark 工具(exe)。但是,这样要搭建整个 Wireshark 编译环境,比较麻烦。而且,不利于自定义解码器的共享,每个人都需要安装带特定解码器的 Wireshark 版本才行。
我们安装的公版 Wireshark 已经带了 libwireshark.dll,通过反编译工具可以查到开发解析器需要使用的 api 符号都未隐藏,如果解析器开发工程能直接链接使用,就可以生成独立的自定义解码器插件(dll),方便在任何版本的 wireshark 中直接使用。
所以,问题的关键变为如何使用 Wireshark 中不带 .lib 的 libwireshark.dll。
- 手动编写 libwireshark.def 定义需要导出的函数。(wireshark 的导出函数,使用 WS_DLL_PUBLIC 宏标记 )
1 | EXPORTS |
- 使用 dumpbin.exe 查看 libwireshark.dll 是32位还是64位。
1
2
3C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64
.\dumpbin.exe /headers libwireshark.dll - 使用 lib.exe 从 .def 生成 libwireshark.lib
1
2
3C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64
.\lib.exe /def:libwireshark.def /machine:x64 /out:libwireshark.lib
有了 libwireshark.lib,就可以在 vs 中直接链接 libwireshark.dll 了。

解析器开发
C++ 解析器的开发逻辑基本同 lua 一致,基本上将对应 lua api 替换为 c++ api 即可。
核心 API

主要逻辑
1 |
|
编译与部署
将编译生成的 dll 放在 Wireshark 的安装目录即可。
lua 与 C++ 插件方案对比
| 维度 | C++ 原生插件 | Lua 脚本插件 |
|---|---|---|
| 性能 | 高(直接调用核心 API) | 中(脚本解释执行) |
| 开发效率 | 低(需配置环境、编译) | 高(无编译、实时生效) |
| 复杂度支持 | 支持复杂协议(加密、嵌套) | 适合简单协议 |
| 部署成本 | 需分发动态库,与wireshark版本耦合性强 | 仅需分发脚本文件,兼容性强 |
C++ 与 Lua 交互(混合方案)
C++ 方案由于涉及到 Wireshark 接口导出、新的 API 用法学习,成本会相对比较高。
通常我们会采用折中的方案,即 “Lua 调用 C++” 的混合方案:用 C++ 实现核心解析逻辑,暴露接口给 Lua,兼顾灵活性与性能。
- Lua 层:注册 Wireshark 解析器,具体协议执行调用 C++ 注册的函数,处理复杂逻辑后继续解析。
- C++ 层:编写函数(如 decrypt_payload 解密载荷),用 lua_register 注册到 Lua 环境。
这样,C++ 层开发时,只需要引入 lua 开发环境及自身逻辑所需要的依赖,大大降低了开发成本。