My favorites | Sign in
Project Logo
                
Search
for
Updated Jul 01, 2009 by giorak
Labels: Featured
ExplainFastDissect  
step by step explanation how to create wireshark dissector

Wireshark dissector with bitstring

Wireshark is an open source protocol analyzer used by network professionals world wide. It is an amazing software with support for endless list of protocols, powerful display and capture filters and coloring rules. Although Wireshark is evolving to support more protocols it has an extension interface in Lua that lets you add new protocols.

The Lua extension interface is very powerful and is continuously evolving but has some known limitations – the access to individual bits is still not implemented(version 1.2.0). So if you have to know a value of a bit to parse correctly the rest of the buffer you have to write (for now) it in C.

This tutorial will show how to use the power of Wireshark Lua extensions and how to overcome the limitations mentioned above with bitstring.

We will implement a toy dissector for EAP-FAST like protocol that will be carried over UDP on port 1818. Note: this is an example; wireshark has and excellent EAP-FAST dissector.

Before you start please download and install Wireshark, Lua and bitstring. Copy the bitstring.dll on win32 systems to example directory or ensure it is on your LUA_CPATH.

Create a packet generator for testing our example. It sends two EAP-FAST packets over UDP to be analyzed by our dissector.

-- usage: $ lua ./packet-gen.lua
...
sock = socket.udp()
sock:sendto(packet_with_length, "1.1.1.1", 1818)
sock:sendto(packet_no_lenght, "1.1.1.1", 1818)

See packetgen.lua for complete code listing.

Create the dissector

    local fastudp = Proto("fastudp", "Example for EAP-FAST over UDP dissector")

Create the init function. It is called once before any packets are forwarded to dissector.

    function fastudp.init()
    end

Define fields for the protocol. A field specifies the type of protocol element, its name for filters, displayed name and optional base, value string, mask and description. See wireshark user guide for details.

    local f = fastudp.fields
    f.code = ProtoField.uint8("fastudp.code", "code")
    f.identifier = ProtoField.uint8("fastudp.identifier", "identifier")
    f.length = ProtoField.uint16("fastudp.length", "length")
    f.eap_type = ProtoField.uint8("fastudp.eap_type", "eap type")
    f.lflag = ProtoField.uint8("fastudp.lflag", "lflag", base.HEX, nil, 0x80)
    ...
    f.fast_length = ProtoField.uint32("fastudp.fast_length", "eap-fast length")
    f.data = ProtoField.bytes("fastudp.data", "eap-fast data")

Create the dissector function that will be called for each captured packet that passes the filter. The function will update the dissection tree using field definitions from above.

    function fastudp.dissector(buffer, pinfo, tree)
        local subtree = tree:add(fastudp, buffer())
        local offset = 0
        -- find the chunk of buffer that holds the code
        local code = buffer(offset, 1)
        subtree:add(f.code, code)
        local identifier = buffer(offset + 1, 1)
        subtree:add(f.identifier, identifier)
        local length = buffer(offset + 2, 2)
        subtree:add(f.length, length)
        local eap_type = buffer(offset + 4, 1)
        subtree:add(f.eap_type, eap_type)

        local flags = buffer(offset + 5, 1)
        subtree:add(f.lflag, flags)
        subtree:add(f.mflag, flags)
        subtree:add(f.sflag, flags)
        subtree:add(f.rflag, flags)
        subtree:add(f.version, flags)

        -- get flags bit values using bitstring
        local lflag, mflag, sflag, rflags, version = 
        bitstring.unpack("1:int, 1:int, 1:int, 2:int, 3:int", 
        bitstring.fromhexstream(tostring(flags:bytes())))

        -- if length flag is set add length field
        -- to subtree
        if lflag == 1 then
            local fast_length = buffer(offset + 6, 4)
            subtree:add(f.fast_length, fast_length)
        end

        local data = buffer(offset + 10)
        subtree:add(f.data, data)
    end

Subscribe for PROTOCOL.PORT that carries your protocol.

    local udp_table = DissectorTable.get("udp.port")
    udp_table:add(1818, fastudp)

See fastdissect.lua for complete code listing.

comment out the following line in init.lua file in wireshark directory

disable_lua = true; do return end;

add following line to the end of init.lua file in wireshark directory. The path of the file should point to were you copied the fastdissect.lua example

dofile([[example-dir-path/fastdissect.lua]])

Screen shots

Captured packet with the length bit set and length field displayed

Captured packet with the length bit not set

Credits

This example is based on tutorial by Stig Bjørlykke. The tutorial contains more information on how to write dissectors, post dissectors and listeners.


Sign in to add a comment
Hosted by Google Code