Reassemble PDUs in lua wireshark dissector

2.1k views Asked by At

In a system I have a custom protocol and I would like to implement a Wireshark dissector so that I can use Wireshark to analyze the communication.

  • Objects are sent over the protocol, let us call them "Messages". Each message can be large, maybe up to 100 MB, they can also be very small for example 50 byte.

  • Each Message is split up in chunks of around 1 kB and tagged with a sequence number and a guid message id and those can be used at the other end to reassemble the messages.

So far I have successfully made a dissector that will individually log all chunks to Wireshark but I want to take this further and also log all messages (chunks assembled into messages) in Wireshark. Can this be done and how? Is it maybe possible to implement a dissector on top of the dissector I have developed below?

If it is possible to implement a dissector on top of the one below, how can I make sure it will only analyze myproto PDUs? The dissector below triggers on a specific tcp port, but that is not going to work for the second phase dissector...

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

There are 1 answers

0
distributed On BEST ANSWER

Let's say you have created a second dissector msgproto. Since you don't seem to have any multiplexing between chunks and messages, you don't need to setup a dissector table. Instead, at the end of myproto_proto.dissector you do a

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

This will pass all the chunk data to your msgproto . In the message protocol dissector you can use the chunk protocol's fields and of course the tvb that will contain just the data of one chunk. You will now need to piece together the chunks to one gloriously huge tvb. Make the msgprotohave state:

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

Convert your the tvb into a ByteArray and store into the stateMap together with the arrays from the other calls to your dissector. When you have assembled all your data into one array, let's call it oarr, make a tvb out of it:

    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))

supposed you have payload field of type Protofield.bytes. This code will make a new data pane called "message data" appear next to your regular "Frame" pane at the bottom of your Wireshark window.

I'm not sure how well Wireshark will like your ultra large buffers. Apart from that, I'm quite convinced that the approach outlined above will work. I have not used the described techniques in this exact order, but I have used all the described techniques, for example to make a new byte pane filled with data deflated in pure Lua.