Wireshark C插件开发学习笔记
1. Wireshark对C插件的支持
Wireshark使用插件来实现协议解析,插件可以以两种方式实现:内置方式和插件方式。内置方式将解析器模块编译到主程序中,而插件方式以共享库/DLL形式存在,可以动态加载。
内置方式 vs 插件方式
-
内置方式:
- 插件在主程序中编译,永远可用。
- 对Windows平台,通过列于
libwireshark.def
中的函数,可以访问有限的函数。 - 构建周期较长,但代码布署与内置解析器相同。
-
插件方式:
- 插件构建周期较短,开发初期简单,布署与内置解析器相同。
- 插件可以注册用于处理解析的函数,与内置解析器几乎相同。
详细信息可以在 doc/README.developer
文件中找到。
2. 编译构建C解析器
首先,需要决定解析器是以内置方式还是插件方式实现。插件方式相对容易上手。
解析器初始化
#include "config.h"
#include <epan/packet.h>
#define FOO_PORT 9877
static int proto_foo = -1;
void proto_register_foo(void) {
proto_foo = proto_register_protocol("FOO Protocol", "FOO", "foo");
}
在初始化中,使用 proto_register_protocol
注册协议,为协议提供名称、短名称和缩写。这样,协议将被主程序识别。
Handoff例程
void proto_reg_handoff_foo(void) {
static dissector_handle_t foo_handle;
foo_handle = create_dissector_handle(dissect_foo, proto_foo);
dissector_add_uint("udp.port", FOO_PORT, foo_handle);
}
在 proto_reg_handoff_foo
中,创建 dissector handle 并将其与UDP端口号关联,以便主程序在看到此端口上的UDP数据时调用我们的解析器。
解析器代码
static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
col_clear(pinfo->cinfo, COL_INFO);
}
dissect_foo
函数用于解析交给它的数据包。在这个基本的实现中,我们设置了协议文本并清除INFO列的所有数据。
以上是一个最小化的解析器实现,编译和安装后,它可以标识协议。
编译和安装
将插件源代码文件 packet-foo.c
及必需的支持文件准备好,并根据不同平台选择合适的构建方式,比如 UNIX/Linux 下使用 Makefile.am
和 CMakeLists.txt
,Windows 下使用 Makefile.nmake
。
运行编译命令,例如:
nmake -f Makefile.nmake
将生成的 foo.dll
文件拷贝到 Wireshark 的插件目录。
这样,我们就完成了一个基本的 Wireshark C 插件的开发,可以通过不断完善 dissect_foo
函数来实现更复杂的协议解析。