Wireshark 解析器

解析器(Dissector)是 Wireshark 中用于将报文二进制翻译为网络协议的解码器。Wireshark 本身提供了大量常用协议的解析器,方便日常抓包分析。比如 http、tcp、udp 等数据包,我们都可以通过 Wireshark 直观的查看相关协议头、payload 等信息。在一些网络项目中,我们常常会自定义前后台的私有通信协议,这部分内容 Wireshark 就无法直接解析展示,分析起来比较麻烦。这种情况,我们需要借助 Wireshark 的插件机制,自行实现私有协议解析器,以方便数据分析。

对于私有协议解析器,Wireshark 提供了两种方案:

  1. lua 插件实现
  2. c++ 插件实现

C++ 解析器插件开发

Wireshark 本身就是基于 C++ 开发,官方文档也提供了 C++ API 实现解析器的相关说明,我们可以根据其官网文档 Chapter 9. Packet Dissection 章节内容,实现私有协议解析器的开发。

获取头文件

Wireshark 代码是开源的,我们可以根据自己安装的版本,直接从 githlab 下载对应的源码,以获取到我们开发所需要的头文件。然后将头文件路径添加到我们的解析器开发工程(dll 动态库工程)中。

1
2
{path}\wireshark
{path}\wireshark\include

获取 glib2 头文件

由于 wireshark 的头文件存在 glib2 的引用,但这部分依赖不在源码中,因此,还要额外准备 glib2 头文件。
根据官网文档 5. Library Reference 章节,Wireshark Windows 平台所有的依赖库可以在 https://dev-libs.wireshark.org/windows/ 下载获得。

下载所需的 vcpkg-export 包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
vcpkg-export-xxxxxxxx-x-x64-windows-ws
├── installed
│   ├── ...
│   └── x64-windows
│   ├── bin
│   │   ├── ...
│   │   ├── glib-2.0-0.dll
│   │   ├── glib-2.0-0.pdb
│   │   └── ...
│   ├── include
│   │   ├── ...
│   │   ├── glib-2.0
│   │   │   ├── ...
│   │   │   ├── glib.h
│   │   │   └── ...
│   │   └── ...
│   ├── lib
│   │   ├── ...
│   │   ├── glib-2.0
│   │   │   └── include
│   │   │   └── glibconfig.h
│   │   ├── glib-2.0.lib
│   │   └── ...
│   └── ...
└── ...

将 glib 的头文件路径添加到到我们的解析器开发工程(dll 动态库工程)中即可。

1
2
{path}\vcpkg-export-xxxxxxxx-x-x64-windows-ws\installed\x64-windows\lib\glib-2.0\include
{path}\vcpkg-export-xxxxxxxx-x-x64-windows-ws\installed\x64-windows\include\glib-2.0

链接 libwireshark.dll

配置好 Wireshark 和 glib 头文件,解决了代码的编译问题。但是,最终生成 dll 还是需要依赖链接 Wireshark 中的相关接口符号。

我们直接可以将自定义解码器源码合入 Wireshark 开源项目中,编译出带自定义解码器的完整 Wireshark 工具(exe)。但是,这样要搭建整个 Wireshark 编译环境,比较麻烦。而且,不利于自定义解码器的共享,每个人都需要安装带特定解码器的 Wireshark 版本才行。

我们安装的公版 Wireshark 已经带了 libwireshark.dll,通过反编译工具可以查到开发解析器需要使用的 api 符号都未隐藏,如果解析器开发工程能直接链接使用,就可以生成独立的自定义解码器插件(dll),方便在任何版本的 wireshark 中直接使用。

所以,问题的关键变为如何使用 Wireshark 中不带 .lib 的 libwireshark.dll。

  1. 手动编写 libwireshark.def 定义需要导出的函数。(wireshark 的导出函数,使用 WS_DLL_PUBLIC 宏标记 )
1
2
3
4
EXPORTS
tvb_address_to_str
tvb_address_var_to_str
...
  1. 使用 dumpbin.exe 查看 libwireshark.dll 是32位还是64位。
    1
    2
    3
    # C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64

    .\dumpbin.exe /headers libwireshark.dll
  2. 使用 lib.exe 从 .def 生成 libwireshark.lib
    1
    2
    3
    # C:\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 了。

Lua 解析器插件开发

Wireshark 内置了对 Lua 脚本的支持,可以直接编写Lua脚本,无需配置额外的环境就可以使用。官方文档也提供了 Lua API 实现解析器的相关说明,我们可以根据其官网文档 Chapter 11. Wireshark’s Lua API Reference Manual 章节内容,实现私有协议解析器的开发。

lua 与 C++ 交互

自定义协议解析可以完全使用 Lua 语言实现,对于复杂的协议,需要在 c++ 层解析的,也可以利用 lua 与 c++ 语言的交互特性,实现 lua 解析器插件调用 c++。

使用自定义解析器

将生成的自定义解析器放置在 wireshark 安装插件目录即可。插件目录路径可以通过“帮助 - 关于 wireshark - 文件夹”查看。
Lua 脚本插件放置在 “Lua Scripts”目录下,二进制 dll 放置在“Binary plugins”目录下。(如果存在 lua 与 c++ 交互,需要将对应的 c++ 二进制放置在安装的 wireshark 根目录,确保正常加载)