Wireshark C插件开发第一周进展

发布时间 2023-11-19 17:36:08作者: 20211406张顺扬

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.amCMakeLists.txt,Windows 下使用 Makefile.nmake

运行编译命令,例如:

nmake -f Makefile.nmake

将生成的 foo.dll 文件拷贝到 Wireshark 的插件目录。

这样,我们就完成了一个基本的 Wireshark C 插件的开发,可以通过不断完善 dissect_foo 函数来实现更复杂的协议解析。