Соберите PDU в Луа Wireshark диссектора

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

  • Объекты отправляются по протоколу, назовем их "Сообщения". Каждое сообщение может быть большим, может быть до 100 МБ, оно также может быть очень маленьким, например, 50 байт.

  • Каждое сообщение разбивается на куски размером около 1 кБ и помечается порядковым номером и идентификатором сообщения-подсказки, которые можно использовать на другом конце для повторной сборки сообщений.

До сих пор я успешно создал диссектор, который будет индивидуально регистрировать все чанки в Wireshark, но я хочу пойти дальше и также записывать все сообщения (чанки, собранные в сообщения) в Wireshark. Можно ли это сделать и как? Возможно ли реализовать диссектор поверх того диссектора, который я разработал ниже?

Если возможно реализовать диссектор поверх приведенного ниже, как я могу убедиться, что он будет анализировать только мои прото-PDU? Приведенный ниже диссектор запускает определенный порт TCP, но это не сработает для диссектора второй фазы...

myproto_proto = Proto("myproto", "My Protocol")

function myproto_proto.dissector(buffer, pinfo, tree)
    pinfo.cols.protocol = "myproto"

    local message_length = buffer(0, 4):le_uint()+4

    if message_length>pinfo.len then
        pinfo.desegment_len = message_length
        pinfo.desegment_offset = 0
        return;
    end

    local subtree = tree:add(myproto_proto, buffer(), "My Protocol Data")
    local packet = subtree:add(buffer(0, message_length), "Chunk")
    packet:add(buffer(0, 4), "Packet length: " .. buffer(0, 4):le_uint())
    packet:add(buffer(32, 16), "Message ID")
    packet:add(buffer(48, 4), "Block ID: " .. buffer(48, 4):le_uint())
    packet:add(buffer(52, 4), "Max Block ID: " .. buffer(52, 4):le_uint())
    packet:add(buffer(68, message_length-68-20), "Data")

    pinfo.desegment_len = 0
    pinfo.desegment_offset = message_length
    return

end

tcp_table = DissectorTable.get("tcp.port")
tcp_table:add(1234, myproto_proto)

1 ответ

Решение

Допустим, вы создали второй диссектор msgproto, Поскольку у вас, кажется, нет мультиплексирования между порциями и сообщениями, вам не нужно настраивать таблицу анализатора. Вместо этого в конце myproto_proto.dissector ты делаешь

 msgproto.dissector:call(buffer(68, message_length-68-20):tvb, pinfo, tree)

Это передаст все данные чанка на ваш msgproto, В диссекторе протокола сообщений вы можете использовать поля протокола чанка и, конечно, tvb, который будет содержать только данные одного чанка. Теперь вам нужно собрать куски в один великолепно огромный телевизор. Сделать msgprotoиметь состояние:

 local stateMap = {}
 function msgproto.init()
     stateMap = {}
 end

Преобразуйте свой TVB в ByteArray и сохраните в stateMap вместе с массивами из других вызовов вашего диссектора. Когда вы собрали все свои данные в один массив, давайте назовем его oarr, сделайте из этого твб:

    local otvb = ByteArray.tvb(oarr, "message data")
    -- starting from 0, need to pass a tvb range, not a tvb.
    stree:add(msgproto.fields.payload, otvb(0))

Предполагается, что у вас есть payload поле типа Protofield.bytes, Этот код заставит новую область данных под названием "данные сообщения" появиться рядом с вашей обычной панелью "Рамка" в нижней части окна Wireshark.

Я не уверен, насколько хорошо Wireshark понравятся ваши сверхбольшие буферы. Кроме того, я совершенно уверен, что изложенный выше подход будет работать. Я не использовал описанные методы в этом точном порядке, но я использовал все описанные методы, например, чтобы создать новую панель байтов, заполненную данными, сдутыми в чистом Lua.

Другие вопросы по тегам