Введение
Бывает ситуация когда надо посмотреть данные в сетевом дампе, а Wireshark не поддерживает такой протокол и вместо данных в нем можно видеть только набор байт.

В таком случаем при наличии спецификации можно написать свой парсер протокла, что я и покажу на примере протокола EGTS, о разборе которого я писал ранее.
Создание плагинов в wireshark
Плагины в Wireshark для произвольных протоколов можно делать двумя способами:
Про первый способ, как создавать библиотеку можно прочитать на Habr’e. Для себя я выбрал второй способ изза меньших трудозатрат.
Также надо отметить, что если писать планины на С, то придется пересобирать wireshark что мне делать не очень хотелось.
Работа с lua плагинами
Первым шагом нужно убедиться что включена поддержка Lua. Для этого в директори с глобальными настройками в файле init.lua
нужно убедиться чт enable_lua = true
.
После этого добавляем файл плагина c расширением lua в папку с плагинами, путь до которой можно посмотреть в меню About.
При старте wireshark палинг будет загружен.
Создание плагина для EGTS
Первое что необходимо сделать это объявить объект протокола:
local egts_proto = Proto("egts", "EGTS")
Далее, если нужна кофигурация плагина из мею настроек, то нужно добавить default_settings
:
local default_settings =
{
port = 20629
}
После того как настройки заданы необходимо задасть поля протокола:
local header =
{
prv = ProtoField.new("ProtocolVersion", "egts.prv", ftypes.UINT8, nil, base.DEC),
skid = ProtoField.new("SecurityKeyID", "egts.skid", ftypes.UINT8, nil, base.DEC),
prf = ProtoField.new("Prefix", "egts.prf", ftypes.UINT8, nil, base.DEC, 0xc0),
...
}
egts_proto.fields = header
Функция ProtoField.new
создает прототип поля в дереве вывода и имеет следующие параметры:
- имя поля в дереве вывода
- синоним для поиска из интерфейса Wireshark
- тип поля
- псевдоним отображения (необязательно)
- тип для вывода (необязательно)
- маска для получения значения по смещению (необязательно)
Теперь для разбора протокола необходито задать функцию dissector
:
function egts_proto.dissector(tvbuf, pktinfo, root)
dissect_tcp_pdus(tvbuf, root, MIN_HEADE_LENGHT, get_egts_length, dissect_egts_pdu)
local bytes_consumed = tvbuf:len()
return bytes_consumed
end
Тут видно что вызывается функция dissect_tcp_pdus
, которая отвечает за разбивку фреймов в tcp, так как пакет tcp может собедражать в себе несколько фреймов. С помощью данной функции происходит разбиение пакетов по секциям, что актуально только для tcp. В функцию объект пакета в байтах (tvbuf), объект дерева для вывода в интерфейсе (root), размер заголовка пакета, функция для вычисления длины tcp пакета и функция парсинга пакета.
Для функции получения длины сигнатура содержит объект TvbRange с данными (tvbuf), объект с информацией о пакете (pktinfo) и смещение.
Функция для парсинга примает следующие параметры: объект TvbRange, объект Pinfo c информацией о пакете (pktinfo) и объект дерева пакета (root).
После того как парсер написан необходимо добавить его в таблицу декодировщиков:
DissectorTable.get("tcp.port"):add(default_settings.port, egts_proto)
Теперь можно запусть wireshark и в случае корректно написнного планига он загурзится или же будет выдана ошибка с номером строки, которую нужно поправить.
Полный плагин можно посмотреть на Github
Для отладки плагина используется функция print()
, сначала открывается wireshark, в нем открывается lua консоль, а потом загружете файл дампа и в Lua консоли пойдут сообщения.
Заключение
В итоге получилось следующее:

Задача написания плагина для Wireshark на Lua, довольно тривиальная задача и все основная работа сводится именно к описанию данных в самом протоколе.
Так же надо отметить что в статье не описано подробно как строить вложенные деревья, но они есть в полном тексте плагина, поэтому разобраться с ним не составит труда.
Ссылки
- Packet Dissection
- Пишем плагин-диссектор для Wireshark
- Lua Support in Wireshark
- Wireshark Developer’s Guide