Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
228 views
in Technique[技术] by (71.8m points)

lua - Two Wireshark Dissectors with shared fields

I am writing a wireshark dissector for a custom protocol. The protocol has two variants, which are indistinguishable in general when looking at the dump. So usually the user will simply select the correct variant to decode.

Both variants share quite a lot of ProtoFields and also a lot of structure, which is why I had hoped to write most of the dissection code only once and then have two top-level dissectors calling those components.

The rough idea is:

local custom_var1 = Proto("custom_var1", "My custom protocol Variant 1")
local custom_var2 = Proto("custom_var2", "My custom protocol Variant 2")

-- my actual header and data blocks are a lot more complex than single integers of course
local header = ProtoField.uint8("custom.head", "Header")
local data1 = ProtoField.uint64("custom.data1", "Data 1")
local data2 = ProtoField.uint32("custom.data2", "Data 2")
local data3 = ProtoField.uint8("custom.data3", "Data 3")

custom_var1.fields = {header, data1, data2}
custom_var2.fields = {header, data1, data2, data3}

local function dissect_header(tvb, tree)
    tree:add(header, tvb(0, 1))
end

local function dissect_data1(tvb, tree)
    tree:add(data1, tvb(0, 8))
end

local function dissect_data2(tvb, tree)
    tree:add(data2, tvb(0, 4))
end

local function dissect_data3(tvb, tree)
    tree:add(data3, tvb(0, 1))
end

function custom_var1.dissector(tvb, pinfo, root)
    pinfo.cols.protocol:set(custom_var1.name)
    local tree = root:add(custom_var1, tvb(0, 13))

    dissect_header(tvb(0), tree)
    dissect_data1(tvb(1), tree)
    dissect_data2(tvb(9), tree)
end

function custom_var2.dissector(tvb, pinfo, root)
    pinfo.cols.protocol:set(custom_var2.name)
    local tree = root:add(custom_var2, tvb(0, 14))

    dissect_header(tvb(0), tree)
    dissect_data2(tvb(1), tree)
    dissect_data1(tvb(5), tree)
    dissect_data3(tvb(13), tree)
end

tcp_port = DissectorTable.get("tcp.port")
tcp_port:add(31337, custom_var1)
tcp_port:add(31337, custom_var2)

My problem: When I place the lua file into my plugin directory and start wireshark, I see a Wireshark Debug Console (with black background and not white, a with the lua console) with the message 18:08:56.505 Err LUA PANIC: fields can be registered only once followed by Press any key to exit before I can do anything else. After pressing a key, wireshark immediately exists.

How can I write two dissectors with shared fields, without too much code duplication?

question from:https://stackoverflow.com/questions/66067613/two-wireshark-dissectors-with-shared-fields

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Why not just write one dissector and add a preference for the user to choose which variant to apply? For example:

-- Protocol
local p_custom = Proto("custom", "My custom protocol")
local data_dis = Dissector.get("data")

-- Preferences
local default_settings = {
    variant = 1
}

local variant_pref_enum = {
    { 1, "1", 1 },
    { 2, "2", 2 }
}

p_custom.prefs.variant = Pref.enum("Variant", default_settings.variant,
    "The variant", variant_pref_enum)

-- Fields
local pf = {
    header = ProtoField.bytes("custom.head", "Header"),
    data1 = ProtoField.uint64("custom.data1", "Data 1"),
    data2 = ProtoField.uint32("custom.data2", "Data 2"),
    data3 = ProtoField.uint8("custom.data3", "Data 3")
}
p_custom.fields = pf

-- Dissection
function p_custom.dissector(tvbuf, pinfo, tree)
    local custom_tree = tree:add(p_custom, tvbuf(0, -1))

    custom_tree:add(pf.header, tvbuf(0, 1))
    if p_custom.prefs.variant == 1 then
        -- Dissect Variant 1
        pinfo.cols.protocol:set("CUSTOM 1")
        custom_tree:append_text(": Variant 1")
        custom_tree:add(pf.data1, tvbuf(1, 8))
        custom_tree:add(pf.data2, tvbuf(9, 4))
    elseif p_custom.prefs.variant == 2 then
        -- Dissect Variant 2
        pinfo.cols.protocol:set("CUSTOM 2")
        custom_tree:append_text(": Variant 2")
        custom_tree:add(pf.data2, tvbuf(1, 4))
        custom_tree:add(pf.data1, tvbuf(5, 8))
        custom_tree:add(pf.data3, tvbuf(13, 1))
    else
        -- Unknown Variant
        pinfo.cols.protocol:set("CUSTOM ?")
        custom_tree:append_text(": Unknown Variant")
        data_dis:call(tvbuf:range(1, tvbuf:len() - 1):tvb(), pinfo, tree)
    end
end

-- Registration
local tcp_port = DissectorTable.get("tcp.port")
tcp_port:add(31337, p_custom)

Of course, if there's information available in the common header that can help determine which variant to apply automatically, then a preference isn't needed at all.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...